📄 partialevaluator.java
字号:
/* $Id: PartialEvaluator.java,v 1.37.2.1 2006/01/16 22:57:56 eric Exp $ * * ProGuard -- shrinking, optimization, and obfuscation of Java class files. * * Copyright (c) 2002-2006 Eric Lafortune (eric@graphics.cornell.edu) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */package proguard.optimize.evaluation;import proguard.classfile.*;import proguard.classfile.attribute.*;import proguard.classfile.instruction.*;import proguard.classfile.util.ClassUtil;import proguard.optimize.evaluation.value.*;import proguard.optimize.peephole.BranchTargetFinder;/** * This class performs partial evaluation. * * @author Eric Lafortune */public class PartialEvaluatorimplements ExceptionInfoVisitor, InstructionVisitor{ //* private static final boolean DEBUG = false; private static final boolean DEBUG_RESULTS = false; /*/ private static boolean DEBUG = true; private static boolean DEBUG_RESULTS = true; //*/ private static final int INITIAL_CODE_LENGTH = 1024; private static final int INITIAL_VALUE_COUNT = 32; //private static final int MAXIMUM_EVALUATION_COUNT = 100; public static final int AT_METHOD_ENTRY = -1; public static final int AT_CATCH_ENTRY = -1; public static final int NONE = -1; private BranchTargetFinder branchTargetFinder = new BranchTargetFinder(1024); private InstructionOffsetValue[] varProducerValues = new InstructionOffsetValue[INITIAL_CODE_LENGTH]; private InstructionOffsetValue[] stackProducerValues = new InstructionOffsetValue[INITIAL_CODE_LENGTH]; private InstructionOffsetValue[] unusedProducerValues = new InstructionOffsetValue[INITIAL_CODE_LENGTH]; private InstructionOffsetValue[] branchOriginValues = new InstructionOffsetValue[INITIAL_CODE_LENGTH]; private InstructionOffsetValue[] branchTargetValues = new InstructionOffsetValue[INITIAL_CODE_LENGTH]; private TracedVariables[] vars = new TracedVariables[INITIAL_CODE_LENGTH]; private TracedStack[] stacks = new TracedStack[INITIAL_CODE_LENGTH]; private int[] evaluationCounts = new int[INITIAL_CODE_LENGTH]; private int[] initializedVariables = new int[INITIAL_CODE_LENGTH]; private boolean evaluateExceptions; private TracedVariables variables = new TracedVariables(INITIAL_VALUE_COUNT); private TracedStack stack = new TracedStack(INITIAL_VALUE_COUNT); private TracedBranchUnit branchUnit = new TracedBranchUnit(); /** * Performs partial evaluation of the given method with the given parameters. * @param classFile the method's class file. * @param methodInfo the method's header. * @param codeAttrInfo the method's code. * @param parameters the method parameters. * @return the partial result. */ public Value evaluate(ClassFile classFile, MethodInfo methodInfo, CodeAttrInfo codeAttrInfo, Variables parameters) { // Initialize the reusable arrays and variables. initializeVariables(codeAttrInfo, parameters); // Find all instruction offsets,... codeAttrInfo.accept(classFile, methodInfo, branchTargetFinder); // Evaluate the instructions, starting at the entry point. if (DEBUG) System.out.println("Partial evaluation: "); evaluateInstructionBlock(classFile, methodInfo, codeAttrInfo, variables, stack, branchUnit, 0); // Evaluate the exception catch blocks, until their entry variables // have stabilized. do { // Reset the flag to stop evaluating. evaluateExceptions = false; // Evaluate all relevant exception catch blocks once. codeAttrInfo.exceptionsAccept(classFile, methodInfo, this); } while (evaluateExceptions); if (DEBUG_RESULTS) { System.out.println("Evaluation results:"); int codeLength = codeAttrInfo.u4codeLength; int offset = 0; do { Instruction instruction = InstructionFactory.create(codeAttrInfo.code, offset); System.out.println(instruction.toString(offset)); if (isTraced(offset)) { InstructionOffsetValue varProducerOffsets = varProducerOffsets(offset); if (varProducerOffsets.instructionOffsetCount() > 0) { System.out.println(" has overall been using information from instructions setting vars: "+varProducerOffsets); } InstructionOffsetValue stackProducerOffsets = stackProducerOffsets(offset); if (stackProducerOffsets.instructionOffsetCount() > 0) { System.out.println(" has overall been using information from instructions setting stack: "+stackProducerOffsets); } InstructionOffsetValue unusedProducerOffsets = unusedProducerOffsets(offset); if (unusedProducerOffsets.instructionOffsetCount() > 0) { System.out.println(" no longer needs information from instructions setting stack: "+unusedProducerOffsets); } InstructionOffsetValue branchTargets = branchTargets(offset); if (branchTargets != null) { System.out.println(" has overall been branching to "+branchTargets); } System.out.println(" Vars: "+vars[offset]); System.out.println(" Stack: "+stacks[offset]); } offset += instruction.length(offset); } while (offset < codeLength); } if (DEBUG) { Value returnValue = branchUnit.getTraceReturnValue(); if (returnValue != null) { System.out.println("Return value for method "+ ClassUtil.externalFullMethodDescription(classFile.getName(), 0, methodInfo.getName(classFile), methodInfo.getDescriptor(classFile))+ " -> ["+returnValue.toString()+"]"); System.out.println(); } } // Mark special dependencies of constructors. codeAttrInfo.instructionsAccept(classFile, methodInfo, this); return branchUnit.getTraceReturnValue(); } /** * Returns whether a block of instructions is ever used. */ public boolean isTraced(int startOffset, int endOffset) { for (int index = startOffset; index < endOffset; index++) { if (isTraced(index)) { return true; } } return false; } /** * Returns whether the instruction at the given offset has ever been * executed during the partial evaluation. */ public boolean isTraced(int instructionOffset) { return evaluationCounts[instructionOffset] > 0; } /** * Returns the variable value at the given instruction offset and variable * index. */ public Value variableValue(int instructionOffset, int variableIndex) { return vars[instructionOffset].load(variableIndex); } /** * Returns the instruction offsets that set the variable value at at the given * instruction offset and variable index. */ public InstructionOffsetValue variableProducerOffsets(int instructionOffset, int variableIndex) { return vars[instructionOffset].getStoredTraceValue(variableIndex).instructionOffsetValue(); } /** * Returns the instruction offsets that set the variable that is being * used at the given instruction offset. */ public InstructionOffsetValue varProducerOffsets(int instructionOffset) { return varProducerValues[instructionOffset]; } /** * Returns the stack value at the given instruction offset and stack index. */ public Value stackTopValue(int instructionOffset, int stackIndex) { return stacks[instructionOffset].getTop(stackIndex); } /** * Returns the instruction offsets that set the stack value at at the given * instruction offset and stack index. */ public InstructionOffsetValue stackTopProducerOffsets(int instructionOffset, int stackIndex) { return stacks[instructionOffset].getTopProducerValue(stackIndex).instructionOffsetValue(); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -