📄 evaluationsimplifier.java
字号:
* @param delete specifies whether the instruction should be * deleted. */ private void increaseStackSize(int offset, int computationalType, boolean delete) { // Mark this instruction. isNecessary[offset] = true; // Create a simple push instrucion. byte replacementOpcode = computationalType == Value.TYPE_INTEGER ? InstructionConstants.OP_ICONST_0 : computationalType == Value.TYPE_LONG ? InstructionConstants.OP_LCONST_0 : computationalType == Value.TYPE_FLOAT ? InstructionConstants.OP_FCONST_0 : computationalType == Value.TYPE_DOUBLE ? InstructionConstants.OP_DCONST_0 : computationalType == Value.TYPE_REFERENCE ? InstructionConstants.OP_ACONST_NULL : InstructionConstants.OP_NOP; Instruction replacementInstruction = new SimpleInstruction(replacementOpcode); // Insert the pop or push instruction. codeAttributeEditor.insertBeforeInstruction(offset, replacementInstruction); if (extraAddedInstructionVisitor != null) { replacementInstruction.accept(null, null, null, offset, extraAddedInstructionVisitor); } // Delete the original instruction if necessary. if (delete) { codeAttributeEditor.deleteInstruction(offset); if (extraDeletedInstructionVisitor != null) { extraDeletedInstructionVisitor.visitSimpleInstruction(null, null, null, offset, null); } } } /** * Puts the required pop instruction at the given index. The * instruction is marked as necessary. * @param offset the offset of the instruction. * @param popCount the required reduction of the stack size. * @param before specifies whether the pop instruction should be inserted * before or after the present instruction. * @param delete specifies whether the instruction should be deleted. */ private void decreaseStackSize(int offset, int popCount, boolean before, boolean delete) { // Mark this instruction. isNecessary[offset] = true; boolean after = !before; int remainingPopCount = popCount; if (delete) { // Replace the original instruction. int count = remainingPopCount == 1 ? 1 : 2; // Create a simple pop instrucion. byte replacementOpcode = count == 1 ? InstructionConstants.OP_POP : InstructionConstants.OP_POP2; Instruction replacementInstruction = new SimpleInstruction(replacementOpcode); // Insert the pop instruction. codeAttributeEditor.replaceInstruction(offset, replacementInstruction); remainingPopCount -= count; // We may insert other pop instructions before and after this one. before = true; after = true; } if (before && remainingPopCount > 0) { // Insert before the original instruction. int count = remainingPopCount == 1 ? 1 : 2; // Create a simple pop instrucion. byte replacementOpcode = count == 1 ? InstructionConstants.OP_POP : InstructionConstants.OP_POP2; Instruction replacementInstruction = new SimpleInstruction(replacementOpcode); // Insert the pop instruction. codeAttributeEditor.insertBeforeInstruction(offset, replacementInstruction); remainingPopCount -= count; if (extraAddedInstructionVisitor != null) { replacementInstruction.accept(null, null, null, offset, extraAddedInstructionVisitor); } } if (after && remainingPopCount > 0) { // Insert after the original instruction. int count = remainingPopCount == 1 ? 1 : 2; // Create a simple pop instrucion. byte replacementOpcode = count == 1 ? InstructionConstants.OP_POP : InstructionConstants.OP_POP2; Instruction replacementInstruction = new SimpleInstruction(replacementOpcode); // Insert the pop instruction. codeAttributeEditor.insertAfterInstruction(offset, replacementInstruction); remainingPopCount -= count; if (extraAddedInstructionVisitor != null) { replacementInstruction.accept(null, null, null, offset, extraAddedInstructionVisitor); } } if (remainingPopCount > 0) { throw new IllegalArgumentException("Unsupported stack size reduction ["+popCount+"]"); } } // Implementations for InstructionVisitor. public void visitSimpleInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SimpleInstruction simpleInstruction) { if (partialEvaluator.isTraced(offset)) { switch (simpleInstruction.opcode) { case InstructionConstants.OP_IALOAD: case InstructionConstants.OP_BALOAD: case InstructionConstants.OP_CALOAD: case InstructionConstants.OP_SALOAD: case InstructionConstants.OP_IADD: case InstructionConstants.OP_ISUB: case InstructionConstants.OP_IMUL: case InstructionConstants.OP_IDIV: case InstructionConstants.OP_IREM: case InstructionConstants.OP_INEG: case InstructionConstants.OP_ISHL: case InstructionConstants.OP_ISHR: case InstructionConstants.OP_IUSHR: case InstructionConstants.OP_IAND: case InstructionConstants.OP_IOR: case InstructionConstants.OP_IXOR: case InstructionConstants.OP_L2I: case InstructionConstants.OP_F2I: case InstructionConstants.OP_D2I: case InstructionConstants.OP_I2B: case InstructionConstants.OP_I2C: case InstructionConstants.OP_I2S: replaceIntegerPushInstruction(offset); break; case InstructionConstants.OP_LALOAD: case InstructionConstants.OP_LADD: case InstructionConstants.OP_LSUB: case InstructionConstants.OP_LMUL: case InstructionConstants.OP_LDIV: case InstructionConstants.OP_LREM: case InstructionConstants.OP_LNEG: case InstructionConstants.OP_LSHL: case InstructionConstants.OP_LSHR: case InstructionConstants.OP_LUSHR: case InstructionConstants.OP_LAND: case InstructionConstants.OP_LOR: case InstructionConstants.OP_LXOR: case InstructionConstants.OP_I2L: case InstructionConstants.OP_F2L: case InstructionConstants.OP_D2L: replaceLongPushInstruction(offset); break; case InstructionConstants.OP_FALOAD: case InstructionConstants.OP_FADD: case InstructionConstants.OP_FSUB: case InstructionConstants.OP_FMUL: case InstructionConstants.OP_FDIV: case InstructionConstants.OP_FREM: case InstructionConstants.OP_FNEG: case InstructionConstants.OP_I2F: case InstructionConstants.OP_L2F: case InstructionConstants.OP_D2F: replaceFloatPushInstruction(offset); break; case InstructionConstants.OP_DALOAD: case InstructionConstants.OP_DADD: case InstructionConstants.OP_DSUB: case InstructionConstants.OP_DMUL: case InstructionConstants.OP_DDIV: case InstructionConstants.OP_DREM: case InstructionConstants.OP_DNEG: case InstructionConstants.OP_I2D: case InstructionConstants.OP_L2D: case InstructionConstants.OP_F2D: replaceDoublePushInstruction(offset); break; case InstructionConstants.OP_AALOAD: replaceReferencePushInstruction(offset); break; } } } public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction) { if (partialEvaluator.isTraced(offset)) { 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: replaceIntegerPushInstruction(offset); 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: replaceLongPushInstruction(offset); 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: replaceFloatPushInstruction(offset); 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: replaceDoublePushInstruction(offset); 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: replaceReferencePushInstruction(offset); break; } } } public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction) { if (partialEvaluator.isTraced(offset)) { switch (constantInstruction.opcode) { case InstructionConstants.OP_GETSTATIC: case InstructionConstants.OP_GETFIELD: replaceAnyPushInstruction(offset); break; case InstructionConstants.OP_INVOKEVIRTUAL: case InstructionConstants.OP_INVOKESPECIAL: case InstructionConstants.OP_INVOKESTATIC: case InstructionConstants.OP_INVOKEINTERFACE: if (constantInstruction.stackPushCount(clazz) > 0 && !sideEffectInstructionChecker.hasSideEffects(clazz, method, codeAttribute, offset, constantInstruction)) { replaceAnyPushInstruction(offset); } break; case InstructionConstants.OP_CHECKCAST:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -