📄 partialevaluator.java
字号:
} break; } // Actually replace the instruction with the new opcde, if any. if (replacementOpcode != 0) { Instruction replacementInstruction = new SimpleInstruction(replacementOpcode); codeAttrInfoEditor.replaceInstruction(offset, replacementInstruction); if (DEBUG_ANALYSIS) System.out.println(" Replacing instruction at ["+offset+"] by "+replacementInstruction.toString()); } } /** * Returns whether the given stack entry is present after execution of the * instruction at the given offset. */ private boolean isStackEntryPresent(int instructionOffset, int stackIndex) { return isAnyNecessary(stacks[instructionOffset].getTopTraceValue(stackIndex).instructionOffsetValue()); } // 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 doesn't have associated instruction offsets. Value storeValue = InstructionOffsetValueFactory.create(); variables.setStoreValue(storeValue); stack.setStoreValue(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; } } /** * Returns whether a block of instructions is ever used. */ private boolean isTraced(int startOffset, int endOffset) { for (int index = startOffset; index < endOffset; index++) { if (isTraced(index)) { return true; } } return false; } /** * Generalize the local variable frames of a block of instructions. */ private void generalizeVariables(int startOffset, int endOffset, TracedVariables generalizedVariables) { for (int index = startOffset; index < endOffset; index++) { if (isTraced(index)) { // We can't use the return value, because local generalization // can be different a couple of times, with the global // generalization being the same. generalizedVariables.generalize(vars[index]); } } } // 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); // Evaluate the subsequent instructions. while (true) { // Maintain a generalized trace instruction offset. int evaluationCount = evaluationCounts[instructionOffset]++; if (evaluationCount == 0) { varTraceValues[instructionOffset] = InstructionOffsetValueFactory.create(); stackTraceValues[instructionOffset] = InstructionOffsetValueFactory.create(); } // Remember this instruction's offset with any stored value. Value storeValue = InstructionOffsetValueFactory.create(instructionOffset); variables.setStoreValue(storeValue); stack.setStoreValue(storeValue); // Reset the trace value. InstructionOffsetValue traceValue = InstructionOffsetValueFactory.create(); variables.setTraceValue(traceValue); stack.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); 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 this evaluator. 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()+"]"); System.err.println(" Method = ["+methodInfo.getName(classFile)+methodInfo.getDescriptor(classFile)+"]"); System.err.println(" Instruction = "+instruction.toString(instructionOffset)); throw ex; } // Collect the offsets of the instructions whose results were used. InstructionOffsetValue variablesTraceValue = variables.getTraceValue().instructionOffsetValue(); InstructionOffsetValue stackTraceValue = stack.getTraceValue().instructionOffsetValue(); varTraceValues[instructionOffset] = varTraceValues[instructionOffset].generalize(variablesTraceValue).instructionOffsetValue(); stackTraceValues[instructionOffset] = stackTraceValues[instructionOffset].generalize(stackTraceValue).instructionOffsetValue(); initialization[instructionOffset] = initialization[instructionOffset] || variables.wasInitialization(); // Collect the branch targets from the branch unit. InstructionOffsetValue branchTargets = branchUnit.getTraceBranchTargets(); int branchTargetCount = branchTargets.instructionOffsetCount(); // Stop tracing. variables.setTraceValue(traceValue); stack.setTraceValue(traceValue); branchUnit.setTraceBranchTargets(traceValue); if (DEBUG) { if (variablesTraceValue.instructionOffsetCount() > 0) { System.out.println(" has used information from instructions setting vars: "+variablesTraceValue); } if (stackTraceValue.instructionOffsetCount() > 0) { System.out.println(" has used information from instructions setting stack: "+stackTraceValue); } if (branchUnit.wasCalled()) { System.out.println(" is branching to "+branchTargets); } if (varTraceValues[instructionOffset].instructionOffsetCount() > 0) { System.out.println(" has up til now been using information from instructions setting vars: "+varTraceValues[instructionOffset]); } if (stackTraceValues[instructionOffset].instructionOffsetCount() > 0) { System.out.println(" has up till now been using information from instructions setting stack: "+stackTraceValues[instructionOffset]); } if (branchTargetValues[instructionOffset] != null) { System.out.println(" has up till now been branching to "+branchTargetValues[instructionOffset]); } System.out.println(" Vars: "+variables); System.out.println(" Stack: "+stack); } // Maintain a generalized local variable frame and stack at this // branch instruction offset. if (vars[instructionOffset] == null) { // First time we're passing by this instruction. // There's not even a context at this index yet. vars[instructionOffset] = new TracedVariables(variables); stacks[instructionOffset] = new TracedStack(stack); } else if (evaluationCount == 0) { // First time we're passing by this instruction. // Reuse the context objects at this index. vars[instructionOffset].initialize(variables); stacks[instructionOffset].copy(stack); } else { // If there are multiple alternative branches, or if this // instruction has been evaluated an excessive number of // times, then generalize the current context. // TODO: See if we can avoid generalizing the current context. //if (branchTargetCount > 1 || // evaluationCount > MAXIMUM_EVALUATION_COUNT) //{ // variables.generalize(vars[instructionOffset]); // stack.generalize(stacks[instructionOffset]); //} boolean vars_changed = vars[instructionOffset].generalize(variables); boolean stack_changed = stacks[instructionOffset].generalize(stack); // Bail out if the current context is the same as last time. if (!vars_changed && !stack_changed && branchTargets.equals(branchTargetValues[instructionOffset])) { if (DE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -