📄 partialevaluator.java
字号:
/** * Returns the instruction offsets that set the stack entries that are being * used at the given instruction offset. */ public InstructionOffsetValue stackProducerOffsets(int instructionOffset) { return stackProducerValues[instructionOffset]; } /** * Returns the instruction offsets that use the stack value at at the given * instruction offset and stack index. */ public InstructionOffsetValue stackTopConsumerOffsets(int instructionOffset, int stackIndex) { return stacks[instructionOffset].getTopConsumerValue(stackIndex).instructionOffsetValue(); } /** * Returns the instruction offsets that set stack entries that are not being * used at the given instruction offset (e.g. because the parameters are not * being used). */ public InstructionOffsetValue unusedProducerOffsets(int instructionOffset) { return unusedProducerValues[instructionOffset]; } /** * Returns the instruction offsets that branch to the given instruction * offset. */ public InstructionOffsetValue branchOrigins(int instructionOffset) { return branchOriginValues[instructionOffset]; } /** * Returns the instruction offsets to which the given instruction offset * branches. */ public InstructionOffsetValue branchTargets(int instructionOffset) { return branchTargetValues[instructionOffset]; } /** * Returns the variable that is initialized at the given instruction offset, * or NONE if no variable was initialized. */ public int initializedVariable(int instructionOffset) { return initializedVariables[instructionOffset]; } // Implementations for ExceptionInfoVisitor. public void visitExceptionInfo(ClassFile classFile, MethodInfo methodInfo, CodeAttrInfo codeAttrInfo, ExceptionInfo exceptionInfo) { if (isTraced(exceptionInfo.u2startpc, exceptionInfo.u2endpc)) { if (DEBUG) System.out.println("Partial evaluation of exception ["+exceptionInfo.u2startpc+","+exceptionInfo.u2endpc+"] -> ["+exceptionInfo.u2handlerpc+"]:"); // Generalize the variables of the try block. variables.reset(codeAttrInfo.u2maxLocals); generalizeVariables(exceptionInfo.u2startpc, exceptionInfo.u2endpc, variables); // Remember the entry variables of the exception. TracedVariables exceptionVariables = (TracedVariables)exceptionInfo.getVisitorInfo(); if (exceptionVariables == null) { exceptionVariables = new TracedVariables(codeAttrInfo.u2maxLocals); exceptionInfo.setVisitorInfo(exceptionVariables); } else { // Bail out if the entry variables are the same as last time. if (exceptionVariables.equals(variables)) { if (DEBUG) System.out.println(" Repeated initial variables"); return; } } exceptionVariables.initialize(variables); // Reuse the existing variables and stack objects, ensuring the right size. variables.reset(codeAttrInfo.u2maxLocals); stack.reset(codeAttrInfo.u2maxStack); // The initial stack has a generic instruction offset. Value storeValue = InstructionOffsetValueFactory.create(AT_CATCH_ENTRY); variables.setProducerValue(storeValue); stack.setProducerValue(storeValue); // Initialize the local variables and the stack. variables.initialize(exceptionVariables); //stack.push(ReferenceValueFactory.create((ClassCpInfo)((ProgramClassFile)classFile).getCpEntry(exceptionInfo.u2catchType), false)); stack.push(ReferenceValueFactory.create(false)); // Evaluate the instructions, starting at the entry point. evaluateInstructionBlock(classFile, methodInfo, codeAttrInfo, variables, stack, branchUnit, exceptionInfo.u2handlerpc); // Remember to check this exception and other exceptions once more. evaluateExceptions = true; } } // Implementations for InstructionVisitor. public void visitSimpleInstruction(ClassFile classFile, MethodInfo methodInfo, CodeAttrInfo codeAttrInfo, int offset, SimpleInstruction simpleInstruction) {} public void visitVariableInstruction(ClassFile classFile, MethodInfo methodInfo, CodeAttrInfo codeAttrInfo, int offset, VariableInstruction variableInstruction) {} public void visitBranchInstruction(ClassFile classFile, MethodInfo methodInfo, CodeAttrInfo codeAttrInfo, int offset, BranchInstruction branchInstruction) {} public void visitTableSwitchInstruction(ClassFile classFile, MethodInfo methodInfo, CodeAttrInfo codeAttrInfo, int offset, TableSwitchInstruction tableSwitchInstruction) {} public void visitLookUpSwitchInstruction(ClassFile classFile, MethodInfo methodInfo, CodeAttrInfo codeAttrInfo, int offset, LookUpSwitchInstruction lookUpSwitchInstruction) {} public void visitCpInstruction(ClassFile classFile, MethodInfo methodInfo, CodeAttrInfo codeAttrInfo, int offset, CpInstruction cpInstruction) { // Make sure 'new' instructions (or subsequent 'dup' instructions) // depend on the subsequent initializer calls, in case these calls // are marked as not having any side effects. // Check if the invoked method is an initalizer. if (isTraced(offset) && branchTargetFinder.isInitializer(offset)) { // Find the previous instruction (assuming there was no branch). int previousOffset = offset - 1; while (!isTraced(previousOffset)) { previousOffset--; } // Compute the stack index of the uninitialized object. int stackIndex = stacks[offset].size(); // Get the (first and presumably only) offset of the instruction // that put it there. This is typically a dup instruction. int newOffset = stacks[previousOffset].getBottomProducerValue(stackIndex).instructionOffsetValue().instructionOffset(0); // Add a reverse dependency. The source instruction depends on // the initializer instruction, thus making sure that the latter // is preserved whenever the former is used. stackProducerValues[newOffset] = stackProducerValues[newOffset].generalize(InstructionOffsetValueFactory.create(offset)).instructionOffsetValue(); } } // Utility methods to evaluate instruction blocks. /** * Evaluates a block of instructions, starting at the given offset and ending * at a branch instruction, a return instruction, or a throw instruction. */ private void evaluateInstructionBlock(ClassFile classFile, MethodInfo methodInfo, CodeAttrInfo codeAttrInfo, TracedVariables variables, TracedStack stack, TracedBranchUnit branchUnit, int instructionOffset) { byte[] code = codeAttrInfo.code; if (DEBUG) { System.out.println("Instruction block starting at ["+instructionOffset+"] in "+ ClassUtil.externalFullMethodDescription(classFile.getName(), 0, methodInfo.getName(classFile), methodInfo.getDescriptor(classFile))); System.out.println("Init vars: "+variables); System.out.println("Init stack: "+stack); } Processor processor = new Processor(variables, stack, branchUnit); UnusedParameterCleaner unusedParameterCleaner = new UnusedParameterCleaner(stack); // Evaluate the subsequent instructions. while (true) { // Maintain a generalized trace instruction offset. int evaluationCount = evaluationCounts[instructionOffset]++; if (evaluationCount == 0) { varProducerValues[instructionOffset] = InstructionOffsetValueFactory.create(); stackProducerValues[instructionOffset] = InstructionOffsetValueFactory.create(); unusedProducerValues[instructionOffset] = InstructionOffsetValueFactory.create(); } // Remember this instruction's offset with any stored value. Value storeValue = InstructionOffsetValueFactory.create(instructionOffset); variables.setProducerValue(storeValue); stack.setProducerValue(storeValue); // Reset the trace value. InstructionOffsetValue traceValue = InstructionOffsetValueFactory.create(); variables.setCollectedProducerValue(traceValue); stack.setCollectedProducerValue(traceValue); unusedParameterCleaner.setTraceValue(traceValue); // Reset the initialization flag. variables.resetInitialization(); // Note that the instruction is only volatile. Instruction instruction = InstructionFactory.create(code, instructionOffset); // By default, the next instruction will be the one after this // instruction. int nextInstructionOffset = instructionOffset + instruction.length(instructionOffset); InstructionOffsetValue nextInstructionOffsetValue = InstructionOffsetValueFactory.create(nextInstructionOffset); branchUnit.resetCalled(); branchUnit.setTraceBranchTargets(nextInstructionOffsetValue); // First clean all traces to unused parameters if this is a method // invocation. instruction.accept(classFile, methodInfo, codeAttrInfo, instructionOffset, unusedParameterCleaner); if (DEBUG) { System.out.println(instruction.toString(instructionOffset)); } try { // Process the instruction. The processor may call // the Variables methods of 'variables', // the Stack methods of 'stack', and // the BranchUnit methods of 'branchUnit'. instruction.accept(classFile, methodInfo, codeAttrInfo, instructionOffset, processor); } catch (RuntimeException ex) { System.err.println("Unexpected error while performing partial evaluation:"); System.err.println(" ClassFile = ["+classFile.getName()+"]");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -