📄 partialevaluator.java
字号:
instructionOffset, processor); } catch (RuntimeException ex) { System.err.println("Unexpected error while evaluating instruction:"); System.err.println(" Class = ["+clazz.getName()+"]"); System.err.println(" Method = ["+method.getName(clazz)+method.getDescriptor(clazz)+"]"); System.err.println(" Instruction = "+instruction.toString(instructionOffset)); System.err.println(" Exception = ["+ex.getClass().getName()+"] ("+ex.getMessage()+")"); throw ex; } // Collect the offsets of the instructions whose results were used. InstructionOffsetValue variablesTraceValue = variables.getCollectedProducerValue().instructionOffsetValue(); InstructionOffsetValue stackTraceValue = stack.getCollectedProducerValue().instructionOffsetValue(); varProducerValues[instructionOffset] = varProducerValues[instructionOffset].generalize(variablesTraceValue).instructionOffsetValue(); stackProducerValues[instructionOffset] = stackProducerValues[instructionOffset].generalize(stackTraceValue).instructionOffsetValue(); initializedVariables[instructionOffset] = variables.getInitializationIndex(); // Collect the branch targets from the branch unit. InstructionOffsetValue branchTargets = branchUnit.getTraceBranchTargets(); int branchTargetCount = branchTargets.instructionOffsetCount(); // Stop tracing. variables.setCollectedProducerValue(traceValue); stack.setCollectedProducerValue(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 (varProducerValues[instructionOffset].instructionOffsetCount() > 0) { System.out.println(" has up till now been using information from instructions setting vars: "+varProducerValues[instructionOffset]); } if (stackProducerValues[instructionOffset].instructionOffsetCount() > 0) { System.out.println(" has up till now been using information from instructions setting stack: "+stackProducerValues[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 // instruction offset, after execution. if (evaluationCount == 0) { // First time we're passing by this instruction. if (variablesAfter[instructionOffset] == null) { // There's not even a context at this index yet. variablesAfter[instructionOffset] = new TracedVariables(variables); stacksAfter[instructionOffset] = new TracedStack(stack); } else { // Reuse the context objects at this index. variablesAfter[instructionOffset].initialize(variables); stacksAfter[instructionOffset].copy(stack); } } else { // Merge in the current context. variablesAfter[instructionOffset].generalize(variables, true); stacksAfter[instructionOffset].generalize(stack); } // Did the branch unit get called? if (branchUnit.wasCalled()) { // Accumulate the branch targets at this offset. branchTargetValues[instructionOffset] = branchTargetValues[instructionOffset] == null ? branchTargets : branchTargetValues[instructionOffset].generalize(branchTargets).instructionOffsetValue(); // Are there no branch targets at all? if (branchTargetCount == 0) { // Exit from this code block. break; } // Accumulate the branch origins at the branch target offsets. InstructionOffsetValue instructionOffsetValue = new InstructionOffsetValue(instructionOffset); for (int index = 0; index < branchTargetCount; index++) { int branchTarget = branchTargets.instructionOffset(index); branchOriginValues[branchTarget] = branchOriginValues[branchTarget] == null ? instructionOffsetValue: branchOriginValues[branchTarget].generalize(instructionOffsetValue).instructionOffsetValue(); } // Are there multiple branch targets? if (branchTargetCount > 1) { // Handle them recursively and exit from this code block. for (int index = 0; index < branchTargetCount; index++) { if (DEBUG) System.out.println("Alternative branch #"+index+" out of "+branchTargetCount+", from ["+instructionOffset+"] to ["+branchTargets.instructionOffset(index)+"]"); evaluateInstructionBlock(clazz, method, codeAttribute, new TracedVariables(variables), new TracedStack(stack), branchTargets.instructionOffset(index)); } break; } if (DEBUG) System.out.println("Definite branch from ["+instructionOffset+"] to ["+branchTargets.instructionOffset(0)+"]"); } // Just continue with the next instruction. instructionOffset = branchTargets.instructionOffset(0); // Clear the context of a subroutine before entering it, in order // to avoid context conflicts across different invocations. if (instruction.opcode == InstructionConstants.OP_JSR || instruction.opcode == InstructionConstants.OP_JSR_W) { // A subroutine has a single entry point and a single exit point, // so we can easily loop over its instructions. int subroutineEnd = branchTargetFinder.subroutineEnd(instructionOffset); if (DEBUG) System.out.println("Clearing context of subroutine from "+instructionOffset+" to "+subroutineEnd); for (int offset = instructionOffset; offset < subroutineEnd; offset++) { if (branchTargetFinder.isInstruction(offset)) { evaluationCounts[offset] = 0; } } evaluateInstructionBlock(clazz, method, codeAttribute, new TracedVariables(variables), new TracedStack(stack), instructionOffset); if (DEBUG) System.out.println("Evaluating exceptions of subroutine from "+instructionOffset+" to "+subroutineEnd); // Evaluate all relevant exception catch blocks once. codeAttribute.exceptionsAccept(clazz, method, instructionOffset, subroutineEnd, this); if (DEBUG) System.out.println("Ending subroutine from "+instructionOffset+" to "+subroutineEnd); break; } } if (DEBUG) System.out.println("Ending processing of instruction block starting at ["+startOffset+"]"); } // Small utility methods. /** * Initializes the data structures for the variables, stack, etc. */ private void initializeVariables(Clazz clazz, Method method, CodeAttribute codeAttribute, TracedVariables variables, TracedStack stack) { int codeLength = codeAttribute.u4codeLength; // Create new arrays for storing information at each instruction offset. if (variablesAfter.length < codeLength) { // Create new arrays. varProducerValues = new InstructionOffsetValue[codeLength]; stackProducerValues = new InstructionOffsetValue[codeLength]; branchOriginValues = new InstructionOffsetValue[codeLength]; branchTargetValues = new InstructionOffsetValue[codeLength]; variablesBefore = new TracedVariables[codeLength]; stacksBefore = new TracedStack[codeLength]; variablesAfter = new TracedVariables[codeLength]; stacksAfter = new TracedStack[codeLength]; generalizedContexts = new boolean[codeLength]; evaluationCounts = new int[codeLength]; initializedVariables = new int[codeLength]; // Reset the arrays. for (int index = 0; index < codeLength; index++) { varProducerValues[index] = InstructionOffsetValue.EMPTY_VALUE; stackProducerValues[index] = InstructionOffsetValue.EMPTY_VALUE; initializedVariables[index] = NONE; } } else { // Reset the arrays. for (int index = 0; index < codeLength; index++) { varProducerValues[index] = InstructionOffsetValue.EMPTY_VALUE; stackProducerValues[index] = InstructionOffsetValue.EMPTY_VALUE; branchOriginValues[index] = null; branchTargetValues[index] = null; generalizedContexts[index] = false; evaluationCounts[index] = 0; initializedVariables[index] = NONE; if (variablesBefore[index] != null) { variablesBefore[index].reset(codeAttribute.u2maxLocals); } if (stacksBefore[index] != null) { stacksBefore[index].reset(codeAttribute.u2maxStack); } if (variablesAfter[index] != null) { variablesAfter[index].reset(codeAttribute.u2maxLocals); } if (stacksAfter[index] != null) { stacksAfter[index].reset(codeAttribute.u2maxStack); } } } // Create the method parameters. TracedVariables parameters = new TracedVariables(codeAttribute.u2maxLocals); // Remember this instruction's offset with any stored value. Value storeValue = new InstructionOffsetValue(AT_METHOD_ENTRY); parameters.setProducerValue(storeValue); // Reset the trace value. InstructionOffsetValue traceValue = InstructionOffsetValue.EMPTY_VALUE; parameters.setCollectedProducerValue(traceValue); // Initialize the method parameters. invocationUnit.enterMethod(clazz, method, parameters); if (DEBUG) { System.out.println(" Params: "+parameters); } // Initialize the variables with the parameters. variables.initialize(parameters); // Set the store value of each parameter variable. InstructionOffsetValue atMethodEntry = new InstructionOffsetValue(AT_METHOD_ENTRY); for (int index = 0; index < parameters.size(); index++) { variables.setProducerValue(index, atMethodEntry); } } /** * Generalize the local variable frames of a block of instructions. */ private void generalizeVariables(int startOffset, int endOffset, TracedVariables generalizedVariables) { boolean first = true; for (int index = startOffset; index < endOffset; index++) { if (isTraced(index)) { TracedVariables tracedVariables = variablesBefore[index]; if (first) { // Initialize the variables with the first traced local // variable frame. generalizedVariables.initialize(tracedVariables); first = false; } else { // Generalize the variables with the traced local variable // frame. 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(tracedVariables, false); } } } // Just clear the variables if there aren't any traced instructions // in the block. if (first) { generalizedVariables.reset(generalizedVariables.size()); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -