summaryrefslogtreecommitdiff
path: root/src/proguard/evaluation/Processor.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/proguard/evaluation/Processor.java')
-rw-r--r--src/proguard/evaluation/Processor.java927
1 files changed, 0 insertions, 927 deletions
diff --git a/src/proguard/evaluation/Processor.java b/src/proguard/evaluation/Processor.java
deleted file mode 100644
index d03b853..0000000
--- a/src/proguard/evaluation/Processor.java
+++ /dev/null
@@ -1,927 +0,0 @@
-/*
- * ProGuard -- shrinking, optimization, obfuscation, and preverification
- * of Java bytecode.
- *
- * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu)
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-package proguard.evaluation;
-
-import proguard.classfile.*;
-import proguard.classfile.attribute.CodeAttribute;
-import proguard.classfile.instruction.*;
-import proguard.classfile.instruction.visitor.InstructionVisitor;
-import proguard.evaluation.value.*;
-
-/**
- * This InstructionVisitor executes the instructions that it visits on a given
- * local variable frame and stack.
- *
- * @author Eric Lafortune
- */
-public class Processor
-implements InstructionVisitor
-{
- private final Variables variables;
- private final Stack stack;
- private final ValueFactory valueFactory;
- private final BranchUnit branchUnit;
- private final InvocationUnit invocationUnit;
- private final boolean alwaysCast;
-
- private final ConstantValueFactory constantValueFactory;
- private final ClassConstantValueFactory classConstantValueFactory;
-
-
- /**
- * Creates a new processor that operates on the given environment.
- * @param variables the local variable frame.
- * @param stack the local stack.
- * @param branchUnit the class that can affect the program counter.
- * @param invocationUnit the class that can access other program members.
- * @param alwaysCast a flag that specifies whether downcasts or casts
- * of null values should always be performed.
- */
- public Processor(Variables variables,
- Stack stack,
- ValueFactory valueFactory,
- BranchUnit branchUnit,
- InvocationUnit invocationUnit,
- boolean alwaysCast)
- {
- this.variables = variables;
- this.stack = stack;
- this.valueFactory = valueFactory;
- this.branchUnit = branchUnit;
- this.invocationUnit = invocationUnit;
- this.alwaysCast = alwaysCast;
-
- constantValueFactory = new ConstantValueFactory(valueFactory);
- classConstantValueFactory = new ClassConstantValueFactory(valueFactory);
- }
-
-
- // Implementations for InstructionVisitor.
-
- public void visitSimpleInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SimpleInstruction simpleInstruction)
- {
- switch (simpleInstruction.opcode)
- {
- case InstructionConstants.OP_NOP:
- break;
-
- case InstructionConstants.OP_ACONST_NULL:
- stack.push(valueFactory.createReferenceValueNull());
- break;
-
- case InstructionConstants.OP_ICONST_M1:
- case InstructionConstants.OP_ICONST_0:
- case InstructionConstants.OP_ICONST_1:
- case InstructionConstants.OP_ICONST_2:
- case InstructionConstants.OP_ICONST_3:
- case InstructionConstants.OP_ICONST_4:
- case InstructionConstants.OP_ICONST_5:
- case InstructionConstants.OP_BIPUSH:
- case InstructionConstants.OP_SIPUSH:
- stack.push(valueFactory.createIntegerValue(simpleInstruction.constant));
- break;
-
- case InstructionConstants.OP_LCONST_0:
- case InstructionConstants.OP_LCONST_1:
- stack.push(valueFactory.createLongValue(simpleInstruction.constant));
- break;
-
- case InstructionConstants.OP_FCONST_0:
- case InstructionConstants.OP_FCONST_1:
- case InstructionConstants.OP_FCONST_2:
- stack.push(valueFactory.createFloatValue((float)simpleInstruction.constant));
- break;
-
- case InstructionConstants.OP_DCONST_0:
- case InstructionConstants.OP_DCONST_1:
- stack.push(valueFactory.createDoubleValue((double)simpleInstruction.constant));
- break;
-
- case InstructionConstants.OP_IALOAD:
- case InstructionConstants.OP_BALOAD:
- case InstructionConstants.OP_CALOAD:
- case InstructionConstants.OP_SALOAD:
- {
- IntegerValue arrayIndex = stack.ipop();
- ReferenceValue arrayReference = stack.apop();
- stack.push(arrayReference.integerArrayLoad(arrayIndex, valueFactory));
- break;
- }
- case InstructionConstants.OP_LALOAD:
- {
- IntegerValue arrayIndex = stack.ipop();
- ReferenceValue arrayReference = stack.apop();
- stack.push(arrayReference.longArrayLoad(arrayIndex, valueFactory));
- break;
- }
- case InstructionConstants.OP_FALOAD:
- {
- IntegerValue arrayIndex = stack.ipop();
- ReferenceValue arrayReference = stack.apop();
- stack.push(arrayReference.floatArrayLoad(arrayIndex, valueFactory));
- break;
- }
- case InstructionConstants.OP_DALOAD:
- {
- IntegerValue arrayIndex = stack.ipop();
- ReferenceValue arrayReference = stack.apop();
- stack.push(arrayReference.doubleArrayLoad(arrayIndex, valueFactory));
- break;
- }
- case InstructionConstants.OP_AALOAD:
- {
- IntegerValue arrayIndex = stack.ipop();
- ReferenceValue arrayReference = stack.apop();
- stack.push(arrayReference.referenceArrayLoad(arrayIndex, valueFactory));
- break;
- }
- case InstructionConstants.OP_IASTORE:
- case InstructionConstants.OP_BASTORE:
- case InstructionConstants.OP_CASTORE:
- case InstructionConstants.OP_SASTORE:
- {
- Value value = stack.ipop();
- IntegerValue arrayIndex = stack.ipop();
- ReferenceValue arrayReference = stack.apop();
- arrayReference.arrayStore(arrayIndex, value);
- break;
- }
- case InstructionConstants.OP_LASTORE:
- {
- Value value = stack.lpop();
- IntegerValue arrayIndex = stack.ipop();
- ReferenceValue arrayReference = stack.apop();
- arrayReference.arrayStore(arrayIndex, value);
- break;
- }
- case InstructionConstants.OP_FASTORE:
- {
- Value value = stack.fpop();
- IntegerValue arrayIndex = stack.ipop();
- ReferenceValue arrayReference = stack.apop();
- arrayReference.arrayStore(arrayIndex, value);
- break;
- }
- case InstructionConstants.OP_DASTORE:
- {
- Value value = stack.dpop();
- IntegerValue arrayIndex = stack.ipop();
- ReferenceValue arrayReference = stack.apop();
- arrayReference.arrayStore(arrayIndex, value);
- break;
- }
- case InstructionConstants.OP_AASTORE:
- {
- Value value = stack.apop();
- IntegerValue arrayIndex = stack.ipop();
- ReferenceValue arrayReference = stack.apop();
- arrayReference.arrayStore(arrayIndex, value);
- break;
- }
- case InstructionConstants.OP_POP:
- stack.pop1();
- break;
-
- case InstructionConstants.OP_POP2:
- stack.pop2();
- break;
-
- case InstructionConstants.OP_DUP:
- stack.dup();
- break;
-
- case InstructionConstants.OP_DUP_X1:
- stack.dup_x1();
- break;
-
- case InstructionConstants.OP_DUP_X2:
- stack.dup_x2();
- break;
-
- case InstructionConstants.OP_DUP2:
- stack.dup2();
- break;
-
- case InstructionConstants.OP_DUP2_X1:
- stack.dup2_x1();
- break;
-
- case InstructionConstants.OP_DUP2_X2:
- stack.dup2_x2();
- break;
-
- case InstructionConstants.OP_SWAP:
- stack.swap();
- break;
-
- case InstructionConstants.OP_IADD:
- stack.push(stack.ipop().add(stack.ipop()));
- break;
-
- case InstructionConstants.OP_LADD:
- stack.push(stack.lpop().add(stack.lpop()));
- break;
-
- case InstructionConstants.OP_FADD:
- stack.push(stack.fpop().add(stack.fpop()));
- break;
-
- case InstructionConstants.OP_DADD:
- stack.push(stack.dpop().add(stack.dpop()));
- break;
-
- case InstructionConstants.OP_ISUB:
- stack.push(stack.ipop().subtractFrom(stack.ipop()));
- break;
-
- case InstructionConstants.OP_LSUB:
- stack.push(stack.lpop().subtractFrom(stack.lpop()));
- break;
-
- case InstructionConstants.OP_FSUB:
- stack.push(stack.fpop().subtractFrom(stack.fpop()));
- break;
-
- case InstructionConstants.OP_DSUB:
- stack.push(stack.dpop().subtractFrom(stack.dpop()));
- break;
-
- case InstructionConstants.OP_IMUL:
- stack.push(stack.ipop().multiply(stack.ipop()));
- break;
-
- case InstructionConstants.OP_LMUL:
- stack.push(stack.lpop().multiply(stack.lpop()));
- break;
-
- case InstructionConstants.OP_FMUL:
- stack.push(stack.fpop().multiply(stack.fpop()));
- break;
-
- case InstructionConstants.OP_DMUL:
- stack.push(stack.dpop().multiply(stack.dpop()));
- break;
-
- case InstructionConstants.OP_IDIV:
- try
- {
- stack.push(stack.ipop().divideOf(stack.ipop()));
- }
- catch (ArithmeticException ex)
- {
- stack.push(valueFactory.createIntegerValue());
- // TODO: Forward ArithmeticExceptions.
- //stack.clear();
- //stack.push(valueFactory.createReference(false));
- //branchUnit.throwException();
- }
- break;
-
- case InstructionConstants.OP_LDIV:
- try
- {
- stack.push(stack.lpop().divideOf(stack.lpop()));
- }
- catch (ArithmeticException ex)
- {
- stack.push(valueFactory.createLongValue());
- // TODO: Forward ArithmeticExceptions.
- //stack.clear();
- //stack.push(valueFactory.createReference(false));
- //branchUnit.throwException();
- }
- break;
-
- case InstructionConstants.OP_FDIV:
- stack.push(stack.fpop().divideOf(stack.fpop()));
- break;
-
- case InstructionConstants.OP_DDIV:
- stack.push(stack.dpop().divideOf(stack.dpop()));
- break;
-
- case InstructionConstants.OP_IREM:
- try
- {
- stack.push(stack.ipop().remainderOf(stack.ipop()));
- }
- catch (ArithmeticException ex)
- {
- stack.push(valueFactory.createIntegerValue());
- // TODO: Forward ArithmeticExceptions.
- //stack.clear();
- //stack.push(valueFactory.createReference(false));
- //branchUnit.throwException();
- }
- break;
-
- case InstructionConstants.OP_LREM:
- try
- {
- stack.push(stack.lpop().remainderOf(stack.lpop()));
- }
- catch (ArithmeticException ex)
- {
- stack.push(valueFactory.createLongValue());
- // TODO: Forward ArithmeticExceptions.
- //stack.clear();
- //stack.push(valueFactory.createReference(false));
- //branchUnit.throwException();
- }
- break;
-
- case InstructionConstants.OP_FREM:
- stack.push(stack.fpop().remainderOf(stack.fpop()));
- break;
-
- case InstructionConstants.OP_DREM:
- stack.push(stack.dpop().remainderOf(stack.dpop()));
- break;
-
- case InstructionConstants.OP_INEG:
- stack.push(stack.ipop().negate());
- break;
-
- case InstructionConstants.OP_LNEG:
- stack.push(stack.lpop().negate());
- break;
-
- case InstructionConstants.OP_FNEG:
- stack.push(stack.fpop().negate());
- break;
-
- case InstructionConstants.OP_DNEG:
- stack.push(stack.dpop().negate());
- break;
-
- case InstructionConstants.OP_ISHL:
- stack.push(stack.ipop().shiftLeftOf(stack.ipop()));
- break;
-
- case InstructionConstants.OP_LSHL:
- stack.push(stack.ipop().shiftLeftOf(stack.lpop()));
- break;
-
- case InstructionConstants.OP_ISHR:
- stack.push(stack.ipop().shiftRightOf(stack.ipop()));
- break;
-
- case InstructionConstants.OP_LSHR:
- stack.push(stack.ipop().shiftRightOf(stack.lpop()));
- break;
-
- case InstructionConstants.OP_IUSHR:
- stack.push(stack.ipop().unsignedShiftRightOf(stack.ipop()));
- break;
-
- case InstructionConstants.OP_LUSHR:
- stack.push(stack.ipop().unsignedShiftRightOf(stack.lpop()));
- break;
-
- case InstructionConstants.OP_IAND:
- stack.push(stack.ipop().and(stack.ipop()));
- break;
-
- case InstructionConstants.OP_LAND:
- stack.push(stack.lpop().and(stack.lpop()));
- break;
-
- case InstructionConstants.OP_IOR:
- stack.push(stack.ipop().or(stack.ipop()));
- break;
-
- case InstructionConstants.OP_LOR:
- stack.push(stack.lpop().or(stack.lpop()));
- break;
-
- case InstructionConstants.OP_IXOR:
- stack.push(stack.ipop().xor(stack.ipop()));
- break;
-
- case InstructionConstants.OP_LXOR:
- stack.push(stack.lpop().xor(stack.lpop()));
- break;
-
- case InstructionConstants.OP_I2L:
- stack.push(stack.ipop().convertToLong());
- break;
-
- case InstructionConstants.OP_I2F:
- stack.push(stack.ipop().convertToFloat());
- break;
-
- case InstructionConstants.OP_I2D:
- stack.push(stack.ipop().convertToDouble());
- break;
-
- case InstructionConstants.OP_L2I:
- stack.push(stack.lpop().convertToInteger());
- break;
-
- case InstructionConstants.OP_L2F:
- stack.push(stack.lpop().convertToFloat());
- break;
-
- case InstructionConstants.OP_L2D:
- stack.push(stack.lpop().convertToDouble());
- break;
-
- case InstructionConstants.OP_F2I:
- stack.push(stack.fpop().convertToInteger());
- break;
-
- case InstructionConstants.OP_F2L:
- stack.push(stack.fpop().convertToLong());
- break;
-
- case InstructionConstants.OP_F2D:
- stack.push(stack.fpop().convertToDouble());
- break;
-
- case InstructionConstants.OP_D2I:
- stack.push(stack.dpop().convertToInteger());
- break;
-
- case InstructionConstants.OP_D2L:
- stack.push(stack.dpop().convertToLong());
- break;
-
- case InstructionConstants.OP_D2F:
- stack.push(stack.dpop().convertToFloat());
- break;
-
- case InstructionConstants.OP_I2B:
- stack.push(stack.ipop().convertToByte());
- break;
-
- case InstructionConstants.OP_I2C:
- stack.push(stack.ipop().convertToCharacter());
- break;
-
- case InstructionConstants.OP_I2S:
- stack.push(stack.ipop().convertToShort());
- break;
-
- case InstructionConstants.OP_LCMP:
-// stack.push(stack.lpop().compareReverse(stack.lpop()));
-
- LongValue longValue1 = stack.lpop();
- LongValue longValue2 = stack.lpop();
- stack.push(longValue2.compare(longValue1));
- break;
-
- case InstructionConstants.OP_FCMPL:
- FloatValue floatValue1 = stack.fpop();
- FloatValue floatValue2 = stack.fpop();
- stack.push(floatValue2.compare(floatValue1));
- break;
-
- case InstructionConstants.OP_FCMPG:
- stack.push(stack.fpop().compareReverse(stack.fpop()));
- break;
-
- case InstructionConstants.OP_DCMPL:
- DoubleValue doubleValue1 = stack.dpop();
- DoubleValue doubleValue2 = stack.dpop();
- stack.push(doubleValue2.compare(doubleValue1));
- break;
-
- case InstructionConstants.OP_DCMPG:
- stack.push(stack.dpop().compareReverse(stack.dpop()));
- break;
-
- case InstructionConstants.OP_IRETURN:
- invocationUnit.exitMethod(clazz, method, stack.ipop());
- branchUnit.returnFromMethod();
- break;
-
- case InstructionConstants.OP_LRETURN:
- invocationUnit.exitMethod(clazz, method, stack.lpop());
- branchUnit.returnFromMethod();
- break;
-
- case InstructionConstants.OP_FRETURN:
- invocationUnit.exitMethod(clazz, method, stack.fpop());
- branchUnit.returnFromMethod();
- break;
-
- case InstructionConstants.OP_DRETURN:
- invocationUnit.exitMethod(clazz, method, stack.dpop());
- branchUnit.returnFromMethod();
- break;
-
- case InstructionConstants.OP_ARETURN:
- invocationUnit.exitMethod(clazz, method, stack.apop());
- branchUnit.returnFromMethod();
- break;
-
- case InstructionConstants.OP_RETURN:
- branchUnit.returnFromMethod();
- break;
-
- case InstructionConstants.OP_NEWARRAY:
- IntegerValue arrayLength = stack.ipop();
- stack.push(valueFactory.createArrayReferenceValue(String.valueOf(InstructionUtil.internalTypeFromArrayType((byte)simpleInstruction.constant)),
- null,
- arrayLength));
- break;
-
- case InstructionConstants.OP_ARRAYLENGTH:
- ReferenceValue referenceValue = stack.apop();
- stack.push(referenceValue.arrayLength(valueFactory));
- break;
-
- case InstructionConstants.OP_ATHROW:
- ReferenceValue exceptionReferenceValue = stack.apop();
- stack.clear();
- stack.push(exceptionReferenceValue);
- branchUnit.throwException();
- break;
-
- case InstructionConstants.OP_MONITORENTER:
- case InstructionConstants.OP_MONITOREXIT:
- stack.apop();
- break;
-
- default:
- throw new IllegalArgumentException("Unknown simple instruction ["+simpleInstruction.opcode+"]");
- }
- }
-
-
- public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
- {
- int constantIndex = constantInstruction.constantIndex;
-
- switch (constantInstruction.opcode)
- {
- case InstructionConstants.OP_LDC:
- case InstructionConstants.OP_LDC_W:
- case InstructionConstants.OP_LDC2_W:
- stack.push(classConstantValueFactory.constantValue(clazz, constantIndex));
- break;
-
- case InstructionConstants.OP_GETSTATIC:
- case InstructionConstants.OP_PUTSTATIC:
- case InstructionConstants.OP_GETFIELD:
- case InstructionConstants.OP_PUTFIELD:
- case InstructionConstants.OP_INVOKEVIRTUAL:
- case InstructionConstants.OP_INVOKESPECIAL:
- case InstructionConstants.OP_INVOKESTATIC:
- case InstructionConstants.OP_INVOKEINTERFACE:
- case InstructionConstants.OP_INVOKEDYNAMIC:
- invocationUnit.invokeMember(clazz, method, codeAttribute, offset, constantInstruction, stack);
- break;
-
- case InstructionConstants.OP_NEW:
- stack.push(constantValueFactory.constantValue(clazz, constantIndex).referenceValue());
- break;
-
- case InstructionConstants.OP_ANEWARRAY:
- {
- ReferenceValue referenceValue = constantValueFactory.constantValue(clazz, constantIndex).referenceValue();
-
- stack.push(valueFactory.createArrayReferenceValue(referenceValue.internalType(),
- referenceValue.getReferencedClass(),
- stack.ipop()));
- break;
- }
-
- case InstructionConstants.OP_CHECKCAST:
- // TODO: Check cast.
- ReferenceValue castValue = stack.apop();
- ReferenceValue castResultValue =
- !alwaysCast &&
- castValue.isNull() == Value.ALWAYS ? castValue :
- castValue.isNull() == Value.NEVER ? constantValueFactory.constantValue(clazz, constantIndex).referenceValue() :
- constantValueFactory.constantValue(clazz, constantIndex).referenceValue().generalize(valueFactory.createReferenceValueNull());
- stack.push(castResultValue);
- break;
-
- case InstructionConstants.OP_INSTANCEOF:
- {
- ReferenceValue referenceValue = constantValueFactory.constantValue(clazz, constantIndex).referenceValue();
-
- int instanceOf = stack.apop().instanceOf(referenceValue.getType(),
- referenceValue.getReferencedClass());
-
- stack.push(instanceOf == Value.NEVER ? valueFactory.createIntegerValue(0) :
- instanceOf == Value.ALWAYS ? valueFactory.createIntegerValue(1) :
- valueFactory.createIntegerValue());
- break;
- }
-
- case InstructionConstants.OP_MULTIANEWARRAY:
- {
- int dimensionCount = constantInstruction.constant;
- for (int dimension = 0; dimension < dimensionCount; dimension++)
- {
- // TODO: Use array lengths.
- IntegerValue arrayLength = stack.ipop();
- }
-
- stack.push(constantValueFactory.constantValue(clazz, constantIndex).referenceValue());
- break;
- }
-
- default:
- throw new IllegalArgumentException("Unknown constant pool instruction ["+constantInstruction.opcode+"]");
- }
- }
-
-
- public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction)
- {
- int variableIndex = variableInstruction.variableIndex;
-
- switch (variableInstruction.opcode)
- {
- case InstructionConstants.OP_ILOAD:
- case InstructionConstants.OP_ILOAD_0:
- case InstructionConstants.OP_ILOAD_1:
- case InstructionConstants.OP_ILOAD_2:
- case InstructionConstants.OP_ILOAD_3:
- stack.push(variables.iload(variableIndex));
- break;
-
- case InstructionConstants.OP_LLOAD:
- case InstructionConstants.OP_LLOAD_0:
- case InstructionConstants.OP_LLOAD_1:
- case InstructionConstants.OP_LLOAD_2:
- case InstructionConstants.OP_LLOAD_3:
- stack.push(variables.lload(variableIndex));
- break;
-
- case InstructionConstants.OP_FLOAD:
- case InstructionConstants.OP_FLOAD_0:
- case InstructionConstants.OP_FLOAD_1:
- case InstructionConstants.OP_FLOAD_2:
- case InstructionConstants.OP_FLOAD_3:
- stack.push(variables.fload(variableIndex));
- break;
-
- case InstructionConstants.OP_DLOAD:
- case InstructionConstants.OP_DLOAD_0:
- case InstructionConstants.OP_DLOAD_1:
- case InstructionConstants.OP_DLOAD_2:
- case InstructionConstants.OP_DLOAD_3:
- stack.push(variables.dload(variableIndex));
- break;
-
- case InstructionConstants.OP_ALOAD:
- case InstructionConstants.OP_ALOAD_0:
- case InstructionConstants.OP_ALOAD_1:
- case InstructionConstants.OP_ALOAD_2:
- case InstructionConstants.OP_ALOAD_3:
- stack.push(variables.aload(variableIndex));
- break;
-
- case InstructionConstants.OP_ISTORE:
- case InstructionConstants.OP_ISTORE_0:
- case InstructionConstants.OP_ISTORE_1:
- case InstructionConstants.OP_ISTORE_2:
- case InstructionConstants.OP_ISTORE_3:
- variables.store(variableIndex, stack.ipop());
- break;
-
- case InstructionConstants.OP_LSTORE:
- case InstructionConstants.OP_LSTORE_0:
- case InstructionConstants.OP_LSTORE_1:
- case InstructionConstants.OP_LSTORE_2:
- case InstructionConstants.OP_LSTORE_3:
- variables.store(variableIndex, stack.lpop());
- break;
-
- case InstructionConstants.OP_FSTORE:
- case InstructionConstants.OP_FSTORE_0:
- case InstructionConstants.OP_FSTORE_1:
- case InstructionConstants.OP_FSTORE_2:
- case InstructionConstants.OP_FSTORE_3:
- variables.store(variableIndex, stack.fpop());
- break;
-
- case InstructionConstants.OP_DSTORE:
- case InstructionConstants.OP_DSTORE_0:
- case InstructionConstants.OP_DSTORE_1:
- case InstructionConstants.OP_DSTORE_2:
- case InstructionConstants.OP_DSTORE_3:
- variables.store(variableIndex, stack.dpop());
- break;
-
- case InstructionConstants.OP_ASTORE:
- case InstructionConstants.OP_ASTORE_0:
- case InstructionConstants.OP_ASTORE_1:
- case InstructionConstants.OP_ASTORE_2:
- case InstructionConstants.OP_ASTORE_3:
- // The operand on the stack can be a reference or a return
- // address, so we'll relax the pop operation.
- //variables.store(variableIndex, stack.apop());
- variables.store(variableIndex, stack.pop());
- break;
-
- case InstructionConstants.OP_IINC:
- variables.store(variableIndex,
- variables.iload(variableIndex).add(
- valueFactory.createIntegerValue(variableInstruction.constant)));
- break;
-
- case InstructionConstants.OP_RET:
- // The return address should be in the last offset of the
- // given instruction offset variable (even though there may
- // be other offsets).
- InstructionOffsetValue instructionOffsetValue = variables.oload(variableIndex);
- branchUnit.branch(clazz,
- codeAttribute,
- offset,
- instructionOffsetValue.instructionOffset(instructionOffsetValue.instructionOffsetCount()-1));
- break;
-
- default:
- throw new IllegalArgumentException("Unknown variable instruction ["+variableInstruction.opcode+"]");
- }
- }
-
-
- public void visitBranchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction)
- {
- int branchTarget = offset + branchInstruction.branchOffset;
-
- switch (branchInstruction.opcode)
- {
- case InstructionConstants.OP_IFEQ:
- branchUnit.branchConditionally(clazz, codeAttribute, offset, branchTarget,
- stack.ipop().equal(valueFactory.createIntegerValue(0)));
- break;
-
- case InstructionConstants.OP_IFNE:
- branchUnit.branchConditionally(clazz, codeAttribute, offset, branchTarget,
- stack.ipop().notEqual(valueFactory.createIntegerValue(0)));
- break;
-
- case InstructionConstants.OP_IFLT:
- branchUnit.branchConditionally(clazz, codeAttribute, offset, branchTarget,
- stack.ipop().lessThan(valueFactory.createIntegerValue(0)));
- break;
-
- case InstructionConstants.OP_IFGE:
- branchUnit.branchConditionally(clazz, codeAttribute, offset, branchTarget,
- stack.ipop().greaterThanOrEqual(valueFactory.createIntegerValue(0)));
- break;
-
- case InstructionConstants.OP_IFGT:
- branchUnit.branchConditionally(clazz, codeAttribute, offset, branchTarget,
- stack.ipop().greaterThan(valueFactory.createIntegerValue(0)));
- break;
-
- case InstructionConstants.OP_IFLE:
- branchUnit.branchConditionally(clazz, codeAttribute, offset, branchTarget,
- stack.ipop().lessThanOrEqual(valueFactory.createIntegerValue(0)));
- break;
-
-
- case InstructionConstants.OP_IFICMPEQ:
- branchUnit.branchConditionally(clazz, codeAttribute, offset, branchTarget,
- stack.ipop().equal(stack.ipop()));
- break;
-
- case InstructionConstants.OP_IFICMPNE:
- branchUnit.branchConditionally(clazz, codeAttribute, offset, branchTarget,
- stack.ipop().notEqual(stack.ipop()));
- break;
-
- case InstructionConstants.OP_IFICMPLT:
- // Note that the stack entries are popped in reverse order.
- branchUnit.branchConditionally(clazz, codeAttribute, offset, branchTarget,
- stack.ipop().greaterThan(stack.ipop()));
- break;
-
- case InstructionConstants.OP_IFICMPGE:
- // Note that the stack entries are popped in reverse order.
- branchUnit.branchConditionally(clazz, codeAttribute, offset, branchTarget,
- stack.ipop().lessThanOrEqual(stack.ipop()));
- break;
-
- case InstructionConstants.OP_IFICMPGT:
- // Note that the stack entries are popped in reverse order.
- branchUnit.branchConditionally(clazz, codeAttribute, offset, branchTarget,
- stack.ipop().lessThan(stack.ipop()));
- break;
-
- case InstructionConstants.OP_IFICMPLE:
- // Note that the stack entries are popped in reverse order.
- branchUnit.branchConditionally(clazz, codeAttribute, offset, branchTarget,
- stack.ipop().greaterThanOrEqual(stack.ipop()));
- break;
-
- case InstructionConstants.OP_IFACMPEQ:
- branchUnit.branchConditionally(clazz, codeAttribute, offset, branchTarget,
- stack.apop().equal(stack.apop()));
- break;
-
- case InstructionConstants.OP_IFACMPNE:
- branchUnit.branchConditionally(clazz, codeAttribute, offset, branchTarget,
- stack.apop().notEqual(stack.apop()));
- break;
-
- case InstructionConstants.OP_GOTO:
- case InstructionConstants.OP_GOTO_W:
- branchUnit.branch(clazz, codeAttribute, offset, branchTarget);
- break;
-
-
- case InstructionConstants.OP_JSR:
- case InstructionConstants.OP_JSR_W:
- stack.push(new InstructionOffsetValue(offset +
- branchInstruction.length(offset)));
- branchUnit.branch(clazz, codeAttribute, offset, branchTarget);
- break;
-
- case InstructionConstants.OP_IFNULL:
- branchUnit.branchConditionally(clazz, codeAttribute, offset, branchTarget,
- stack.apop().isNull());
- break;
-
- case InstructionConstants.OP_IFNONNULL:
- branchUnit.branchConditionally(clazz, codeAttribute, offset, branchTarget,
- stack.apop().isNotNull());
- break;
-
- default:
- throw new IllegalArgumentException("Unknown branch instruction ["+branchInstruction.opcode+"]");
- }
- }
-
-
- public void visitTableSwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, TableSwitchInstruction tableSwitchInstruction)
- {
- IntegerValue indexValue = stack.ipop();
-
- // If there is no definite branch in any of the cases below,
- // branch to the default offset.
- branchUnit.branch(clazz, codeAttribute,
- offset,
- offset + tableSwitchInstruction.defaultOffset);
-
- for (int index = 0; index < tableSwitchInstruction.jumpOffsets.length; index++)
- {
- int conditional = indexValue.equal(valueFactory.createIntegerValue(
- tableSwitchInstruction.lowCase + index));
- branchUnit.branchConditionally(clazz, codeAttribute,
- offset,
- offset + tableSwitchInstruction.jumpOffsets[index],
- conditional);
-
- // If this branch is always taken, we can skip the rest.
- if (conditional == Value.ALWAYS)
- {
- break;
- }
- }
- }
-
-
- public void visitLookUpSwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, LookUpSwitchInstruction lookUpSwitchInstruction)
- {
- IntegerValue indexValue = stack.ipop();
-
- // If there is no definite branch in any of the cases below,
- // branch to the default offset.
- branchUnit.branch(clazz, codeAttribute,
- offset,
- offset + lookUpSwitchInstruction.defaultOffset);
-
- for (int index = 0; index < lookUpSwitchInstruction.jumpOffsets.length; index++)
- {
- int conditional = indexValue.equal(valueFactory.createIntegerValue(
- lookUpSwitchInstruction.cases[index]));
- branchUnit.branchConditionally(clazz, codeAttribute,
- offset,
- offset + lookUpSwitchInstruction.jumpOffsets[index],
- conditional);
-
- // If this branch is always taken, we can skip the rest.
- if (conditional == Value.ALWAYS)
- {
- break;
- }
- }
- }
-}