Refactor, simplify InstructionSubject to prepare the CF implementation.
InstructionSubject, InvokeInstructionSubject,
FieldAccessInstructionSubject and InstructionIterator
changed to interfaces with explicit Dex implementation classes.
InstructionSubjectFactory merged into DexInstructionSubject.
Change-Id: Id024fc168bdaf1d27191eead84bb1cf6a7f112a1
diff --git a/src/test/java/com/android/tools/r8/neverreturnsnormally/NeverReturnsNormallyTest.java b/src/test/java/com/android/tools/r8/neverreturnsnormally/NeverReturnsNormallyTest.java
index c929eaf..878cb7c 100644
--- a/src/test/java/com/android/tools/r8/neverreturnsnormally/NeverReturnsNormallyTest.java
+++ b/src/test/java/com/android/tools/r8/neverreturnsnormally/NeverReturnsNormallyTest.java
@@ -16,6 +16,7 @@
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.DexInspector;
import com.android.tools.r8.utils.DexInspector.ClassSubject;
+import com.android.tools.r8.utils.DexInspector.DexInstructionSubject;
import com.android.tools.r8.utils.DexInspector.InstructionSubject;
import com.android.tools.r8.utils.DexInspector.InvokeInstructionSubject;
import com.android.tools.r8.utils.DexInspector.MethodSubject;
@@ -82,7 +83,8 @@
assertTrue(insn.isInvoke());
assertTrue(((InvokeInstructionSubject) insn)
.invokedMethod().name.toString().equals("throwNpe"));
- assertTrue(nextInstruction(instructions).isConst4());
+ insn = nextInstruction(instructions);
+ assertTrue(insn instanceof DexInstructionSubject && ((DexInstructionSubject) insn).isConst4());
assertTrue(nextInstruction(instructions).isThrow());
assertFalse(instructions.hasNext());
@@ -105,7 +107,8 @@
assertTrue(((InvokeInstructionSubject) insn)
.invokedMethod().name.toString().equals("throwNpe"));
}
- assertTrue(nextInstruction(instructions).isConst4());
+ insn = nextInstruction(instructions);
+ assertTrue(insn instanceof DexInstructionSubject && ((DexInstructionSubject) insn).isConst4());
assertTrue(nextInstruction(instructions).isThrow());
assertFalse(instructions.hasNext());
@@ -119,7 +122,8 @@
assertTrue(insn.isInvoke());
assertTrue(((InvokeInstructionSubject) insn)
.invokedMethod().name.toString().equals("innerNotReachable"));
- assertTrue(nextInstruction(instructions).isConst4());
+ insn = nextInstruction(instructions);
+ assertTrue(insn instanceof DexInstructionSubject && ((DexInstructionSubject) insn).isConst4());
assertTrue(nextInstruction(instructions).isThrow());
assertFalse(instructions.hasNext());
}
diff --git a/src/test/java/com/android/tools/r8/utils/DexInspector.java b/src/test/java/com/android/tools/r8/utils/DexInspector.java
index 955d1ee..059a24a 100644
--- a/src/test/java/com/android/tools/r8/utils/DexInspector.java
+++ b/src/test/java/com/android/tools/r8/utils/DexInspector.java
@@ -54,6 +54,7 @@
import com.android.tools.r8.code.SputWide;
import com.android.tools.r8.code.Throw;
import com.android.tools.r8.dex.ApplicationReader;
+import com.android.tools.r8.graph.Code;
import com.android.tools.r8.graph.DexAnnotation;
import com.android.tools.r8.graph.DexAnnotationElement;
import com.android.tools.r8.graph.DexAnnotationSet;
@@ -81,6 +82,7 @@
import com.android.tools.r8.naming.signature.GenericSignatureAction;
import com.android.tools.r8.naming.signature.GenericSignatureParser;
import com.android.tools.r8.smali.SmaliBuilder;
+import com.android.tools.r8.utils.DexInspector.FieldAccessInstructionSubject;
import com.google.common.collect.BiMap;
import com.google.common.collect.ImmutableList;
import java.io.IOException;
@@ -106,8 +108,6 @@
private final ClassNameMapper mapping;
private final BiMap<String, String> originalToObfuscatedMapping;
- private final InstructionSubjectFactory factory = new InstructionSubjectFactory();
-
public static MethodSignature MAIN =
new MethodSignature("main", "void", new String[]{"java.lang.String[]"});
@@ -304,18 +304,18 @@
return obfuscatedType;
}
- public abstract class Subject {
+ public abstract static class Subject {
public abstract boolean isPresent();
public abstract boolean isRenamed();
}
- public abstract class AnnotationSubject extends Subject {
+ public abstract static class AnnotationSubject extends Subject {
public abstract DexEncodedAnnotation getAnnotation();
}
- public class FoundAnnotationSubject extends AnnotationSubject {
+ public static class FoundAnnotationSubject extends AnnotationSubject {
private final DexAnnotation annotation;
@@ -339,7 +339,7 @@
}
}
- public class AbsentAnnotationSubject extends AnnotationSubject {
+ public static class AbsentAnnotationSubject extends AnnotationSubject {
@Override
public boolean isPresent() {
@@ -357,8 +357,7 @@
}
}
-
- public abstract class ClassSubject extends Subject {
+ public abstract static class ClassSubject extends Subject {
public abstract void forAllMethods(Consumer<FoundMethodSubject> inspection);
@@ -737,7 +736,7 @@
}
}
- public abstract class MemberSubject extends Subject {
+ public abstract static class MemberSubject extends Subject {
public abstract boolean isPublic();
@@ -760,7 +759,7 @@
}
}
- public abstract class MethodSubject extends MemberSubject {
+ public abstract static class MethodSubject extends MemberSubject {
public abstract boolean isAbstract();
@@ -970,7 +969,7 @@
@Override
public Iterator<InstructionSubject> iterateInstructions() {
- return new InstructionIterator(this);
+ return createInstructionIterator(this);
}
@Override
@@ -985,7 +984,7 @@
}
}
- public abstract class FieldSubject extends MemberSubject {
+ public abstract static class FieldSubject extends MemberSubject {
public abstract boolean hasExplicitStaticValue();
public abstract DexEncodedField getField();
@@ -999,7 +998,7 @@
public abstract String getFinalSignatureAttribute();
}
- public class AbsentFieldSubject extends FieldSubject {
+ public static class AbsentFieldSubject extends FieldSubject {
@Override
public boolean isPublic() {
@@ -1192,91 +1191,139 @@
}
}
- private class InstructionSubjectFactory {
+ public interface InstructionSubject {
+ boolean isFieldAccess();
- InstructionSubject create(Instruction instruction) {
- if (isInvoke(instruction)) {
- return new InvokeInstructionSubject(this, instruction);
- } else if (isFieldAccess(instruction)) {
- return new FieldAccessInstructionSubject(this, instruction);
- } else {
- return new InstructionSubject(this, instruction);
- }
+ boolean isInvokeVirtual();
+
+ boolean isInvokeInterface();
+
+ boolean isInvokeDirect();
+
+ boolean isInvokeSuper();
+
+ boolean isInvokeStatic();
+
+ boolean isNop();
+
+ boolean isConstString();
+
+ boolean isConstString(String value);
+
+ boolean isGoto();
+
+ boolean isIfNez();
+
+ boolean isIfEqz();
+
+ boolean isReturnVoid();
+
+ boolean isThrow();
+
+ default boolean isInvoke() {
+ return isInvokeVirtual()
+ || isInvokeInterface()
+ || isInvokeDirect()
+ || isInvokeSuper()
+ || isInvokeStatic();
+ }
+ }
+
+ public InstructionSubject createInstructionSubject(Instruction instruction) {
+ DexInstructionSubject dexInst = new DexInstructionSubject(instruction);
+ if (dexInst.isInvoke()) {
+ return new InvokeDexInstructionSubject(instruction);
+ } else if (dexInst.isFieldAccess()) {
+ return new FieldAccessDexInstructionSubject(instruction);
+ } else {
+ return dexInst;
+ }
+ }
+
+ public class DexInstructionSubject implements InstructionSubject {
+ protected Instruction instruction;
+
+ public DexInstructionSubject(Instruction instruction) {
+ this.instruction = instruction;
}
- boolean isInvoke(Instruction instruction) {
- return isInvokeVirtual(instruction)
- || isInvokeInterface(instruction)
- || isInvokeDirect(instruction)
- || isInvokeSuper(instruction)
- || isInvokeStatic(instruction);
+ @Override
+ public boolean isFieldAccess() {
+ return isInstanceGet() || isInstancePut() || isStaticGet() || isStaticSet();
}
- boolean isInvokeVirtual(Instruction instruction) {
+ @Override
+ public boolean isInvokeVirtual() {
return instruction instanceof InvokeVirtual || instruction instanceof InvokeVirtualRange;
}
- boolean isInvokeInterface(Instruction instruction) {
+ @Override
+ public boolean isInvokeInterface() {
return instruction instanceof InvokeInterface || instruction instanceof InvokeInterfaceRange;
}
- boolean isInvokeDirect(Instruction instruction) {
+ @Override
+ public boolean isInvokeDirect() {
return instruction instanceof InvokeDirect || instruction instanceof InvokeDirectRange;
}
- boolean isInvokeSuper(Instruction instruction) {
+ @Override
+ public boolean isInvokeSuper() {
return instruction instanceof InvokeSuper || instruction instanceof InvokeSuperRange;
}
- boolean isInvokeStatic(Instruction instruction) {
+ @Override
+ public boolean isInvokeStatic() {
return instruction instanceof InvokeStatic || instruction instanceof InvokeStaticRange;
}
- boolean isNop(Instruction instruction) {
+ @Override
+ public boolean isNop() {
return instruction instanceof Nop;
}
- boolean isGoto(Instruction instruction) {
- return instruction instanceof Goto;
- }
-
- boolean isReturnVoid(Instruction instruction) {
- return instruction instanceof ReturnVoid;
- }
-
- boolean isConst4(Instruction instruction) {
- return instruction instanceof Const4;
- }
-
- boolean isThrow(Instruction instruction) {
- return instruction instanceof Throw;
- }
-
- boolean isConstString(Instruction instruction) {
+ @Override
+ public boolean isConstString() {
return instruction instanceof ConstString;
}
- boolean isConstString(Instruction instruction, String value) {
+ @Override
+ public boolean isConstString(String value) {
return instruction instanceof ConstString
&& ((ConstString) instruction).BBBB.toSourceString().equals(value);
}
- boolean isIfNez(Instruction instruction) {
+ @Override
+ public boolean isGoto() {
+
+ return instruction instanceof Goto;
+ }
+
+ @Override
+ public boolean isIfNez() {
return instruction instanceof IfNez;
}
- boolean isIfEqz(Instruction instruction) {
+ @Override
+ public boolean isIfEqz() {
return instruction instanceof IfEqz;
}
- boolean isFieldAccess(Instruction instruction) {
- return isInstanceGet(instruction)
- || isInstancePut(instruction)
- || isStaticGet(instruction)
- || isStaticSet(instruction);
+ @Override
+ public boolean isReturnVoid() {
+ return instruction instanceof ReturnVoid;
}
- boolean isInstanceGet(Instruction instruction) {
+ @Override
+ public boolean isThrow() {
+ return instruction instanceof Throw;
+ }
+
+ public boolean isConst4() {
+ return instruction instanceof Const4;
+ }
+
+ public boolean isInstanceGet() {
return instruction instanceof Iget
|| instruction instanceof IgetBoolean
|| instruction instanceof IgetByte
@@ -1286,7 +1333,7 @@
|| instruction instanceof IgetObject;
}
- boolean isInstancePut(Instruction instruction) {
+ public boolean isInstancePut() {
return instruction instanceof Iput
|| instruction instanceof IputBoolean
|| instruction instanceof IputByte
@@ -1296,7 +1343,7 @@
|| instruction instanceof IputObject;
}
- boolean isStaticGet(Instruction instruction) {
+ public boolean isStaticGet() {
return instruction instanceof Sget
|| instruction instanceof SgetBoolean
|| instruction instanceof SgetByte
@@ -1306,7 +1353,7 @@
|| instruction instanceof SgetObject;
}
- boolean isStaticSet(Instruction instruction) {
+ public boolean isStaticSet() {
return instruction instanceof Sput
|| instruction instanceof SputBoolean
|| instruction instanceof SputByte
@@ -1317,89 +1364,21 @@
}
}
- public class InstructionSubject {
+ public interface InvokeInstructionSubject extends InstructionSubject {
+ TypeSubject holder();
- protected final InstructionSubjectFactory factory;
- protected final Instruction instruction;
-
- protected InstructionSubject(InstructionSubjectFactory factory, Instruction instruction) {
- this.factory = factory;
- this.instruction = instruction;
- }
-
- public boolean isInvoke() {
- return factory.isInvoke(instruction);
- }
-
- public boolean isFieldAccess() {
- return factory.isFieldAccess(instruction);
- }
-
- public boolean isInvokeVirtual() {
- return factory.isInvokeVirtual(instruction);
- }
-
- public boolean isInvokeInterface() {
- return factory.isInvokeInterface(instruction);
- }
-
- public boolean isInvokeDirect() {
- return factory.isInvokeDirect(instruction);
- }
-
- public boolean isInvokeSuper() {
- return factory.isInvokeSuper(instruction);
- }
-
- public boolean isInvokeStatic() {
- return factory.isInvokeStatic(instruction);
- }
-
- boolean isFieldAccess(Instruction instruction) {
- return factory.isFieldAccess(instruction);
- }
-
- public boolean isNop() {
- return factory.isNop(instruction);
- }
-
- public boolean isConstString() {
- return factory.isConstString(instruction);
- }
-
- public boolean isConstString(String value) {
- return factory.isConstString(instruction, value);
- }
-
- public boolean isGoto() {
- return factory.isGoto(instruction);
- }
-
- public boolean isIfNez() {
- return factory.isIfNez(instruction);
- }
-
- public boolean isIfEqz() {
- return factory.isIfEqz(instruction);
- }
-
- public boolean isReturnVoid() {
- return factory.isReturnVoid(instruction);
- }
-
- public boolean isConst4() {
- return factory.isConst4(instruction);
- }
-
- public boolean isThrow() {
- return factory.isThrow(instruction);
- }
+ DexMethod invokedMethod();
}
- public class InvokeInstructionSubject extends InstructionSubject {
+ public interface FieldAccessInstructionSubject extends InstructionSubject {
+ TypeSubject holder();
+ }
- InvokeInstructionSubject(InstructionSubjectFactory factory, Instruction instruction) {
- super(factory, instruction);
+ public class InvokeDexInstructionSubject extends DexInstructionSubject
+ implements InvokeInstructionSubject {
+
+ public InvokeDexInstructionSubject(Instruction instruction) {
+ super(instruction);
assert isInvoke();
}
@@ -1408,156 +1387,41 @@
}
public DexMethod invokedMethod() {
- if (instruction instanceof InvokeVirtual) {
- return ((InvokeVirtual) instruction).getMethod();
- }
- if (instruction instanceof InvokeVirtualRange) {
- return ((InvokeVirtualRange) instruction).getMethod();
- }
- if (instruction instanceof InvokeInterface) {
- return ((InvokeInterface) instruction).getMethod();
- }
- if (instruction instanceof InvokeInterfaceRange) {
- return ((InvokeInterfaceRange) instruction).getMethod();
- }
- if (instruction instanceof InvokeDirect) {
- return ((InvokeDirect) instruction).getMethod();
- }
- if (instruction instanceof InvokeDirectRange) {
- return ((InvokeDirectRange) instruction).getMethod();
- }
- if (instruction instanceof InvokeSuper) {
- return ((InvokeSuper) instruction).getMethod();
- }
- if (instruction instanceof InvokeSuperRange) {
- return ((InvokeSuperRange) instruction).getMethod();
- }
- if (instruction instanceof InvokeDirect) {
- return ((InvokeDirect) instruction).getMethod();
- }
- if (instruction instanceof InvokeDirectRange) {
- return ((InvokeDirectRange) instruction).getMethod();
- }
- if (instruction instanceof InvokeStatic) {
- return ((InvokeStatic) instruction).getMethod();
- }
- if (instruction instanceof InvokeStaticRange) {
- return ((InvokeStaticRange) instruction).getMethod();
- }
- assert false;
- return null;
+ return instruction.getMethod();
}
}
- public class FieldAccessInstructionSubject extends InstructionSubject {
+ public class FieldAccessDexInstructionSubject extends DexInstructionSubject
+ implements FieldAccessInstructionSubject {
- FieldAccessInstructionSubject(InstructionSubjectFactory factory, Instruction instruction) {
- super(factory, instruction);
+ public FieldAccessDexInstructionSubject(Instruction instruction) {
+ super(instruction);
assert isFieldAccess();
}
public TypeSubject holder() {
- return new TypeSubject(accessedField().getHolder());
- }
-
- public DexField accessedField() {
- if (instruction instanceof Iget) {
- return ((Iget) instruction).getField();
- }
- if (instruction instanceof IgetBoolean) {
- return ((IgetBoolean) instruction).getField();
- }
- if (instruction instanceof IgetByte) {
- return ((IgetByte) instruction).getField();
- }
- if (instruction instanceof IgetShort) {
- return ((IgetShort) instruction).getField();
- }
- if (instruction instanceof IgetChar) {
- return ((IgetChar) instruction).getField();
- }
- if (instruction instanceof IgetWide) {
- return ((IgetWide) instruction).getField();
- }
- if (instruction instanceof IgetObject) {
- return ((IgetObject) instruction).getField();
- }
- if (instruction instanceof Iput) {
- return ((Iput) instruction).getField();
- }
- if (instruction instanceof IputBoolean) {
- return ((IputBoolean) instruction).getField();
- }
- if (instruction instanceof IputByte) {
- return ((IputByte) instruction).getField();
- }
- if (instruction instanceof IputShort) {
- return ((IputShort) instruction).getField();
- }
- if (instruction instanceof IputChar) {
- return ((IputChar) instruction).getField();
- }
- if (instruction instanceof IputWide) {
- return ((IputWide) instruction).getField();
- }
- if (instruction instanceof IputObject) {
- return ((IputObject) instruction).getField();
- }
- if (instruction instanceof Sget) {
- return ((Sget) instruction).getField();
- }
- if (instruction instanceof SgetBoolean) {
- return ((SgetBoolean) instruction).getField();
- }
- if (instruction instanceof SgetByte) {
- return ((SgetByte) instruction).getField();
- }
- if (instruction instanceof SgetShort) {
- return ((SgetShort) instruction).getField();
- }
- if (instruction instanceof SgetChar) {
- return ((SgetChar) instruction).getField();
- }
- if (instruction instanceof SgetWide) {
- return ((SgetWide) instruction).getField();
- }
- if (instruction instanceof SgetObject) {
- return ((SgetObject) instruction).getField();
- }
- if (instruction instanceof Sput) {
- return ((Sput) instruction).getField();
- }
- if (instruction instanceof SputBoolean) {
- return ((SputBoolean) instruction).getField();
- }
- if (instruction instanceof SputByte) {
- return ((SputByte) instruction).getField();
- }
- if (instruction instanceof SputShort) {
- return ((SputShort) instruction).getField();
- }
- if (instruction instanceof SputChar) {
- return ((SputChar) instruction).getField();
- }
- if (instruction instanceof SputWide) {
- return ((SputWide) instruction).getField();
- }
- if (instruction instanceof SputObject) {
- return ((SputObject) instruction).getField();
- }
- assert false;
- return null;
+ return new TypeSubject(instruction.getField().getHolder());
}
}
- private class InstructionIterator implements Iterator<InstructionSubject> {
+ private interface InstructionIterator extends Iterator<InstructionSubject> {}
+
+ private InstructionIterator createInstructionIterator(MethodSubject method) {
+ Code code = method.getMethod().getCode();
+ assert code != null && code.isDexCode();
+ return new DexInstructionIterator(method);
+ }
+
+ private class DexInstructionIterator implements InstructionIterator {
private final DexCode code;
private int index;
- InstructionIterator(MethodSubject method) {
+ DexInstructionIterator(MethodSubject method) {
assert method.isPresent();
- this.code = method.getMethod().getCode().asDexCode();
+ Code code = method.getMethod().getCode();
+ assert code != null && code.isDexCode();
+ this.code = code.asDexCode();
this.index = 0;
}
@@ -1571,7 +1435,7 @@
if (index == code.instructions.length) {
throw new NoSuchElementException();
}
- return factory.create(code.instructions[index++]);
+ return createInstructionSubject(code.instructions[index++]);
}
}
@@ -1582,7 +1446,7 @@
private InstructionSubject pendingNext = null;
FilteredInstructionIterator(MethodSubject method, Predicate<InstructionSubject> predicate) {
- this.iterator = new InstructionIterator(method);
+ this.iterator = createInstructionIterator(method);
this.predicate = predicate;
hasNext();
}