diff options
Diffstat (limited to 'src/proguard/optimize/Optimizer.java')
-rw-r--r-- | src/proguard/optimize/Optimizer.java | 1087 |
1 files changed, 0 insertions, 1087 deletions
diff --git a/src/proguard/optimize/Optimizer.java b/src/proguard/optimize/Optimizer.java deleted file mode 100644 index 20f4083..0000000 --- a/src/proguard/optimize/Optimizer.java +++ /dev/null @@ -1,1087 +0,0 @@ -/* - * ProGuard -- shrinking, optimization, obfuscation, and preverification - * of Java bytecode. - * - * Copyright (c) 2002-2014 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; - -import proguard.*; -import proguard.classfile.*; -import proguard.classfile.attribute.visitor.*; -import proguard.classfile.constant.visitor.*; -import proguard.classfile.editor.*; -import proguard.classfile.instruction.visitor.*; -import proguard.classfile.util.MethodLinker; -import proguard.classfile.visitor.*; -import proguard.evaluation.InvocationUnit; -import proguard.evaluation.value.*; -import proguard.optimize.evaluation.*; -import proguard.optimize.info.*; -import proguard.optimize.peephole.*; -import proguard.util.*; - -import java.io.IOException; -import java.util.*; - -/** - * This class optimizes class pools according to a given configuration. - * - * @author Eric Lafortune - */ -public class Optimizer -{ - private static final String CLASS_MARKING_FINAL = "class/marking/final"; - private static final String CLASS_UNBOXING_ENUM = "class/unboxing/enum"; - private static final String CLASS_MERGING_VERTICAL = "class/merging/vertical"; - private static final String CLASS_MERGING_HORIZONTAL = "class/merging/horizontal"; - private static final String FIELD_REMOVAL_WRITEONLY = "field/removal/writeonly"; - private static final String FIELD_MARKING_PRIVATE = "field/marking/private"; - private static final String FIELD_PROPAGATION_VALUE = "field/propagation/value"; - private static final String METHOD_MARKING_PRIVATE = "method/marking/private"; - private static final String METHOD_MARKING_STATIC = "method/marking/static"; - private static final String METHOD_MARKING_FINAL = "method/marking/final"; - private static final String METHOD_REMOVAL_PARAMETER = "method/removal/parameter"; - private static final String METHOD_PROPAGATION_PARAMETER = "method/propagation/parameter"; - private static final String METHOD_PROPAGATION_RETURNVALUE = "method/propagation/returnvalue"; - private static final String METHOD_INLINING_SHORT = "method/inlining/short"; - private static final String METHOD_INLINING_UNIQUE = "method/inlining/unique"; - private static final String METHOD_INLINING_TAILRECURSION = "method/inlining/tailrecursion"; - private static final String CODE_MERGING = "code/merging"; - private static final String CODE_SIMPLIFICATION_VARIABLE = "code/simplification/variable"; - private static final String CODE_SIMPLIFICATION_ARITHMETIC = "code/simplification/arithmetic"; - private static final String CODE_SIMPLIFICATION_CAST = "code/simplification/cast"; - private static final String CODE_SIMPLIFICATION_FIELD = "code/simplification/field"; - private static final String CODE_SIMPLIFICATION_BRANCH = "code/simplification/branch"; - private static final String CODE_SIMPLIFICATION_STRING = "code/simplification/string"; - private static final String CODE_SIMPLIFICATION_ADVANCED = "code/simplification/advanced"; - private static final String CODE_REMOVAL_ADVANCED = "code/removal/advanced"; - private static final String CODE_REMOVAL_SIMPLE = "code/removal/simple"; - private static final String CODE_REMOVAL_VARIABLE = "code/removal/variable"; - private static final String CODE_REMOVAL_EXCEPTION = "code/removal/exception"; - private static final String CODE_ALLOCATION_VARIABLE = "code/allocation/variable"; - - - public static final String[] OPTIMIZATION_NAMES = new String[] - { - CLASS_MARKING_FINAL, - CLASS_MERGING_VERTICAL, - CLASS_MERGING_HORIZONTAL, - FIELD_REMOVAL_WRITEONLY, - FIELD_MARKING_PRIVATE, - FIELD_PROPAGATION_VALUE, - METHOD_MARKING_PRIVATE, - METHOD_MARKING_STATIC, - METHOD_MARKING_FINAL, - METHOD_REMOVAL_PARAMETER, - METHOD_PROPAGATION_PARAMETER, - METHOD_PROPAGATION_RETURNVALUE, - METHOD_INLINING_SHORT, - METHOD_INLINING_UNIQUE, - METHOD_INLINING_TAILRECURSION, - CODE_MERGING, - CODE_SIMPLIFICATION_VARIABLE, - CODE_SIMPLIFICATION_ARITHMETIC, - CODE_SIMPLIFICATION_CAST, - CODE_SIMPLIFICATION_FIELD, - CODE_SIMPLIFICATION_BRANCH, - CODE_SIMPLIFICATION_STRING, - CODE_SIMPLIFICATION_ADVANCED, - CODE_REMOVAL_ADVANCED, - CODE_REMOVAL_SIMPLE, - CODE_REMOVAL_VARIABLE, - CODE_REMOVAL_EXCEPTION, - CODE_ALLOCATION_VARIABLE, - }; - - - private final Configuration configuration; - - - /** - * Creates a new Optimizer. - */ - public Optimizer(Configuration configuration) - { - this.configuration = configuration; - } - - - /** - * Performs optimization of the given program class pool. - */ - public boolean execute(ClassPool programClassPool, - ClassPool libraryClassPool) throws IOException - { - // Check if we have at least some keep commands. - if (configuration.keep == null && - configuration.applyMapping == null && - configuration.printMapping == null) - { - throw new IOException("You have to specify '-keep' options for the optimization step."); - } - - // Create a matcher for filtering optimizations. - StringMatcher filter = configuration.optimizations != null ? - new ListParser(new NameParser()).parse(configuration.optimizations) : - new ConstantMatcher(true); - - boolean classMarkingFinal = filter.matches(CLASS_MARKING_FINAL); - boolean classUnboxingEnum = filter.matches(CLASS_UNBOXING_ENUM); - boolean classMergingVertical = filter.matches(CLASS_MERGING_VERTICAL); - boolean classMergingHorizontal = filter.matches(CLASS_MERGING_HORIZONTAL); - boolean fieldRemovalWriteonly = filter.matches(FIELD_REMOVAL_WRITEONLY); - boolean fieldMarkingPrivate = filter.matches(FIELD_MARKING_PRIVATE); - boolean fieldPropagationValue = filter.matches(FIELD_PROPAGATION_VALUE); - boolean methodMarkingPrivate = filter.matches(METHOD_MARKING_PRIVATE); - boolean methodMarkingStatic = filter.matches(METHOD_MARKING_STATIC); - boolean methodMarkingFinal = filter.matches(METHOD_MARKING_FINAL); - boolean methodRemovalParameter = filter.matches(METHOD_REMOVAL_PARAMETER); - boolean methodPropagationParameter = filter.matches(METHOD_PROPAGATION_PARAMETER); - boolean methodPropagationReturnvalue = filter.matches(METHOD_PROPAGATION_RETURNVALUE); - boolean methodInliningShort = filter.matches(METHOD_INLINING_SHORT); - boolean methodInliningUnique = filter.matches(METHOD_INLINING_UNIQUE); - boolean methodInliningTailrecursion = filter.matches(METHOD_INLINING_TAILRECURSION); - boolean codeMerging = filter.matches(CODE_MERGING); - boolean codeSimplificationVariable = filter.matches(CODE_SIMPLIFICATION_VARIABLE); - boolean codeSimplificationArithmetic = filter.matches(CODE_SIMPLIFICATION_ARITHMETIC); - boolean codeSimplificationCast = filter.matches(CODE_SIMPLIFICATION_CAST); - boolean codeSimplificationField = filter.matches(CODE_SIMPLIFICATION_FIELD); - boolean codeSimplificationBranch = filter.matches(CODE_SIMPLIFICATION_BRANCH); - boolean codeSimplificationString = filter.matches(CODE_SIMPLIFICATION_STRING); - boolean codeSimplificationAdvanced = filter.matches(CODE_SIMPLIFICATION_ADVANCED); - boolean codeRemovalAdvanced = filter.matches(CODE_REMOVAL_ADVANCED); - boolean codeRemovalSimple = filter.matches(CODE_REMOVAL_SIMPLE); - boolean codeRemovalVariable = filter.matches(CODE_REMOVAL_VARIABLE); - boolean codeRemovalException = filter.matches(CODE_REMOVAL_EXCEPTION); - boolean codeAllocationVariable = filter.matches(CODE_ALLOCATION_VARIABLE); - - // Create counters to count the numbers of optimizations. - ClassCounter classMarkingFinalCounter = new ClassCounter(); - ClassCounter classUnboxingEnumCounter = new ClassCounter(); - ClassCounter classMergingVerticalCounter = new ClassCounter(); - ClassCounter classMergingHorizontalCounter = new ClassCounter(); - MemberCounter fieldRemovalWriteonlyCounter = new MemberCounter(); - MemberCounter fieldMarkingPrivateCounter = new MemberCounter(); - MemberCounter fieldPropagationValueCounter = new MemberCounter(); - MemberCounter methodMarkingPrivateCounter = new MemberCounter(); - MemberCounter methodMarkingStaticCounter = new MemberCounter(); - MemberCounter methodMarkingFinalCounter = new MemberCounter(); - MemberCounter methodRemovalParameterCounter = new MemberCounter(); - MemberCounter methodPropagationParameterCounter = new MemberCounter(); - MemberCounter methodPropagationReturnvalueCounter = new MemberCounter(); - InstructionCounter methodInliningShortCounter = new InstructionCounter(); - InstructionCounter methodInliningUniqueCounter = new InstructionCounter(); - InstructionCounter methodInliningTailrecursionCounter = new InstructionCounter(); - InstructionCounter codeMergingCounter = new InstructionCounter(); - InstructionCounter codeSimplificationVariableCounter = new InstructionCounter(); - InstructionCounter codeSimplificationArithmeticCounter = new InstructionCounter(); - InstructionCounter codeSimplificationCastCounter = new InstructionCounter(); - InstructionCounter codeSimplificationFieldCounter = new InstructionCounter(); - InstructionCounter codeSimplificationBranchCounter = new InstructionCounter(); - InstructionCounter codeSimplificationStringCounter = new InstructionCounter(); - InstructionCounter codeSimplificationAdvancedCounter = new InstructionCounter(); - InstructionCounter deletedCounter = new InstructionCounter(); - InstructionCounter addedCounter = new InstructionCounter(); - MemberCounter codeRemovalVariableCounter = new MemberCounter(); - ExceptionCounter codeRemovalExceptionCounter = new ExceptionCounter(); - MemberCounter codeAllocationVariableCounter = new MemberCounter(); - MemberCounter initializerFixCounter1 = new MemberCounter(); - MemberCounter initializerFixCounter2 = new MemberCounter(); - - // Some optimizations are required by other optimizations. - codeSimplificationAdvanced = - codeSimplificationAdvanced || - fieldPropagationValue || - methodPropagationParameter || - methodPropagationReturnvalue; - - codeRemovalAdvanced = - codeRemovalAdvanced || - fieldRemovalWriteonly || - methodMarkingStatic || - methodRemovalParameter; - - codeRemovalSimple = - codeRemovalSimple || - codeSimplificationBranch; - - codeRemovalException = - codeRemovalException || - codeRemovalAdvanced || - codeRemovalSimple; - - // Clean up any old visitor info. - programClassPool.classesAccept(new ClassCleaner()); - libraryClassPool.classesAccept(new ClassCleaner()); - - // Link all methods that should get the same optimization info. - programClassPool.classesAccept(new BottomClassFilter( - new MethodLinker())); - libraryClassPool.classesAccept(new BottomClassFilter( - new MethodLinker())); - - // Create a visitor for marking the seeds. - KeepMarker keepMarker = new KeepMarker(); - ClassPoolVisitor classPoolvisitor = - ClassSpecificationVisitorFactory.createClassPoolVisitor(configuration.keep, - keepMarker, - keepMarker, - false, - true, - false); - // Mark the seeds. - programClassPool.accept(classPoolvisitor); - libraryClassPool.accept(classPoolvisitor); - - // All library classes and library class members remain unchanged. - libraryClassPool.classesAccept(keepMarker); - libraryClassPool.classesAccept(new AllMemberVisitor(keepMarker)); - - // We also keep all classes that are involved in .class constructs. - // We're not looking at enum classes though, so they can be simplified. - programClassPool.classesAccept( - new ClassAccessFilter(0, ClassConstants.ACC_ENUM, - new AllMethodVisitor( - new AllAttributeVisitor( - new AllInstructionVisitor( - new DotClassClassVisitor(keepMarker)))))); - - // We also keep all classes that are accessed dynamically. - programClassPool.classesAccept( - new AllConstantVisitor( - new ConstantTagFilter(ClassConstants.CONSTANT_String, - new ReferencedClassVisitor(keepMarker)))); - - // We also keep all class members that are accessed dynamically. - programClassPool.classesAccept( - new AllConstantVisitor( - new ConstantTagFilter(ClassConstants.CONSTANT_String, - new ReferencedMemberVisitor(keepMarker)))); - - // We also keep all bootstrap method signatures. - programClassPool.classesAccept( - new ClassVersionFilter(ClassConstants.CLASS_VERSION_1_7, - new AllAttributeVisitor( - new AttributeNameFilter(ClassConstants.ATTR_BootstrapMethods, - new AllBootstrapMethodInfoVisitor( - new BootstrapMethodHandleTraveler( - new MethodrefTraveler( - new ReferencedMemberVisitor(keepMarker)))))))); - - // We also keep all bootstrap method arguments that point to methods. - // These arguments are typically the method handles for - // java.lang.invoke.LambdaMetafactory#metafactory, which provides the - // implementations for closures. - programClassPool.classesAccept( - new ClassVersionFilter(ClassConstants.CLASS_VERSION_1_7, - new AllAttributeVisitor( - new AttributeNameFilter(ClassConstants.ATTR_BootstrapMethods, - new AllBootstrapMethodInfoVisitor( - new BootstrapMethodArgumentVisitor( - new MethodrefTraveler( - new ReferencedMemberVisitor(keepMarker)))))))); - - // We also keep all classes (and their methods) returned by dynamic - // method invocations. They may return dynamic implementations of - // interfaces that otherwise appear unused. - programClassPool.classesAccept( - new ClassVersionFilter(ClassConstants.CLASS_VERSION_1_7, - new AllConstantVisitor( - new DynamicReturnedClassVisitor( - new MultiClassVisitor(new ClassVisitor[] - { - keepMarker, - new AllMemberVisitor(keepMarker) - }))))); - - // Attach some optimization info to all classes and class members, so - // it can be filled out later. - programClassPool.classesAccept(new ClassOptimizationInfoSetter()); - - programClassPool.classesAccept(new AllMemberVisitor( - new MemberOptimizationInfoSetter())); - - if (configuration.assumeNoSideEffects != null) - { - // Create a visitor for marking methods that don't have any side effects. - NoSideEffectMethodMarker noSideEffectMethodMarker = new NoSideEffectMethodMarker(); - ClassPoolVisitor noClassPoolvisitor = - ClassSpecificationVisitorFactory.createClassPoolVisitor(configuration.assumeNoSideEffects, - null, - noSideEffectMethodMarker); - - // Mark the seeds. - programClassPool.accept(noClassPoolvisitor); - libraryClassPool.accept(noClassPoolvisitor); - } - - if (classMarkingFinal) - { - // Make classes final, whereever possible. - programClassPool.classesAccept( - new ClassFinalizer(classMarkingFinalCounter)); - } - - if (methodMarkingFinal) - { - // Make methods final, whereever possible. - programClassPool.classesAccept( - new ClassAccessFilter(0, ClassConstants.ACC_INTERFACE, - new AllMethodVisitor( - new MethodFinalizer(methodMarkingFinalCounter)))); - } - - if (fieldRemovalWriteonly) - { - // Mark all fields that are write-only. - programClassPool.classesAccept( - new AllMethodVisitor( - new AllAttributeVisitor( - new AllInstructionVisitor( - new ReadWriteFieldMarker())))); - - // Count the write-only fields. - programClassPool.classesAccept( - new AllFieldVisitor( - new WriteOnlyFieldFilter(fieldRemovalWriteonlyCounter))); - } - else - { - // Mark all fields as read/write. - programClassPool.classesAccept( - new AllFieldVisitor( - new ReadWriteFieldMarker())); - } - - if (classUnboxingEnum) - { - ClassCounter counter = new ClassCounter(); - - // Mark all final enums that qualify as simple enums. - programClassPool.classesAccept( - new ClassAccessFilter(ClassConstants.ACC_FINAL | - ClassConstants.ACC_ENUM, 0, - new SimpleEnumClassChecker())); - - // Count the preliminary number of simple enums. - programClassPool.classesAccept( - new SimpleEnumFilter(counter)); - - // Only continue checking simple enums if there are any candidates. - if (counter.getCount() > 0) - { - // Unmark all simple enums that are explicitly used as objects. - programClassPool.classesAccept( - new SimpleEnumUseChecker()); - - // Count the definitive number of simple enums. - programClassPool.classesAccept( - new SimpleEnumFilter(classUnboxingEnumCounter)); - - // Only start handling simple enums if there are any. - if (classUnboxingEnumCounter.getCount() > 0) - { - // Simplify the use of the enum classes in code. - programClassPool.classesAccept( - new AllMethodVisitor( - new AllAttributeVisitor( - new SimpleEnumUseSimplifier()))); - - // Simplify the static initializers of simple enum classes. - programClassPool.classesAccept( - new SimpleEnumFilter( - new SimpleEnumClassSimplifier())); - - // Simplify the use of the enum classes in descriptors. - programClassPool.classesAccept( - new SimpleEnumDescriptorSimplifier()); - - // Update references to class members with simple enum classes. - programClassPool.classesAccept(new MemberReferenceFixer()); - } - } - } - - // Mark all used parameters, including the 'this' parameters. - programClassPool.classesAccept( - new AllMethodVisitor( - new OptimizationInfoMemberFilter( - new ParameterUsageMarker(!methodMarkingStatic, - !methodRemovalParameter)))); - - // Mark all classes that have static initializers. - programClassPool.classesAccept(new StaticInitializerContainingClassMarker()); - - // Mark all methods that have side effects. - programClassPool.accept(new SideEffectMethodMarker()); - -// System.out.println("Optimizer.execute: before evaluation simplification"); -// programClassPool.classAccept("abc/Def", new NamedMethodVisitor("abc", null, new ClassPrinter())); - - // Perform partial evaluation for filling out fields, method parameters, - // and method return values, so they can be propagated. - if (fieldPropagationValue || - methodPropagationParameter || - methodPropagationReturnvalue) - { - // We'll create values to be stored with fields, method parameters, - // and return values. - ValueFactory valueFactory = new ParticularValueFactory(); - ValueFactory detailedValueFactory = new DetailedValueFactory(); - - InvocationUnit storingInvocationUnit = - new StoringInvocationUnit(valueFactory, - fieldPropagationValue, - methodPropagationParameter, - methodPropagationReturnvalue); - - // Evaluate synthetic classes in more detail, notably to propagate - // the arrays of the classes generated for enum switch statements. - programClassPool.classesAccept( - new ClassAccessFilter(ClassConstants.ACC_SYNTHETIC, 0, - new AllMethodVisitor( - new AllAttributeVisitor( - new PartialEvaluator(detailedValueFactory, storingInvocationUnit, false))))); - - // Evaluate non-synthetic classes. - programClassPool.classesAccept( - new ClassAccessFilter(0, ClassConstants.ACC_SYNTHETIC, - new AllMethodVisitor( - new AllAttributeVisitor( - new PartialEvaluator(valueFactory, storingInvocationUnit, false))))); - - if (fieldPropagationValue) - { - // Count the constant fields. - programClassPool.classesAccept( - new AllFieldVisitor( - new ConstantMemberFilter(fieldPropagationValueCounter))); - } - - if (methodPropagationParameter) - { - // Count the constant method parameters. - programClassPool.classesAccept( - new AllMethodVisitor( - new ConstantParameterFilter(methodPropagationParameterCounter))); - } - - if (methodPropagationReturnvalue) - { - // Count the constant method return values. - programClassPool.classesAccept( - new AllMethodVisitor( - new ConstantMemberFilter(methodPropagationReturnvalueCounter))); - } - - if (classUnboxingEnumCounter.getCount() > 0) - { - // Propagate the simple enum constant counts. - programClassPool.classesAccept( - new SimpleEnumFilter( - new SimpleEnumArrayPropagator())); - } - - if (codeSimplificationAdvanced) - { - // Fill out constants into the arrays of synthetic classes, - // notably the arrays of the classes generated for enum switch - // statements. - InvocationUnit loadingInvocationUnit = - new LoadingInvocationUnit(valueFactory, - fieldPropagationValue, - methodPropagationParameter, - methodPropagationReturnvalue); - - programClassPool.classesAccept( - new ClassAccessFilter(ClassConstants.ACC_SYNTHETIC, 0, - new AllMethodVisitor( - new AllAttributeVisitor( - new PartialEvaluator(valueFactory, loadingInvocationUnit, false))))); - } - } - - // Perform partial evaluation again, now loading any previously stored - // values for fields, method parameters, and method return values. - ValueFactory valueFactory = new IdentifiedValueFactory(); - - InvocationUnit loadingInvocationUnit = - new LoadingInvocationUnit(valueFactory, - fieldPropagationValue, - methodPropagationParameter, - methodPropagationReturnvalue); - - if (codeSimplificationAdvanced) - { - // Simplify based on partial evaluation, propagating constant - // field values, method parameter values, and return values. - programClassPool.classesAccept( - new AllMethodVisitor( - new AllAttributeVisitor( - new EvaluationSimplifier( - new PartialEvaluator(valueFactory, loadingInvocationUnit, false), - codeSimplificationAdvancedCounter)))); - } - - if (codeRemovalAdvanced) - { - // Remove code based on partial evaluation, also removing unused - // parameters from method invocations, and making methods static - // if possible. - programClassPool.classesAccept( - new AllMethodVisitor( - new AllAttributeVisitor( - new EvaluationShrinker( - new PartialEvaluator(valueFactory, loadingInvocationUnit, !codeSimplificationAdvanced), - deletedCounter, addedCounter)))); - } - - if (methodRemovalParameter) - { - // Shrink the parameters in the method descriptors. - programClassPool.classesAccept( - new AllMethodVisitor( - new OptimizationInfoMemberFilter( - new MethodDescriptorShrinker()))); - } - - if (methodMarkingStatic) - { - // Make all non-static methods that don't require the 'this' - // parameter static. - programClassPool.classesAccept( - new AllMethodVisitor( - new OptimizationInfoMemberFilter( - new MemberAccessFilter(0, ClassConstants.ACC_STATIC, - new MethodStaticizer(methodMarkingStaticCounter))))); - } - - if (methodRemovalParameter) - { - // Fix all references to class members. - // This operation also updates the stack sizes. - programClassPool.classesAccept( - new MemberReferenceFixer()); - - // Remove unused bootstrap method arguments. - programClassPool.classesAccept( - new AllAttributeVisitor( - new AllBootstrapMethodInfoVisitor( - new BootstrapMethodArgumentShrinker()))); - } - - if (methodRemovalParameter || - methodMarkingPrivate || - methodMarkingStatic) - { - // Remove all unused parameters from the byte code, shifting all - // remaining variables. - // This operation also updates the local variable frame sizes. - programClassPool.classesAccept( - new AllMethodVisitor( - new AllAttributeVisitor( - new ParameterShrinker(methodRemovalParameterCounter)))); - } - else if (codeRemovalAdvanced) - { - // Just update the local variable frame sizes. - programClassPool.classesAccept( - new AllMethodVisitor( - new AllAttributeVisitor( - new StackSizeUpdater()))); - } - - if (methodRemovalParameter && - methodRemovalParameterCounter.getCount() > 0) - { - // Tweak the descriptors of duplicate initializers, due to removed - // method parameters. - programClassPool.classesAccept( - new AllMethodVisitor( - new DuplicateInitializerFixer(initializerFixCounter1))); - - if (initializerFixCounter1.getCount() > 0) - { - // Fix all invocations of tweaked initializers. - programClassPool.classesAccept( - new AllMethodVisitor( - new AllAttributeVisitor( - new DuplicateInitializerInvocationFixer(addedCounter)))); - - // Fix all references to tweaked initializers. - programClassPool.classesAccept(new MemberReferenceFixer()); - } - } - - //// Specializing the class member descriptors seems to increase the - //// class file size, on average. - //// Specialize all class member descriptors. - //programClassPool.classesAccept(new AllMemberVisitor( - // new OptimizationInfoMemberFilter( - // new MemberDescriptorSpecializer()))); - // - //// Fix all references to classes, for MemberDescriptorSpecializer. - //programClassPool.classesAccept(new AllMemberVisitor( - // new OptimizationInfoMemberFilter( - // new ClassReferenceFixer(true)))); - - // Mark all classes with package visible members. - // Mark all exception catches of methods. - // Count all method invocations. - // Mark super invocations and other access of methods. - programClassPool.classesAccept( - new MultiClassVisitor( - new ClassVisitor[] - { - new PackageVisibleMemberContainingClassMarker(), - new AllConstantVisitor( - new PackageVisibleMemberInvokingClassMarker()), - new AllMethodVisitor( - new MultiMemberVisitor( - new MemberVisitor[] - { - new AllAttributeVisitor( - new MultiAttributeVisitor( - new AttributeVisitor[] - { - new CatchExceptionMarker(), - new AllInstructionVisitor( - new MultiInstructionVisitor( - new InstructionVisitor[] - { - new InstantiationClassMarker(), - new InstanceofClassMarker(), - new DotClassMarker(), - new MethodInvocationMarker(), - new SuperInvocationMarker(), - new DynamicInvocationMarker(), - new BackwardBranchMarker(), - new AccessMethodMarker(), - })), - new AllExceptionInfoVisitor( - new ExceptionHandlerConstantVisitor( - new ReferencedClassVisitor( - new CaughtClassMarker()))), - })), - })), - })); - - if (classMergingVertical) - { - // Merge subclasses up into their superclasses or - // merge interfaces down into their implementing classes. - programClassPool.classesAccept( - new VerticalClassMerger(configuration.allowAccessModification, - configuration.mergeInterfacesAggressively, - classMergingVerticalCounter)); - } - - if (classMergingHorizontal) - { - // Merge classes into their sibling classes. - programClassPool.classesAccept( - new HorizontalClassMerger(configuration.allowAccessModification, - configuration.mergeInterfacesAggressively, - classMergingHorizontalCounter)); - } - - if (classMergingVerticalCounter .getCount() > 0 || - classMergingHorizontalCounter.getCount() > 0) - { - // Clean up inner class attributes to avoid loops. - programClassPool.classesAccept(new RetargetedInnerClassAttributeRemover()); - - // Update references to merged classes. - programClassPool.classesAccept(new TargetClassChanger()); - programClassPool.classesAccept(new ClassReferenceFixer(true)); - programClassPool.classesAccept(new MemberReferenceFixer()); - - if (configuration.allowAccessModification) - { - // Fix the access flags of referenced merged classes and their - // class members. - programClassPool.classesAccept( - new AccessFixer()); - } - - // Fix the access flags of the inner classes information. - programClassPool.classesAccept( - new AllAttributeVisitor( - new AllInnerClassesInfoVisitor( - new InnerClassesAccessFixer()))); - - // Tweak the descriptors of duplicate initializers, due to merged - // parameter classes. - programClassPool.classesAccept( - new AllMethodVisitor( - new DuplicateInitializerFixer(initializerFixCounter2))); - - if (initializerFixCounter2.getCount() > 0) - { - // Fix all invocations of tweaked initializers. - programClassPool.classesAccept( - new AllMethodVisitor( - new AllAttributeVisitor( - new DuplicateInitializerInvocationFixer(addedCounter)))); - - // Fix all references to tweaked initializers. - programClassPool.classesAccept(new MemberReferenceFixer()); - } - } - - if (methodInliningUnique) - { - // Inline methods that are only invoked once. - programClassPool.classesAccept( - new AllMethodVisitor( - new AllAttributeVisitor( - new MethodInliner(configuration.microEdition, - configuration.allowAccessModification, - true, - methodInliningUniqueCounter)))); - } - - if (methodInliningShort) - { - // Inline short methods. - programClassPool.classesAccept( - new AllMethodVisitor( - new AllAttributeVisitor( - new MethodInliner(configuration.microEdition, - configuration.allowAccessModification, - false, - methodInliningShortCounter)))); - } - - if (methodInliningTailrecursion) - { - // Simplify tail recursion calls. - programClassPool.classesAccept( - new AllMethodVisitor( - new AllAttributeVisitor( - new TailRecursionSimplifier(methodInliningTailrecursionCounter)))); - } - - if (fieldMarkingPrivate || - methodMarkingPrivate) - { - // Mark all class members that can not be made private. - programClassPool.classesAccept( - new NonPrivateMemberMarker()); - } - - if (fieldMarkingPrivate) - { - // Make all non-private fields private, whereever possible. - programClassPool.classesAccept( - new ClassAccessFilter(0, ClassConstants.ACC_INTERFACE, - new AllFieldVisitor( - new MemberAccessFilter(0, ClassConstants.ACC_PRIVATE, - new MemberPrivatizer(fieldMarkingPrivateCounter))))); - } - - if (methodMarkingPrivate) - { - // Make all non-private methods private, whereever possible. - programClassPool.classesAccept( - new ClassAccessFilter(0, ClassConstants.ACC_INTERFACE, - new AllMethodVisitor( - new MemberAccessFilter(0, ClassConstants.ACC_PRIVATE, - new MemberPrivatizer(methodMarkingPrivateCounter))))); - } - - if ((methodInliningUniqueCounter .getCount() > 0 || - methodInliningShortCounter .getCount() > 0 || - methodInliningTailrecursionCounter.getCount() > 0) && - configuration.allowAccessModification) - { - // Fix the access flags of referenced classes and class members, - // for MethodInliner. - programClassPool.classesAccept( - new AccessFixer()); - } - - if (methodRemovalParameterCounter .getCount() > 0 || - classMergingVerticalCounter .getCount() > 0 || - classMergingHorizontalCounter .getCount() > 0 || - methodMarkingPrivateCounter .getCount() > 0 ) - { - // Fix invocations of interface methods, of methods that have become - // non-abstract or private, and of methods that have moved to a - // different package. - programClassPool.classesAccept( - new AllMemberVisitor( - new AllAttributeVisitor( - new MethodInvocationFixer()))); - } - - if (codeMerging) - { - // Share common blocks of code at branches. - programClassPool.classesAccept( - new AllMethodVisitor( - new AllAttributeVisitor( - new GotoCommonCodeReplacer(codeMergingCounter)))); - } - - // Create a branch target marker and a code attribute editor that can - // be reused for all code attributes. - BranchTargetFinder branchTargetFinder = new BranchTargetFinder(); - CodeAttributeEditor codeAttributeEditor = new CodeAttributeEditor(); - - List peepholeOptimizations = new ArrayList(); - if (codeSimplificationVariable) - { - // Peephole optimizations involving local variables. - peepholeOptimizations.add( - new InstructionSequencesReplacer(InstructionSequenceConstants.CONSTANTS, - InstructionSequenceConstants.VARIABLE, - branchTargetFinder, codeAttributeEditor, codeSimplificationVariableCounter)); - } - - if (codeSimplificationArithmetic) - { - // Peephole optimizations involving arithmetic operations. - peepholeOptimizations.add( - new InstructionSequencesReplacer(InstructionSequenceConstants.CONSTANTS, - InstructionSequenceConstants.ARITHMETIC, - branchTargetFinder, codeAttributeEditor, codeSimplificationArithmeticCounter)); - } - - if (codeSimplificationCast) - { - // Peephole optimizations involving cast operations. - peepholeOptimizations.add( - new InstructionSequencesReplacer(InstructionSequenceConstants.CONSTANTS, - InstructionSequenceConstants.CAST, - branchTargetFinder, codeAttributeEditor, codeSimplificationCastCounter)); - } - - if (codeSimplificationField) - { - // Peephole optimizations involving fields. - peepholeOptimizations.add( - new InstructionSequencesReplacer(InstructionSequenceConstants.CONSTANTS, - InstructionSequenceConstants.FIELD, - branchTargetFinder, codeAttributeEditor, codeSimplificationFieldCounter)); - } - - if (codeSimplificationBranch) - { - // Peephole optimizations involving branches. - peepholeOptimizations.add( - new InstructionSequencesReplacer(InstructionSequenceConstants.CONSTANTS, - InstructionSequenceConstants.BRANCH, - branchTargetFinder, codeAttributeEditor, codeSimplificationBranchCounter)); - - // Include optimization of branches to branches and returns. - peepholeOptimizations.add( - new GotoGotoReplacer(codeAttributeEditor, codeSimplificationBranchCounter)); - peepholeOptimizations.add( - new GotoReturnReplacer(codeAttributeEditor, codeSimplificationBranchCounter)); - } - - if (codeSimplificationString) - { - // Peephole optimizations involving branches. - peepholeOptimizations.add( - new InstructionSequencesReplacer(InstructionSequenceConstants.CONSTANTS, - InstructionSequenceConstants.STRING, - branchTargetFinder, codeAttributeEditor, codeSimplificationStringCounter)); - } - - if (!peepholeOptimizations.isEmpty()) - { - // Convert the list into an array. - InstructionVisitor[] peepholeOptimizationsArray = - new InstructionVisitor[peepholeOptimizations.size()]; - peepholeOptimizations.toArray(peepholeOptimizationsArray); - - // Perform the peephole optimisations. - programClassPool.classesAccept( - new AllMethodVisitor( - new AllAttributeVisitor( - new PeepholeOptimizer(branchTargetFinder, codeAttributeEditor, - new MultiInstructionVisitor( - peepholeOptimizationsArray))))); - } - - if (codeRemovalException) - { - // Remove unnecessary exception handlers. - programClassPool.classesAccept( - new AllMethodVisitor( - new AllAttributeVisitor( - new UnreachableExceptionRemover(codeRemovalExceptionCounter)))); - } - - if (codeRemovalSimple) - { - // Remove unreachable code. - programClassPool.classesAccept( - new AllMethodVisitor( - new AllAttributeVisitor( - new UnreachableCodeRemover(deletedCounter)))); - } - - if (codeRemovalVariable) - { - // Remove all unused local variables. - programClassPool.classesAccept( - new AllMethodVisitor( - new AllAttributeVisitor( - new VariableShrinker(codeRemovalVariableCounter)))); - } - - if (codeAllocationVariable) - { - // Optimize the variables. - programClassPool.classesAccept( - new AllMethodVisitor( - new AllAttributeVisitor( - new VariableOptimizer(false, codeAllocationVariableCounter)))); - } - - - // Remove unused constants. - programClassPool.classesAccept( - new ConstantPoolShrinker()); - - int classMarkingFinalCount = classMarkingFinalCounter .getCount(); - int classUnboxingEnumCount = classUnboxingEnumCounter .getCount(); - int classMergingVerticalCount = classMergingVerticalCounter .getCount(); - int classMergingHorizontalCount = classMergingHorizontalCounter .getCount(); - int fieldRemovalWriteonlyCount = fieldRemovalWriteonlyCounter .getCount(); - int fieldMarkingPrivateCount = fieldMarkingPrivateCounter .getCount(); - int fieldPropagationValueCount = fieldPropagationValueCounter .getCount(); - int methodMarkingPrivateCount = methodMarkingPrivateCounter .getCount(); - int methodMarkingStaticCount = methodMarkingStaticCounter .getCount(); - int methodMarkingFinalCount = methodMarkingFinalCounter .getCount(); - int methodRemovalParameterCount = methodRemovalParameterCounter .getCount() - methodMarkingStaticCounter.getCount() - initializerFixCounter1.getCount() - initializerFixCounter2.getCount(); - int methodPropagationParameterCount = methodPropagationParameterCounter .getCount(); - int methodPropagationReturnvalueCount = methodPropagationReturnvalueCounter.getCount(); - int methodInliningShortCount = methodInliningShortCounter .getCount(); - int methodInliningUniqueCount = methodInliningUniqueCounter .getCount(); - int methodInliningTailrecursionCount = methodInliningTailrecursionCounter .getCount(); - int codeMergingCount = codeMergingCounter .getCount(); - int codeSimplificationVariableCount = codeSimplificationVariableCounter .getCount(); - int codeSimplificationArithmeticCount = codeSimplificationArithmeticCounter.getCount(); - int codeSimplificationCastCount = codeSimplificationCastCounter .getCount(); - int codeSimplificationFieldCount = codeSimplificationFieldCounter .getCount(); - int codeSimplificationBranchCount = codeSimplificationBranchCounter .getCount(); - int codeSimplificationStringCount = codeSimplificationStringCounter .getCount(); - int codeSimplificationAdvancedCount = codeSimplificationAdvancedCounter .getCount(); - int codeRemovalCount = deletedCounter .getCount() - addedCounter.getCount(); - int codeRemovalVariableCount = codeRemovalVariableCounter .getCount(); - int codeRemovalExceptionCount = codeRemovalExceptionCounter .getCount(); - int codeAllocationVariableCount = codeAllocationVariableCounter .getCount(); - - // Forget about constant fields, parameters, and return values, if they - // didn't lead to any useful optimizations. We want to avoid fruitless - // additional optimization passes. - if (codeSimplificationAdvancedCount == 0) - { - fieldPropagationValueCount = 0; - methodPropagationParameterCount = 0; - methodPropagationReturnvalueCount = 0; - } - - if (configuration.verbose) - { - System.out.println(" Number of finalized classes: " + classMarkingFinalCount + disabled(classMarkingFinal)); - System.out.println(" Number of unboxed enum classes: " + classUnboxingEnumCount + disabled(classUnboxingEnum)); - System.out.println(" Number of vertically merged classes: " + classMergingVerticalCount + disabled(classMergingVertical)); - System.out.println(" Number of horizontally merged classes: " + classMergingHorizontalCount + disabled(classMergingHorizontal)); - System.out.println(" Number of removed write-only fields: " + fieldRemovalWriteonlyCount + disabled(fieldRemovalWriteonly)); - System.out.println(" Number of privatized fields: " + fieldMarkingPrivateCount + disabled(fieldMarkingPrivate)); - System.out.println(" Number of inlined constant fields: " + fieldPropagationValueCount + disabled(fieldPropagationValue)); - System.out.println(" Number of privatized methods: " + methodMarkingPrivateCount + disabled(methodMarkingPrivate)); - System.out.println(" Number of staticized methods: " + methodMarkingStaticCount + disabled(methodMarkingStatic)); - System.out.println(" Number of finalized methods: " + methodMarkingFinalCount + disabled(methodMarkingFinal)); - System.out.println(" Number of removed method parameters: " + methodRemovalParameterCount + disabled(methodRemovalParameter)); - System.out.println(" Number of inlined constant parameters: " + methodPropagationParameterCount + disabled(methodPropagationParameter)); - System.out.println(" Number of inlined constant return values: " + methodPropagationReturnvalueCount + disabled(methodPropagationReturnvalue)); - System.out.println(" Number of inlined short method calls: " + methodInliningShortCount + disabled(methodInliningShort)); - System.out.println(" Number of inlined unique method calls: " + methodInliningUniqueCount + disabled(methodInliningUnique)); - System.out.println(" Number of inlined tail recursion calls: " + methodInliningTailrecursionCount + disabled(methodInliningTailrecursion)); - System.out.println(" Number of merged code blocks: " + codeMergingCount + disabled(codeMerging)); - System.out.println(" Number of variable peephole optimizations: " + codeSimplificationVariableCount + disabled(codeSimplificationVariable)); - System.out.println(" Number of arithmetic peephole optimizations: " + codeSimplificationArithmeticCount + disabled(codeSimplificationArithmetic)); - System.out.println(" Number of cast peephole optimizations: " + codeSimplificationCastCount + disabled(codeSimplificationCast)); - System.out.println(" Number of field peephole optimizations: " + codeSimplificationFieldCount + disabled(codeSimplificationField)); - System.out.println(" Number of branch peephole optimizations: " + codeSimplificationBranchCount + disabled(codeSimplificationBranch)); - System.out.println(" Number of string peephole optimizations: " + codeSimplificationStringCount + disabled(codeSimplificationString)); - System.out.println(" Number of simplified instructions: " + codeSimplificationAdvancedCount + disabled(codeSimplificationAdvanced)); - System.out.println(" Number of removed instructions: " + codeRemovalCount + disabled(codeRemovalAdvanced)); - System.out.println(" Number of removed local variables: " + codeRemovalVariableCount + disabled(codeRemovalVariable)); - System.out.println(" Number of removed exception blocks: " + codeRemovalExceptionCount + disabled(codeRemovalException)); - System.out.println(" Number of optimized local variable frames: " + codeAllocationVariableCount + disabled(codeAllocationVariable)); - } - - return classMarkingFinalCount > 0 || - classUnboxingEnumCount > 0 || - classMergingVerticalCount > 0 || - classMergingHorizontalCount > 0 || - fieldRemovalWriteonlyCount > 0 || - fieldMarkingPrivateCount > 0 || - methodMarkingPrivateCount > 0 || - methodMarkingStaticCount > 0 || - methodMarkingFinalCount > 0 || - fieldPropagationValueCount > 0 || - methodRemovalParameterCount > 0 || - methodPropagationParameterCount > 0 || - methodPropagationReturnvalueCount > 0 || - methodInliningShortCount > 0 || - methodInliningUniqueCount > 0 || - methodInliningTailrecursionCount > 0 || - codeMergingCount > 0 || - codeSimplificationVariableCount > 0 || - codeSimplificationArithmeticCount > 0 || - codeSimplificationCastCount > 0 || - codeSimplificationFieldCount > 0 || - codeSimplificationBranchCount > 0 || - codeSimplificationStringCount > 0 || - codeSimplificationAdvancedCount > 0 || - codeRemovalCount > 0 || - codeRemovalVariableCount > 0 || - codeRemovalExceptionCount > 0 || - codeAllocationVariableCount > 0; - } - - - /** - * Returns a String indicating whether the given flag is enabled or - * disabled. - */ - private String disabled(boolean flag) - { - return flag ? "" : " (disabled)"; - } - - - /** - * Returns a String indicating whether the given flags are enabled or - * disabled. - */ - private String disabled(boolean flag1, boolean flag2) - { - return flag1 && flag2 ? "" : - flag1 || flag2 ? " (partially disabled)" : - " (disabled)"; - } -} |