📄 partialevaluator.java
字号:
/* $Id: PartialEvaluator.java,v 1.26 2004/12/11 16:35:23 eric Exp $ * * ProGuard -- shrinking, optimization, and obfuscation of Java class files. * * Copyright (c) 2002-2004 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.attribute.annotation.*;import proguard.classfile.editor.*;import proguard.classfile.instruction.*;import proguard.classfile.util.*;import proguard.classfile.visitor.*;import proguard.optimize.*;import proguard.optimize.evaluation.value.*;/** * This MemberInfoVisitor performs partial evaluation on the program methods * that it visits. * * @author Eric Lafortune */public class PartialEvaluatorimplements MemberInfoVisitor, AttrInfoVisitor, ExceptionInfoVisitor, InstructionVisitor, CpInfoVisitor{ //* private static final boolean DEBUG_RESULTS = false; private static final boolean DEBUG_ANALYSIS = false; private static final boolean DEBUG = false; /*/ private static boolean DEBUG_RESULTS = true; private static boolean DEBUG_ANALYSIS = true; private static boolean DEBUG = 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; private InstructionOffsetValue[] varTraceValues = new InstructionOffsetValue[INITIAL_CODE_LENGTH]; private InstructionOffsetValue[] stackTraceValues = 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 boolean[] initialization = new boolean[INITIAL_CODE_LENGTH]; private boolean[] isNecessary = new boolean[INITIAL_CODE_LENGTH]; private boolean evaluateExceptions; private TracedVariables parameters = new TracedVariables(INITIAL_VALUE_COUNT); private TracedVariables variables = new TracedVariables(INITIAL_VALUE_COUNT); private TracedStack stack = new TracedStack(INITIAL_VALUE_COUNT); private TracedBranchUnit branchUnit = new TracedBranchUnit(); private ClassFileCleaner classFileCleaner = new ClassFileCleaner(); private SideEffectInstructionChecker sideEffectInstructionChecker = new SideEffectInstructionChecker(true); private CodeAttrInfoEditor codeAttrInfoEditor = new CodeAttrInfoEditor(INITIAL_CODE_LENGTH); private boolean isInitializer; // Implementations for MemberInfoVisitor. public void visitProgramFieldInfo(ProgramClassFile programClassFile, ProgramFieldInfo programFieldInfo) {} public void visitProgramMethodInfo(ProgramClassFile programClassFile, ProgramMethodInfo programMethodInfo) {// DEBUG = DEBUG_ANALYSIS = DEBUG_RESULTS =// programClassFile.getName().equals("abc/Def") &&// programMethodInfo.getName(programClassFile).equals("abc"); // Initialize the parameters. boolean isStatic = (programMethodInfo.u2accessFlags & ClassConstants.INTERNAL_ACC_STATIC) != 0; // Count the number of parameters, taking into account their Categories. String parameterDescriptor = programMethodInfo.getDescriptor(programClassFile); int count = (isStatic ? 0 : 1) + ClassUtil.internalMethodParameterSize(parameterDescriptor); // Reuse the existing parameters object, ensuring the right size. parameters.reset(count); // Go over the parameters again. InternalTypeEnumeration internalTypeEnumeration = new InternalTypeEnumeration(parameterDescriptor); int index = 0; // Clear the store value of each parameter. parameters.setStoreValue(InstructionOffsetValueFactory.create()); // Put the caller's reference in parameter 0. if (!isStatic) { parameters.store(index++, ReferenceValueFactory.create(false)); } while (internalTypeEnumeration.hasMoreTypes()) { String type = internalTypeEnumeration.nextType(); // Get a generic corresponding value. Value value = ValueFactory.create(type); // Store the value in the parameter. parameters.store(index, value); // Increment the index according to the Category of the value. index += value.isCategory2() ? 2 : 1; } // Reset the return value. branchUnit.setTraceReturnValue(null); try { // Process the code. programMethodInfo.attributesAccept(programClassFile, this); } catch (RuntimeException ex) { // TODO: Remove this when the partial evaluator has stabilized. System.err.println("Unexpected error while optimizing after partial evaluation:"); System.err.println(" ClassFile = ["+programClassFile.getName()+"]"); System.err.println(" Method = ["+programMethodInfo.getName(programClassFile)+programMethodInfo.getDescriptor(programClassFile)+"]"); System.err.println("Not optimizing this method"); if (DEBUG) { throw ex; } } if (DEBUG) { Value returnValue = branchUnit.getTraceReturnValue(); if (returnValue != null) { System.out.println("Return value for method "+ ClassUtil.externalFullMethodDescription(programClassFile.getName(), 0, programMethodInfo.getName(programClassFile), programMethodInfo.getDescriptor(programClassFile))+ " -> ["+returnValue.toString()+"]"); System.out.println(); } } } public void visitLibraryFieldInfo(LibraryClassFile libraryClassFile, LibraryFieldInfo libraryFieldInfo) {} public void visitLibraryMethodInfo(LibraryClassFile libraryClassFile, LibraryMethodInfo libraryMethodInfo) {} // Implementations for AttrInfoVisitor. public void visitUnknownAttrInfo(ClassFile classFile, UnknownAttrInfo unknownAttrInfo) {} public void visitInnerClassesAttrInfo(ClassFile classFile, InnerClassesAttrInfo innerClassesAttrInfo) {} public void visitEnclosingMethodAttrInfo(ClassFile classFile, EnclosingMethodAttrInfo enclosingMethodAttrInfo) {} public void visitConstantValueAttrInfo(ClassFile classFile, FieldInfo fieldInfo, ConstantValueAttrInfo constantValueAttrInfo) {} public void visitExceptionsAttrInfo(ClassFile classFile, MethodInfo methodInfo, ExceptionsAttrInfo exceptionsAttrInfo) {} public void visitLineNumberTableAttrInfo(ClassFile classFile, MethodInfo methodInfo, CodeAttrInfo codeAttrInfo, LineNumberTableAttrInfo lineNumberTableAttrInfo) {} public void visitLocalVariableTableAttrInfo(ClassFile classFile, MethodInfo methodInfo, CodeAttrInfo codeAttrInfo, LocalVariableTableAttrInfo localVariableTableAttrInfo) {} public void visitLocalVariableTypeTableAttrInfo(ClassFile classFile, MethodInfo methodInfo, CodeAttrInfo codeAttrInfo, LocalVariableTypeTableAttrInfo localVariableTypeTableAttrInfo) {} public void visitSourceFileAttrInfo(ClassFile classFile, SourceFileAttrInfo sourceFileAttrInfo) {} public void visitSourceDirAttrInfo(ClassFile classFile, SourceDirAttrInfo sourceDirAttrInfo) {} public void visitDeprecatedAttrInfo(ClassFile classFile, DeprecatedAttrInfo deprecatedAttrInfo) {} public void visitSyntheticAttrInfo(ClassFile classFile, SyntheticAttrInfo syntheticAttrInfo) {} public void visitSignatureAttrInfo(ClassFile classFile, SignatureAttrInfo signatureAttrInfo) {} public void visitRuntimeVisibleAnnotationAttrInfo(ClassFile classFile, RuntimeVisibleAnnotationsAttrInfo runtimeVisibleAnnotationsAttrInfo) {} public void visitRuntimeInvisibleAnnotationAttrInfo(ClassFile classFile, RuntimeInvisibleAnnotationsAttrInfo runtimeInvisibleAnnotationsAttrInfo) {} public void visitRuntimeVisibleParameterAnnotationAttrInfo(ClassFile classFile, RuntimeVisibleParameterAnnotationsAttrInfo runtimeVisibleParameterAnnotationsAttrInfo) {} public void visitRuntimeInvisibleParameterAnnotationAttrInfo(ClassFile classFile, RuntimeInvisibleParameterAnnotationsAttrInfo runtimeInvisibleParameterAnnotationsAttrInfo) {} public void visitAnnotationDefaultAttrInfo(ClassFile classFile, AnnotationDefaultAttrInfo annotationDefaultAttrInfo) {} public void visitCodeAttrInfo(ClassFile classFile, MethodInfo methodInfo, CodeAttrInfo codeAttrInfo) { if (DEBUG_RESULTS) { System.out.println(); System.out.println("Class "+ClassUtil.externalClassName(classFile.getName())); System.out.println("Method "+ClassUtil.externalFullMethodDescription(classFile.getName(), 0, methodInfo.getName(classFile), methodInfo.getDescriptor(classFile))); System.out.println(" Params:"+parameters); } int codeLength = codeAttrInfo.u4codeLength; // Reset the code changes. codeAttrInfoEditor.reset(codeLength); if (DEBUG) { System.out.println(" Max locals = "+codeAttrInfo.u2maxLocals); System.out.println(" Max stack = "+codeAttrInfo.u2maxStack); } // Create new arrays for storing a stack and a set of variables at each // branch target. if (isNecessary.length < codeLength) { varTraceValues = new InstructionOffsetValue[codeLength]; stackTraceValues = new InstructionOffsetValue[codeLength]; branchOriginValues = new InstructionOffsetValue[codeLength]; branchTargetValues = new InstructionOffsetValue[codeLength]; vars = new TracedVariables[codeLength]; stacks = new TracedStack[codeLength]; evaluationCounts = new int[codeLength]; initialization = new boolean[codeLength]; isNecessary = new boolean[codeLength]; } else { for (int index = 0; index < codeLength; index++) { varTraceValues[index] = null; stackTraceValues[index] = null; branchOriginValues[index] = null; branchTargetValues[index] = null; evaluationCounts[index] = 0; initialization[index] = false; isNecessary[index] = false; if (vars[index] != null) { vars[index].reset(codeAttrInfo.u2maxLocals); } if (stacks[index] != null) { stacks[index].reset(codeAttrInfo.u2maxStack); } } } // Reuse the existing variables and stack objects, ensuring the right size. variables.reset(codeAttrInfo.u2maxLocals); stack.reset(codeAttrInfo.u2maxStack); // Initialize the local variables with the parameters. variables.initialize(parameters); // 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); // Clean up the visitor information in the exceptions right away. codeAttrInfo.exceptionsAccept(classFile, methodInfo, classFileCleaner); // Replace any instructions that can be simplified. if (DEBUG_ANALYSIS) System.out.println("Instruction simplification:"); codeAttrInfo.instructionsAccept(classFile, methodInfo, this); // Mark all essential instructions that have been encountered as used.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -