summaryrefslogtreecommitdiff
path: root/src/proguard/optimize/Optimizer.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/proguard/optimize/Optimizer.java')
-rw-r--r--src/proguard/optimize/Optimizer.java197
1 files changed, 142 insertions, 55 deletions
diff --git a/src/proguard/optimize/Optimizer.java b/src/proguard/optimize/Optimizer.java
index a3e8a6e..8042825 100644
--- a/src/proguard/optimize/Optimizer.java
+++ b/src/proguard/optimize/Optimizer.java
@@ -2,7 +2,7 @@
* ProGuard -- shrinking, optimization, obfuscation, and preverification
* of Java bytecode.
*
- * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
+ * Copyright (c) 2002-2013 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
@@ -23,7 +23,8 @@ package proguard.optimize;
import proguard.*;
import proguard.classfile.*;
import proguard.classfile.attribute.visitor.*;
-import proguard.classfile.constant.visitor.AllConstantVisitor;
+import proguard.classfile.constant.Constant;
+import proguard.classfile.constant.visitor.*;
import proguard.classfile.editor.*;
import proguard.classfile.instruction.visitor.*;
import proguard.classfile.util.MethodLinker;
@@ -66,6 +67,7 @@ public class Optimizer
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";
@@ -80,6 +82,7 @@ public class Optimizer
CLASS_MERGING_VERTICAL,
CLASS_MERGING_HORIZONTAL,
FIELD_REMOVAL_WRITEONLY,
+ FIELD_MARKING_PRIVATE,
FIELD_PROPAGATION_VALUE,
METHOD_MARKING_PRIVATE,
METHOD_MARKING_STATIC,
@@ -96,6 +99,7 @@ public class Optimizer
CODE_SIMPLIFICATION_CAST,
CODE_SIMPLIFICATION_FIELD,
CODE_SIMPLIFICATION_BRANCH,
+ CODE_SIMPLIFICATION_STRING,
CODE_SIMPLIFICATION_ADVANCED,
CODE_REMOVAL_ADVANCED,
CODE_REMOVAL_SIMPLE,
@@ -157,6 +161,7 @@ public class Optimizer
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);
@@ -186,13 +191,15 @@ public class Optimizer
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 initializerFixCounter = new MemberCounter();
+ MemberCounter initializerFixCounter1 = new MemberCounter();
+ MemberCounter initializerFixCounter2 = new MemberCounter();
// Some optimizations are required by other optimizations.
codeSimplificationAdvanced =
@@ -250,10 +257,27 @@ public class Optimizer
new AllInstructionVisitor(
new DotClassClassVisitor(keepMarker)))));
- // We also keep all classes that are involved in Class.forName constructs.
+ // We also keep all classes that are accessed dynamically.
programClassPool.classesAccept(
new AllConstantVisitor(
- new ClassForNameClassVisitor(keepMarker)));
+ 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.INTERNAL_CLASS_VERSION_1_7,
+ new AllAttributeVisitor(
+ new AttributeNameFilter(ClassConstants.ATTR_BootstrapMethods,
+ new AllBootstrapMethodInfoVisitor(
+ new BootstrapMethodHandleTraveler(
+ new MethodrefTraveler(
+ new ReferencedMemberVisitor(keepMarker))))))));
// Attach some optimization info to all classes and class members, so
// it can be filled out later.
@@ -320,6 +344,9 @@ public class Optimizer
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());
@@ -347,18 +374,29 @@ public class Optimizer
new AllAttributeVisitor(
new PartialEvaluator(valueFactory, storingInvocationUnit, false))));
- // Count the constant fields and methods.
- programClassPool.classesAccept(
- new MultiClassVisitor(
- new ClassVisitor[]
- {
+ if (fieldPropagationValue)
+ {
+ // Count the constant fields.
+ programClassPool.classesAccept(
new AllFieldVisitor(
- new ConstantMemberFilter(fieldPropagationValueCounter)),
+ new ConstantMemberFilter(fieldPropagationValueCounter)));
+ }
+
+ if (methodPropagationParameter)
+ {
+ // Count the constant method parameters.
+ programClassPool.classesAccept(
new AllMethodVisitor(
- new ConstantParameterFilter(methodPropagationParameterCounter)),
+ new ConstantParameterFilter(methodPropagationParameterCounter)));
+ }
+
+ if (methodPropagationReturnvalue)
+ {
+ // Count the constant method return values.
+ programClassPool.classesAccept(
new AllMethodVisitor(
- new ConstantMemberFilter(methodPropagationReturnvalueCounter)),
- }));
+ new ConstantMemberFilter(methodPropagationReturnvalueCounter)));
+ }
}
InvocationUnit loadingInvocationUnit =
@@ -418,6 +456,12 @@ public class Optimizer
// 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 ||
@@ -441,17 +485,39 @@ public class Optimizer
new StackSizeUpdater())));
}
-// // 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))));
+ 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.
@@ -461,13 +527,13 @@ public class Optimizer
new MultiClassVisitor(
new ClassVisitor[]
{
+ new PackageVisibleMemberContainingClassMarker(),
new AllConstantVisitor(
new PackageVisibleMemberInvokingClassMarker()),
new AllMethodVisitor(
new MultiMemberVisitor(
new MemberVisitor[]
{
- new PackageVisibleMemberContainingClassMarker(),
new AllAttributeVisitor(
new MultiAttributeVisitor(
new AttributeVisitor[]
@@ -511,8 +577,8 @@ public class Optimizer
classMergingHorizontalCounter));
}
- if (classMergingVertical ||
- classMergingHorizontal)
+ if (classMergingVerticalCounter .getCount() > 0 ||
+ classMergingHorizontalCounter.getCount() > 0)
{
// Clean up inner class attributes to avoid loops.
programClassPool.classesAccept(new RetargetedInnerClassAttributeRemover());
@@ -530,18 +596,20 @@ public class Optimizer
new AllConstantVisitor(
new AccessFixer()));
}
- }
- if (methodRemovalParameter ||
- classMergingVertical ||
- classMergingHorizontal)
- {
- // Tweak the descriptors of duplicate initializers.
+ // 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(initializerFixCounter)));
+ new DuplicateInitializerFixer(initializerFixCounter2)));
- if (initializerFixCounter.getCount() > 0)
+ if (initializerFixCounter2.getCount() > 0)
{
// Fix all invocations of tweaked initializers.
programClassPool.classesAccept(
@@ -595,14 +663,14 @@ public class Optimizer
new NonPrivateMemberMarker());
}
- if (fieldMarkingPrivate ||
- methodMarkingPrivate)
+ if (fieldMarkingPrivate)
{
// Make all non-private fields private, whereever possible.
programClassPool.classesAccept(
+ new ClassAccessFilter(0, ClassConstants.INTERNAL_ACC_INTERFACE,
new AllFieldVisitor(
new MemberAccessFilter(0, ClassConstants.INTERNAL_ACC_PRIVATE,
- new MemberPrivatizer(fieldMarkingPrivateCounter))));
+ new MemberPrivatizer(fieldMarkingPrivateCounter)))));
}
if (methodMarkingPrivate)
@@ -615,9 +683,9 @@ public class Optimizer
new MemberPrivatizer(methodMarkingPrivateCounter)))));
}
- if ((methodInliningUnique ||
- methodInliningShort ||
- methodInliningTailrecursion) &&
+ if ((methodInliningUniqueCounter .getCount() > 0 ||
+ methodInliningShortCounter .getCount() > 0 ||
+ methodInliningTailrecursionCounter.getCount() > 0) &&
configuration.allowAccessModification)
{
// Fix the access flags of referenced classes and class members,
@@ -627,10 +695,10 @@ public class Optimizer
new AccessFixer()));
}
- if (methodRemovalParameter ||
- classMergingVertical ||
- classMergingHorizontal ||
- methodMarkingPrivate)
+ 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
@@ -707,6 +775,15 @@ public class Optimizer
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.
@@ -749,14 +826,6 @@ public class Optimizer
new AllAttributeVisitor(
new VariableShrinker(codeRemovalVariableCounter))));
}
- else
- {
- // Clean up all unused local variables.
- programClassPool.classesAccept(
- new AllMethodVisitor(
- new AllAttributeVisitor(
- new VariableCleaner())));
- }
if (codeAllocationVariable)
{
@@ -767,6 +836,11 @@ public class Optimizer
new VariableOptimizer(false, codeAllocationVariableCounter))));
}
+
+ // Remove unused constants.
+ programClassPool.classesAccept(
+ new ConstantPoolShrinker());
+
int classMarkingFinalCount = classMarkingFinalCounter .getCount();
int classMergingVerticalCount = classMergingVerticalCounter .getCount();
int classMergingHorizontalCount = classMergingHorizontalCounter .getCount();
@@ -776,7 +850,7 @@ public class Optimizer
int methodMarkingPrivateCount = methodMarkingPrivateCounter .getCount();
int methodMarkingStaticCount = methodMarkingStaticCounter .getCount();
int methodMarkingFinalCount = methodMarkingFinalCounter .getCount();
- int methodRemovalParameterCount = methodRemovalParameterCounter .getCount() - methodMarkingStaticCounter.getCount() - initializerFixCounter.getCount();
+ int methodRemovalParameterCount = methodRemovalParameterCounter .getCount() - methodMarkingStaticCounter.getCount() - initializerFixCounter1.getCount() - initializerFixCounter2.getCount();
int methodPropagationParameterCount = methodPropagationParameterCounter .getCount();
int methodPropagationReturnvalueCount = methodPropagationReturnvalueCounter.getCount();
int methodInliningShortCount = methodInliningShortCounter .getCount();
@@ -788,12 +862,23 @@ public class Optimizer
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));
@@ -817,6 +902,7 @@ public class Optimizer
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));
@@ -845,6 +931,7 @@ public class Optimizer
codeSimplificationCastCount > 0 ||
codeSimplificationFieldCount > 0 ||
codeSimplificationBranchCount > 0 ||
+ codeSimplificationStringCount > 0 ||
codeSimplificationAdvancedCount > 0 ||
codeRemovalCount > 0 ||
codeRemovalVariableCount > 0 ||