Extend InstructionSubject to have a back reference to MethodSubject
This will allow for asking questions such as getLineNumber() and
retracePosition() for any instruction.
Bug: 145903423
Change-Id: I139953c753b657e691ceba5398c3df4addec29ff
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/CfInstructionIterator.java b/src/test/java/com/android/tools/r8/utils/codeinspector/CfInstructionIterator.java
index 0a3263a..6273334 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/CfInstructionIterator.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/CfInstructionIterator.java
@@ -11,10 +11,12 @@
class CfInstructionIterator implements InstructionIterator {
private final CodeInspector codeInspector;
+ private final MethodSubject method;
private final Iterator<CfInstruction> iterator;
CfInstructionIterator(CodeInspector codeInspector, MethodSubject method) {
this.codeInspector = codeInspector;
+ this.method = method;
assert method.isPresent();
Code code = method.getMethod().getCode();
assert code != null && code.isCfCode();
@@ -28,6 +30,6 @@
@Override
public InstructionSubject next() {
- return codeInspector.createInstructionSubject(iterator.next());
+ return codeInspector.createInstructionSubject(iterator.next(), method);
}
}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/CfInstructionSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/CfInstructionSubject.java
index d7ea3ae..a9ea1b7 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/CfInstructionSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/CfInstructionSubject.java
@@ -40,10 +40,13 @@
import org.objectweb.asm.Opcodes;
public class CfInstructionSubject implements InstructionSubject {
- protected final CfInstruction instruction;
- public CfInstructionSubject(CfInstruction instruction) {
+ protected final CfInstruction instruction;
+ private final MethodSubject method;
+
+ public CfInstructionSubject(CfInstruction instruction, MethodSubject method) {
this.instruction = instruction;
+ this.method = method;
}
@Override
@@ -330,6 +333,7 @@
return instruction instanceof CfArrayStore;
}
+
@Override
public int size() {
// TODO(b/122302789): CfInstruction#getSize()
@@ -343,6 +347,11 @@
}
@Override
+ public MethodSubject getMethodSubject() {
+ return method;
+ }
+
+ @Override
public boolean equals(Object other) {
return other instanceof CfInstructionSubject
&& instruction.equals(((CfInstructionSubject) other).instruction);
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java b/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java
index 535bceb..4aec544 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/CodeInspector.java
@@ -37,6 +37,8 @@
import com.android.tools.r8.references.FieldReference;
import com.android.tools.r8.references.MethodReference;
import com.android.tools.r8.references.Reference;
+import com.android.tools.r8.retrace.RetraceBase;
+import com.android.tools.r8.retrace.RetraceBaseImpl;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.BiMapContainer;
import com.android.tools.r8.utils.DescriptorUtils;
@@ -335,31 +337,31 @@
return originalTypeName != null ? originalTypeName : minifiedTypeName;
}
- InstructionSubject createInstructionSubject(Instruction instruction) {
- DexInstructionSubject dexInst = new DexInstructionSubject(instruction);
+ InstructionSubject createInstructionSubject(Instruction instruction, MethodSubject method) {
+ DexInstructionSubject dexInst = new DexInstructionSubject(instruction, method);
if (dexInst.isInvoke()) {
- return new InvokeDexInstructionSubject(this, instruction);
+ return new InvokeDexInstructionSubject(this, instruction, method);
} else if (dexInst.isFieldAccess()) {
- return new FieldAccessDexInstructionSubject(this, instruction);
+ return new FieldAccessDexInstructionSubject(this, instruction, method);
} else if (dexInst.isNewInstance()) {
- return new NewInstanceDexInstructionSubject(instruction);
+ return new NewInstanceDexInstructionSubject(instruction, method);
} else if (dexInst.isConstString(JumboStringMode.ALLOW)) {
- return new ConstStringDexInstructionSubject(instruction);
+ return new ConstStringDexInstructionSubject(instruction, method);
} else {
return dexInst;
}
}
- InstructionSubject createInstructionSubject(CfInstruction instruction) {
- CfInstructionSubject cfInst = new CfInstructionSubject(instruction);
+ InstructionSubject createInstructionSubject(CfInstruction instruction, MethodSubject method) {
+ CfInstructionSubject cfInst = new CfInstructionSubject(instruction, method);
if (cfInst.isInvoke()) {
- return new InvokeCfInstructionSubject(this, instruction);
+ return new InvokeCfInstructionSubject(this, instruction, method);
} else if (cfInst.isFieldAccess()) {
- return new FieldAccessCfInstructionSubject(this, instruction);
+ return new FieldAccessCfInstructionSubject(this, instruction, method);
} else if (cfInst.isNewInstance()) {
- return new NewInstanceCfInstructionSubject(instruction);
+ return new NewInstanceCfInstructionSubject(instruction, method);
} else if (cfInst.isConstString(JumboStringMode.ALLOW)) {
- return new ConstStringCfInstructionSubject(instruction);
+ return new ConstStringCfInstructionSubject(instruction, method);
} else {
return cfInst;
}
@@ -462,4 +464,8 @@
// nothing to do
}
}
+
+ public RetraceBase retrace() {
+ return RetraceBaseImpl.create(mapping);
+ }
}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/ConstStringCfInstructionSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/ConstStringCfInstructionSubject.java
index da545e4..c351e10 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/ConstStringCfInstructionSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/ConstStringCfInstructionSubject.java
@@ -10,8 +10,8 @@
public class ConstStringCfInstructionSubject extends CfInstructionSubject
implements ConstStringInstructionSubject {
- public ConstStringCfInstructionSubject(CfInstruction instruction) {
- super(instruction);
+ public ConstStringCfInstructionSubject(CfInstruction instruction, MethodSubject method) {
+ super(instruction, method);
assert isConstString(JumboStringMode.ALLOW);
}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/ConstStringDexInstructionSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/ConstStringDexInstructionSubject.java
index cb69144..ddff370 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/ConstStringDexInstructionSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/ConstStringDexInstructionSubject.java
@@ -11,8 +11,8 @@
public class ConstStringDexInstructionSubject extends DexInstructionSubject
implements ConstStringInstructionSubject {
- public ConstStringDexInstructionSubject(Instruction instruction) {
- super(instruction);
+ public ConstStringDexInstructionSubject(Instruction instruction, MethodSubject method) {
+ super(instruction, method);
assert isConstString(JumboStringMode.ALLOW);
}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/DexInstructionIterator.java b/src/test/java/com/android/tools/r8/utils/codeinspector/DexInstructionIterator.java
index 8ae5609..0d98b29 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/DexInstructionIterator.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/DexInstructionIterator.java
@@ -12,10 +12,12 @@
private final CodeInspector codeInspector;
private final DexCode code;
+ private final MethodSubject methodSubject;
private int index;
DexInstructionIterator(CodeInspector codeInspector, MethodSubject method) {
this.codeInspector = codeInspector;
+ this.methodSubject = method;
assert method.isPresent();
Code code = method.getMethod().getCode();
assert code != null && code.isDexCode();
@@ -33,6 +35,6 @@
if (index == code.instructions.length) {
throw new NoSuchElementException();
}
- return codeInspector.createInstructionSubject(code.instructions[index++]);
+ return codeInspector.createInstructionSubject(code.instructions[index++], methodSubject);
}
}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/DexInstructionSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/DexInstructionSubject.java
index 53fb02c..c46c123 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/DexInstructionSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/DexInstructionSubject.java
@@ -104,10 +104,13 @@
import com.android.tools.r8.ir.code.WideConstant;
public class DexInstructionSubject implements InstructionSubject {
- protected final Instruction instruction;
- public DexInstructionSubject(Instruction instruction) {
+ protected final Instruction instruction;
+ protected final MethodSubject method;
+
+ public DexInstructionSubject(Instruction instruction, MethodSubject method) {
this.instruction = instruction;
+ this.method = method;
}
@Override
@@ -438,6 +441,11 @@
}
@Override
+ public MethodSubject getMethodSubject() {
+ return method;
+ }
+
+ @Override
public boolean equals(Object other) {
return other instanceof DexInstructionSubject
&& instruction.equals(((DexInstructionSubject) other).instruction);
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/FieldAccessCfInstructionSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/FieldAccessCfInstructionSubject.java
index ae7d420..2e1d073 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/FieldAccessCfInstructionSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/FieldAccessCfInstructionSubject.java
@@ -11,8 +11,9 @@
implements FieldAccessInstructionSubject {
private final CodeInspector codeInspector;
- public FieldAccessCfInstructionSubject(CodeInspector codeInspector, CfInstruction instruction) {
- super(instruction);
+ public FieldAccessCfInstructionSubject(
+ CodeInspector codeInspector, CfInstruction instruction, MethodSubject method) {
+ super(instruction, method);
this.codeInspector = codeInspector;
assert isFieldAccess();
}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/FieldAccessDexInstructionSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/FieldAccessDexInstructionSubject.java
index 361213a..fcfdbbe 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/FieldAccessDexInstructionSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/FieldAccessDexInstructionSubject.java
@@ -11,8 +11,9 @@
private final CodeInspector codeInspector;
- public FieldAccessDexInstructionSubject(CodeInspector codeInspector, Instruction instruction) {
- super(instruction);
+ public FieldAccessDexInstructionSubject(
+ CodeInspector codeInspector, Instruction instruction, MethodSubject method) {
+ super(instruction, method);
this.codeInspector = codeInspector;
assert isFieldAccess();
}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundMethodSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundMethodSubject.java
index 0466c4e..071fb4f 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/FoundMethodSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/FoundMethodSubject.java
@@ -29,15 +29,18 @@
import com.android.tools.r8.naming.MemberNaming.MethodSignature;
import com.android.tools.r8.naming.signature.GenericSignatureParser;
import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.references.MethodReference;
+import com.android.tools.r8.references.Reference;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.codeinspector.LocalVariableTable.LocalVariableTableEntry;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableList;
-import it.unimi.dsi.fastutil.objects.Reference2IntMap;
-import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap;
+import it.unimi.dsi.fastutil.objects.Object2IntMap;
+import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import java.util.Arrays;
import java.util.Iterator;
import java.util.function.Predicate;
+import java.util.stream.Collectors;
public class FoundMethodSubject extends MethodSubject {
@@ -260,14 +263,14 @@
private LineNumberTable getCfLineNumberTable(CfCode code) {
int currentLine = -1;
- Reference2IntMap<InstructionSubject> lineNumberTable =
- new Reference2IntOpenHashMap<>(code.getInstructions().size());
+ Object2IntMap<InstructionSubject> lineNumberTable =
+ new Object2IntOpenHashMap<>(code.getInstructions().size());
for (CfInstruction insn : code.getInstructions()) {
if (insn instanceof CfPosition) {
currentLine = ((CfPosition) insn).getPosition().line;
}
if (currentLine != -1) {
- lineNumberTable.put(new CfInstructionSubject(insn), currentLine);
+ lineNumberTable.put(new CfInstructionSubject(insn, this), currentLine);
}
}
return currentLine == -1 ? null : new LineNumberTable(lineNumberTable);
@@ -278,8 +281,7 @@
if (debugInfo == null) {
return null;
}
- Reference2IntMap<InstructionSubject> lineNumberTable =
- new Reference2IntOpenHashMap<>(code.instructions.length);
+ Object2IntMap<InstructionSubject> lineNumberTable = new Object2IntOpenHashMap<>();
DexDebugPositionState state =
new DexDebugPositionState(debugInfo.startLine, getMethod().method);
Iterator<DexDebugEvent> iterator = Arrays.asList(debugInfo.events).iterator();
@@ -288,7 +290,7 @@
while (state.getCurrentPc() < offset && iterator.hasNext()) {
iterator.next().accept(state);
}
- lineNumberTable.put(new DexInstructionSubject(insn), state.getCurrentLine());
+ lineNumberTable.put(new DexInstructionSubject(insn, this), state.getCurrentLine());
}
return new LineNumberTable(lineNumberTable);
}
@@ -316,8 +318,8 @@
localVariable.getLocal().signature == null
? null
: localVariable.getLocal().signature.toString(),
- new CfInstructionSubject(localVariable.getStart()),
- new CfInstructionSubject(localVariable.getEnd())));
+ new CfInstructionSubject(localVariable.getStart(), this),
+ new CfInstructionSubject(localVariable.getEnd(), this)));
}
return new LocalVariableTable(builder.build());
}
@@ -338,4 +340,20 @@
? new AbsentAnnotationSubject()
: new FoundAnnotationSubject(annotation);
}
+
+ @Override
+ public FoundMethodSubject asFoundMethodSubject() {
+ return this;
+ }
+
+ public MethodReference asMethodReference() {
+ DexMethod method = dexMethod.method;
+ return Reference.method(
+ Reference.classFromDescriptor(method.holder.toDescriptorString()),
+ method.name.toString(),
+ Arrays.stream(method.proto.parameters.values)
+ .map(type -> Reference.typeFromDescriptor(type.toDescriptorString()))
+ .collect(Collectors.toList()),
+ Reference.returnTypeFromDescriptor(method.proto.returnType.toDescriptorString()));
+ }
}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/InstructionSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/InstructionSubject.java
index 25e10f4..9c67ece 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/InstructionSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/InstructionSubject.java
@@ -6,6 +6,8 @@
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.retrace.RetraceBase;
+import com.android.tools.r8.retrace.RetraceMethodResult;
public interface InstructionSubject {
@@ -107,4 +109,19 @@
int size();
InstructionOffsetSubject getOffset(MethodSubject methodSubject);
+
+ MethodSubject getMethodSubject();
+
+ default int getLineNumber() {
+ return getMethodSubject().getLineNumberTable().getLineForInstruction(this);
+ }
+
+ default RetraceMethodResult retracePosition(RetraceBase retraceBase) {
+ MethodSubject methodSubject = getMethodSubject();
+ assert methodSubject.isPresent();
+ int lineNumber = getLineNumber();
+ return retraceBase
+ .retrace(methodSubject.asFoundMethodSubject().asMethodReference())
+ .narrowByLine(lineNumber);
+ }
}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/InvokeCfInstructionSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/InvokeCfInstructionSubject.java
index c5ceb74..e43ece1 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/InvokeCfInstructionSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/InvokeCfInstructionSubject.java
@@ -13,8 +13,9 @@
implements InvokeInstructionSubject {
private final CodeInspector codeInspector;
- public InvokeCfInstructionSubject(CodeInspector codeInspector, CfInstruction instruction) {
- super(instruction);
+ public InvokeCfInstructionSubject(
+ CodeInspector codeInspector, CfInstruction instruction, MethodSubject method) {
+ super(instruction, method);
assert isInvoke();
this.codeInspector = codeInspector;
}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/InvokeDexInstructionSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/InvokeDexInstructionSubject.java
index 57a0e71..7f5c6ff 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/InvokeDexInstructionSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/InvokeDexInstructionSubject.java
@@ -12,8 +12,9 @@
private final CodeInspector codeInspector;
- public InvokeDexInstructionSubject(CodeInspector codeInspector, Instruction instruction) {
- super(instruction);
+ public InvokeDexInstructionSubject(
+ CodeInspector codeInspector, Instruction instruction, MethodSubject method) {
+ super(instruction, method);
this.codeInspector = codeInspector;
assert isInvoke();
}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/LineNumberTable.java b/src/test/java/com/android/tools/r8/utils/codeinspector/LineNumberTable.java
index 7c9c30f..a90707f 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/LineNumberTable.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/LineNumberTable.java
@@ -4,16 +4,20 @@
package com.android.tools.r8.utils.codeinspector;
import it.unimi.dsi.fastutil.ints.IntCollection;
-import it.unimi.dsi.fastutil.objects.Reference2IntMap;
+import it.unimi.dsi.fastutil.objects.Object2IntMap;
public class LineNumberTable {
- private final Reference2IntMap<InstructionSubject> lineNumberTable;
+ private final Object2IntMap<InstructionSubject> lineNumberTable;
- public LineNumberTable(Reference2IntMap<InstructionSubject> lineNumberTable) {
+ public LineNumberTable(Object2IntMap<InstructionSubject> lineNumberTable) {
this.lineNumberTable = lineNumberTable;
}
public IntCollection getLines() {
return lineNumberTable.values();
}
+
+ public int getLineForInstruction(InstructionSubject subject) {
+ return lineNumberTable.getInt(subject);
+ }
}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/MethodSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/MethodSubject.java
index 4fe5fb0..af6e1a4 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/MethodSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/MethodSubject.java
@@ -41,6 +41,10 @@
public abstract boolean isVirtual();
+ public FoundMethodSubject asFoundMethodSubject() {
+ return null;
+ }
+
@Override
public abstract MethodSignature getOriginalSignature();
@@ -82,6 +86,11 @@
return Streams.stream(iterateInstructions());
}
+ public void getLineNumberForInstruction(InstructionSubject subject) {
+ assert hasLineNumberTable();
+ getLineNumberTable().getLineForInstruction(subject);
+ }
+
@Override
public MethodSubject asMethodSubject() {
return this;
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/NewInstanceCfInstructionSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/NewInstanceCfInstructionSubject.java
index d3b0a93..f4e0a95 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/NewInstanceCfInstructionSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/NewInstanceCfInstructionSubject.java
@@ -10,8 +10,8 @@
public class NewInstanceCfInstructionSubject extends CfInstructionSubject
implements NewInstanceInstructionSubject {
- public NewInstanceCfInstructionSubject(CfInstruction instruction) {
- super(instruction);
+ public NewInstanceCfInstructionSubject(CfInstruction instruction, MethodSubject method) {
+ super(instruction, method);
}
@Override
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/NewInstanceDexInstructionSubject.java b/src/test/java/com/android/tools/r8/utils/codeinspector/NewInstanceDexInstructionSubject.java
index a396468..ef883fa 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/NewInstanceDexInstructionSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/NewInstanceDexInstructionSubject.java
@@ -10,8 +10,8 @@
public class NewInstanceDexInstructionSubject extends DexInstructionSubject
implements NewInstanceInstructionSubject {
- public NewInstanceDexInstructionSubject(Instruction instruction) {
- super(instruction);
+ public NewInstanceDexInstructionSubject(Instruction instruction, MethodSubject method) {
+ super(instruction, method);
}
@Override