--- old/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Frame.java Thu Apr 25 10:10:59 2013 +++ new/src/share/classes/jdk/internal/org/objectweb/asm/tree/analysis/Frame.java Thu Apr 25 10:10:59 2013 @@ -73,10 +73,11 @@ /** * A symbolic execution stack frame. A stack frame contains a set of local * variable slots, and an operand stack. Warning: long and double values are - * represented by two slots in local variables, and by one slot - * in the operand stack. + * represented by two slots in local variables, and by one slot in + * the operand stack. * - * @param type of the Value used for the analysis. + * @param + * type of the Value used for the analysis. * * @author Eric Bruneton */ @@ -106,8 +107,10 @@ /** * Constructs a new frame with the given size. * - * @param nLocals the maximum number of local variables of the frame. - * @param nStack the maximum stack size of the frame. + * @param nLocals + * the maximum number of local variables of the frame. + * @param nStack + * the maximum stack size of the frame. */ public Frame(final int nLocals, final int nStack) { this.values = (V[]) new Value[nLocals + nStack]; @@ -117,7 +120,8 @@ /** * Constructs a new frame that is identical to the given frame. * - * @param src a frame. + * @param src + * a frame. */ public Frame(final Frame src) { this(src.locals, src.values.length - src.locals); @@ -127,7 +131,8 @@ /** * Copies the state of the given frame into this frame. * - * @param src a frame. + * @param src + * a frame. * @return this frame. */ public Frame init(final Frame src) { @@ -140,8 +145,9 @@ /** * Sets the expected return type of the analyzed method. * - * @param v the expected return type of the analyzed method, or - * null if the method returns void. + * @param v + * the expected return type of the analyzed method, or + * null if the method returns void. */ public void setReturn(final V v) { returnValue = v; @@ -159,13 +165,16 @@ /** * Returns the value of the given local variable. * - * @param i a local variable index. + * @param i + * a local variable index. * @return the value of the given local variable. - * @throws IndexOutOfBoundsException if the variable does not exist. + * @throws IndexOutOfBoundsException + * if the variable does not exist. */ public V getLocal(final int i) throws IndexOutOfBoundsException { if (i >= locals) { - throw new IndexOutOfBoundsException("Trying to access an inexistant local variable"); + throw new IndexOutOfBoundsException( + "Trying to access an inexistant local variable"); } return values[i]; } @@ -173,15 +182,18 @@ /** * Sets the value of the given local variable. * - * @param i a local variable index. - * @param value the new value of this local variable. - * @throws IndexOutOfBoundsException if the variable does not exist. + * @param i + * a local variable index. + * @param value + * the new value of this local variable. + * @throws IndexOutOfBoundsException + * if the variable does not exist. */ public void setLocal(final int i, final V value) - throws IndexOutOfBoundsException - { + throws IndexOutOfBoundsException { if (i >= locals) { - throw new IndexOutOfBoundsException("Trying to access an inexistant local variable "+i); + throw new IndexOutOfBoundsException( + "Trying to access an inexistant local variable " + i); } values[i] = value; } @@ -199,10 +211,11 @@ /** * Returns the value of the given operand stack slot. * - * @param i the index of an operand stack slot. + * @param i + * the index of an operand stack slot. * @return the value of the given operand stack slot. - * @throws IndexOutOfBoundsException if the operand stack slot does not - * exist. + * @throws IndexOutOfBoundsException + * if the operand stack slot does not exist. */ public V getStack(final int i) throws IndexOutOfBoundsException { return values[i + locals]; @@ -219,11 +232,13 @@ * Pops a value from the operand stack of this frame. * * @return the value that has been popped from the stack. - * @throws IndexOutOfBoundsException if the operand stack is empty. + * @throws IndexOutOfBoundsException + * if the operand stack is empty. */ public V pop() throws IndexOutOfBoundsException { if (top == 0) { - throw new IndexOutOfBoundsException("Cannot pop operand off an empty stack."); + throw new IndexOutOfBoundsException( + "Cannot pop operand off an empty stack."); } return values[--top + locals]; } @@ -231,459 +246,462 @@ /** * Pushes a value into the operand stack of this frame. * - * @param value the value that must be pushed into the stack. - * @throws IndexOutOfBoundsException if the operand stack is full. + * @param value + * the value that must be pushed into the stack. + * @throws IndexOutOfBoundsException + * if the operand stack is full. */ public void push(final V value) throws IndexOutOfBoundsException { if (top + locals >= values.length) { - throw new IndexOutOfBoundsException("Insufficient maximum stack size."); + throw new IndexOutOfBoundsException( + "Insufficient maximum stack size."); } values[top++ + locals] = value; } - public void execute( - final AbstractInsnNode insn, - final Interpreter interpreter) throws AnalyzerException - { + public void execute(final AbstractInsnNode insn, + final Interpreter interpreter) throws AnalyzerException { V value1, value2, value3, value4; List values; int var; switch (insn.getOpcode()) { - case Opcodes.NOP: - break; - case Opcodes.ACONST_NULL: - case Opcodes.ICONST_M1: - case Opcodes.ICONST_0: - case Opcodes.ICONST_1: - case Opcodes.ICONST_2: - case Opcodes.ICONST_3: - case Opcodes.ICONST_4: - case Opcodes.ICONST_5: - case Opcodes.LCONST_0: - case Opcodes.LCONST_1: - case Opcodes.FCONST_0: - case Opcodes.FCONST_1: - case Opcodes.FCONST_2: - case Opcodes.DCONST_0: - case Opcodes.DCONST_1: - case Opcodes.BIPUSH: - case Opcodes.SIPUSH: - case Opcodes.LDC: - push(interpreter.newOperation(insn)); - break; - case Opcodes.ILOAD: - case Opcodes.LLOAD: - case Opcodes.FLOAD: - case Opcodes.DLOAD: - case Opcodes.ALOAD: - push(interpreter.copyOperation(insn, - getLocal(((VarInsnNode) insn).var))); - break; - case Opcodes.IALOAD: - case Opcodes.LALOAD: - case Opcodes.FALOAD: - case Opcodes.DALOAD: - case Opcodes.AALOAD: - case Opcodes.BALOAD: - case Opcodes.CALOAD: - case Opcodes.SALOAD: - value2 = pop(); - value1 = pop(); - push(interpreter.binaryOperation(insn, value1, value2)); - break; - case Opcodes.ISTORE: - case Opcodes.LSTORE: - case Opcodes.FSTORE: - case Opcodes.DSTORE: - case Opcodes.ASTORE: - value1 = interpreter.copyOperation(insn, pop()); - var = ((VarInsnNode) insn).var; - setLocal(var, value1); - if (value1.getSize() == 2) { - setLocal(var + 1, interpreter.newValue(null)); + case Opcodes.NOP: + break; + case Opcodes.ACONST_NULL: + case Opcodes.ICONST_M1: + case Opcodes.ICONST_0: + case Opcodes.ICONST_1: + case Opcodes.ICONST_2: + case Opcodes.ICONST_3: + case Opcodes.ICONST_4: + case Opcodes.ICONST_5: + case Opcodes.LCONST_0: + case Opcodes.LCONST_1: + case Opcodes.FCONST_0: + case Opcodes.FCONST_1: + case Opcodes.FCONST_2: + case Opcodes.DCONST_0: + case Opcodes.DCONST_1: + case Opcodes.BIPUSH: + case Opcodes.SIPUSH: + case Opcodes.LDC: + push(interpreter.newOperation(insn)); + break; + case Opcodes.ILOAD: + case Opcodes.LLOAD: + case Opcodes.FLOAD: + case Opcodes.DLOAD: + case Opcodes.ALOAD: + push(interpreter.copyOperation(insn, + getLocal(((VarInsnNode) insn).var))); + break; + case Opcodes.IALOAD: + case Opcodes.LALOAD: + case Opcodes.FALOAD: + case Opcodes.DALOAD: + case Opcodes.AALOAD: + case Opcodes.BALOAD: + case Opcodes.CALOAD: + case Opcodes.SALOAD: + value2 = pop(); + value1 = pop(); + push(interpreter.binaryOperation(insn, value1, value2)); + break; + case Opcodes.ISTORE: + case Opcodes.LSTORE: + case Opcodes.FSTORE: + case Opcodes.DSTORE: + case Opcodes.ASTORE: + value1 = interpreter.copyOperation(insn, pop()); + var = ((VarInsnNode) insn).var; + setLocal(var, value1); + if (value1.getSize() == 2) { + setLocal(var + 1, interpreter.newValue(null)); + } + if (var > 0) { + Value local = getLocal(var - 1); + if (local != null && local.getSize() == 2) { + setLocal(var - 1, interpreter.newValue(null)); } - if (var > 0) { - Value local = getLocal(var - 1); - if (local != null && local.getSize() == 2) { - setLocal(var - 1, interpreter.newValue(null)); - } + } + break; + case Opcodes.IASTORE: + case Opcodes.LASTORE: + case Opcodes.FASTORE: + case Opcodes.DASTORE: + case Opcodes.AASTORE: + case Opcodes.BASTORE: + case Opcodes.CASTORE: + case Opcodes.SASTORE: + value3 = pop(); + value2 = pop(); + value1 = pop(); + interpreter.ternaryOperation(insn, value1, value2, value3); + break; + case Opcodes.POP: + if (pop().getSize() == 2) { + throw new AnalyzerException(insn, "Illegal use of POP"); + } + break; + case Opcodes.POP2: + if (pop().getSize() == 1) { + if (pop().getSize() != 1) { + throw new AnalyzerException(insn, "Illegal use of POP2"); } - break; - case Opcodes.IASTORE: - case Opcodes.LASTORE: - case Opcodes.FASTORE: - case Opcodes.DASTORE: - case Opcodes.AASTORE: - case Opcodes.BASTORE: - case Opcodes.CASTORE: - case Opcodes.SASTORE: - value3 = pop(); + } + break; + case Opcodes.DUP: + value1 = pop(); + if (value1.getSize() != 1) { + throw new AnalyzerException(insn, "Illegal use of DUP"); + } + push(value1); + push(interpreter.copyOperation(insn, value1)); + break; + case Opcodes.DUP_X1: + value1 = pop(); + value2 = pop(); + if (value1.getSize() != 1 || value2.getSize() != 1) { + throw new AnalyzerException(insn, "Illegal use of DUP_X1"); + } + push(interpreter.copyOperation(insn, value1)); + push(value2); + push(value1); + break; + case Opcodes.DUP_X2: + value1 = pop(); + if (value1.getSize() == 1) { value2 = pop(); - value1 = pop(); - interpreter.ternaryOperation(insn, value1, value2, value3); - break; - case Opcodes.POP: - if (pop().getSize() == 2) { - throw new AnalyzerException(insn, "Illegal use of POP"); - } - break; - case Opcodes.POP2: - if (pop().getSize() == 1) { - if (pop().getSize() != 1) { - throw new AnalyzerException(insn, "Illegal use of POP2"); + if (value2.getSize() == 1) { + value3 = pop(); + if (value3.getSize() == 1) { + push(interpreter.copyOperation(insn, value1)); + push(value3); + push(value2); + push(value1); + break; } + } else { + push(interpreter.copyOperation(insn, value1)); + push(value2); + push(value1); + break; } - break; - case Opcodes.DUP: - value1 = pop(); - if (value1.getSize() != 1) { - throw new AnalyzerException(insn, "Illegal use of DUP"); + } + throw new AnalyzerException(insn, "Illegal use of DUP_X2"); + case Opcodes.DUP2: + value1 = pop(); + if (value1.getSize() == 1) { + value2 = pop(); + if (value2.getSize() == 1) { + push(value2); + push(value1); + push(interpreter.copyOperation(insn, value2)); + push(interpreter.copyOperation(insn, value1)); + break; } + } else { push(value1); push(interpreter.copyOperation(insn, value1)); break; - case Opcodes.DUP_X1: - value1 = pop(); + } + throw new AnalyzerException(insn, "Illegal use of DUP2"); + case Opcodes.DUP2_X1: + value1 = pop(); + if (value1.getSize() == 1) { value2 = pop(); - if (value1.getSize() != 1 || value2.getSize() != 1) { - throw new AnalyzerException(insn, "Illegal use of DUP_X1"); - } - push(interpreter.copyOperation(insn, value1)); - push(value2); - push(value1); - break; - case Opcodes.DUP_X2: - value1 = pop(); - if (value1.getSize() == 1) { - value2 = pop(); - if (value2.getSize() == 1) { - value3 = pop(); - if (value3.getSize() == 1) { - push(interpreter.copyOperation(insn, value1)); - push(value3); - push(value2); - push(value1); - break; - } - } else { + if (value2.getSize() == 1) { + value3 = pop(); + if (value3.getSize() == 1) { + push(interpreter.copyOperation(insn, value2)); push(interpreter.copyOperation(insn, value1)); + push(value3); push(value2); push(value1); break; } } - throw new AnalyzerException(insn, "Illegal use of DUP_X2"); - case Opcodes.DUP2: - value1 = pop(); - if (value1.getSize() == 1) { - value2 = pop(); - if (value2.getSize() == 1) { - push(value2); - push(value1); - push(interpreter.copyOperation(insn, value2)); - push(interpreter.copyOperation(insn, value1)); - break; - } - } else { - push(value1); + } else { + value2 = pop(); + if (value2.getSize() == 1) { push(interpreter.copyOperation(insn, value1)); + push(value2); + push(value1); break; } - throw new AnalyzerException(insn, "Illegal use of DUP2"); - case Opcodes.DUP2_X1: - value1 = pop(); - if (value1.getSize() == 1) { - value2 = pop(); - if (value2.getSize() == 1) { - value3 = pop(); - if (value3.getSize() == 1) { + } + throw new AnalyzerException(insn, "Illegal use of DUP2_X1"); + case Opcodes.DUP2_X2: + value1 = pop(); + if (value1.getSize() == 1) { + value2 = pop(); + if (value2.getSize() == 1) { + value3 = pop(); + if (value3.getSize() == 1) { + value4 = pop(); + if (value4.getSize() == 1) { push(interpreter.copyOperation(insn, value2)); push(interpreter.copyOperation(insn, value1)); + push(value4); push(value3); push(value2); push(value1); break; } - } - } else { - value2 = pop(); - if (value2.getSize() == 1) { + } else { + push(interpreter.copyOperation(insn, value2)); push(interpreter.copyOperation(insn, value1)); + push(value3); push(value2); push(value1); break; } } - throw new AnalyzerException(insn, "Illegal use of DUP2_X1"); - case Opcodes.DUP2_X2: - value1 = pop(); - if (value1.getSize() == 1) { - value2 = pop(); - if (value2.getSize() == 1) { - value3 = pop(); - if (value3.getSize() == 1) { - value4 = pop(); - if (value4.getSize() == 1) { - push(interpreter.copyOperation(insn, value2)); - push(interpreter.copyOperation(insn, value1)); - push(value4); - push(value3); - push(value2); - push(value1); - break; - } - } else { - push(interpreter.copyOperation(insn, value2)); - push(interpreter.copyOperation(insn, value1)); - push(value3); - push(value2); - push(value1); - break; - } - } - } else { - value2 = pop(); - if (value2.getSize() == 1) { - value3 = pop(); - if (value3.getSize() == 1) { - push(interpreter.copyOperation(insn, value1)); - push(value3); - push(value2); - push(value1); - break; - } - } else { + } else { + value2 = pop(); + if (value2.getSize() == 1) { + value3 = pop(); + if (value3.getSize() == 1) { push(interpreter.copyOperation(insn, value1)); + push(value3); push(value2); push(value1); break; } - } - throw new AnalyzerException(insn, "Illegal use of DUP2_X2"); - case Opcodes.SWAP: - value2 = pop(); - value1 = pop(); - if (value1.getSize() != 1 || value2.getSize() != 1) { - throw new AnalyzerException(insn, "Illegal use of SWAP"); - } - push(interpreter.copyOperation(insn, value2)); - push(interpreter.copyOperation(insn, value1)); - break; - case Opcodes.IADD: - case Opcodes.LADD: - case Opcodes.FADD: - case Opcodes.DADD: - case Opcodes.ISUB: - case Opcodes.LSUB: - case Opcodes.FSUB: - case Opcodes.DSUB: - case Opcodes.IMUL: - case Opcodes.LMUL: - case Opcodes.FMUL: - case Opcodes.DMUL: - case Opcodes.IDIV: - case Opcodes.LDIV: - case Opcodes.FDIV: - case Opcodes.DDIV: - case Opcodes.IREM: - case Opcodes.LREM: - case Opcodes.FREM: - case Opcodes.DREM: - value2 = pop(); - value1 = pop(); - push(interpreter.binaryOperation(insn, value1, value2)); - break; - case Opcodes.INEG: - case Opcodes.LNEG: - case Opcodes.FNEG: - case Opcodes.DNEG: - push(interpreter.unaryOperation(insn, pop())); - break; - case Opcodes.ISHL: - case Opcodes.LSHL: - case Opcodes.ISHR: - case Opcodes.LSHR: - case Opcodes.IUSHR: - case Opcodes.LUSHR: - case Opcodes.IAND: - case Opcodes.LAND: - case Opcodes.IOR: - case Opcodes.LOR: - case Opcodes.IXOR: - case Opcodes.LXOR: - value2 = pop(); - value1 = pop(); - push(interpreter.binaryOperation(insn, value1, value2)); - break; - case Opcodes.IINC: - var = ((IincInsnNode) insn).var; - setLocal(var, interpreter.unaryOperation(insn, getLocal(var))); - break; - case Opcodes.I2L: - case Opcodes.I2F: - case Opcodes.I2D: - case Opcodes.L2I: - case Opcodes.L2F: - case Opcodes.L2D: - case Opcodes.F2I: - case Opcodes.F2L: - case Opcodes.F2D: - case Opcodes.D2I: - case Opcodes.D2L: - case Opcodes.D2F: - case Opcodes.I2B: - case Opcodes.I2C: - case Opcodes.I2S: - push(interpreter.unaryOperation(insn, pop())); - break; - case Opcodes.LCMP: - case Opcodes.FCMPL: - case Opcodes.FCMPG: - case Opcodes.DCMPL: - case Opcodes.DCMPG: - value2 = pop(); - value1 = pop(); - push(interpreter.binaryOperation(insn, value1, value2)); - break; - case Opcodes.IFEQ: - case Opcodes.IFNE: - case Opcodes.IFLT: - case Opcodes.IFGE: - case Opcodes.IFGT: - case Opcodes.IFLE: - interpreter.unaryOperation(insn, pop()); - break; - case Opcodes.IF_ICMPEQ: - case Opcodes.IF_ICMPNE: - case Opcodes.IF_ICMPLT: - case Opcodes.IF_ICMPGE: - case Opcodes.IF_ICMPGT: - case Opcodes.IF_ICMPLE: - case Opcodes.IF_ACMPEQ: - case Opcodes.IF_ACMPNE: - value2 = pop(); - value1 = pop(); - interpreter.binaryOperation(insn, value1, value2); - break; - case Opcodes.GOTO: - break; - case Opcodes.JSR: - push(interpreter.newOperation(insn)); - break; - case Opcodes.RET: - break; - case Opcodes.TABLESWITCH: - case Opcodes.LOOKUPSWITCH: - interpreter.unaryOperation(insn, pop()); - break; - case Opcodes.IRETURN: - case Opcodes.LRETURN: - case Opcodes.FRETURN: - case Opcodes.DRETURN: - case Opcodes.ARETURN: - value1 = pop(); - interpreter.unaryOperation(insn, value1); - interpreter.returnOperation(insn, value1, returnValue); - break; - case Opcodes.RETURN: - if (returnValue != null) { - throw new AnalyzerException(insn, "Incompatible return type"); - } - break; - case Opcodes.GETSTATIC: - push(interpreter.newOperation(insn)); - break; - case Opcodes.PUTSTATIC: - interpreter.unaryOperation(insn, pop()); - break; - case Opcodes.GETFIELD: - push(interpreter.unaryOperation(insn, pop())); - break; - case Opcodes.PUTFIELD: - value2 = pop(); - value1 = pop(); - interpreter.binaryOperation(insn, value1, value2); - break; - case Opcodes.INVOKEVIRTUAL: - case Opcodes.INVOKESPECIAL: - case Opcodes.INVOKESTATIC: - case Opcodes.INVOKEINTERFACE: { - values = new ArrayList(); - String desc = ((MethodInsnNode) insn).desc; - for (int i = Type.getArgumentTypes(desc).length; i > 0; --i) { - values.add(0, pop()); - } - if (insn.getOpcode() != Opcodes.INVOKESTATIC) { - values.add(0, pop()); - } - if (Type.getReturnType(desc) == Type.VOID_TYPE) { - interpreter.naryOperation(insn, values); } else { - push(interpreter.naryOperation(insn, values)); + push(interpreter.copyOperation(insn, value1)); + push(value2); + push(value1); + break; } - break; } - case Opcodes.INVOKEDYNAMIC: { - values = new ArrayList(); - String desc = ((InvokeDynamicInsnNode) insn).desc; - for (int i = Type.getArgumentTypes(desc).length; i > 0; --i) { - values.add(0, pop()); - } - if (Type.getReturnType(desc) == Type.VOID_TYPE) { - interpreter.naryOperation(insn, values); - } else { - push(interpreter.naryOperation(insn, values)); - } - break; + throw new AnalyzerException(insn, "Illegal use of DUP2_X2"); + case Opcodes.SWAP: + value2 = pop(); + value1 = pop(); + if (value1.getSize() != 1 || value2.getSize() != 1) { + throw new AnalyzerException(insn, "Illegal use of SWAP"); } - case Opcodes.NEW: - push(interpreter.newOperation(insn)); - break; - case Opcodes.NEWARRAY: - case Opcodes.ANEWARRAY: - case Opcodes.ARRAYLENGTH: - push(interpreter.unaryOperation(insn, pop())); - break; - case Opcodes.ATHROW: - interpreter.unaryOperation(insn, pop()); - break; - case Opcodes.CHECKCAST: - case Opcodes.INSTANCEOF: - push(interpreter.unaryOperation(insn, pop())); - break; - case Opcodes.MONITORENTER: - case Opcodes.MONITOREXIT: - interpreter.unaryOperation(insn, pop()); - break; - case Opcodes.MULTIANEWARRAY: - values = new ArrayList(); - for (int i = ((MultiANewArrayInsnNode) insn).dims; i > 0; --i) { - values.add(0, pop()); - } + push(interpreter.copyOperation(insn, value2)); + push(interpreter.copyOperation(insn, value1)); + break; + case Opcodes.IADD: + case Opcodes.LADD: + case Opcodes.FADD: + case Opcodes.DADD: + case Opcodes.ISUB: + case Opcodes.LSUB: + case Opcodes.FSUB: + case Opcodes.DSUB: + case Opcodes.IMUL: + case Opcodes.LMUL: + case Opcodes.FMUL: + case Opcodes.DMUL: + case Opcodes.IDIV: + case Opcodes.LDIV: + case Opcodes.FDIV: + case Opcodes.DDIV: + case Opcodes.IREM: + case Opcodes.LREM: + case Opcodes.FREM: + case Opcodes.DREM: + value2 = pop(); + value1 = pop(); + push(interpreter.binaryOperation(insn, value1, value2)); + break; + case Opcodes.INEG: + case Opcodes.LNEG: + case Opcodes.FNEG: + case Opcodes.DNEG: + push(interpreter.unaryOperation(insn, pop())); + break; + case Opcodes.ISHL: + case Opcodes.LSHL: + case Opcodes.ISHR: + case Opcodes.LSHR: + case Opcodes.IUSHR: + case Opcodes.LUSHR: + case Opcodes.IAND: + case Opcodes.LAND: + case Opcodes.IOR: + case Opcodes.LOR: + case Opcodes.IXOR: + case Opcodes.LXOR: + value2 = pop(); + value1 = pop(); + push(interpreter.binaryOperation(insn, value1, value2)); + break; + case Opcodes.IINC: + var = ((IincInsnNode) insn).var; + setLocal(var, interpreter.unaryOperation(insn, getLocal(var))); + break; + case Opcodes.I2L: + case Opcodes.I2F: + case Opcodes.I2D: + case Opcodes.L2I: + case Opcodes.L2F: + case Opcodes.L2D: + case Opcodes.F2I: + case Opcodes.F2L: + case Opcodes.F2D: + case Opcodes.D2I: + case Opcodes.D2L: + case Opcodes.D2F: + case Opcodes.I2B: + case Opcodes.I2C: + case Opcodes.I2S: + push(interpreter.unaryOperation(insn, pop())); + break; + case Opcodes.LCMP: + case Opcodes.FCMPL: + case Opcodes.FCMPG: + case Opcodes.DCMPL: + case Opcodes.DCMPG: + value2 = pop(); + value1 = pop(); + push(interpreter.binaryOperation(insn, value1, value2)); + break; + case Opcodes.IFEQ: + case Opcodes.IFNE: + case Opcodes.IFLT: + case Opcodes.IFGE: + case Opcodes.IFGT: + case Opcodes.IFLE: + interpreter.unaryOperation(insn, pop()); + break; + case Opcodes.IF_ICMPEQ: + case Opcodes.IF_ICMPNE: + case Opcodes.IF_ICMPLT: + case Opcodes.IF_ICMPGE: + case Opcodes.IF_ICMPGT: + case Opcodes.IF_ICMPLE: + case Opcodes.IF_ACMPEQ: + case Opcodes.IF_ACMPNE: + value2 = pop(); + value1 = pop(); + interpreter.binaryOperation(insn, value1, value2); + break; + case Opcodes.GOTO: + break; + case Opcodes.JSR: + push(interpreter.newOperation(insn)); + break; + case Opcodes.RET: + break; + case Opcodes.TABLESWITCH: + case Opcodes.LOOKUPSWITCH: + interpreter.unaryOperation(insn, pop()); + break; + case Opcodes.IRETURN: + case Opcodes.LRETURN: + case Opcodes.FRETURN: + case Opcodes.DRETURN: + case Opcodes.ARETURN: + value1 = pop(); + interpreter.unaryOperation(insn, value1); + interpreter.returnOperation(insn, value1, returnValue); + break; + case Opcodes.RETURN: + if (returnValue != null) { + throw new AnalyzerException(insn, "Incompatible return type"); + } + break; + case Opcodes.GETSTATIC: + push(interpreter.newOperation(insn)); + break; + case Opcodes.PUTSTATIC: + interpreter.unaryOperation(insn, pop()); + break; + case Opcodes.GETFIELD: + push(interpreter.unaryOperation(insn, pop())); + break; + case Opcodes.PUTFIELD: + value2 = pop(); + value1 = pop(); + interpreter.binaryOperation(insn, value1, value2); + break; + case Opcodes.INVOKEVIRTUAL: + case Opcodes.INVOKESPECIAL: + case Opcodes.INVOKESTATIC: + case Opcodes.INVOKEINTERFACE: { + values = new ArrayList(); + String desc = ((MethodInsnNode) insn).desc; + for (int i = Type.getArgumentTypes(desc).length; i > 0; --i) { + values.add(0, pop()); + } + if (insn.getOpcode() != Opcodes.INVOKESTATIC) { + values.add(0, pop()); + } + if (Type.getReturnType(desc) == Type.VOID_TYPE) { + interpreter.naryOperation(insn, values); + } else { push(interpreter.naryOperation(insn, values)); - break; - case Opcodes.IFNULL: - case Opcodes.IFNONNULL: - interpreter.unaryOperation(insn, pop()); - break; - default: - throw new RuntimeException("Illegal opcode "+insn.getOpcode()); + } + break; } + case Opcodes.INVOKEDYNAMIC: { + values = new ArrayList(); + String desc = ((InvokeDynamicInsnNode) insn).desc; + for (int i = Type.getArgumentTypes(desc).length; i > 0; --i) { + values.add(0, pop()); + } + if (Type.getReturnType(desc) == Type.VOID_TYPE) { + interpreter.naryOperation(insn, values); + } else { + push(interpreter.naryOperation(insn, values)); + } + break; + } + case Opcodes.NEW: + push(interpreter.newOperation(insn)); + break; + case Opcodes.NEWARRAY: + case Opcodes.ANEWARRAY: + case Opcodes.ARRAYLENGTH: + push(interpreter.unaryOperation(insn, pop())); + break; + case Opcodes.ATHROW: + interpreter.unaryOperation(insn, pop()); + break; + case Opcodes.CHECKCAST: + case Opcodes.INSTANCEOF: + push(interpreter.unaryOperation(insn, pop())); + break; + case Opcodes.MONITORENTER: + case Opcodes.MONITOREXIT: + interpreter.unaryOperation(insn, pop()); + break; + case Opcodes.MULTIANEWARRAY: + values = new ArrayList(); + for (int i = ((MultiANewArrayInsnNode) insn).dims; i > 0; --i) { + values.add(0, pop()); + } + push(interpreter.naryOperation(insn, values)); + break; + case Opcodes.IFNULL: + case Opcodes.IFNONNULL: + interpreter.unaryOperation(insn, pop()); + break; + default: + throw new RuntimeException("Illegal opcode " + insn.getOpcode()); + } } /** * Merges this frame with the given frame. * - * @param frame a frame. - * @param interpreter the interpreter used to merge values. + * @param frame + * a frame. + * @param interpreter + * the interpreter used to merge values. * @return true if this frame has been changed as a result of the * merge operation, or false otherwise. - * @throws AnalyzerException if the frames have incompatible sizes. + * @throws AnalyzerException + * if the frames have incompatible sizes. */ - public boolean merge(final Frame frame, final Interpreter interpreter) - throws AnalyzerException - { + public boolean merge(final Frame frame, + final Interpreter interpreter) throws AnalyzerException { if (top != frame.top) { throw new AnalyzerException(null, "Incompatible stack heights"); } @@ -690,9 +708,9 @@ boolean changes = false; for (int i = 0; i < locals + top; ++i) { V v = interpreter.merge(values[i], frame.values[i]); - if (v != values[i]) { + if (!v.equals(values[i])) { values[i] = v; - changes |= true; + changes = true; } } return changes; @@ -701,9 +719,11 @@ /** * Merges this frame with the given frame (case of a RET instruction). * - * @param frame a frame - * @param access the local variables that have been accessed by the - * subroutine to which the RET instruction corresponds. + * @param frame + * a frame + * @param access + * the local variables that have been accessed by the subroutine + * to which the RET instruction corresponds. * @return true if this frame has been changed as a result of the * merge operation, or false otherwise. */