aboutsummaryrefslogtreecommitdiffstats
path: root/src/proguard/optimize/info/SideEffectInstructionChecker.java
diff options
context:
space:
mode:
authorYing Wang <wangying@google.com>2012-02-27 18:34:24 -0800
committerYing Wang <wangying@google.com>2012-02-27 18:34:24 -0800
commit9f606f95f03a75961498803e24bee6799a7c0885 (patch)
treea45f4d74feda9b76277a0c9ced55ad15d82248a1 /src/proguard/optimize/info/SideEffectInstructionChecker.java
parentcfead78069f3dc32998dc118ee08cab3867acea2 (diff)
downloadandroid_external_proguard-9f606f95f03a75961498803e24bee6799a7c0885.tar.gz
android_external_proguard-9f606f95f03a75961498803e24bee6799a7c0885.tar.bz2
android_external_proguard-9f606f95f03a75961498803e24bee6799a7c0885.zip
This reverts commit cfead78069f3dc32998dc118ee08cab3867acea2. Bug: 6079915
Diffstat (limited to 'src/proguard/optimize/info/SideEffectInstructionChecker.java')
-rw-r--r--src/proguard/optimize/info/SideEffectInstructionChecker.java109
1 files changed, 44 insertions, 65 deletions
diff --git a/src/proguard/optimize/info/SideEffectInstructionChecker.java b/src/proguard/optimize/info/SideEffectInstructionChecker.java
index 1444e5a..8be9dc1 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-2011 Eric Lafortune (eric@graphics.cornell.edu)
+ * 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
@@ -29,14 +29,11 @@ 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.
*
* @see ReadWriteFieldMarker
- * @see StaticInitializerContainingClassMarker
* @see NoSideEffectMethodMarker
* @see SideEffectMethodMarker
* @author Eric Lafortune
@@ -50,7 +47,6 @@ implements InstructionVisitor,
private final boolean includeReturnInstructions;
// A return value for the visitor methods.
- private Clazz referencingClass;
private boolean hasSideEffects;
@@ -64,7 +60,7 @@ implements InstructionVisitor,
{
hasSideEffects = false;
- instruction.accept(clazz, method, codeAttribute, offset, this);
+ instruction.accept(clazz, method, codeAttribute, offset, this);
return hasSideEffects;
}
@@ -122,16 +118,14 @@ implements InstructionVisitor,
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_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_INVOKEDYNAMIC)
+ 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.
@@ -156,36 +150,48 @@ implements InstructionVisitor,
// 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, if known.
+ // Check the referenced field.
fieldrefConstant.referencedMemberAccept(this);
}
public void visitAnyMethodrefConstant(Clazz clazz, RefConstant refConstant)
{
- // Pass the referencing class.
- referencingClass = clazz;
+ Member referencedMember = refConstant.referencedMember;
- // We'll have to assume invoking an unknown method has side effects.
- hasSideEffects = true;
-
- // Check the referenced method, if known.
- refConstant.referencedMemberAccept(this);
+ // 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));
+ }
+ }
+ }
}
@@ -193,24 +199,14 @@ implements InstructionVisitor,
public void visitProgramField(ProgramClass programClass, ProgramField programField)
{
- hasSideEffects =
- (ReadWriteFieldMarker.isRead(programField) &&
- ReadWriteFieldMarker.isWritten(programField)) ||
- ((programField.getAccessFlags() & ClassConstants.INTERNAL_ACC_VOLATILE) != 0) ||
- (!programClass.equals(referencingClass) &&
- !initializedSuperClasses(referencingClass).containsAll(initializedSuperClasses(programClass)));
+ hasSideEffects = ReadWriteFieldMarker.isRead(programField);
}
public void visitProgramMethod(ProgramClass programClass, ProgramMethod 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))));
+ hasSideEffects = hasSideEffects ||
+ SideEffectMethodMarker.hasSideEffects(programMethod);
}
@@ -222,24 +218,7 @@ implements InstructionVisitor,
public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod 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 ClassCollector(set)));
-
- return set;
+ hasSideEffects = hasSideEffects ||
+ !NoSideEffectMethodMarker.hasNoSideEffects(libraryMethod);
}
}