summaryrefslogtreecommitdiff
path: root/src/proguard/optimize/info
diff options
context:
space:
mode:
authorJoe Onorato <joeo@android.com>2009-08-31 10:12:00 -0700
committerJoe Onorato <joeo@android.com>2009-08-31 10:12:00 -0700
commitb72c5c2e5482cf10117b2b25f642f7616b2326c3 (patch)
treef02ba1bc29f4fe6853d9b7008eed37cdcfb96e81 /src/proguard/optimize/info
parenta23344a828357fe4b6596f8af5fed467d72757ab (diff)
downloadproguard-eclair-sholes-release.tar.gz
Diffstat (limited to 'src/proguard/optimize/info')
-rw-r--r--src/proguard/optimize/info/AccessMethodMarker.java187
-rw-r--r--src/proguard/optimize/info/BackwardBranchMarker.java90
-rw-r--r--src/proguard/optimize/info/CatchExceptionMarker.java69
-rw-r--r--src/proguard/optimize/info/CaughtClassFilter.java63
-rw-r--r--src/proguard/optimize/info/CaughtClassMarker.java63
-rw-r--r--src/proguard/optimize/info/ClassOptimizationInfo.java151
-rw-r--r--src/proguard/optimize/info/ClassOptimizationInfoSetter.java47
-rw-r--r--src/proguard/optimize/info/DotClassFilter.java63
-rw-r--r--src/proguard/optimize/info/DotClassMarker.java96
-rw-r--r--src/proguard/optimize/info/ExceptionInstructionChecker.java187
-rw-r--r--src/proguard/optimize/info/FieldOptimizationInfo.java162
-rw-r--r--src/proguard/optimize/info/InstanceofClassFilter.java63
-rw-r--r--src/proguard/optimize/info/InstanceofClassMarker.java93
-rw-r--r--src/proguard/optimize/info/InstantiationClassFilter.java62
-rw-r--r--src/proguard/optimize/info/InstantiationClassMarker.java93
-rw-r--r--src/proguard/optimize/info/MemberOptimizationInfoSetter.java59
-rw-r--r--src/proguard/optimize/info/MethodInvocationMarker.java107
-rw-r--r--src/proguard/optimize/info/MethodOptimizationInfo.java302
-rw-r--r--src/proguard/optimize/info/NoSideEffectMethodMarker.java91
-rw-r--r--src/proguard/optimize/info/NonPrivateMemberMarker.java177
-rw-r--r--src/proguard/optimize/info/PackageVisibleMemberContainingClassMarker.java67
-rw-r--r--src/proguard/optimize/info/PackageVisibleMemberInvokingClassMarker.java81
-rw-r--r--src/proguard/optimize/info/ParameterUsageMarker.java285
-rw-r--r--src/proguard/optimize/info/ReadWriteFieldMarker.java163
-rw-r--r--src/proguard/optimize/info/SideEffectInstructionChecker.java224
-rw-r--r--src/proguard/optimize/info/SideEffectMethodMarker.java175
-rw-r--r--src/proguard/optimize/info/SuperInvocationMarker.java93
-rw-r--r--src/proguard/optimize/info/VariableUsageMarker.java95
-rw-r--r--src/proguard/optimize/info/package.html4
29 files changed, 3412 insertions, 0 deletions
diff --git a/src/proguard/optimize/info/AccessMethodMarker.java b/src/proguard/optimize/info/AccessMethodMarker.java
new file mode 100644
index 0000000..6965cec
--- /dev/null
+++ b/src/proguard/optimize/info/AccessMethodMarker.java
@@ -0,0 +1,187 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2009 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.attribute.CodeAttribute;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.*;
+
+/**
+ * This InstructionVisitor marks the types of class accesses and class member
+ * accesses of the methods whose instructions it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class AccessMethodMarker
+extends SimplifiedVisitor
+implements InstructionVisitor,
+ ConstantVisitor,
+ ClassVisitor,
+ MemberVisitor
+{
+ private Method invokingMethod;
+
+
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
+
+
+ public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
+ {
+ invokingMethod = method;
+
+ clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyConstant(Clazz clazz, Constant constant) {}
+
+
+ public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
+ {
+ // Check the referenced class or class member, if any.
+ stringConstant.referencedClassAccept(this);
+ stringConstant.referencedMemberAccept(this);
+ }
+
+
+ public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
+ {
+ // Check the referenced class.
+ clazz.constantPoolEntryAccept(refConstant.u2classIndex, this);
+
+ // Check the referenced class member itself.
+ refConstant.referencedClassAccept(this);
+ refConstant.referencedMemberAccept(this);
+ }
+
+
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+ {
+ // Check the referenced class.
+ classConstant.referencedClassAccept(this);
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitAnyClass(Clazz clazz)
+ {
+ int accessFlags = clazz.getAccessFlags();
+
+ if ((accessFlags & ClassConstants.INTERNAL_ACC_PUBLIC) == 0)
+ {
+ setAccessesPackageCode(invokingMethod);
+ }
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitAnyMember(Clazz clazz, Member member)
+ {
+ int accessFlags = member.getAccessFlags();
+
+ if ((accessFlags & ClassConstants.INTERNAL_ACC_PRIVATE) != 0)
+ {
+ setAccessesPrivateCode(invokingMethod);
+ }
+ else if ((accessFlags & ClassConstants.INTERNAL_ACC_PROTECTED) != 0)
+ {
+ setAccessesProtectedCode(invokingMethod);
+ }
+ else if ((accessFlags & ClassConstants.INTERNAL_ACC_PUBLIC) == 0)
+ {
+ setAccessesPackageCode(invokingMethod);
+ }
+ }
+
+
+ // Small utility methods.
+
+ private static void setAccessesPrivateCode(Method method)
+ {
+ MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
+ if (info != null)
+ {
+ info.setAccessesPrivateCode();
+ }
+ }
+
+
+ /**
+ * Returns whether the given method accesses private class members.
+ */
+ public static boolean accessesPrivateCode(Method method)
+ {
+ MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
+ return info == null || info.accessesPrivateCode();
+ }
+
+
+ private static void setAccessesPackageCode(Method method)
+ {
+ MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
+ if (info != null)
+ {
+ info.setAccessesPackageCode();
+ }
+ }
+
+
+ /**
+ * Returns whether the given method accesses package visible classes or class
+ * members.
+ */
+ public static boolean accessesPackageCode(Method method)
+ {
+ MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
+ return info == null || info.accessesPackageCode();
+ }
+
+
+ private static void setAccessesProtectedCode(Method method)
+ {
+ MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
+ if (info != null)
+ {
+ info.setAccessesProtectedCode();
+ }
+ }
+
+
+ /**
+ * Returns whether the given method accesses protected class members.
+ */
+ public static boolean accessesProtectedCode(Method method)
+ {
+ MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
+ return info == null || info.accessesProtectedCode();
+ }
+}
diff --git a/src/proguard/optimize/info/BackwardBranchMarker.java b/src/proguard/optimize/info/BackwardBranchMarker.java
new file mode 100644
index 0000000..9e09b0f
--- /dev/null
+++ b/src/proguard/optimize/info/BackwardBranchMarker.java
@@ -0,0 +1,90 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2009 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.attribute.CodeAttribute;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+
+/**
+ * This InstructionVisitor marks all methods that branch backward in any of the
+ * instructions that it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class BackwardBranchMarker
+extends SimplifiedVisitor
+implements InstructionVisitor
+{
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
+
+
+ public void visitBranchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction)
+ {
+ markBackwardBranch(method, branchInstruction.branchOffset);
+ }
+
+
+ public void visitAnySwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SwitchInstruction switchInstruction)
+ {
+ markBackwardBranch(method, switchInstruction.defaultOffset);
+
+ for (int index = 0; index < switchInstruction.jumpOffsets.length; index++)
+ {
+ markBackwardBranch(method, switchInstruction.jumpOffsets[index]);
+ }
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Marks the given method if the given branch offset is negative.
+ */
+ private void markBackwardBranch(Method method, int branchOffset)
+ {
+ if (branchOffset < 0)
+ {
+ setBranchesBackward(method);
+ }
+ }
+
+
+ private static void setBranchesBackward(Method method)
+ {
+ MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
+ if (info != null)
+ {
+ info.setBranchesBackward();
+ }
+ }
+
+
+ public static boolean branchesBackward(Method method)
+ {
+ MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
+ return info == null || info.branchesBackward();
+ }
+}
diff --git a/src/proguard/optimize/info/CatchExceptionMarker.java b/src/proguard/optimize/info/CatchExceptionMarker.java
new file mode 100644
index 0000000..3f2a06f
--- /dev/null
+++ b/src/proguard/optimize/info/CatchExceptionMarker.java
@@ -0,0 +1,69 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2009 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.attribute.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+
+/**
+ * This AttributeVisitor marks all methods that catch exceptions.
+ *
+ * @author Eric Lafortune
+ */
+public class CatchExceptionMarker
+extends SimplifiedVisitor
+implements AttributeVisitor
+{
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ if (codeAttribute.u2exceptionTableLength > 0)
+ {
+ markCatchException(method);
+ }
+ }
+
+
+ // Small utility methods.
+
+ private static void markCatchException(Method method)
+ {
+ MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
+ if (info != null)
+ {
+ info.setCatchesExceptions();
+ }
+ }
+
+
+ public static boolean catchesExceptions(Method method)
+ {
+ MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
+ return info == null ||
+ info.catchesExceptions();
+ }
+}
diff --git a/src/proguard/optimize/info/CaughtClassFilter.java b/src/proguard/optimize/info/CaughtClassFilter.java
new file mode 100644
index 0000000..5e17763
--- /dev/null
+++ b/src/proguard/optimize/info/CaughtClassFilter.java
@@ -0,0 +1,63 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2009 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 caught as exceptions.
+ *
+ * @see CaughtClassMarker
+ * @author Eric Lafortune
+ */
+public class CaughtClassFilter
+implements ClassVisitor
+{
+ private final ClassVisitor classVisitor;
+
+
+ public CaughtClassFilter(ClassVisitor classVisitor)
+ {
+ this.classVisitor = classVisitor;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ if (CaughtClassMarker.isCaught(programClass))
+ {
+ classVisitor.visitProgramClass(programClass);
+ }
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ if (CaughtClassMarker.isCaught(libraryClass))
+ {
+ classVisitor.visitLibraryClass(libraryClass);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/proguard/optimize/info/CaughtClassMarker.java b/src/proguard/optimize/info/CaughtClassMarker.java
new file mode 100644
index 0000000..0cc350e
--- /dev/null
+++ b/src/proguard/optimize/info/CaughtClassMarker.java
@@ -0,0 +1,63 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2009 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.ClassVisitor;
+
+/**
+ * This InstructionVisitor marks all classes that are used in an 'instanceof'
+ * test by any of the instructions that it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class CaughtClassMarker
+implements ClassVisitor
+{
+ // Implementations for ClassVisitor.
+
+ public void visitLibraryClass(LibraryClass libraryClass) {}
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ setCaught(programClass);
+ }
+
+
+ // Small utility methods.
+
+ private static void setCaught(Clazz clazz)
+ {
+ ClassOptimizationInfo info = ClassOptimizationInfo.getClassOptimizationInfo(clazz);
+ if (info != null)
+ {
+ info.setCaught();
+ }
+ }
+
+
+ public static boolean isCaught(Clazz clazz)
+ {
+ ClassOptimizationInfo info = ClassOptimizationInfo.getClassOptimizationInfo(clazz);
+ return info == null || info.isCaught();
+ }
+} \ No newline at end of file
diff --git a/src/proguard/optimize/info/ClassOptimizationInfo.java b/src/proguard/optimize/info/ClassOptimizationInfo.java
new file mode 100644
index 0000000..99b6e7b
--- /dev/null
+++ b/src/proguard/optimize/info/ClassOptimizationInfo.java
@@ -0,0 +1,151 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2009 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.Clazz;
+
+/**
+ * This class stores some optimization information that can be attached to
+ * a class.
+ *
+ * @author Eric Lafortune
+ */
+public class ClassOptimizationInfo
+{
+ private boolean isInstantiated = false;
+ private boolean isInstanceofed = false;
+ private boolean isDotClassed = false;
+ private boolean isCaught = false;
+ private boolean containsPackageVisibleMembers = false;
+ private boolean invokesPackageVisibleMembers = false;
+ private Clazz targetClass;
+
+
+ public void setInstantiated()
+ {
+ isInstantiated = true;
+ }
+
+
+ public boolean isInstantiated()
+ {
+ return isInstantiated;
+ }
+
+
+ public void setInstanceofed()
+ {
+ isInstanceofed = true;
+ }
+
+
+ public boolean isInstanceofed()
+ {
+ return isInstanceofed;
+ }
+
+
+ public void setDotClassed()
+ {
+ isDotClassed = true;
+ }
+
+
+ public boolean isDotClassed()
+ {
+ return isDotClassed;
+ }
+
+
+ public void setCaught()
+ {
+ isCaught = true;
+ }
+
+
+ public boolean isCaught()
+ {
+ return isCaught;
+ }
+
+
+ public void setContainsPackageVisibleMembers()
+ {
+ containsPackageVisibleMembers = true;
+ }
+
+
+ public boolean containsPackageVisibleMembers()
+ {
+ return containsPackageVisibleMembers;
+ }
+
+
+ public void setInvokesPackageVisibleMembers()
+ {
+ invokesPackageVisibleMembers = true;
+ }
+
+
+ public boolean invokesPackageVisibleMembers()
+ {
+ return invokesPackageVisibleMembers;
+ }
+
+
+ public void setTargetClass(Clazz targetClass)
+ {
+ this.targetClass = targetClass;
+ }
+
+
+ public Clazz getTargetClass()
+ {
+ return targetClass;
+ }
+
+
+ public void merge(ClassOptimizationInfo other)
+ {
+ this.isInstantiated |= other.isInstantiated;
+ this.isInstanceofed |= other.isInstanceofed;
+ this.isDotClassed |= other.isDotClassed;
+ this.isCaught |= other.isCaught;
+ this.containsPackageVisibleMembers |= other.containsPackageVisibleMembers;
+ this.invokesPackageVisibleMembers |= other.invokesPackageVisibleMembers;
+ }
+
+
+ public static void setClassOptimizationInfo(Clazz clazz)
+ {
+ clazz.setVisitorInfo(new ClassOptimizationInfo());
+ }
+
+
+ public static ClassOptimizationInfo getClassOptimizationInfo(Clazz clazz)
+ {
+ Object visitorInfo = clazz.getVisitorInfo();
+
+ return visitorInfo instanceof ClassOptimizationInfo ?
+ (ClassOptimizationInfo)visitorInfo :
+ null;
+ }
+}
diff --git a/src/proguard/optimize/info/ClassOptimizationInfoSetter.java b/src/proguard/optimize/info/ClassOptimizationInfoSetter.java
new file mode 100644
index 0000000..9cb167c
--- /dev/null
+++ b/src/proguard/optimize/info/ClassOptimizationInfoSetter.java
@@ -0,0 +1,47 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2009 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.ClassVisitor;
+import proguard.optimize.KeepMarker;
+
+/**
+ * This ClassVisitor attaches a ClassOptimizationInfo instance to every class
+ * that is not being kept that it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class ClassOptimizationInfoSetter
+extends SimplifiedVisitor
+implements ClassVisitor
+{
+ // Implementations for MemberVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ if (!KeepMarker.isKept(programClass))
+ {
+ ClassOptimizationInfo.setClassOptimizationInfo(programClass);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/proguard/optimize/info/DotClassFilter.java b/src/proguard/optimize/info/DotClassFilter.java
new file mode 100644
index 0000000..8cbe7f0
--- /dev/null
+++ b/src/proguard/optimize/info/DotClassFilter.java
@@ -0,0 +1,63 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2009 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 used in a .class construct.
+ *
+ * @see DotClassMarker
+ * @author Eric Lafortune
+ */
+public class DotClassFilter
+implements ClassVisitor
+{
+ private final ClassVisitor classVisitor;
+
+
+ public DotClassFilter(ClassVisitor classVisitor)
+ {
+ this.classVisitor = classVisitor;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ if (DotClassMarker.isDotClassed(programClass))
+ {
+ classVisitor.visitProgramClass(programClass);
+ }
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ if (DotClassMarker.isDotClassed(libraryClass))
+ {
+ classVisitor.visitLibraryClass(libraryClass);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/proguard/optimize/info/DotClassMarker.java b/src/proguard/optimize/info/DotClassMarker.java
new file mode 100644
index 0000000..b5f12a7
--- /dev/null
+++ b/src/proguard/optimize/info/DotClassMarker.java
@@ -0,0 +1,96 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2009 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.attribute.CodeAttribute;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.ClassVisitor;
+
+/**
+ * This InstructionVisitor marks all classes that are used in a .class
+ * construct by any of the instructions that it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class DotClassMarker
+extends SimplifiedVisitor
+implements InstructionVisitor,
+ ConstantVisitor,
+ ClassVisitor
+{
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
+
+
+ public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
+ {
+ if (constantInstruction.opcode == InstructionConstants.OP_LDC ||
+ constantInstruction.opcode == InstructionConstants.OP_LDC_W)
+ {
+ clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
+ }
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyConstant(Clazz clazz, Constant constant) {}
+
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+ {
+ classConstant.referencedClassAccept(this);
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitLibraryClass(LibraryClass libraryClass) {}
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ setDotClassed(programClass);
+ }
+
+
+ // Small utility methods.
+
+ private static void setDotClassed(Clazz clazz)
+ {
+ ClassOptimizationInfo info = ClassOptimizationInfo.getClassOptimizationInfo(clazz);
+ if (info != null)
+ {
+ info.setDotClassed();
+ }
+ }
+
+
+ public static boolean isDotClassed(Clazz clazz)
+ {
+ ClassOptimizationInfo info = ClassOptimizationInfo.getClassOptimizationInfo(clazz);
+ return info == null || info.isDotClassed();
+ }
+} \ No newline at end of file
diff --git a/src/proguard/optimize/info/ExceptionInstructionChecker.java b/src/proguard/optimize/info/ExceptionInstructionChecker.java
new file mode 100644
index 0000000..2792d90
--- /dev/null
+++ b/src/proguard/optimize/info/ExceptionInstructionChecker.java
@@ -0,0 +1,187 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2009 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.attribute.CodeAttribute;
+import proguard.classfile.constant.RefConstant;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.MemberVisitor;
+
+/**
+ * This class can tell whether an instruction might throw exceptions.
+ *
+ * @author Eric Lafortune
+ */
+public class ExceptionInstructionChecker
+extends SimplifiedVisitor
+implements InstructionVisitor
+// ConstantVisitor,
+// MemberVisitor
+{
+ // A return value for the visitor methods.
+ private boolean mayThrowExceptions;
+
+
+ /**
+ * Returns whether the given instruction may throw exceptions.
+ */
+ public boolean mayThrowExceptions(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction)
+ {
+ mayThrowExceptions = false;
+
+ instruction.accept(clazz, method, codeAttribute, offset, this);
+
+ return mayThrowExceptions;
+ }
+
+
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
+
+
+ public void visitSimpleInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SimpleInstruction simpleInstruction)
+ {
+ 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)
+ {
+ // These instructions may throw exceptions.
+ mayThrowExceptions = true;
+ }
+
+ }
+
+
+ public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
+ {
+ 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)
+ {
+ // 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)
+// {
+// // Check if the invoking the method may throw an exception.
+// clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
+// }
+ }
+
+
+// // Implementations for ConstantVisitor.
+//
+// public void visitAnyMethodrefConstant(Clazz clazz, RefConstant refConstant)
+// {
+// Member referencedMember = refConstant.referencedMember;
+//
+// // Do we have a reference to the method?
+// if (referencedMember == null)
+// {
+// // We'll have to assume invoking the unknown method may throw an
+// // an exception.
+// mayThrowExceptions = true;
+// }
+// else
+// {
+// // First check the referenced method itself.
+// refConstant.referencedMemberAccept(this);
+//
+// // If the result isn't conclusive, check down the hierarchy.
+// if (!mayThrowExceptions)
+// {
+// Clazz referencedClass = refConstant.referencedClass;
+// Method referencedMethod = (Method)referencedMember;
+//
+// // Check all other implementations of the method in the class
+// // hierarchy.
+// referencedClass.methodImplementationsAccept(referencedMethod,
+// false,
+// false,
+// true,
+// true,
+// this);
+// }
+// }
+// }
+//
+//
+// // Implementations for MemberVisitor.
+//
+// public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+// {
+// mayThrowExceptions = mayThrowExceptions ||
+// ExceptionMethodMarker.mayThrowExceptions(programMethod);
+// }
+//
+//
+// public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
+// {
+// mayThrowExceptions = mayThrowExceptions ||
+// !NoExceptionMethodMarker.doesntThrowExceptions(libraryMethod);
+// }
+}
diff --git a/src/proguard/optimize/info/FieldOptimizationInfo.java b/src/proguard/optimize/info/FieldOptimizationInfo.java
new file mode 100644
index 0000000..7a2d068
--- /dev/null
+++ b/src/proguard/optimize/info/FieldOptimizationInfo.java
@@ -0,0 +1,162 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2009 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.MethodLinker;
+import proguard.evaluation.value.*;
+
+/**
+ * This class stores some optimization information that can be attached to
+ * a field.
+ *
+ * @author Eric Lafortune
+ */
+public class FieldOptimizationInfo
+{
+ private static final SpecificValueFactory VALUE_FACTORY = new SpecificValueFactory();
+
+ private boolean isWritten;
+ private boolean isRead;
+ private boolean canBeMadePrivate = true;
+ private ReferenceValue referencedClass;
+ private Value value;
+
+
+ public FieldOptimizationInfo(Clazz clazz, Field field)
+ {
+ isWritten =
+ isRead = (field.getAccessFlags() & ClassConstants.INTERNAL_ACC_VOLATILE) != 0;
+ value = initialValue(field.getDescriptor(clazz));
+ }
+
+
+ public void setWritten()
+ {
+ isWritten = true;
+ }
+
+
+ public boolean isWritten()
+ {
+ return isWritten;
+ }
+
+
+ public void setRead()
+ {
+ isRead = true;
+ }
+
+
+ public boolean isRead()
+ {
+ return isRead;
+ }
+
+
+ public void setCanNotBeMadePrivate()
+ {
+ canBeMadePrivate = false;
+ }
+
+
+ public boolean canBeMadePrivate()
+ {
+ return canBeMadePrivate;
+ }
+
+
+ public void generalizeReferencedClass(ReferenceValue referencedClass)
+ {
+ this.referencedClass = this.referencedClass != null ?
+ this.referencedClass.generalize(referencedClass) :
+ referencedClass;
+ }
+
+
+ public ReferenceValue getReferencedClass()
+ {
+ return referencedClass;
+ }
+
+
+ public void generalizeValue(Value value)
+ {
+ this.value = this.value != null ?
+ this.value.generalize(value) :
+ value;
+ }
+
+
+ public Value getValue()
+ {
+ return value;
+ }
+
+
+ // Small utility methods.
+
+ private Value initialValue(String type)
+ {
+ switch (type.charAt(0))
+ {
+ case ClassConstants.INTERNAL_TYPE_BOOLEAN:
+ case ClassConstants.INTERNAL_TYPE_BYTE:
+ case ClassConstants.INTERNAL_TYPE_CHAR:
+ case ClassConstants.INTERNAL_TYPE_SHORT:
+ case ClassConstants.INTERNAL_TYPE_INT:
+ return VALUE_FACTORY.createIntegerValue(0);
+
+ case ClassConstants.INTERNAL_TYPE_LONG:
+ return VALUE_FACTORY.createLongValue(0L);
+
+ case ClassConstants.INTERNAL_TYPE_FLOAT:
+ return VALUE_FACTORY.createFloatValue(0.0f);
+
+ case ClassConstants.INTERNAL_TYPE_DOUBLE:
+ return VALUE_FACTORY.createDoubleValue(0.0);
+
+ case ClassConstants.INTERNAL_TYPE_CLASS_START:
+ case ClassConstants.INTERNAL_TYPE_ARRAY:
+ return VALUE_FACTORY.createReferenceValueNull();
+
+ default:
+ throw new IllegalArgumentException("Invalid type ["+type+"]");
+ }
+ }
+
+
+ public static void setFieldOptimizationInfo(Clazz clazz, Field field)
+ {
+ MethodLinker.lastMember(field).setVisitorInfo(new FieldOptimizationInfo(clazz, field));
+ }
+
+
+ public static FieldOptimizationInfo getFieldOptimizationInfo(Field field)
+ {
+ Object visitorInfo = MethodLinker.lastMember(field).getVisitorInfo();
+
+ return visitorInfo instanceof FieldOptimizationInfo ?
+ (FieldOptimizationInfo)visitorInfo :
+ null;
+ }
+}
diff --git a/src/proguard/optimize/info/InstanceofClassFilter.java b/src/proguard/optimize/info/InstanceofClassFilter.java
new file mode 100644
index 0000000..35e1d77
--- /dev/null
+++ b/src/proguard/optimize/info/InstanceofClassFilter.java
@@ -0,0 +1,63 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2009 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 used in an 'instanceof' test.
+ *
+ * @see InstanceofClassMarker
+ * @author Eric Lafortune
+ */
+public class InstanceofClassFilter
+implements ClassVisitor
+{
+ private final ClassVisitor classVisitor;
+
+
+ public InstanceofClassFilter(ClassVisitor classVisitor)
+ {
+ this.classVisitor = classVisitor;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ if (InstanceofClassMarker.isInstanceofed(programClass))
+ {
+ classVisitor.visitProgramClass(programClass);
+ }
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ if (InstanceofClassMarker.isInstanceofed(libraryClass))
+ {
+ classVisitor.visitLibraryClass(libraryClass);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/proguard/optimize/info/InstanceofClassMarker.java b/src/proguard/optimize/info/InstanceofClassMarker.java
new file mode 100644
index 0000000..c60e1f8
--- /dev/null
+++ b/src/proguard/optimize/info/InstanceofClassMarker.java
@@ -0,0 +1,93 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2009 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.attribute.CodeAttribute;
+import proguard.classfile.constant.ClassConstant;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+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.
+ *
+ * @author Eric Lafortune
+ */
+public class InstanceofClassMarker
+extends SimplifiedVisitor
+implements InstructionVisitor,
+ ConstantVisitor,
+ ClassVisitor
+{
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
+
+
+ public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
+ {
+ if (constantInstruction.opcode == InstructionConstants.OP_INSTANCEOF)
+ {
+ clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
+ }
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+ {
+ classConstant.referencedClassAccept(this);
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitLibraryClass(LibraryClass libraryClass) {}
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ setInstanceofed(programClass);
+ }
+
+
+ // Small utility methods.
+
+ private static void setInstanceofed(Clazz clazz)
+ {
+ ClassOptimizationInfo info = ClassOptimizationInfo.getClassOptimizationInfo(clazz);
+ if (info != null)
+ {
+ info.setInstanceofed();
+ }
+ }
+
+
+ public static boolean isInstanceofed(Clazz clazz)
+ {
+ ClassOptimizationInfo info = ClassOptimizationInfo.getClassOptimizationInfo(clazz);
+ return info == null || info.isInstanceofed();
+ }
+} \ No newline at end of file
diff --git a/src/proguard/optimize/info/InstantiationClassFilter.java b/src/proguard/optimize/info/InstantiationClassFilter.java
new file mode 100644
index 0000000..a24e617
--- /dev/null
+++ b/src/proguard/optimize/info/InstantiationClassFilter.java
@@ -0,0 +1,62 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2009 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 InstantiationClassFilter
+implements ClassVisitor
+{
+ private final ClassVisitor classVisitor;
+
+
+ public InstantiationClassFilter(ClassVisitor classVisitor)
+ {
+ this.classVisitor = classVisitor;
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ if (InstantiationClassMarker.isInstantiated(programClass))
+ {
+ classVisitor.visitProgramClass(programClass);
+ }
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ if (InstantiationClassMarker.isInstantiated(libraryClass))
+ {
+ classVisitor.visitLibraryClass(libraryClass);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/proguard/optimize/info/InstantiationClassMarker.java b/src/proguard/optimize/info/InstantiationClassMarker.java
new file mode 100644
index 0000000..124c23b
--- /dev/null
+++ b/src/proguard/optimize/info/InstantiationClassMarker.java
@@ -0,0 +1,93 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2009 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.attribute.CodeAttribute;
+import proguard.classfile.constant.ClassConstant;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.ClassVisitor;
+
+/**
+ * This InstructionVisitor marks all classes that are instantiated by any of
+ * the instructions that it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class InstantiationClassMarker
+extends SimplifiedVisitor
+implements InstructionVisitor,
+ ConstantVisitor,
+ ClassVisitor
+{
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
+
+
+ public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
+ {
+ if (constantInstruction.opcode == InstructionConstants.OP_NEW)
+ {
+ clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
+ }
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
+ {
+ classConstant.referencedClassAccept(this);
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitLibraryClass(LibraryClass libraryClass) {}
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ setInstantiated(programClass);
+ }
+
+
+ // Small utility methods.
+
+ private static void setInstantiated(Clazz clazz)
+ {
+ ClassOptimizationInfo info = ClassOptimizationInfo.getClassOptimizationInfo(clazz);
+ if (info != null)
+ {
+ info.setInstantiated();
+ }
+ }
+
+
+ public static boolean isInstantiated(Clazz clazz)
+ {
+ ClassOptimizationInfo info = ClassOptimizationInfo.getClassOptimizationInfo(clazz);
+ return info == null || info.isInstantiated();
+ }
+} \ No newline at end of file
diff --git a/src/proguard/optimize/info/MemberOptimizationInfoSetter.java b/src/proguard/optimize/info/MemberOptimizationInfoSetter.java
new file mode 100644
index 0000000..a170a8e
--- /dev/null
+++ b/src/proguard/optimize/info/MemberOptimizationInfoSetter.java
@@ -0,0 +1,59 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2009 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.MemberVisitor;
+import proguard.optimize.KeepMarker;
+
+/**
+ * This MemberVisitor attaches a FieldOptimizationInfo instance to every field
+ * and a MethodOptimizationInfo instance to every method that is not being kept
+ * that it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class MemberOptimizationInfoSetter
+extends SimplifiedVisitor
+implements MemberVisitor
+{
+ // Implementations for MemberVisitor.
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ if (!KeepMarker.isKept(programMethod))
+ {
+ MethodOptimizationInfo.setMethodOptimizationInfo(programClass,
+ programMethod);
+ }
+ }
+
+
+ public void visitProgramField(ProgramClass programClass, ProgramField programField)
+ {
+ if (!KeepMarker.isKept(programField))
+ {
+ FieldOptimizationInfo.setFieldOptimizationInfo(programClass,
+ programField);
+ }
+ }
+}
diff --git a/src/proguard/optimize/info/MethodInvocationMarker.java b/src/proguard/optimize/info/MethodInvocationMarker.java
new file mode 100644
index 0000000..2528c94
--- /dev/null
+++ b/src/proguard/optimize/info/MethodInvocationMarker.java
@@ -0,0 +1,107 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2009 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.attribute.CodeAttribute;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.MemberVisitor;
+
+/**
+ * This InstructionVisitor counts the number of times methods are invoked from
+ * the instructions that are visited.
+ *
+ * @author Eric Lafortune
+ */
+public class MethodInvocationMarker
+extends SimplifiedVisitor
+implements InstructionVisitor,
+ ConstantVisitor,
+ MemberVisitor
+{
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
+
+
+ public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
+ {
+ clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyConstant(Clazz clazz, Constant constant) {}
+
+
+ public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
+ {
+ // Mark the referenced method, if any.
+ stringConstant.referencedMemberAccept(this);
+ }
+
+
+ public void visitAnyMethodrefConstant(Clazz clazz, RefConstant refConstant)
+ {
+ // Mark the referenced method.
+ refConstant.referencedMemberAccept(this);
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitAnyMember(Clazz Clazz, Member member) {}
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ incrementInvocationCount(programMethod);
+ }
+
+
+ // Small utility methods.
+
+ private static void incrementInvocationCount(Method method)
+ {
+ MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
+ if (info != null)
+ {
+ info.incrementInvocationCount();
+ }
+ }
+
+
+ /**
+ * Returns the number of times the given method was invoked by the
+ * instructions that were visited.
+ */
+ public static int getInvocationCount(Method method)
+ {
+ MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
+ return info != null ? info.getInvocationCount() :
+ Integer.MAX_VALUE;
+ }
+}
diff --git a/src/proguard/optimize/info/MethodOptimizationInfo.java b/src/proguard/optimize/info/MethodOptimizationInfo.java
new file mode 100644
index 0000000..d3b1bde
--- /dev/null
+++ b/src/proguard/optimize/info/MethodOptimizationInfo.java
@@ -0,0 +1,302 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2009 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.*;
+import proguard.evaluation.value.Value;
+
+/**
+ * This class stores some optimization information that can be attached to
+ * a method.
+ *
+ * @author Eric Lafortune
+ */
+public class MethodOptimizationInfo
+{
+ private boolean hasNoSideEffects = false;
+ private boolean hasSideEffects = false;
+ private boolean canBeMadePrivate = true;
+ private boolean catchesExceptions = false;
+ private boolean branchesBackward = false;
+ private boolean invokesSuperMethods = false;
+ private boolean accessesPrivateCode = false;
+ private boolean accessesPackageCode = false;
+ private boolean accessesProtectedCode = false;
+ private int invocationCount = 0;
+ private int parameterSize = 0;
+ private long usedParameters = 0L;
+ private Value[] parameters;
+ private Value returnValue;
+
+
+ /**
+ * Creates a new MethodOptimizationInfo for the given method.
+ */
+ public MethodOptimizationInfo(Clazz clazz, Method method)
+ {
+ // Set up an array of the right size for storing information about the
+ // passed parameters.
+ int parameterCount =
+ ClassUtil.internalMethodParameterCount(method.getDescriptor(clazz));
+
+ if ((method.getAccessFlags() & ClassConstants.INTERNAL_ACC_STATIC) == 0)
+ {
+ parameterCount++;
+ }
+
+ if (parameterCount > 0)
+ {
+ parameters = new Value[parameterCount];
+ }
+ }
+
+
+ public void setNoSideEffects()
+ {
+ hasNoSideEffects = true;
+ }
+
+
+ public boolean hasNoSideEffects()
+ {
+ return hasNoSideEffects;
+ }
+
+
+ public void setSideEffects()
+ {
+ hasSideEffects = true;
+ }
+
+
+ public boolean hasSideEffects()
+ {
+ return hasSideEffects;
+ }
+
+
+ public void setCanNotBeMadePrivate()
+ {
+ canBeMadePrivate = false;
+ }
+
+
+ public boolean canBeMadePrivate()
+ {
+ return canBeMadePrivate;
+ }
+
+
+ public void setCatchesExceptions()
+ {
+ catchesExceptions = true;
+ }
+
+
+ public boolean catchesExceptions()
+ {
+ return catchesExceptions;
+ }
+
+
+ public void setBranchesBackward()
+ {
+ branchesBackward = true;
+ }
+
+
+ public boolean branchesBackward()
+ {
+ return branchesBackward;
+ }
+
+
+ public void setInvokesSuperMethods()
+ {
+ invokesSuperMethods = true;
+ }
+
+
+ public boolean invokesSuperMethods()
+ {
+ return invokesSuperMethods;
+ }
+
+
+ public void setAccessesPrivateCode()
+ {
+ accessesPrivateCode = true;
+ }
+
+
+ public boolean accessesPrivateCode()
+ {
+ return accessesPrivateCode;
+ }
+
+
+ public void setAccessesPackageCode()
+ {
+ accessesPackageCode = true;
+ }
+
+
+ public boolean accessesPackageCode()
+ {
+ return accessesPackageCode;
+ }
+
+
+ public void setAccessesProtectedCode()
+ {
+ accessesProtectedCode = true;
+ }
+
+
+ public boolean accessesProtectedCode()
+ {
+ return accessesProtectedCode;
+ }
+
+
+ public void incrementInvocationCount()
+ {
+ invocationCount++;
+ }
+
+
+ public int getInvocationCount()
+ {
+ return invocationCount;
+ }
+
+
+ public void setParameterSize(int parameterSize)
+ {
+ this.parameterSize = parameterSize;
+ }
+
+
+ public int getParameterSize()
+ {
+ return parameterSize;
+ }
+
+
+ public void setParameterUsed(int parameterIndex)
+ {
+ usedParameters |= 1 << parameterIndex;
+ }
+
+
+ public void setUsedParameters(long usedParameters)
+ {
+ this.usedParameters = usedParameters;
+ }
+
+
+ public boolean isParameterUsed(int parameterIndex)
+ {
+ return parameterIndex >= 64 || (usedParameters & (1 << parameterIndex)) != 0;
+ }
+
+
+ public long getUsedParameters()
+ {
+ return usedParameters;
+ }
+
+
+ public void generalizeParameter(int parameterIndex, Value parameter)
+ {
+ parameters[parameterIndex] = parameters[parameterIndex] != null ?
+ parameters[parameterIndex].generalize(parameter) :
+ parameter;
+ }
+
+
+ public Value getParameter(int parameterIndex)
+ {
+ return parameters != null ?
+ parameters[parameterIndex] :
+ null;
+ }
+
+
+ public void generalizeReturnValue(Value returnValue)
+ {
+ this.returnValue = this.returnValue != null ?
+ this.returnValue.generalize(returnValue) :
+ returnValue;
+ }
+
+
+ public Value getReturnValue()
+ {
+ return returnValue;
+ }
+
+
+ public void merge(MethodOptimizationInfo other)
+ {
+ if (other != null)
+ {
+ this.hasNoSideEffects &= other.hasNoSideEffects;
+ this.hasSideEffects |= other.hasSideEffects;
+ //this.canBeMadePrivate &= other.canBeMadePrivate;
+ this.catchesExceptions |= other.catchesExceptions;
+ this.branchesBackward |= other.branchesBackward;
+ this.invokesSuperMethods |= other.invokesSuperMethods;
+ this.accessesPrivateCode |= other.accessesPrivateCode;
+ this.accessesPackageCode |= other.accessesPackageCode;
+ this.accessesProtectedCode |= other.accessesProtectedCode;
+ }
+ else
+ {
+ this.hasNoSideEffects = false;
+ this.hasSideEffects = true;
+ //this.canBeMadePrivate = false;
+ this.catchesExceptions = true;
+ this.branchesBackward = true;
+ this.invokesSuperMethods = true;
+ this.accessesPrivateCode = true;
+ this.accessesPackageCode = true;
+ this.accessesProtectedCode = true;
+ }
+ }
+
+
+ public static void setMethodOptimizationInfo(Clazz clazz, Method method)
+ {
+ MethodLinker.lastMember(method).setVisitorInfo(new MethodOptimizationInfo(clazz, method));
+ }
+
+
+ public static MethodOptimizationInfo getMethodOptimizationInfo(Method method)
+ {
+ Object visitorInfo = MethodLinker.lastMember(method).getVisitorInfo();
+
+ return visitorInfo instanceof MethodOptimizationInfo ?
+ (MethodOptimizationInfo)visitorInfo :
+ null;
+ }
+}
diff --git a/src/proguard/optimize/info/NoSideEffectMethodMarker.java b/src/proguard/optimize/info/NoSideEffectMethodMarker.java
new file mode 100644
index 0000000..5c78408
--- /dev/null
+++ b/src/proguard/optimize/info/NoSideEffectMethodMarker.java
@@ -0,0 +1,91 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2009 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.*;
+import proguard.classfile.visitor.MemberVisitor;
+
+/**
+ * This MemberVisitor marks all methods that it visits as not having any side
+ * effects. It will make the SideEffectMethodMarker consider them as such
+ * without further analysis.
+ *
+ * @see SideEffectMethodMarker
+ * @author Eric Lafortune
+ */
+public class NoSideEffectMethodMarker
+extends SimplifiedVisitor
+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();
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitAnyMember(Clazz Clazz, Member member)
+ {
+ // Ignore any attempts to mark fields.
+ }
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ markNoSideEffects(programMethod);
+ }
+
+
+ public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
+ {
+ markNoSideEffects(libraryMethod);
+ }
+
+
+ // Small utility methods.
+
+ private static void markNoSideEffects(Method method)
+ {
+ MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
+ if (info != null)
+ {
+ info.setNoSideEffects();
+ }
+ else
+ {
+ MethodLinker.lastMember(method).setVisitorInfo(KEPT_BUT_NO_SIDE_EFFECTS);
+ }
+ }
+
+
+ public static boolean hasNoSideEffects(Method method)
+ {
+ if (MethodLinker.lastVisitorAccepter(method).getVisitorInfo() == KEPT_BUT_NO_SIDE_EFFECTS)
+ {
+ return true;
+ }
+
+ MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
+ return info != null &&
+ info.hasNoSideEffects();
+ }
+}
diff --git a/src/proguard/optimize/info/NonPrivateMemberMarker.java b/src/proguard/optimize/info/NonPrivateMemberMarker.java
new file mode 100644
index 0000000..d451643
--- /dev/null
+++ b/src/proguard/optimize/info/NonPrivateMemberMarker.java
@@ -0,0 +1,177 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2009 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.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.*;
+
+/**
+ * This ClassVisitor marks all class members that can not be made private in the
+ * classes that it visits, and in the classes to which they refer.
+ *
+ * @author Eric Lafortune
+ */
+public class NonPrivateMemberMarker
+extends SimplifiedVisitor
+implements ClassVisitor,
+ ConstantVisitor,
+ MemberVisitor
+{
+ private final MethodImplementationFilter filteredMethodMarker = new MethodImplementationFilter(this);
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ // Mark all referenced class members in different classes.
+ programClass.constantPoolEntriesAccept(this);
+
+ // Explicitly mark the <clinit> method.
+ programClass.methodAccept(ClassConstants.INTERNAL_METHOD_NAME_CLINIT,
+ ClassConstants.INTERNAL_METHOD_TYPE_CLINIT,
+ this);
+
+ // Explicitly mark the parameterless <init> method.
+ programClass.methodAccept(ClassConstants.INTERNAL_METHOD_NAME_INIT,
+ ClassConstants.INTERNAL_METHOD_TYPE_INIT,
+ this);
+
+ // Mark all methods that may have implementations.
+ programClass.methodsAccept(filteredMethodMarker);
+ }
+
+
+ public void visitLibraryClass(LibraryClass libraryClass)
+ {
+ // Go over all methods.
+ libraryClass.methodsAccept(this);
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyConstant(Clazz clazz, Constant constant) {}
+
+
+ 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);
+ }
+ }
+
+
+ public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
+ {
+ Clazz referencedClass = refConstant.referencedClass;
+
+ // Is it refering 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 &&
+ !referencedClass.equals(clazz) ||
+ !refConstant.getClassName(clazz).equals(clazz.getName()))
+ {
+ // The referenced class member can never be made private.
+ refConstant.referencedMemberAccept(this);
+ }
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramField(ProgramClass programClass, ProgramField programField)
+ {
+ markCanNotBeMadePrivate(programField);
+ }
+
+
+ public void visitLibraryField(LibraryClass libraryClass, LibraryField libraryField)
+ {
+ markCanNotBeMadePrivate(libraryField);
+ }
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ markCanNotBeMadePrivate(programMethod);
+ }
+
+
+ public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
+ {
+ markCanNotBeMadePrivate(libraryMethod);
+ }
+
+
+ // Small utility methods.
+
+ private static void markCanNotBeMadePrivate(Field field)
+ {
+ FieldOptimizationInfo info = FieldOptimizationInfo.getFieldOptimizationInfo(field);
+ if (info != null)
+ {
+ info.setCanNotBeMadePrivate();
+ }
+ }
+
+
+ /**
+ * Returns whether the given field can be made private.
+ */
+ public static boolean canBeMadePrivate(Field field)
+ {
+ FieldOptimizationInfo info = FieldOptimizationInfo.getFieldOptimizationInfo(field);
+ return info != null &&
+ info.canBeMadePrivate();
+ }
+
+
+ private static void markCanNotBeMadePrivate(Method method)
+ {
+ MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
+ if (info != null)
+ {
+ info.setCanNotBeMadePrivate();
+ }
+ }
+
+
+ /**
+ * Returns whether the given method can be made private.
+ */
+ public static boolean canBeMadePrivate(Method method)
+ {
+ MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
+ return info != null &&
+ info.canBeMadePrivate();
+ }
+}
diff --git a/src/proguard/optimize/info/PackageVisibleMemberContainingClassMarker.java b/src/proguard/optimize/info/PackageVisibleMemberContainingClassMarker.java
new file mode 100644
index 0000000..d40bc6b
--- /dev/null
+++ b/src/proguard/optimize/info/PackageVisibleMemberContainingClassMarker.java
@@ -0,0 +1,67 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2009 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.MemberVisitor;
+
+/**
+ * This MemberVisitor marks all classes that contain visited package visible
+ * members.
+ *
+ * @author Eric Lafortune
+ */
+public class PackageVisibleMemberContainingClassMarker
+extends SimplifiedVisitor
+implements MemberVisitor
+{
+ // Implementations for MemberVisitor.
+
+ public void visitAnyMember(Clazz clazz, Member member)
+ {
+ if ((member.getAccessFlags() &
+ (ClassConstants.INTERNAL_ACC_PRIVATE |
+ ClassConstants.INTERNAL_ACC_PUBLIC)) == 0)
+ {
+ setPackageVisibleMembers(clazz);
+ }
+ }
+
+
+ // Small utility methods.
+
+ private static void setPackageVisibleMembers(Clazz clazz)
+ {
+ ClassOptimizationInfo info = ClassOptimizationInfo.getClassOptimizationInfo(clazz);
+ if (info != null)
+ {
+ info.setContainsPackageVisibleMembers();
+ }
+ }
+
+
+ public static boolean containsPackageVisibleMembers(Clazz clazz)
+ {
+ ClassOptimizationInfo info = ClassOptimizationInfo.getClassOptimizationInfo(clazz);
+ return info == null || info.containsPackageVisibleMembers();
+ }
+} \ No newline at end of file
diff --git a/src/proguard/optimize/info/PackageVisibleMemberInvokingClassMarker.java b/src/proguard/optimize/info/PackageVisibleMemberInvokingClassMarker.java
new file mode 100644
index 0000000..9ec8ec6
--- /dev/null
+++ b/src/proguard/optimize/info/PackageVisibleMemberInvokingClassMarker.java
@@ -0,0 +1,81 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2009 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.constant.visitor.ConstantVisitor;
+import proguard.classfile.constant.*;
+import proguard.classfile.util.SimplifiedVisitor;
+
+/**
+ * This ConstantVisitor marks all classes that invoke package visible members
+ * in other classes.
+ *
+ * @author Eric Lafortune
+ */
+public class PackageVisibleMemberInvokingClassMarker
+extends SimplifiedVisitor
+implements ConstantVisitor
+{
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyConstant(Clazz clazz, Constant constant) {}
+
+
+ public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
+ {
+ Clazz referencedClass = refConstant.referencedClass;
+ if (referencedClass != null &&
+ (referencedClass.getAccessFlags() &
+ ClassConstants.INTERNAL_ACC_PUBLIC) == 0)
+ {
+ setInvokesPackageVisibleMembers(clazz);
+ }
+
+ Member referencedMember = refConstant.referencedMember;
+ if (referencedMember != null &&
+ (referencedMember.getAccessFlags() &
+ (ClassConstants.INTERNAL_ACC_PUBLIC |
+ ClassConstants.INTERNAL_ACC_PRIVATE)) == 0)
+ {
+ setInvokesPackageVisibleMembers(clazz);
+ }
+ }
+
+
+ // Small utility methods.
+
+ private static void setInvokesPackageVisibleMembers(Clazz clazz)
+ {
+ ClassOptimizationInfo info = ClassOptimizationInfo.getClassOptimizationInfo(clazz);
+ if (info != null)
+ {
+ info.setInvokesPackageVisibleMembers();
+ }
+ }
+
+
+ public static boolean invokesPackageVisibleMembers(Clazz clazz)
+ {
+ ClassOptimizationInfo info = ClassOptimizationInfo.getClassOptimizationInfo(clazz);
+ return info == null || info.invokesPackageVisibleMembers();
+ }
+} \ No newline at end of file
diff --git a/src/proguard/optimize/info/ParameterUsageMarker.java b/src/proguard/optimize/info/ParameterUsageMarker.java
new file mode 100644
index 0000000..15ce88a
--- /dev/null
+++ b/src/proguard/optimize/info/ParameterUsageMarker.java
@@ -0,0 +1,285 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2009 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.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.optimize.evaluation.PartialEvaluator;
+import proguard.evaluation.value.*;
+
+/**
+ * This MemberVisitor counts the parameters and marks the used parameters
+ * of the methods that it visits. It also marks the 'this' parameters of
+ * methods that have hierarchies.
+ *
+ * @author Eric Lafortune
+ */
+public class ParameterUsageMarker
+extends SimplifiedVisitor
+implements MemberVisitor,
+ AttributeVisitor,
+ InstructionVisitor
+{
+ private static final boolean DEBUG = false;
+
+
+ private final boolean markThisParameter;
+ private final boolean markAllParameters;
+ private final PartialEvaluator partialEvaluator = new PartialEvaluator();
+
+
+ /**
+ * Creates a new ParameterUsageMarker.
+ */
+ public ParameterUsageMarker()
+ {
+ this(false, false);
+ }
+
+
+ /**
+ * Creates a new ParameterUsageMarker that optionally marks all parameters.
+ * @param markThisParameter specifies whether all 'this' parameters should
+ * be marked as being used.
+ * @param markAllParameters specifies whether all other parameters should
+ * be marked as being used.
+ */
+ public ParameterUsageMarker(boolean markThisParameter,
+ boolean markAllParameters)
+ {
+ this.markThisParameter = markThisParameter;
+ this.markAllParameters = markAllParameters;
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ int parameterSize =
+ ClassUtil.internalMethodParameterSize(programMethod.getDescriptor(programClass),
+ programMethod.getAccessFlags());
+
+ if (parameterSize > 0)
+ {
+ int accessFlags = programMethod.getAccessFlags();
+
+ // Must we mark the 'this' parameter?
+ if (markThisParameter &&
+ (accessFlags & ClassConstants.INTERNAL_ACC_STATIC) == 0)
+ {
+ // Mark the 'this' parameter.
+ markParameterUsed(programMethod, 0);
+ }
+
+ // Must we mark all other parameters?
+ if (markAllParameters)
+ {
+ // Mark all parameters, without the 'this' parameter.
+ markUsedParameters(programMethod,
+ (accessFlags & ClassConstants.INTERNAL_ACC_STATIC) != 0 ?
+ -1L : -2L);
+ }
+
+ // Is it a native method?
+ if ((accessFlags & ClassConstants.INTERNAL_ACC_NATIVE) != 0)
+ {
+ // Mark all parameters.
+ markUsedParameters(programMethod, -1L);
+ }
+
+ // Is it an abstract method?
+ else if ((accessFlags & ClassConstants.INTERNAL_ACC_ABSTRACT) != 0)
+ {
+ // Mark the 'this' parameter.
+ markParameterUsed(programMethod, 0);
+ }
+
+ // Is it a non-native, concrete method?
+ else
+ {
+ // Is the method not static, but synchronized, or can it have
+ // other implementations, or is it a class instance initializer?
+ if ((accessFlags & ClassConstants.INTERNAL_ACC_STATIC) == 0 &&
+ ((accessFlags & ClassConstants.INTERNAL_ACC_SYNCHRONIZED) != 0 ||
+ programClass.mayHaveImplementations(programMethod) ||
+ programMethod.getName(programClass).equals(ClassConstants.INTERNAL_METHOD_NAME_INIT)))
+ {
+ // Mark the 'this' parameter.
+ markParameterUsed(programMethod, 0);
+ }
+
+ // Mark the parameters that are used by the code.
+ programMethod.attributesAccept(programClass, this);
+ }
+
+ if (DEBUG)
+ {
+ System.out.print("ParameterUsageMarker: ["+programClass.getName() +"."+programMethod.getName(programClass)+programMethod.getDescriptor(programClass)+"]: ");
+ for (int index = 0; index < parameterSize; index++)
+ {
+ System.out.print(isParameterUsed(programMethod, index) ? '+' : '-');
+ }
+ System.out.println();
+ }
+
+ }
+
+ // Set the parameter size.
+ setParameterSize(programMethod, parameterSize);
+ }
+
+
+ public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
+ {
+ // Can the method have other implementations?
+ if (libraryClass.mayHaveImplementations(libraryMethod))
+ {
+ // All implementations must keep all parameters of this method,
+ // including the 'this' parameter.
+ markUsedParameters(libraryMethod, -1L);
+ }
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ // Evaluate the code.
+ partialEvaluator.visitCodeAttribute(clazz, method, codeAttribute);
+
+ // Mark the parameters that are used by the code.
+ codeAttribute.instructionsAccept(clazz, method, this);
+ }
+
+
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
+
+
+ public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction)
+ {
+ if (partialEvaluator.isTraced(offset) &&
+ variableInstruction.isLoad())
+ {
+ int parameterIndex = variableInstruction.variableIndex;
+ if (parameterIndex < codeAttribute.u2maxLocals)
+ {
+ Value producer =
+ partialEvaluator.getVariablesBefore(offset).getProducerValue(parameterIndex);
+ if (producer != null &&
+ producer.instructionOffsetValue().contains(PartialEvaluator.AT_METHOD_ENTRY))
+ {
+ // Mark the variable.
+ markParameterUsed(method, parameterIndex);
+
+ // Account for Category 2 instructions, which take up two entries.
+ if (variableInstruction.isCategory2())
+ {
+ markParameterUsed(method, parameterIndex + 1);
+ }
+ }
+ }
+ }
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Sets the total size of the parameters.
+ */
+ private static void setParameterSize(Method method, int parameterSize)
+ {
+ MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
+ if (info != null)
+ {
+ info.setParameterSize(parameterSize);
+ }
+ }
+
+
+ /**
+ * Returns the total size of the parameters.
+ */
+ public static int getParameterSize(Method method)
+ {
+ MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
+ return info != null ? info.getParameterSize() : 0;
+ }
+
+
+ /**
+ * Marks the given parameter as being used.
+ */
+ public static void markParameterUsed(Method method, int variableIndex)
+ {
+ MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
+ if (info != null)
+ {
+ info.setParameterUsed(variableIndex);
+ }
+ }
+
+
+ /**
+ * Marks the given parameters as being used.
+ */
+ public static void markUsedParameters(Method method, long usedParameters)
+ {
+ MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
+ if (info != null)
+ {
+ info.setUsedParameters(info.getUsedParameters() | usedParameters);
+ }
+ }
+
+
+ /**
+ * Returns whether the given parameter is being used.
+ */
+ public static boolean isParameterUsed(Method method, int variableIndex)
+ {
+ MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
+ return info == null ||
+ info.isParameterUsed(variableIndex);
+ }
+
+
+ /**
+ * Returns which parameters are being used.
+ */
+ public static long getUsedParameters(Method method)
+ {
+ MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
+ return info != null ? info.getUsedParameters() : -1L;
+ }
+}
diff --git a/src/proguard/optimize/info/ReadWriteFieldMarker.java b/src/proguard/optimize/info/ReadWriteFieldMarker.java
new file mode 100644
index 0000000..57d8561
--- /dev/null
+++ b/src/proguard/optimize/info/ReadWriteFieldMarker.java
@@ -0,0 +1,163 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2009 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.attribute.CodeAttribute;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.MemberVisitor;
+
+/**
+ * This InstructionVisitor marks all fields that are write-only.
+ *
+ * @author Eric Lafortune
+ */
+public class ReadWriteFieldMarker
+extends SimplifiedVisitor
+implements InstructionVisitor,
+ ConstantVisitor,
+ MemberVisitor
+{
+ // Parameters for the visitor methods.
+ private boolean reading = true;
+ private boolean writing = true;
+
+
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
+
+
+ public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
+ {
+ byte opcode = constantInstruction.opcode;
+
+ // Check for instructions that involve fields.
+ switch (opcode)
+ {
+ case InstructionConstants.OP_LDC:
+ case InstructionConstants.OP_LDC_W:
+ // Mark the field, if any, as being read from and written to.
+ reading = true;
+ writing = true;
+ clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
+ break;
+
+ case InstructionConstants.OP_GETSTATIC:
+ case InstructionConstants.OP_GETFIELD:
+ // Mark the field as being read from.
+ reading = true;
+ writing = false;
+ clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
+ break;
+
+ case InstructionConstants.OP_PUTSTATIC:
+ case InstructionConstants.OP_PUTFIELD:
+ // Mark the field as being written to.
+ reading = false;
+ writing = true;
+ clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
+ break;
+ }
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyConstant(Clazz clazz, Constant constant) {}
+
+
+ public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
+ {
+ // Mark the referenced field, if any.
+ stringConstant.referencedMemberAccept(this);
+ }
+
+
+ public void visitFieldrefConstant(Clazz clazz, FieldrefConstant fieldrefConstant)
+ {
+ // Mark the referenced field.
+ fieldrefConstant.referencedMemberAccept(this);
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitAnyMember(Clazz Clazz, Member member) {}
+
+
+ public void visitProgramField(ProgramClass programClass, ProgramField programField)
+ {
+ // Mark the field if it is being read from.
+ if (reading)
+ {
+ markAsRead(programField);
+ }
+
+ // Mark the field if it is being written to.
+ if (writing)
+ {
+ markAsWritten(programField);
+ }
+ }
+
+
+ // Small utility methods.
+
+ private static void markAsRead(Field field)
+ {
+ FieldOptimizationInfo info = FieldOptimizationInfo.getFieldOptimizationInfo(field);
+ if (info != null)
+ {
+ info.setRead();
+ }
+ }
+
+
+ public static boolean isRead(Field field)
+ {
+ FieldOptimizationInfo info = FieldOptimizationInfo.getFieldOptimizationInfo(field);
+ return info == null ||
+ info.isRead();
+ }
+
+
+ private static void markAsWritten(Field field)
+ {
+ FieldOptimizationInfo info = FieldOptimizationInfo.getFieldOptimizationInfo(field);
+ if (info != null)
+ {
+ info.setWritten();
+ }
+ }
+
+
+ public static boolean isWritten(Field field)
+ {
+ FieldOptimizationInfo info = FieldOptimizationInfo.getFieldOptimizationInfo(field);
+ return info == null ||
+ info.isWritten();
+ }
+}
diff --git a/src/proguard/optimize/info/SideEffectInstructionChecker.java b/src/proguard/optimize/info/SideEffectInstructionChecker.java
new file mode 100644
index 0000000..8be9dc1
--- /dev/null
+++ b/src/proguard/optimize/info/SideEffectInstructionChecker.java
@@ -0,0 +1,224 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2009 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.attribute.CodeAttribute;
+import proguard.classfile.constant.*;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.*;
+
+/**
+ * This class can tell whether an instruction has any side effects. Return
+ * instructions can be included or not.
+ *
+ * @see ReadWriteFieldMarker
+ * @see NoSideEffectMethodMarker
+ * @see SideEffectMethodMarker
+ * @author Eric Lafortune
+ */
+public class SideEffectInstructionChecker
+extends SimplifiedVisitor
+implements InstructionVisitor,
+ ConstantVisitor,
+ MemberVisitor
+{
+ private final boolean includeReturnInstructions;
+
+ // A return value for the visitor methods.
+ private boolean hasSideEffects;
+
+
+ public SideEffectInstructionChecker(boolean includeReturnInstructions)
+ {
+ this.includeReturnInstructions = includeReturnInstructions;
+ }
+
+
+ public boolean hasSideEffects(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction)
+ {
+ hasSideEffects = false;
+
+ instruction.accept(clazz, method, codeAttribute, offset, this);
+
+ return hasSideEffects;
+ }
+
+
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
+
+
+ public void visitSimpleInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SimpleInstruction simpleInstruction)
+ {
+ 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)))
+ {
+ // These instructions always cause a side effect.
+ hasSideEffects = true;
+ }
+
+ }
+
+
+ public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction)
+ {
+ byte opcode = variableInstruction.opcode;
+
+ // Check for instructions that might cause side effects.
+ if (includeReturnInstructions &&
+ opcode == InstructionConstants.OP_RET)
+ {
+ hasSideEffects = true;
+ }
+ }
+
+
+ public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
+ {
+ 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)
+ {
+ // Check if the field is write-only or volatile, or if the invoked
+ // method is causing any side effects.
+ clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
+ }
+ }
+
+
+ public void visitBranchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction)
+ {
+ byte opcode = branchInstruction.opcode;
+
+ // Check for instructions that might cause side effects.
+ if (includeReturnInstructions &&
+ (opcode == InstructionConstants.OP_JSR ||
+ opcode == InstructionConstants.OP_JSR_W))
+ {
+ hasSideEffects = true;
+ }
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitFieldrefConstant(Clazz clazz, FieldrefConstant fieldrefConstant)
+ {
+ // We'll have to assume accessing an unknown field has side effects.
+ hasSideEffects = true;
+
+ // Check the referenced field.
+ fieldrefConstant.referencedMemberAccept(this);
+ }
+
+
+ public void visitAnyMethodrefConstant(Clazz clazz, RefConstant refConstant)
+ {
+ Member referencedMember = refConstant.referencedMember;
+
+ // 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));
+ }
+ }
+ }
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramField(ProgramClass programClass, ProgramField programField)
+ {
+ hasSideEffects = ReadWriteFieldMarker.isRead(programField);
+ }
+
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ hasSideEffects = hasSideEffects ||
+ SideEffectMethodMarker.hasSideEffects(programMethod);
+ }
+
+
+ public void visitLibraryField(LibraryClass libraryClass, LibraryField libraryField)
+ {
+ hasSideEffects = true;
+ }
+
+
+ public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
+ {
+ hasSideEffects = hasSideEffects ||
+ !NoSideEffectMethodMarker.hasNoSideEffects(libraryMethod);
+ }
+}
diff --git a/src/proguard/optimize/info/SideEffectMethodMarker.java b/src/proguard/optimize/info/SideEffectMethodMarker.java
new file mode 100644
index 0000000..25fda72
--- /dev/null
+++ b/src/proguard/optimize/info/SideEffectMethodMarker.java
@@ -0,0 +1,175 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2009 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.attribute.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.instruction.*;
+import proguard.classfile.util.SimplifiedVisitor;
+import proguard.classfile.visitor.*;
+
+/**
+ * This ClassPoolVisitor marks all methods that have side effects.
+ *
+ * @see ReadWriteFieldMarker
+ * @see NoSideEffectMethodMarker
+ * @author Eric Lafortune
+ */
+public class SideEffectMethodMarker
+extends SimplifiedVisitor
+implements ClassPoolVisitor,
+ ClassVisitor,
+ MemberVisitor,
+ AttributeVisitor
+{
+ // A reusable object for checking whether instructions have side effects.
+ private final SideEffectInstructionChecker sideEffectInstructionChecker = new SideEffectInstructionChecker(false);
+
+ // Parameters and values for visitor methods.
+ private int newSideEffectCount;
+ private boolean hasSideEffects;
+
+
+ // Implementations for ClassPoolVisitor.
+
+ public void visitClassPool(ClassPool classPool)
+ {
+ // Go over all classes and their methods, marking if they have side
+ // effects, until no new cases can be found.
+ do
+ {
+ newSideEffectCount = 0;
+
+ // Go over all classes and their methods once.
+ classPool.classesAccept(this);
+ }
+ while (newSideEffectCount > 0);
+ }
+
+
+ // Implementations for ClassVisitor.
+
+ public void visitProgramClass(ProgramClass programClass)
+ {
+ // Go over all methods.
+ programClass.methodsAccept(this);
+ }
+
+
+ // Implementations for MemberVisitor.
+
+ public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
+ {
+ if (!hasSideEffects(programMethod) &&
+ !NoSideEffectMethodMarker.hasNoSideEffects(programMethod))
+ {
+ // Initialize the return value.
+ hasSideEffects =
+ (programMethod.getAccessFlags() &
+ (ClassConstants.INTERNAL_ACC_NATIVE |
+ ClassConstants.INTERNAL_ACC_SYNCHRONIZED)) != 0;
+
+ // Look further if the method hasn't been marked yet.
+ if (!hasSideEffects)
+ {
+ // Investigate the actual code.
+ programMethod.attributesAccept(programClass, this);
+ }
+
+ // Mark the method depending on the return value.
+ if (hasSideEffects)
+ {
+ markSideEffects(programMethod);
+
+ newSideEffectCount++;
+ }
+ }
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ // Remember whether the code has any side effects.
+ hasSideEffects = hasSideEffects(clazz, method, codeAttribute);
+ }
+
+
+ // Small utility methods.
+
+ /**
+ * Returns whether the given code has any side effects.
+ */
+ private boolean hasSideEffects(Clazz clazz,
+ Method method,
+ CodeAttribute codeAttribute)
+ {
+ byte[] code = codeAttribute.code;
+ int length = codeAttribute.u4codeLength;
+
+ // Go over all instructions.
+ int offset = 0;
+ do
+ {
+ // Get the current instruction.
+ Instruction instruction = InstructionFactory.create(code, offset);
+
+ // Check if it may be throwing exceptions.
+ if (sideEffectInstructionChecker.hasSideEffects(clazz,
+ method,
+ codeAttribute,
+ offset,
+ instruction))
+ {
+ return true;
+ }
+
+ // Go to the next instruction.
+ offset += instruction.length(offset);
+ }
+ while (offset < length);
+
+ return false;
+ }
+
+
+ private static void markSideEffects(Method method)
+ {
+ MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
+ if (info != null)
+ {
+ info.setSideEffects();
+ }
+ }
+
+
+ public static boolean hasSideEffects(Method method)
+ {
+ MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
+ return info == null ||
+ info.hasSideEffects();
+ }
+}
diff --git a/src/proguard/optimize/info/SuperInvocationMarker.java b/src/proguard/optimize/info/SuperInvocationMarker.java
new file mode 100644
index 0000000..6f3d3bd
--- /dev/null
+++ b/src/proguard/optimize/info/SuperInvocationMarker.java
@@ -0,0 +1,93 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2009 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.attribute.CodeAttribute;
+import proguard.classfile.constant.RefConstant;
+import proguard.classfile.constant.visitor.ConstantVisitor;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+
+/**
+ * This InstructionVisitor marks all methods that invoke super methods (other
+ * than initializers) from the instructions that it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class SuperInvocationMarker
+extends SimplifiedVisitor
+implements InstructionVisitor,
+ ConstantVisitor
+{
+ private boolean invokesSuperMethods;
+
+
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
+
+
+ public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
+ {
+ if (constantInstruction.opcode == InstructionConstants.OP_INVOKESPECIAL)
+ {
+ invokesSuperMethods = false;
+
+ clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
+
+ if (invokesSuperMethods)
+ {
+ setInvokesSuperMethods(method);
+ }
+ }
+ }
+
+
+ // Implementations for ConstantVisitor.
+
+ public void visitAnyMethodrefConstant(Clazz clazz, RefConstant refConstant)
+ {
+ invokesSuperMethods =
+ !clazz.equals(refConstant.referencedClass) &&
+ !refConstant.getName(clazz).equals(ClassConstants.INTERNAL_METHOD_NAME_INIT);
+ }
+
+
+ // Small utility methods.
+
+ private static void setInvokesSuperMethods(Method method)
+ {
+ MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
+ if (info != null)
+ {
+ info.setInvokesSuperMethods();
+ }
+ }
+
+
+ public static boolean invokesSuperMethods(Method method)
+ {
+ MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
+ return info == null || info.invokesSuperMethods();
+ }
+}
diff --git a/src/proguard/optimize/info/VariableUsageMarker.java b/src/proguard/optimize/info/VariableUsageMarker.java
new file mode 100644
index 0000000..660c4ba
--- /dev/null
+++ b/src/proguard/optimize/info/VariableUsageMarker.java
@@ -0,0 +1,95 @@
+/*
+ * ProGuard -- shrinking, optimization, obfuscation, and preverification
+ * of Java bytecode.
+ *
+ * Copyright (c) 2002-2009 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.attribute.*;
+import proguard.classfile.attribute.visitor.AttributeVisitor;
+import proguard.classfile.instruction.*;
+import proguard.classfile.instruction.visitor.InstructionVisitor;
+import proguard.classfile.util.SimplifiedVisitor;
+
+/**
+ * This AttributeVisitor marks the local variables that are used in the code
+ * attributes that it visits.
+ *
+ * @author Eric Lafortune
+ */
+public class VariableUsageMarker
+extends SimplifiedVisitor
+implements AttributeVisitor,
+ InstructionVisitor
+{
+ private boolean[] variableUsed = new boolean[ClassConstants.TYPICAL_VARIABLES_SIZE];
+
+
+ /**
+ * Returns whether the given variable has been marked as being used.
+ */
+ public boolean isVariableUsed(int variableIndex)
+ {
+ return variableUsed[variableIndex];
+ }
+
+
+ // Implementations for AttributeVisitor.
+
+ public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
+
+
+ public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
+ {
+ int maxLocals = codeAttribute.u2maxLocals;
+
+ // Try to reuse the previous array.
+ if (variableUsed.length < maxLocals)
+ {
+ variableUsed = new boolean[maxLocals];
+ }
+ else
+ {
+ for (int index = 0; index < maxLocals; index++)
+ {
+ variableUsed[index] = false;
+ }
+ }
+
+ codeAttribute.instructionsAccept(clazz, method, this);
+ }
+
+
+ // Implementations for InstructionVisitor.
+
+ public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
+
+
+ public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction)
+ {
+ // Mark the variable.
+ variableUsed[variableInstruction.variableIndex] = true;
+
+ // Account for Category 2 instructions, which take up two entries.
+ if (variableInstruction.isCategory2())
+ {
+ variableUsed[variableInstruction.variableIndex + 1] = true;
+ }
+ }
+}
diff --git a/src/proguard/optimize/info/package.html b/src/proguard/optimize/info/package.html
new file mode 100644
index 0000000..d16486e
--- /dev/null
+++ b/src/proguard/optimize/info/package.html
@@ -0,0 +1,4 @@
+<body>
+This package contains classes to collect additional information about classes
+and class members, which can then be used for optimization.
+</body>