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