/** * Extracts a list of exceptions of classes for which not to print notes, from the keep * configuration. */ private StringMatcher createClassNoteExceptionMatcher(List noteExceptions) { if (noteExceptions != null) { List noteExceptionNames = new ArrayList(noteExceptions.size()); for (int index = 0; index < noteExceptions.size(); index++) { KeepClassSpecification keepClassSpecification = (KeepClassSpecification) noteExceptions.get(index); if (keepClassSpecification.markClasses) { // If the class itself is being kept, it's ok. String className = keepClassSpecification.className; if (className != null) { noteExceptionNames.add(className); } // If all of its extensions are being kept, it's ok too. String extendsClassName = keepClassSpecification.extendsClassName; if (extendsClassName != null) { noteExceptionNames.add(extendsClassName); } } } if (noteExceptionNames.size() > 0) { return new ListParser(new ClassNameParser()).parse(noteExceptionNames); } } return null; }
/** * Extracts a list of exceptions of field or method names for which not to print notes, from the * keep configuration. */ private StringMatcher createClassMemberNoteExceptionMatcher( List noteExceptions, boolean isField) { if (noteExceptions != null) { List noteExceptionNames = new ArrayList(); for (int index = 0; index < noteExceptions.size(); index++) { KeepClassSpecification keepClassSpecification = (KeepClassSpecification) noteExceptions.get(index); List memberSpecifications = isField ? keepClassSpecification.fieldSpecifications : keepClassSpecification.methodSpecifications; if (memberSpecifications != null) { for (int index2 = 0; index2 < memberSpecifications.size(); index2++) { MemberSpecification memberSpecification = (MemberSpecification) memberSpecifications.get(index2); String memberName = memberSpecification.name; if (memberName != null) { noteExceptionNames.add(memberName); } } } } if (noteExceptionNames.size() > 0) { return new ListParser(new ClassNameParser()).parse(noteExceptionNames); } } return null; }
/** 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 = StringMatcherUtil.matchesString(filter, CLASS_MARKING_FINAL); boolean classUnboxingEnum = StringMatcherUtil.matchesString(filter, CLASS_UNBOXING_ENUM); boolean classMergingVertical = StringMatcherUtil.matchesString(filter, CLASS_MERGING_VERTICAL); boolean classMergingHorizontal = StringMatcherUtil.matchesString(filter, CLASS_MERGING_HORIZONTAL); boolean fieldRemovalWriteonly = StringMatcherUtil.matchesString(filter, FIELD_REMOVAL_WRITEONLY); boolean fieldMarkingPrivate = StringMatcherUtil.matchesString(filter, FIELD_MARKING_PRIVATE); boolean fieldPropagationValue = StringMatcherUtil.matchesString(filter, FIELD_PROPAGATION_VALUE); boolean methodMarkingPrivate = StringMatcherUtil.matchesString(filter, METHOD_MARKING_PRIVATE); boolean methodMarkingStatic = StringMatcherUtil.matchesString(filter, METHOD_MARKING_STATIC); boolean methodMarkingFinal = StringMatcherUtil.matchesString(filter, METHOD_MARKING_FINAL); boolean methodRemovalParameter = StringMatcherUtil.matchesString(filter, METHOD_REMOVAL_PARAMETER); boolean methodPropagationParameter = StringMatcherUtil.matchesString(filter, METHOD_PROPAGATION_PARAMETER); boolean methodPropagationReturnvalue = StringMatcherUtil.matchesString(filter, METHOD_PROPAGATION_RETURNVALUE); boolean methodInliningShort = StringMatcherUtil.matchesString(filter, METHOD_INLINING_SHORT); boolean methodInliningUnique = StringMatcherUtil.matchesString(filter, METHOD_INLINING_UNIQUE); boolean methodInliningTailrecursion = StringMatcherUtil.matchesString(filter, METHOD_INLINING_TAILRECURSION); boolean codeMerging = StringMatcherUtil.matchesString(filter, CODE_MERGING); boolean codeSimplificationVariable = StringMatcherUtil.matchesString(filter, CODE_SIMPLIFICATION_VARIABLE); boolean codeSimplificationArithmetic = StringMatcherUtil.matchesString(filter, CODE_SIMPLIFICATION_ARITHMETIC); boolean codeSimplificationCast = StringMatcherUtil.matchesString(filter, CODE_SIMPLIFICATION_CAST); boolean codeSimplificationField = StringMatcherUtil.matchesString(filter, CODE_SIMPLIFICATION_FIELD); boolean codeSimplificationBranch = StringMatcherUtil.matchesString(filter, CODE_SIMPLIFICATION_BRANCH); boolean codeSimplificationString = StringMatcherUtil.matchesString(filter, CODE_SIMPLIFICATION_STRING); boolean codeSimplificationAdvanced = StringMatcherUtil.matchesString(filter, CODE_SIMPLIFICATION_ADVANCED); boolean codeRemovalAdvanced = StringMatcherUtil.matchesString(filter, CODE_REMOVAL_ADVANCED); boolean codeRemovalSimple = StringMatcherUtil.matchesString(filter, CODE_REMOVAL_SIMPLE); boolean codeRemovalVariable = StringMatcherUtil.matchesString(filter, CODE_REMOVAL_VARIABLE); boolean codeRemovalException = StringMatcherUtil.matchesString(filter, CODE_REMOVAL_EXCEPTION); boolean codeAllocationVariable = StringMatcherUtil.matchesString(filter, 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; }