📄 partialevaluator.java
字号:
if (DEBUG_ANALYSIS) System.out.println("Usage initialization: "); // The invocation of the "super" or "this" <init> method inside a // constructor is always necessary, even if it is assumed to have no // side effects. boolean markSuperOrThis = methodInfo.getName(classFile).equals(ClassConstants.INTERNAL_METHOD_NAME_INIT); int aload0Index = 0; int index = 0; do { if (isTraced(index)) { Instruction instruction = InstructionFactory.create(codeAttrInfo.code, index); // Remember the most recent aload0 instruction index. if (instruction.opcode == InstructionConstants.OP_ALOAD_0) { aload0Index = index; } // Mark the instruction as necessary if it is the first // invocation of the "super" or "this" <init> method // inside a constructor. else if (markSuperOrThis && instruction.opcode == InstructionConstants.OP_INVOKESPECIAL && stackTraceValues[index].contains(aload0Index)) { markSuperOrThis = false; if (DEBUG_ANALYSIS) System.out.print(index+","); isNecessary[index] = true; } // Mark the instruction as necessary if it has side effects. else if (sideEffectInstructionChecker.hasSideEffects(classFile, methodInfo, codeAttrInfo, index, instruction)) { if (DEBUG_ANALYSIS) System.out.print(index+","); isNecessary[index] = true; } } index++; } while (index < codeLength); if (DEBUG_ANALYSIS) System.out.println(); // Mark all other instructions on which the essential instructions // depend. Instead of doing this recursively, we loop across all // instructions, starting at the last one, and restarting at any // higher, previously unmarked instruction that is being marked. if (DEBUG_ANALYSIS) System.out.println("Usage marking:"); int lowestNecessaryIndex = codeLength; index = codeLength - 1; do { int nextIndex = index - 1; // Update the lowest index of all marked instructions higher up. if (isNecessary[index]) { lowestNecessaryIndex = index; } // Check if this instruction is a branch origin from a branch that // straddles some marked code. nextIndex = markStraddlingBranches(index, branchTargetValues[index], true, lowestNecessaryIndex, nextIndex); // Mark the instructions on which this instruction depends. nextIndex = markDependencies(index, nextIndex); // Update the lowest index of all marked instructions higher up. if (isNecessary[index]) { lowestNecessaryIndex = index; } // Check if this instruction is a branch target from a branch that // straddles some marked code. nextIndex = markStraddlingBranches(index, branchOriginValues[index], false, lowestNecessaryIndex, nextIndex); if (DEBUG_ANALYSIS) { if (nextIndex >= index) { System.out.println(); } } // Update the lowest index of all marked instructions higher up. if (isNecessary[index]) { lowestNecessaryIndex = index; } // Update the index of the instruction to be investigated next. index = nextIndex; } while (index >= 0); if (DEBUG_ANALYSIS) System.out.println(); // Insert pop instructions where necessary, to keep the stack consistent. if (DEBUG_ANALYSIS) System.out.println("Stack consistency marking:"); index = codeLength - 1; do { if (isTraced(index) && !isNecessary[index]) { // Make sure the stack is always consistent at this offset. fixStackConsistency(classFile, codeAttrInfo, index); } index--; } while (index >= 0); if (DEBUG_ANALYSIS) System.out.println(); // Fix dup/swap instructions where necessary, to keep the stack consistent. if (DEBUG_ANALYSIS) System.out.println("Dup/swap fixing:"); index = 0; do { if (isNecessary[index]) { // Make sure any dup/swap instructions are always consistent at this offset. fixDupInstruction(codeAttrInfo, index); } index++; } while (index < codeLength); if (DEBUG_ANALYSIS) System.out.println(); // Mark branches straddling just inserted push/pop instructions. if (DEBUG_ANALYSIS) System.out.println("Final straddling branch marking:"); lowestNecessaryIndex = codeLength; index = codeLength - 1; do { int nextIndex = index - 1; // Update the lowest index of all marked instructions higher up. if (isNecessary[index]) { lowestNecessaryIndex = index; } // Check if this instruction is a branch origin from a branch that // straddles some marked code. nextIndex = markAndSimplifyStraddlingBranches(index, branchTargetValues[index], lowestNecessaryIndex, nextIndex); // Update the lowest index of all marked instructions higher up. if (isNecessary[index]) { lowestNecessaryIndex = index; } // Check if this instruction is a branch target from a branch that // straddles some marked code. nextIndex = markAndSimplifyStraddlingBranches(branchOriginValues[index], index, lowestNecessaryIndex, nextIndex); if (DEBUG_ANALYSIS) { if (nextIndex >= index) { System.out.println(); } } // Update the lowest index of all marked instructions higher up. if (isNecessary[index]) { lowestNecessaryIndex = index; } // Update the index of the instruction to be investigated next. index = nextIndex; } while (index >= 0); if (DEBUG_ANALYSIS) System.out.println(); // Mark variable initializations, even if they aren't strictly necessary. // The virtual machine is not smart enough to see this, and may complain // otherwise. if (DEBUG_ANALYSIS) System.out.println("Initialization marking: "); // TODO: Find a better way. index = 0; do { // Is it an initialization that hasn't been marked yet? if (initialization[index] && !isNecessary[index]) { if (DEBUG_ANALYSIS) System.out.println(index+","); // Figure out what kind of initialization value has to be stored. int pushInstructionOffset = stackTraceValues[index].instructionOffset(0); int pushComputationalType = stacks[pushInstructionOffset].getTop(0).computationalType(); increaseStackSize(index, pushComputationalType, false); } index++; } while (index < codeLength); if (DEBUG_ANALYSIS) System.out.println(); if (DEBUG_RESULTS) { System.out.println("Results:"); int offset = 0; do { Instruction instruction = InstructionFactory.create(codeAttrInfo.code, offset); System.out.println((isNecessary[offset] ? " + " : " - ")+instruction.toString(offset)); if (isTraced(offset)) { if (varTraceValues[offset] != null && varTraceValues[offset].instructionOffsetCount() > 0) { System.out.println(" has overall been using information from instructions setting vars: "+varTraceValues[offset]); } if (stackTraceValues[offset] != null && stackTraceValues[offset].instructionOffsetCount() > 0) { System.out.println(" has overall been using information from instructions setting stack: "+stackTraceValues[offset]); } if (branchTargetValues[offset] != null) { System.out.println(" has overall been branching to "+branchTargetValues[offset]); } if (codeAttrInfoEditor.preInsertions[offset] != null) { System.out.println(" is preceded by: "+codeAttrInfoEditor.preInsertions[offset]); } if (codeAttrInfoEditor.postInsertions[offset] != null) { System.out.println(" is followed by: "+codeAttrInfoEditor.preInsertions[offset]); } System.out.println(" Vars: "+vars[offset]); System.out.println(" Stack: "+stacks[offset]); } offset += instruction.length(offset); } while (offset < codeLength); } // Delete all instructions that are not used. int offset = 0; do { Instruction instruction = InstructionFactory.create(codeAttrInfo.code, offset); if (!isNecessary[offset]) { codeAttrInfoEditor.replaceInstruction(offset, null); codeAttrInfoEditor.replaceInstruction2(offset, null); } offset += instruction.length(offset); } while (offset < codeLength); // Apply all accumulated changes to the code. codeAttrInfoEditor.visitCodeAttrInfo(classFile, methodInfo, codeAttrInfo);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -