169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/*
269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Javassist, a Java-bytecode translator toolkit.
369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Copyright (C) 1999-2007 Shigeru Chiba. All Rights Reserved.
469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * The contents of this file are subject to the Mozilla Public License Version
669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 1.1 (the "License"); you may not use this file except in compliance with
769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the License.  Alternatively, the contents of this file may be used under
869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the terms of the GNU Lesser General Public License Version 2.1 or later.
969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
1069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Software distributed under the License is distributed on an "AS IS" basis,
1169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
1269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * for the specific language governing rights and limitations under the
1369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * License.
1469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */
1569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
1669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpackage javassist.bytecode;
1769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
1869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/**
1969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Utility for computing <code>max_stack</code>.
2069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */
2169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalclass CodeAnalyzer implements Opcode {
2269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private ConstPool constPool;
2369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private CodeAttribute codeAttr;
2469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
2569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public CodeAnalyzer(CodeAttribute ca) {
2669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        codeAttr = ca;
2769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        constPool = ca.getConstPool();
2869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
2969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
3069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public int computeMaxStack()
3169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws BadBytecode
3269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
3369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        /* d = stack[i]
3469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * d == 0: not visited
3569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * d > 0: the depth is d - 1 after executing the bytecode at i.
3669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         * d < 0: not visited. the initial depth (before execution) is 1 - d.
3769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal         */
3869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        CodeIterator ci = codeAttr.iterator();
3969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int length = ci.getCodeLength();
4069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int[] stack = new int[length];
4169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        constPool = codeAttr.getConstPool();
4269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        initStack(stack, codeAttr);
4369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        boolean repeat;
4469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        do {
4569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            repeat = false;
4669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            for (int i = 0; i < length; ++i)
4769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                if (stack[i] < 0) {
4869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    repeat = true;
4969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    visitBytecode(ci, stack, i);
5069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                }
5169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        } while (repeat);
5269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
5369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int maxStack = 1;
5469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        for (int i = 0; i < length; ++i)
5569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (stack[i] > maxStack)
5669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                maxStack = stack[i];
5769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
5869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return maxStack - 1;    // the base is 1.
5969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
6069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
6169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private void initStack(int[] stack, CodeAttribute ca) {
6269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        stack[0] = -1;
6369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ExceptionTable et = ca.getExceptionTable();
6469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (et != null) {
6569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int size = et.size();
6669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            for (int i = 0; i < size; ++i)
6769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                stack[et.handlerPc(i)] = -2;    // an exception is on stack
6869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
6969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
7069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
7169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private void visitBytecode(CodeIterator ci, int[] stack, int index)
7269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws BadBytecode
7369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
7469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int codeLength = stack.length;
7569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ci.move(index);
7669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int stackDepth = -stack[index];
7769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int[] jsrDepth = new int[1];
7869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        jsrDepth[0] = -1;
7969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        while (ci.hasNext()) {
8069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            index = ci.next();
8169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            stack[index] = stackDepth;
8269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int op = ci.byteAt(index);
8369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            stackDepth = visitInst(op, ci, index, stackDepth);
8469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (stackDepth < 1)
8569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                throw new BadBytecode("stack underflow at " + index);
8669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
8769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (processBranch(op, ci, index, codeLength, stack, stackDepth, jsrDepth))
8869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                break;
8969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
9069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (isEnd(op))     // return, ireturn, athrow, ...
9169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                break;
9269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
9369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (op == JSR || op == JSR_W)
9469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                --stackDepth;
9569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
9669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
9769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
9869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private boolean processBranch(int opcode, CodeIterator ci, int index,
9969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                  int codeLength, int[] stack, int stackDepth, int[] jsrDepth)
10069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws BadBytecode
10169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
10269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if ((IFEQ <= opcode && opcode <= IF_ACMPNE)
10369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                            || opcode == IFNULL || opcode == IFNONNULL) {
10469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int target = index + ci.s16bitAt(index + 1);
10569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            checkTarget(index, target, codeLength, stack, stackDepth);
10669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
10769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else {
10869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int target, index2;
10969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            switch (opcode) {
11069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            case GOTO :
11169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                target = index + ci.s16bitAt(index + 1);
11269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                checkTarget(index, target, codeLength, stack, stackDepth);
11369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                return true;
11469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            case GOTO_W :
11569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                target = index + ci.s32bitAt(index + 1);
11669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                checkTarget(index, target, codeLength, stack, stackDepth);
11769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                return true;
11869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            case JSR :
11969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            case JSR_W :
12069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                if (opcode == JSR)
12169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    target = index + ci.s16bitAt(index + 1);
12269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                else
12369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    target = index + ci.s32bitAt(index + 1);
12469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
12569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                checkTarget(index, target, codeLength, stack, stackDepth);
12669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                /*
12769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                 * It is unknown which RET comes back to this JSR.
12869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                 * So we assume that if the stack depth at one JSR instruction
12969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                 * is N, then it is also N at other JSRs and N - 1 at all RET
13069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                 * instructions.  Note that STACK_GROW[JSR] is 1 since it pushes
13169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                 * a return address on the operand stack.
13269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                 */
13369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                if (jsrDepth[0] < 0) {
13469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    jsrDepth[0] = stackDepth;
13569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    return false;
13669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                }
13769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                else if (stackDepth == jsrDepth[0])
13869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    return false;
13969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                else
14069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    throw new BadBytecode(
14169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                        "sorry, cannot compute this data flow due to JSR: "
14269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                            + stackDepth + "," + jsrDepth[0]);
14369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            case RET :
14469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                if (jsrDepth[0] < 0) {
14569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    jsrDepth[0] = stackDepth + 1;
14669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    return false;
14769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                }
14869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                else if (stackDepth + 1 == jsrDepth[0])
14969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    return true;
15069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                else
15169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    throw new BadBytecode(
15269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                        "sorry, cannot compute this data flow due to RET: "
15369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                            + stackDepth + "," + jsrDepth[0]);
15469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            case LOOKUPSWITCH :
15569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            case TABLESWITCH :
15669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                index2 = (index & ~3) + 4;
15769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                target = index + ci.s32bitAt(index2);
15869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                checkTarget(index, target, codeLength, stack, stackDepth);
15969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                if (opcode == LOOKUPSWITCH) {
16069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    int npairs = ci.s32bitAt(index2 + 4);
16169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    index2 += 12;
16269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    for (int i = 0; i < npairs; ++i) {
16369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                        target = index + ci.s32bitAt(index2);
16469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                        checkTarget(index, target, codeLength,
16569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                    stack, stackDepth);
16669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                        index2 += 8;
16769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    }
16869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                }
16969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                else {
17069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    int low = ci.s32bitAt(index2 + 4);
17169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    int high = ci.s32bitAt(index2 + 8);
17269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    int n = high - low + 1;
17369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    index2 += 12;
17469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    for (int i = 0; i < n; ++i) {
17569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                        target = index + ci.s32bitAt(index2);
17669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                        checkTarget(index, target, codeLength,
17769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                    stack, stackDepth);
17869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                        index2 += 4;
17969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    }
18069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                }
18169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
18269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                return true;    // always branch.
18369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
18469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
18569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
18669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return false;   // may not branch.
18769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
18869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
18969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private void checkTarget(int opIndex, int target, int codeLength,
19069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                             int[] stack, int stackDepth)
19169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws BadBytecode
19269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
19369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (target < 0 || codeLength <= target)
19469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throw new BadBytecode("bad branch offset at " + opIndex);
19569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
19669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int d = stack[target];
19769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (d == 0)
19869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            stack[target] = -stackDepth;
19969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else if (d != stackDepth && d != -stackDepth)
20069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throw new BadBytecode("verification error (" + stackDepth +
20169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                  "," + d + ") at " + opIndex);
20269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
20369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
20469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private static boolean isEnd(int opcode) {
20569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return (IRETURN <= opcode && opcode <= RETURN) || opcode == ATHROW;
20669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
20769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
20869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
20969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Visits an instruction.
21069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
21169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private int visitInst(int op, CodeIterator ci, int index, int stack)
21269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws BadBytecode
21369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
21469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        String desc;
21569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        switch (op) {
21669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case GETFIELD :
21769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            stack += getFieldSize(ci, index) - 1;
21869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            break;
21969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case PUTFIELD :
22069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            stack -= getFieldSize(ci, index) + 1;
22169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            break;
22269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case GETSTATIC :
22369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            stack += getFieldSize(ci, index);
22469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            break;
22569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case PUTSTATIC :
22669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            stack -= getFieldSize(ci, index);
22769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            break;
22869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case INVOKEVIRTUAL :
22969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case INVOKESPECIAL :
23069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            desc = constPool.getMethodrefType(ci.u16bitAt(index + 1));
23169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            stack += Descriptor.dataSize(desc) - 1;
23269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            break;
23369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case INVOKESTATIC :
23469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            desc = constPool.getMethodrefType(ci.u16bitAt(index + 1));
23569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            stack += Descriptor.dataSize(desc);
23669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            break;
23769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case INVOKEINTERFACE :
23869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            desc = constPool.getInterfaceMethodrefType(
23969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                            ci.u16bitAt(index + 1));
24069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            stack += Descriptor.dataSize(desc) - 1;
24169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            break;
24269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case ATHROW :
24369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            stack = 1;      // the stack becomes empty (1 means no values).
24469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            break;
24569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case MULTIANEWARRAY :
24669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            stack += 1 - ci.byteAt(index + 3);
24769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            break;
24869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        case WIDE :
24969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            op = ci.byteAt(index + 1);
25069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            // don't break here.
25169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        default :
25269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            stack += STACK_GROW[op];
25369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
25469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
25569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return stack;
25669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
25769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
25869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private int getFieldSize(CodeIterator ci, int index) {
25969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        String desc = constPool.getFieldrefType(ci.u16bitAt(index + 1));
26069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return Descriptor.dataSize(desc);
26169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
26269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal}
263