aboutsummaryrefslogtreecommitdiffstats
path: root/src/proguard/optimize/info
diff options
context:
space:
mode:
Diffstat (limited to 'src/proguard/optimize/info')
-rw-r--r--src/proguard/optimize/info/AccessMethodMarker.java19
-rw-r--r--src/proguard/optimize/info/BackwardBranchMarker.java2
-rw-r--r--src/proguard/optimize/info/CatchExceptionMarker.java2
-rw-r--r--src/proguard/optimize/info/CaughtClassFilter.java2
-rw-r--r--src/proguard/optimize/info/CaughtClassMarker.java7
-rw-r--r--src/proguard/optimize/info/ClassOptimizationInfo.java16
-rw-r--r--src/proguard/optimize/info/ClassOptimizationInfoSetter.java2
-rw-r--r--src/proguard/optimize/info/DotClassFilter.java2
-rw-r--r--src/proguard/optimize/info/DotClassMarker.java2
-rw-r--r--src/proguard/optimize/info/ExceptionInstructionChecker.java104
-rw-r--r--src/proguard/optimize/info/FieldOptimizationInfo.java56
-rw-r--r--src/proguard/optimize/info/InstanceofClassFilter.java2
-rw-r--r--src/proguard/optimize/info/InstanceofClassMarker.java2
-rw-r--r--src/proguard/optimize/info/InstantiationClassFilter.java2
-rw-r--r--src/proguard/optimize/info/InstantiationClassMarker.java2
-rw-r--r--src/proguard/optimize/info/MemberOptimizationInfoSetter.java18
-rw-r--r--src/proguard/optimize/info/MethodInvocationMarker.java2
-rw-r--r--src/proguard/optimize/info/MethodOptimizationInfo.java6
-rw-r--r--src/proguard/optimize/info/NoSideEffectMethodMarker.java4
-rw-r--r--src/proguard/optimize/info/NonPrivateMemberMarker.java16
-rw-r--r--src/proguard/optimize/info/PackageVisibleMemberContainingClassMarker.java28
-rw-r--r--src/proguard/optimize/info/PackageVisibleMemberInvokingClassMarker.java72
-rw-r--r--src/proguard/optimize/info/ParameterUsageMarker.java8
-rw-r--r--src/proguard/optimize/info/ReadWriteFieldMarker.java2
-rw-r--r--src/proguard/optimize/info/SideEffectInstructionChecker.java239
-rw-r--r--src/proguard/optimize/info/SideEffectMethodFilter.java73
-rw-r--r--src/proguard/optimize/info/SideEffectMethodMarker.java22
-rw-r--r--src/proguard/optimize/info/StaticInitializerContainingClassFilter.java62
-rw-r--r--src/proguard/optimize/info/StaticInitializerContainingClassMarker.java65
-rw-r--r--src/proguard/optimize/info/SuperInvocationMarker.java2
-rw-r--r--src/proguard/optimize/info/VariableUsageMarker.java11
31 files changed, 640 insertions, 212 deletions
diff --git a/src/proguard/optimize/info/AccessMethodMarker.java b/src/proguard/optimize/info/AccessMethodMarker.java
index 6965cec..e4c8d7c 100644
--- a/src/proguard/optimize/info/AccessMethodMarker.java
+++ b/src/proguard/optimize/info/AccessMethodMarker.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
@@ -21,7 +21,8 @@
package proguard.optimize.info;
import proguard.classfile.*;
-import proguard.classfile.attribute.CodeAttribute;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.*;
import proguard.classfile.constant.*;
import proguard.classfile.constant.visitor.ConstantVisitor;
import proguard.classfile.instruction.*;
@@ -71,6 +72,20 @@ implements InstructionVisitor,
}
+ public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
+ {
+ // Check the bootstrap method.
+ invokeDynamicConstant.bootstrapMethodHandleAccept(clazz, this);
+ }
+
+
+ public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant)
+ {
+ // Check the method reference.
+ clazz.constantPoolEntryAccept(methodHandleConstant.u2referenceIndex, this);
+ }
+
+
public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
{
// Check the referenced class.
diff --git a/src/proguard/optimize/info/BackwardBranchMarker.java b/src/proguard/optimize/info/BackwardBranchMarker.java
index 9e09b0f..07bfefb 100644
--- a/src/proguard/optimize/info/BackwardBranchMarker.java
+++ b/src/proguard/optimize/info/BackwardBranchMarker.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
diff --git a/src/proguard/optimize/info/CatchExceptionMarker.java b/src/proguard/optimize/info/CatchExceptionMarker.java
index 3f2a06f..8f87a08 100644
--- a/src/proguard/optimize/info/CatchExceptionMarker.java
+++ b/src/proguard/optimize/info/CatchExceptionMarker.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
diff --git a/src/proguard/optimize/info/CaughtClassFilter.java b/src/proguard/optimize/info/CaughtClassFilter.java
index 5e17763..762e7de 100644
--- a/src/proguard/optimize/info/CaughtClassFilter.java
+++ b/src/proguard/optimize/info/CaughtClassFilter.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
diff --git a/src/proguard/optimize/info/CaughtClassMarker.java b/src/proguard/optimize/info/CaughtClassMarker.java
index 0cc350e..1752f0c 100644
--- a/src/proguard/optimize/info/CaughtClassMarker.java
+++ b/src/proguard/optimize/info/CaughtClassMarker.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
@@ -25,8 +25,9 @@ import proguard.classfile.util.SimplifiedVisitor;
import proguard.classfile.visitor.ClassVisitor;
/**
- * This InstructionVisitor marks all classes that are used in an 'instanceof'
- * test by any of the instructions that it visits.
+ * This ClassVisitor marks all program classes that it visits as caught.
+ * This means that these classes are exception classes that occur in exception
+ * handlers.
*
* @author Eric Lafortune
*/
diff --git a/src/proguard/optimize/info/ClassOptimizationInfo.java b/src/proguard/optimize/info/ClassOptimizationInfo.java
index 99b6e7b..dbe041e 100644
--- a/src/proguard/optimize/info/ClassOptimizationInfo.java
+++ b/src/proguard/optimize/info/ClassOptimizationInfo.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
@@ -34,6 +34,7 @@ public class ClassOptimizationInfo
private boolean isInstanceofed = false;
private boolean isDotClassed = false;
private boolean isCaught = false;
+ private boolean containsStaticInitializer = false;
private boolean containsPackageVisibleMembers = false;
private boolean invokesPackageVisibleMembers = false;
private Clazz targetClass;
@@ -87,6 +88,18 @@ public class ClassOptimizationInfo
}
+ public void setContainsStaticInitializer()
+ {
+ containsStaticInitializer = true;
+ }
+
+
+ public boolean containsStaticInitializer()
+ {
+ return containsStaticInitializer;
+ }
+
+
public void setContainsPackageVisibleMembers()
{
containsPackageVisibleMembers = true;
@@ -129,6 +142,7 @@ public class ClassOptimizationInfo
this.isInstanceofed |= other.isInstanceofed;
this.isDotClassed |= other.isDotClassed;
this.isCaught |= other.isCaught;
+ this.containsStaticInitializer |= other.containsStaticInitializer;
this.containsPackageVisibleMembers |= other.containsPackageVisibleMembers;
this.invokesPackageVisibleMembers |= other.invokesPackageVisibleMembers;
}
diff --git a/src/proguard/optimize/info/ClassOptimizationInfoSetter.java b/src/proguard/optimize/info/ClassOptimizationInfoSetter.java
index 9cb167c..f3d78e2 100644
--- a/src/proguard/optimize/info/ClassOptimizationInfoSetter.java
+++ b/src/proguard/optimize/info/ClassOptimizationInfoSetter.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
diff --git a/src/proguard/optimize/info/DotClassFilter.java b/src/proguard/optimize/info/DotClassFilter.java
index 8cbe7f0..c3fd878 100644
--- a/src/proguard/optimize/info/DotClassFilter.java
+++ b/src/proguard/optimize/info/DotClassFilter.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
diff --git a/src/proguard/optimize/info/DotClassMarker.java b/src/proguard/optimize/info/DotClassMarker.java
index b5f12a7..ef5cfd1 100644
--- a/src/proguard/optimize/info/DotClassMarker.java
+++ b/src/proguard/optimize/info/DotClassMarker.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
diff --git a/src/proguard/optimize/info/ExceptionInstructionChecker.java b/src/proguard/optimize/info/ExceptionInstructionChecker.java
index 2792d90..4bfa96f 100644
--- a/src/proguard/optimize/info/ExceptionInstructionChecker.java
+++ b/src/proguard/optimize/info/ExceptionInstructionChecker.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
@@ -67,34 +67,39 @@ implements InstructionVisitor
byte opcode = simpleInstruction.opcode;
// Check for instructions that may throw exceptions.
- if (opcode == InstructionConstants.OP_IDIV ||
- opcode == InstructionConstants.OP_LDIV ||
- opcode == InstructionConstants.OP_IREM ||
- opcode == InstructionConstants.OP_LREM ||
- opcode == InstructionConstants.OP_IALOAD ||
- opcode == InstructionConstants.OP_LALOAD ||
- opcode == InstructionConstants.OP_FALOAD ||
- opcode == InstructionConstants.OP_DALOAD ||
- opcode == InstructionConstants.OP_AALOAD ||
- opcode == InstructionConstants.OP_BALOAD ||
- opcode == InstructionConstants.OP_CALOAD ||
- opcode == InstructionConstants.OP_SALOAD ||
- opcode == InstructionConstants.OP_IASTORE ||
- opcode == InstructionConstants.OP_LASTORE ||
- opcode == InstructionConstants.OP_FASTORE ||
- opcode == InstructionConstants.OP_DASTORE ||
- opcode == InstructionConstants.OP_AASTORE ||
- opcode == InstructionConstants.OP_BASTORE ||
- opcode == InstructionConstants.OP_CASTORE ||
- opcode == InstructionConstants.OP_SASTORE ||
- opcode == InstructionConstants.OP_NEWARRAY ||
- opcode == InstructionConstants.OP_ARRAYLENGTH ||
- opcode == InstructionConstants.OP_ATHROW ||
- opcode == InstructionConstants.OP_MONITORENTER ||
- opcode == InstructionConstants.OP_MONITOREXIT)
+ // Note that monitorexit can not sensibly throw exceptions, except the
+ // broken and deprecated asynchronous ThreadDeath. Removing the
+ // artificial infinite looping exception blocks that recent compilers
+ // add does not strictly follow the JVM specs, but it does have the
+ // additional benefit of avoiding a bug in the JVM in JDK 1.1.
+ switch (opcode)
{
- // These instructions may throw exceptions.
- mayThrowExceptions = true;
+ case InstructionConstants.OP_IDIV:
+ case InstructionConstants.OP_LDIV:
+ case InstructionConstants.OP_IREM:
+ case InstructionConstants.OP_LREM:
+ case InstructionConstants.OP_IALOAD:
+ case InstructionConstants.OP_LALOAD:
+ case InstructionConstants.OP_FALOAD:
+ case InstructionConstants.OP_DALOAD:
+ case InstructionConstants.OP_AALOAD:
+ case InstructionConstants.OP_BALOAD:
+ case InstructionConstants.OP_CALOAD:
+ case InstructionConstants.OP_SALOAD:
+ case InstructionConstants.OP_IASTORE:
+ case InstructionConstants.OP_LASTORE:
+ case InstructionConstants.OP_FASTORE:
+ case InstructionConstants.OP_DASTORE:
+ case InstructionConstants.OP_AASTORE:
+ case InstructionConstants.OP_BASTORE:
+ case InstructionConstants.OP_CASTORE:
+ case InstructionConstants.OP_SASTORE:
+ case InstructionConstants.OP_NEWARRAY:
+ case InstructionConstants.OP_ARRAYLENGTH:
+ case InstructionConstants.OP_ATHROW:
+ case InstructionConstants.OP_MONITORENTER:
+ // These instructions may throw exceptions.
+ mayThrowExceptions = true;
}
}
@@ -105,31 +110,32 @@ implements InstructionVisitor
byte opcode = constantInstruction.opcode;
// Check for instructions that may throw exceptions.
- if (opcode == InstructionConstants.OP_GETSTATIC ||
- opcode == InstructionConstants.OP_PUTSTATIC ||
- opcode == InstructionConstants.OP_GETFIELD ||
- opcode == InstructionConstants.OP_PUTFIELD ||
- opcode == InstructionConstants.OP_INVOKEVIRTUAL ||
- opcode == InstructionConstants.OP_INVOKESPECIAL ||
- opcode == InstructionConstants.OP_INVOKESTATIC ||
- opcode == InstructionConstants.OP_INVOKEINTERFACE ||
- opcode == InstructionConstants.OP_NEW ||
- opcode == InstructionConstants.OP_ANEWARRAY ||
- opcode == InstructionConstants.OP_CHECKCAST ||
- opcode == InstructionConstants.OP_MULTIANEWARRAY)
+ switch (opcode)
{
- // These instructions may throw exceptions.
- mayThrowExceptions = true;
+ case InstructionConstants.OP_GETSTATIC:
+ case InstructionConstants.OP_PUTSTATIC:
+ case InstructionConstants.OP_GETFIELD:
+ case InstructionConstants.OP_PUTFIELD:
+ case InstructionConstants.OP_INVOKEVIRTUAL:
+ case InstructionConstants.OP_INVOKESPECIAL:
+ case InstructionConstants.OP_INVOKESTATIC:
+ case InstructionConstants.OP_INVOKEINTERFACE:
+ case InstructionConstants.OP_INVOKEDYNAMIC:
+ case InstructionConstants.OP_NEW:
+ case InstructionConstants.OP_ANEWARRAY:
+ case InstructionConstants.OP_CHECKCAST:
+ case InstructionConstants.OP_INSTANCEOF:
+ case InstructionConstants.OP_MULTIANEWARRAY:
+ // These instructions may throw exceptions.
+ mayThrowExceptions = true;
}
-// else
-// if (opcode == InstructionConstants.OP_INVOKEVIRTUAL ||
-// opcode == InstructionConstants.OP_INVOKESPECIAL ||
-// opcode == InstructionConstants.OP_INVOKESTATIC ||
-// opcode == InstructionConstants.OP_INVOKEINTERFACE)
-// {
+
+// case InstructionConstants.OP_INVOKEVIRTUAL:
+// case InstructionConstants.OP_INVOKESPECIAL:
+// case InstructionConstants.OP_INVOKESTATIC:
+// case InstructionConstants.OP_INVOKEINTERFACE:
// // Check if the invoking the method may throw an exception.
// clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
-// }
}
diff --git a/src/proguard/optimize/info/FieldOptimizationInfo.java b/src/proguard/optimize/info/FieldOptimizationInfo.java
index 7a2d068..0fa9167 100644
--- a/src/proguard/optimize/info/FieldOptimizationInfo.java
+++ b/src/proguard/optimize/info/FieldOptimizationInfo.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
@@ -21,8 +21,11 @@
package proguard.optimize.info;
import proguard.classfile.*;
-import proguard.classfile.util.MethodLinker;
+import proguard.classfile.attribute.visitor.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.util.*;
import proguard.evaluation.value.*;
+import proguard.evaluation.ConstantValueFactory;
/**
* This class stores some optimization information that can be attached to
@@ -31,8 +34,11 @@ import proguard.evaluation.value.*;
* @author Eric Lafortune
*/
public class FieldOptimizationInfo
+extends SimplifiedVisitor
+implements AttributeVisitor
{
- private static final SpecificValueFactory VALUE_FACTORY = new SpecificValueFactory();
+ private static final SpecificValueFactory VALUE_FACTORY = new SpecificValueFactory();
+ private static final ConstantValueFactory CONSTANT_VALUE_FACTORY = new ConstantValueFactory(VALUE_FACTORY);
private boolean isWritten;
private boolean isRead;
@@ -43,9 +49,33 @@ public class FieldOptimizationInfo
public FieldOptimizationInfo(Clazz clazz, Field field)
{
+ int accessFlags = field.getAccessFlags();
+
isWritten =
- isRead = (field.getAccessFlags() & ClassConstants.INTERNAL_ACC_VOLATILE) != 0;
- value = initialValue(field.getDescriptor(clazz));
+ isRead = (accessFlags & ClassConstants.INTERNAL_ACC_VOLATILE) != 0;
+
+ if ((accessFlags & ClassConstants.INTERNAL_ACC_STATIC) != 0)
+ {
+ // See if we can initialize the static field with a constant value.
+ field.accept(clazz, new AllAttributeVisitor(this));
+ }
+
+ if ((accessFlags & ClassConstants.INTERNAL_ACC_FINAL) == 0 &&
+ value == null)
+ {
+ // Otherwise initialize the non-final field with the default value.
+ value = initialValue(field.getDescriptor(clazz));
+ }
+ }
+
+
+ public FieldOptimizationInfo(FieldOptimizationInfo FieldOptimizationInfo)
+ {
+ this.isWritten = FieldOptimizationInfo.isWritten;
+ this.isRead = FieldOptimizationInfo.isRead;
+ this.canBeMadePrivate = FieldOptimizationInfo.canBeMadePrivate;
+ this.referencedClass = FieldOptimizationInfo.referencedClass;
+ this.value = FieldOptimizationInfo.value;
}
@@ -113,6 +143,18 @@ public class FieldOptimizationInfo
}
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitConstantValueAttribute(Clazz clazz, Field field, ConstantValueAttribute constantValueAttribute)
+ {
+ // Retrieve the initial static field value.
+ value = CONSTANT_VALUE_FACTORY.constantValue(clazz, constantValueAttribute.u2constantValueIndex);
+ }
+
+
// Small utility methods.
private Value initialValue(String type)
@@ -147,13 +189,13 @@ public class FieldOptimizationInfo
public static void setFieldOptimizationInfo(Clazz clazz, Field field)
{
- MethodLinker.lastMember(field).setVisitorInfo(new FieldOptimizationInfo(clazz, field));
+ field.setVisitorInfo(new FieldOptimizationInfo(clazz, field));
}
public static FieldOptimizationInfo getFieldOptimizationInfo(Field field)
{
- Object visitorInfo = MethodLinker.lastMember(field).getVisitorInfo();
+ Object visitorInfo = field.getVisitorInfo();
return visitorInfo instanceof FieldOptimizationInfo ?
(FieldOptimizationInfo)visitorInfo :
diff --git a/src/proguard/optimize/info/InstanceofClassFilter.java b/src/proguard/optimize/info/InstanceofClassFilter.java
index 35e1d77..7cd85bc 100644
--- a/src/proguard/optimize/info/InstanceofClassFilter.java
+++ b/src/proguard/optimize/info/InstanceofClassFilter.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
diff --git a/src/proguard/optimize/info/InstanceofClassMarker.java b/src/proguard/optimize/info/InstanceofClassMarker.java
index c60e1f8..96d5baf 100644
--- a/src/proguard/optimize/info/InstanceofClassMarker.java
+++ b/src/proguard/optimize/info/InstanceofClassMarker.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
diff --git a/src/proguard/optimize/info/InstantiationClassFilter.java b/src/proguard/optimize/info/InstantiationClassFilter.java
index a24e617..a659f06 100644
--- a/src/proguard/optimize/info/InstantiationClassFilter.java
+++ b/src/proguard/optimize/info/InstantiationClassFilter.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
diff --git a/src/proguard/optimize/info/InstantiationClassMarker.java b/src/proguard/optimize/info/InstantiationClassMarker.java
index 124c23b..b4afffd 100644
--- a/src/proguard/optimize/info/InstantiationClassMarker.java
+++ b/src/proguard/optimize/info/InstantiationClassMarker.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
diff --git a/src/proguard/optimize/info/MemberOptimizationInfoSetter.java b/src/proguard/optimize/info/MemberOptimizationInfoSetter.java
index a170a8e..3c27c93 100644
--- a/src/proguard/optimize/info/MemberOptimizationInfoSetter.java
+++ b/src/proguard/optimize/info/MemberOptimizationInfoSetter.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
@@ -38,22 +38,22 @@ implements MemberVisitor
{
// Implementations for MemberVisitor.
- public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ public void visitProgramField(ProgramClass programClass, ProgramField programField)
{
- if (!KeepMarker.isKept(programMethod))
+ if (!KeepMarker.isKept(programField))
{
- MethodOptimizationInfo.setMethodOptimizationInfo(programClass,
- programMethod);
+ FieldOptimizationInfo.setFieldOptimizationInfo(programClass,
+ programField);
}
}
- public void visitProgramField(ProgramClass programClass, ProgramField programField)
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
{
- if (!KeepMarker.isKept(programField))
+ if (!KeepMarker.isKept(programMethod))
{
- FieldOptimizationInfo.setFieldOptimizationInfo(programClass,
- programField);
+ MethodOptimizationInfo.setMethodOptimizationInfo(programClass,
+ programMethod);
}
}
}
diff --git a/src/proguard/optimize/info/MethodInvocationMarker.java b/src/proguard/optimize/info/MethodInvocationMarker.java
index 2528c94..afb2336 100644
--- a/src/proguard/optimize/info/MethodInvocationMarker.java
+++ b/src/proguard/optimize/info/MethodInvocationMarker.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
diff --git a/src/proguard/optimize/info/MethodOptimizationInfo.java b/src/proguard/optimize/info/MethodOptimizationInfo.java
index d3b1bde..fe754e5 100644
--- a/src/proguard/optimize/info/MethodOptimizationInfo.java
+++ b/src/proguard/optimize/info/MethodOptimizationInfo.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
@@ -204,7 +204,7 @@ public class MethodOptimizationInfo
public void setParameterUsed(int parameterIndex)
{
- usedParameters |= 1 << parameterIndex;
+ usedParameters |= 1L << parameterIndex;
}
@@ -216,7 +216,7 @@ public class MethodOptimizationInfo
public boolean isParameterUsed(int parameterIndex)
{
- return parameterIndex >= 64 || (usedParameters & (1 << parameterIndex)) != 0;
+ return parameterIndex >= 64 || (usedParameters & (1L << parameterIndex)) != 0;
}
diff --git a/src/proguard/optimize/info/NoSideEffectMethodMarker.java b/src/proguard/optimize/info/NoSideEffectMethodMarker.java
index 5c78408..bf5ce45 100644
--- a/src/proguard/optimize/info/NoSideEffectMethodMarker.java
+++ b/src/proguard/optimize/info/NoSideEffectMethodMarker.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
@@ -38,7 +38,7 @@ implements MemberVisitor
{
// A visitor info flag to indicate the visitor accepter is being kept,
// but that it doesn't have any side effects.
- private static final Object KEPT_BUT_NO_SIDE_EFFECTS = new Object();
+ public static final Object KEPT_BUT_NO_SIDE_EFFECTS = new Object();
// Implementations for MemberVisitor.
diff --git a/src/proguard/optimize/info/NonPrivateMemberMarker.java b/src/proguard/optimize/info/NonPrivateMemberMarker.java
index d451643..06f8500 100644
--- a/src/proguard/optimize/info/NonPrivateMemberMarker.java
+++ b/src/proguard/optimize/info/NonPrivateMemberMarker.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
@@ -77,15 +77,9 @@ implements ClassVisitor,
public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
{
- Clazz referencedClass = stringConstant.referencedClass;
-
- // Is it refering to another class or class member?
- if (referencedClass != null &&
- !referencedClass.equals(clazz))
- {
- // The referenced class member, if any, can never be made private.
- stringConstant.referencedMemberAccept(this);
- }
+ // The referenced class member, if any, can never be made private,
+ // even if it's in the same class.
+ stringConstant.referencedMemberAccept(this);
}
@@ -93,7 +87,7 @@ implements ClassVisitor,
{
Clazz referencedClass = refConstant.referencedClass;
- // Is it refering to a class member in another class?
+ // Is it referring to a class member in another class?
// The class member might be in another class, or
// it may be referenced through another class.
if (referencedClass != null &&
diff --git a/src/proguard/optimize/info/PackageVisibleMemberContainingClassMarker.java b/src/proguard/optimize/info/PackageVisibleMemberContainingClassMarker.java
index d40bc6b..02e1a18 100644
--- a/src/proguard/optimize/info/PackageVisibleMemberContainingClassMarker.java
+++ b/src/proguard/optimize/info/PackageVisibleMemberContainingClassMarker.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
@@ -22,18 +22,36 @@ package proguard.optimize.info;
import proguard.classfile.*;
import proguard.classfile.util.SimplifiedVisitor;
-import proguard.classfile.visitor.MemberVisitor;
+import proguard.classfile.visitor.*;
/**
- * This MemberVisitor marks all classes that contain visited package visible
- * members.
+ * This ClassVisitor marks all classes that contain package visible members.
*
* @author Eric Lafortune
*/
public class PackageVisibleMemberContainingClassMarker
extends SimplifiedVisitor
-implements MemberVisitor
+implements ClassVisitor,
+ MemberVisitor
{
+ // Implementations for ClassVisitor.
+
+ public void visitAnyClass(Clazz clazz)
+ {
+ // Check the class itself.
+ if ((clazz.getAccessFlags() & ClassConstants.INTERNAL_ACC_PUBLIC) == 0)
+ {
+ setPackageVisibleMembers(clazz);
+ }
+ else
+ {
+ // Check the members.
+ clazz.fieldsAccept(this);
+ clazz.methodsAccept(this);
+ }
+ }
+
+
// Implementations for MemberVisitor.
public void visitAnyMember(Clazz clazz, Member member)
diff --git a/src/proguard/optimize/info/PackageVisibleMemberInvokingClassMarker.java b/src/proguard/optimize/info/PackageVisibleMemberInvokingClassMarker.java
index 9ec8ec6..3148e3d 100644
--- a/src/proguard/optimize/info/PackageVisibleMemberInvokingClassMarker.java
+++ b/src/proguard/optimize/info/PackageVisibleMemberInvokingClassMarker.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
@@ -24,39 +24,87 @@ import proguard.classfile.*;
import proguard.classfile.constant.visitor.ConstantVisitor;
import proguard.classfile.constant.*;
import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.*;
/**
- * This ConstantVisitor marks all classes that invoke package visible members
- * in other classes.
+ * This ConstantVisitor marks all classes that refer to package visible classes
+ * or class members.
*
* @author Eric Lafortune
*/
public class PackageVisibleMemberInvokingClassMarker
extends SimplifiedVisitor
-implements ConstantVisitor
+implements ConstantVisitor,
+ ClassVisitor,
+ MemberVisitor
{
+ private Clazz referencingClass;
+
+
// Implementations for ConstantVisitor.
public void visitAnyConstant(Clazz clazz, Constant constant) {}
+ public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
+ {
+ // Check the referenced class and class member, if any.
+ if (stringConstant.referencedClass != clazz)
+ {
+ referencingClass = clazz;
+
+ stringConstant.referencedClassAccept(this);
+ stringConstant.referencedMemberAccept(this);
+ }
+ }
+
+
public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
{
- Clazz referencedClass = refConstant.referencedClass;
- if (referencedClass != null &&
- (referencedClass.getAccessFlags() &
+ // Check the referenced class and class member.
+ if (refConstant.referencedClass != clazz)
+ {
+ referencingClass = clazz;
+
+ refConstant.referencedClassAccept(this);
+ refConstant.referencedMemberAccept(this);
+ }
+ }
+
+
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+ {
+ // Check the referenced class.
+ if (classConstant.referencedClass != clazz)
+ {
+ referencingClass = clazz;
+
+ classConstant.referencedClassAccept(this);
+ }
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitAnyClass(Clazz clazz)
+ {
+ if ((clazz.getAccessFlags() &
ClassConstants.INTERNAL_ACC_PUBLIC) == 0)
{
- setInvokesPackageVisibleMembers(clazz);
+ setInvokesPackageVisibleMembers(referencingClass);
}
+ }
- Member referencedMember = refConstant.referencedMember;
- if (referencedMember != null &&
- (referencedMember.getAccessFlags() &
+
+ // Implementations for MemberVisitor.
+
+ public void visitAnyMember(Clazz clazz, Member member)
+ {
+ if ((member.getAccessFlags() &
(ClassConstants.INTERNAL_ACC_PUBLIC |
ClassConstants.INTERNAL_ACC_PRIVATE)) == 0)
{
- setInvokesPackageVisibleMembers(clazz);
+ setInvokesPackageVisibleMembers(referencingClass);
}
}
diff --git a/src/proguard/optimize/info/ParameterUsageMarker.java b/src/proguard/optimize/info/ParameterUsageMarker.java
index 15ce88a..a2a264d 100644
--- a/src/proguard/optimize/info/ParameterUsageMarker.java
+++ b/src/proguard/optimize/info/ParameterUsageMarker.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
@@ -21,14 +21,14 @@
package proguard.optimize.info;
import proguard.classfile.*;
+import proguard.classfile.attribute.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
import proguard.classfile.instruction.*;
import proguard.classfile.instruction.visitor.InstructionVisitor;
-import proguard.classfile.attribute.visitor.AttributeVisitor;
-import proguard.classfile.attribute.*;
import proguard.classfile.util.*;
import proguard.classfile.visitor.MemberVisitor;
+import proguard.evaluation.value.Value;
import proguard.optimize.evaluation.PartialEvaluator;
-import proguard.evaluation.value.*;
/**
* This MemberVisitor counts the parameters and marks the used parameters
diff --git a/src/proguard/optimize/info/ReadWriteFieldMarker.java b/src/proguard/optimize/info/ReadWriteFieldMarker.java
index 57d8561..6bd4b2f 100644
--- a/src/proguard/optimize/info/ReadWriteFieldMarker.java
+++ b/src/proguard/optimize/info/ReadWriteFieldMarker.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
diff --git a/src/proguard/optimize/info/SideEffectInstructionChecker.java b/src/proguard/optimize/info/SideEffectInstructionChecker.java
index 8be9dc1..91f1f02 100644
--- a/src/proguard/optimize/info/SideEffectInstructionChecker.java
+++ b/src/proguard/optimize/info/SideEffectInstructionChecker.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
@@ -29,11 +29,14 @@ import proguard.classfile.instruction.visitor.InstructionVisitor;
import proguard.classfile.util.SimplifiedVisitor;
import proguard.classfile.visitor.*;
+import java.util.*;
+
/**
- * This class can tell whether an instruction has any side effects. Return
- * instructions can be included or not.
+ * This class can tell whether an instruction has any side effects outside of
+ * its method. Return instructions can be included or not.
*
* @see ReadWriteFieldMarker
+ * @see StaticInitializerContainingClassMarker
* @see NoSideEffectMethodMarker
* @see SideEffectMethodMarker
* @author Eric Lafortune
@@ -44,23 +47,38 @@ implements InstructionVisitor,
ConstantVisitor,
MemberVisitor
{
+ private static final boolean OPTIMIZE_CONSERVATIVELY = System.getProperty("optimize.conservatively") != null;
+
+
private final boolean includeReturnInstructions;
+ private final boolean includeLocalFieldAccess;
// A return value for the visitor methods.
+ private Clazz referencingClass;
private boolean hasSideEffects;
- public SideEffectInstructionChecker(boolean includeReturnInstructions)
+ public SideEffectInstructionChecker(boolean includeReturnInstructions,
+ boolean includeLocalFieldAccess)
{
this.includeReturnInstructions = includeReturnInstructions;
+ this.includeLocalFieldAccess = includeLocalFieldAccess;
}
- public boolean hasSideEffects(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction)
+ /**
+ * Returns whether the given instruction has side effects outside of its
+ * method.
+ */
+ public boolean hasSideEffects(Clazz clazz,
+ Method method,
+ CodeAttribute codeAttribute,
+ int offset,
+ Instruction instruction)
{
hasSideEffects = false;
- instruction.accept(clazz, method, codeAttribute, offset, this);
+ instruction.accept(clazz, method, codeAttribute, offset, this);
return hasSideEffects;
}
@@ -76,29 +94,46 @@ implements InstructionVisitor,
byte opcode = simpleInstruction.opcode;
// Check for instructions that might cause side effects.
- if (opcode == InstructionConstants.OP_IASTORE ||
- opcode == InstructionConstants.OP_LASTORE ||
- opcode == InstructionConstants.OP_FASTORE ||
- opcode == InstructionConstants.OP_DASTORE ||
- opcode == InstructionConstants.OP_AASTORE ||
- opcode == InstructionConstants.OP_BASTORE ||
- opcode == InstructionConstants.OP_CASTORE ||
- opcode == InstructionConstants.OP_SASTORE ||
- opcode == InstructionConstants.OP_ATHROW ||
- opcode == InstructionConstants.OP_MONITORENTER ||
- opcode == InstructionConstants.OP_MONITOREXIT ||
- (includeReturnInstructions &&
- (opcode == InstructionConstants.OP_IRETURN ||
- opcode == InstructionConstants.OP_LRETURN ||
- opcode == InstructionConstants.OP_FRETURN ||
- opcode == InstructionConstants.OP_DRETURN ||
- opcode == InstructionConstants.OP_ARETURN ||
- opcode == InstructionConstants.OP_RETURN)))
+ switch (opcode)
{
- // These instructions always cause a side effect.
- hasSideEffects = true;
+ case InstructionConstants.OP_IALOAD:
+ case InstructionConstants.OP_LALOAD:
+ case InstructionConstants.OP_FALOAD:
+ case InstructionConstants.OP_DALOAD:
+ case InstructionConstants.OP_AALOAD:
+ case InstructionConstants.OP_BALOAD:
+ case InstructionConstants.OP_CALOAD:
+ case InstructionConstants.OP_SALOAD:
+ // These instructions strictly taken may cause a side effect
+ // (NullPointerException, ArrayIndexOutOfBoundsException).
+ hasSideEffects = OPTIMIZE_CONSERVATIVELY;
+ break;
+
+ case InstructionConstants.OP_IASTORE:
+ case InstructionConstants.OP_LASTORE:
+ case InstructionConstants.OP_FASTORE:
+ case InstructionConstants.OP_DASTORE:
+ case InstructionConstants.OP_AASTORE:
+ case InstructionConstants.OP_BASTORE:
+ case InstructionConstants.OP_CASTORE:
+ case InstructionConstants.OP_SASTORE:
+ case InstructionConstants.OP_ATHROW :
+ case InstructionConstants.OP_MONITORENTER:
+ case InstructionConstants.OP_MONITOREXIT:
+ // These instructions always cause a side effect.
+ hasSideEffects = true;
+ break;
+
+ case InstructionConstants.OP_IRETURN:
+ case InstructionConstants.OP_LRETURN:
+ case InstructionConstants.OP_FRETURN:
+ case InstructionConstants.OP_DRETURN:
+ case InstructionConstants.OP_ARETURN:
+ case InstructionConstants.OP_RETURN:
+ // These instructions may have a side effect.
+ hasSideEffects = includeReturnInstructions;
+ break;
}
-
}
@@ -107,10 +142,12 @@ implements InstructionVisitor,
byte opcode = variableInstruction.opcode;
// Check for instructions that might cause side effects.
- if (includeReturnInstructions &&
- opcode == InstructionConstants.OP_RET)
+ switch (opcode)
{
- hasSideEffects = true;
+ case InstructionConstants.OP_RET:
+ // This instruction may have a side effect.
+ hasSideEffects = includeReturnInstructions;
+ break;
}
}
@@ -120,16 +157,41 @@ implements InstructionVisitor,
byte opcode = constantInstruction.opcode;
// Check for instructions that might cause side effects.
- if (opcode == InstructionConstants.OP_PUTSTATIC ||
- opcode == InstructionConstants.OP_PUTFIELD ||
- opcode == InstructionConstants.OP_INVOKEVIRTUAL ||
- opcode == InstructionConstants.OP_INVOKESPECIAL ||
- opcode == InstructionConstants.OP_INVOKESTATIC ||
- opcode == InstructionConstants.OP_INVOKEINTERFACE)
+ switch (opcode)
{
- // Check if the field is write-only or volatile, or if the invoked
- // method is causing any side effects.
- clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
+ case InstructionConstants.OP_GETSTATIC:
+ case InstructionConstants.OP_PUTSTATIC:
+ case InstructionConstants.OP_INVOKESPECIAL:
+ case InstructionConstants.OP_INVOKESTATIC:
+ // Check if the field is write-only or volatile, or if the
+ // invoked method is causing any side effects.
+ clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
+ break;
+
+ case InstructionConstants.OP_GETFIELD:
+ case InstructionConstants.OP_PUTFIELD:
+ case InstructionConstants.OP_INVOKEVIRTUAL:
+ case InstructionConstants.OP_INVOKEINTERFACE:
+ case InstructionConstants.OP_INVOKEDYNAMIC:
+ if (OPTIMIZE_CONSERVATIVELY)
+ {
+ // These instructions strictly taken may cause a side effect
+ // (NullPointerException).
+ hasSideEffects = true;
+ }
+ else
+ {
+ // Check if the field is write-only or volatile, or if the
+ // invoked method is causing any side effects.
+ clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
+ }
+ break;
+
+ case InstructionConstants.OP_CHECKCAST:
+ // This instructions strictly taken may cause a side effect
+ // (ClassCastException).
+ hasSideEffects = OPTIMIZE_CONSERVATIVELY;
+ break;
}
}
@@ -139,59 +201,48 @@ implements InstructionVisitor,
byte opcode = branchInstruction.opcode;
// Check for instructions that might cause side effects.
- if (includeReturnInstructions &&
- (opcode == InstructionConstants.OP_JSR ||
- opcode == InstructionConstants.OP_JSR_W))
+ switch (opcode)
{
- hasSideEffects = true;
+ case InstructionConstants.OP_JSR:
+ case InstructionConstants.OP_JSR_W:
+ hasSideEffects = includeReturnInstructions;
+ break;
}
}
// Implementations for ConstantVisitor.
+ public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
+ {
+ // We'll have to assume invoking an unknown method has side effects.
+ hasSideEffects = true;
+ }
+
+
public void visitFieldrefConstant(Clazz clazz, FieldrefConstant fieldrefConstant)
{
+ // Pass the referencing class.
+ referencingClass = clazz;
+
// We'll have to assume accessing an unknown field has side effects.
hasSideEffects = true;
- // Check the referenced field.
+ // Check the referenced field, if known.
fieldrefConstant.referencedMemberAccept(this);
}
public void visitAnyMethodrefConstant(Clazz clazz, RefConstant refConstant)
{
- Member referencedMember = refConstant.referencedMember;
+ // Pass the referencing class.
+ referencingClass = clazz;
- // Do we have a reference to the method?
- if (referencedMember == null)
- {
- // We'll have to assume invoking the unknown method has side effects.
- hasSideEffects = true;
- }
- else
- {
- // First check the referenced method itself.
- refConstant.referencedMemberAccept(this);
-
- // If the result isn't conclusive, check down the hierarchy.
- if (!hasSideEffects)
- {
- Clazz referencedClass = refConstant.referencedClass;
- Method referencedMethod = (Method)referencedMember;
-
- // Check all other implementations of the method down the class
- // hierarchy.
- if ((referencedMethod.getAccessFlags() & ClassConstants.INTERNAL_ACC_PRIVATE) == 0)
- {
- clazz.hierarchyAccept(false, false, false, true,
- new NamedMethodVisitor(referencedMethod.getName(referencedClass),
- referencedMethod.getDescriptor(referencedClass),
- this));
- }
- }
- }
+ // We'll have to assume invoking an unknown method has side effects.
+ hasSideEffects = true;
+
+ // Check the referenced method, if known.
+ refConstant.referencedMemberAccept(this);
}
@@ -199,14 +250,25 @@ implements InstructionVisitor,
public void visitProgramField(ProgramClass programClass, ProgramField programField)
{
- hasSideEffects = ReadWriteFieldMarker.isRead(programField);
+ hasSideEffects =
+ (includeLocalFieldAccess || !programClass.equals(referencingClass)) &&
+ ((ReadWriteFieldMarker.isRead(programField) &&
+ ReadWriteFieldMarker.isWritten(programField)) ||
+ ((programField.getAccessFlags() & ClassConstants.INTERNAL_ACC_VOLATILE) != 0) ||
+ (!programClass.equals(referencingClass) &&
+ !initializedSuperClasses(referencingClass).containsAll(initializedSuperClasses(programClass))));
}
public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
{
- hasSideEffects = hasSideEffects ||
- SideEffectMethodMarker.hasSideEffects(programMethod);
+ // Note that side effects already include synchronization of some
+ // implementation of the method.
+ hasSideEffects =
+ !NoSideEffectMethodMarker.hasNoSideEffects(programMethod) &&
+ (SideEffectMethodMarker.hasSideEffects(programMethod) ||
+ (!programClass.equals(referencingClass) &&
+ !initializedSuperClasses(referencingClass).containsAll(initializedSuperClasses(programClass))));
}
@@ -218,7 +280,28 @@ implements InstructionVisitor,
public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
{
- hasSideEffects = hasSideEffects ||
- !NoSideEffectMethodMarker.hasNoSideEffects(libraryMethod);
+ hasSideEffects =
+ !NoSideEffectMethodMarker.hasNoSideEffects(libraryMethod);
+ }
+
+
+ /**
+ * Returns the set of superclasses and interfaces that are initialized.
+ */
+ private Set initializedSuperClasses(Clazz clazz)
+ {
+ Set set = new HashSet();
+
+ // Visit all superclasses and interfaces, collecting the ones that have
+ // static initializers.
+ clazz.hierarchyAccept(true, true, true, false,
+ new StaticInitializerContainingClassFilter(
+ new NamedMethodVisitor(ClassConstants.INTERNAL_METHOD_NAME_CLINIT,
+ ClassConstants.INTERNAL_METHOD_TYPE_CLINIT,
+ new SideEffectMethodFilter(
+ new MemberToClassVisitor(
+ new ClassCollector(set))))));
+
+ return set;
}
}
diff --git a/src/proguard/optimize/info/SideEffectMethodFilter.java b/src/proguard/optimize/info/SideEffectMethodFilter.java
new file mode 100644
index 0000000..52e072a
--- /dev/null
+++ b/src/proguard/optimize/info/SideEffectMethodFilter.java
@@ -0,0 +1,73 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * 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
+ * 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.info;
+
+import proguard.classfile.*;
+import proguard.classfile.visitor.MemberVisitor;
+
+/**
+ * This MemberVisitor delegates all its method calls to another MemberVisitor,
+ * but only for Method objects that are marked as having side effects.
+ *
+ * @see SideEffectMethodMarker
+ *
+ * @author Eric Lafortune
+ */
+public class SideEffectMethodFilter
+implements MemberVisitor
+{
+ private final MemberVisitor memberVisitor;
+
+
+ /**
+ * Creates a new SideEffectMethodFilter.
+ * @param memberVisitor the member visitor to which the visiting will be
+ * delegated.
+ */
+ public SideEffectMethodFilter(MemberVisitor memberVisitor)
+ {
+ this.memberVisitor = memberVisitor;
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramField(ProgramClass programClass, ProgramField programField) {}
+ public void visitLibraryField(LibraryClass libraryClass, LibraryField libraryField) {}
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ if (SideEffectMethodMarker.hasSideEffects(programMethod))
+ {
+ memberVisitor.visitProgramMethod(programClass, programMethod);
+ }
+ }
+
+
+ public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
+ {
+ if (SideEffectMethodMarker.hasSideEffects(libraryMethod))
+ {
+ memberVisitor.visitLibraryMethod(libraryClass, libraryMethod);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/proguard/optimize/info/SideEffectMethodMarker.java b/src/proguard/optimize/info/SideEffectMethodMarker.java
index 25fda72..f7953c0 100644
--- a/src/proguard/optimize/info/SideEffectMethodMarker.java
+++ b/src/proguard/optimize/info/SideEffectMethodMarker.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
@@ -41,8 +41,9 @@ implements ClassPoolVisitor,
MemberVisitor,
AttributeVisitor
{
- // A reusable object for checking whether instructions have side effects.
- private final SideEffectInstructionChecker sideEffectInstructionChecker = new SideEffectInstructionChecker(false);
+ // Reusable objects for checking whether instructions have side effects.
+ private final SideEffectInstructionChecker sideEffectInstructionChecker = new SideEffectInstructionChecker(false, true);
+ private final SideEffectInstructionChecker initializerSideEffectInstructionChecker = new SideEffectInstructionChecker(false, false);
// Parameters and values for visitor methods.
private int newSideEffectCount;
@@ -130,6 +131,11 @@ implements ClassPoolVisitor,
byte[] code = codeAttribute.code;
int length = codeAttribute.u4codeLength;
+ SideEffectInstructionChecker checker =
+ method.getName(clazz).equals(ClassConstants.INTERNAL_METHOD_NAME_CLINIT) ?
+ initializerSideEffectInstructionChecker :
+ sideEffectInstructionChecker;
+
// Go over all instructions.
int offset = 0;
do
@@ -138,11 +144,11 @@ implements ClassPoolVisitor,
Instruction instruction = InstructionFactory.create(code, offset);
// Check if it may be throwing exceptions.
- if (sideEffectInstructionChecker.hasSideEffects(clazz,
- method,
- codeAttribute,
- offset,
- instruction))
+ if (checker.hasSideEffects(clazz,
+ method,
+ codeAttribute,
+ offset,
+ instruction))
{
return true;
}
diff --git a/src/proguard/optimize/info/StaticInitializerContainingClassFilter.java b/src/proguard/optimize/info/StaticInitializerContainingClassFilter.java
new file mode 100644
index 0000000..36aa392
--- /dev/null
+++ b/src/proguard/optimize/info/StaticInitializerContainingClassFilter.java
@@ -0,0 +1,62 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * 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
+ * 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.info;
+
+import proguard.classfile.*;
+import proguard.classfile.visitor.ClassVisitor;
+
+/**
+ * This ClassVisitor delegates all its method calls to another ClassVisitor,
+ * but only for Clazz objects that are instantiated.
+ *
+ * @author Eric Lafortune
+ */
+public class StaticInitializerContainingClassFilter
+implements ClassVisitor
+{
+ private final ClassVisitor classVisitor;
+
+
+ public StaticInitializerContainingClassFilter(ClassVisitor classVisitor)
+ {
+ this.classVisitor = classVisitor;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ if (StaticInitializerContainingClassMarker.containsStaticInitializer(programClass))
+ {
+ classVisitor.visitProgramClass(programClass);
+ }
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ if (StaticInitializerContainingClassMarker.containsStaticInitializer(libraryClass))
+ {
+ classVisitor.visitLibraryClass(libraryClass);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/proguard/optimize/info/StaticInitializerContainingClassMarker.java b/src/proguard/optimize/info/StaticInitializerContainingClassMarker.java
new file mode 100644
index 0000000..3a7e642
--- /dev/null
+++ b/src/proguard/optimize/info/StaticInitializerContainingClassMarker.java
@@ -0,0 +1,65 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * 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
+ * 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.info;
+
+import proguard.classfile.*;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.*;
+
+/**
+ * This ClassVisitor marks all classes that contain static initializers.
+ *
+ * @author Eric Lafortune
+ */
+public class StaticInitializerContainingClassMarker
+extends SimplifiedVisitor
+implements ClassVisitor
+{
+ // Implementations for ClassVisitor.
+
+ public void visitAnyClass(Clazz clazz)
+ {
+ if (clazz.findMethod(ClassConstants.INTERNAL_METHOD_NAME_CLINIT,
+ ClassConstants.INTERNAL_METHOD_TYPE_CLINIT) != null)
+ {
+ setStaticInitializer(clazz);
+ }
+ }
+
+
+ // Small utility methods.
+
+ private static void setStaticInitializer(Clazz clazz)
+ {
+ ClassOptimizationInfo info = ClassOptimizationInfo.getClassOptimizationInfo(clazz);
+ if (info != null)
+ {
+ info.setContainsStaticInitializer();
+ }
+ }
+
+
+ public static boolean containsStaticInitializer(Clazz clazz)
+ {
+ ClassOptimizationInfo info = ClassOptimizationInfo.getClassOptimizationInfo(clazz);
+ return info == null || info.containsStaticInitializer();
+ }
+} \ No newline at end of file
diff --git a/src/proguard/optimize/info/SuperInvocationMarker.java b/src/proguard/optimize/info/SuperInvocationMarker.java
index 6f3d3bd..37b118a 100644
--- a/src/proguard/optimize/info/SuperInvocationMarker.java
+++ b/src/proguard/optimize/info/SuperInvocationMarker.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
diff --git a/src/proguard/optimize/info/VariableUsageMarker.java b/src/proguard/optimize/info/VariableUsageMarker.java
index 660c4ba..b189ca9 100644
--- a/src/proguard/optimize/info/VariableUsageMarker.java
+++ b/src/proguard/optimize/info/VariableUsageMarker.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
@@ -27,6 +27,8 @@ import proguard.classfile.instruction.*;
import proguard.classfile.instruction.visitor.InstructionVisitor;
import proguard.classfile.util.SimplifiedVisitor;
+import java.util.Arrays;
+
/**
* This AttributeVisitor marks the local variables that are used in the code
* attributes that it visits.
@@ -62,14 +64,13 @@ implements AttributeVisitor,
// Try to reuse the previous array.
if (variableUsed.length < maxLocals)
{
+ // Create a new array.
variableUsed = new boolean[maxLocals];
}
else
{
- for (int index = 0; index < maxLocals; index++)
- {
- variableUsed[index] = false;
- }
+ // Reset the array.
+ Arrays.fill(variableUsed, 0, maxLocals, false);
}
codeAttribute.instructionsAccept(clazz, method, this);