[Retrace] Extend the RetraceApi with FrameResult
This change updates the retrace api such than one can structurally
disambiguate inline frames - that are not ambiguous - with ambiguous
results.
Bug: 170491519
Change-Id: I6b7e17aba74b16b04c6fae65413f51c952dab3e8
diff --git a/src/main/java/com/android/tools/r8/retrace/Definition.java b/src/main/java/com/android/tools/r8/retrace/Definition.java
new file mode 100644
index 0000000..f955ac0
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/retrace/Definition.java
@@ -0,0 +1,14 @@
+// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.retrace;
+
+import com.android.tools.r8.references.ClassReference;
+
+interface Definition {
+
+ String getName();
+
+ ClassReference getHolderClass();
+}
diff --git a/src/main/java/com/android/tools/r8/retrace/FieldDefinition.java b/src/main/java/com/android/tools/r8/retrace/FieldDefinition.java
new file mode 100644
index 0000000..3dcf1c9
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/retrace/FieldDefinition.java
@@ -0,0 +1,108 @@
+// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.retrace;
+
+import com.android.tools.r8.references.ClassReference;
+import com.android.tools.r8.references.FieldReference;
+import com.android.tools.r8.references.Reference;
+import java.util.Objects;
+
+/** Internal encoding of a field that allows for having either basic info or full info. */
+abstract class FieldDefinition implements Definition {
+
+ static FieldDefinition create(ClassReference obfuscatedReference, String fieldName) {
+ return new BaseFieldDefinition(obfuscatedReference, fieldName);
+ }
+
+ public static FieldDefinition create(FieldReference field) {
+ return new FullFieldDefinition(field);
+ }
+
+ abstract FieldDefinition substituteHolder(ClassReference newHolder);
+
+ static class BaseFieldDefinition extends FieldDefinition {
+ private final ClassReference classReference;
+ private final String name;
+
+ private BaseFieldDefinition(ClassReference classReference, String name) {
+ this.classReference = classReference;
+ this.name = name;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public ClassReference getHolderClass() {
+ return classReference;
+ }
+
+ @Override
+ FieldDefinition substituteHolder(ClassReference newHolder) {
+ return FieldDefinition.create(classReference, name);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ BaseFieldDefinition that = (BaseFieldDefinition) o;
+ return classReference.equals(that.classReference) && name.equals(that.name);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(classReference, name);
+ }
+ }
+
+ static class FullFieldDefinition extends FieldDefinition {
+
+ private final FieldReference fieldReference;
+
+ private FullFieldDefinition(FieldReference fieldReference) {
+ this.fieldReference = fieldReference;
+ }
+
+ @Override
+ public String getName() {
+ return fieldReference.getFieldName();
+ }
+
+ @Override
+ public ClassReference getHolderClass() {
+ return fieldReference.getHolderClass();
+ }
+
+ @Override
+ FieldDefinition substituteHolder(ClassReference newHolder) {
+ return create(
+ Reference.field(newHolder, fieldReference.getFieldName(), fieldReference.getFieldType()));
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ FullFieldDefinition that = (FullFieldDefinition) o;
+ return fieldReference.equals(that.fieldReference);
+ }
+
+ @Override
+ public int hashCode() {
+ return fieldReference.hashCode();
+ }
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/retrace/MethodDefinition.java b/src/main/java/com/android/tools/r8/retrace/MethodDefinition.java
new file mode 100644
index 0000000..8641f13
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/retrace/MethodDefinition.java
@@ -0,0 +1,135 @@
+// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.retrace;
+
+import com.android.tools.r8.references.ClassReference;
+import com.android.tools.r8.references.MethodReference;
+import com.android.tools.r8.references.Reference;
+import java.util.Objects;
+
+/** Internal encoding of a method that allows for having either basic info or full info. */
+abstract class MethodDefinition implements Definition {
+
+ static MethodDefinition create(ClassReference classReference, String methodName) {
+ return new BaseMethodDefinition(classReference, methodName);
+ }
+
+ static MethodDefinition create(MethodReference methodReference) {
+ return new FullMethodDefinition(methodReference);
+ }
+
+ boolean isFullMethodDefinition() {
+ return false;
+ }
+
+ FullMethodDefinition asFullMethodDefinition() {
+ return null;
+ }
+
+ abstract MethodDefinition substituteHolder(ClassReference newHolder);
+
+ static class BaseMethodDefinition extends MethodDefinition {
+
+ private final ClassReference classReference;
+ private final String name;
+
+ private BaseMethodDefinition(ClassReference classReference, String name) {
+ this.classReference = classReference;
+ this.name = name;
+ }
+
+ @Override
+ public ClassReference getHolderClass() {
+ return classReference;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ MethodDefinition substituteHolder(ClassReference newHolder) {
+ return MethodDefinition.create(newHolder, name);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ BaseMethodDefinition that = (BaseMethodDefinition) o;
+ return classReference.equals(that.classReference) && name.equals(that.name);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(classReference, name);
+ }
+ }
+
+ static class FullMethodDefinition extends MethodDefinition {
+
+ private final MethodReference methodReference;
+
+ private FullMethodDefinition(MethodReference methodReference) {
+ this.methodReference = methodReference;
+ }
+
+ @Override
+ public ClassReference getHolderClass() {
+ return methodReference.getHolderClass();
+ }
+
+ @Override
+ public String getName() {
+ return methodReference.getMethodName();
+ }
+
+ @Override
+ boolean isFullMethodDefinition() {
+ return true;
+ }
+
+ @Override
+ FullMethodDefinition asFullMethodDefinition() {
+ return this;
+ }
+
+ @Override
+ MethodDefinition substituteHolder(ClassReference newHolder) {
+ return MethodDefinition.create(
+ Reference.method(
+ newHolder,
+ methodReference.getMethodName(),
+ methodReference.getFormalTypes(),
+ methodReference.getReturnType()));
+ }
+
+ MethodReference getMethodReference() {
+ return methodReference;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ FullMethodDefinition that = (FullMethodDefinition) o;
+ return methodReference.equals(that.methodReference);
+ }
+
+ @Override
+ public int hashCode() {
+ return methodReference.hashCode();
+ }
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/retrace/RetraceApi.java b/src/main/java/com/android/tools/r8/retrace/RetraceApi.java
index d3bd6d3..7a1eb4e 100644
--- a/src/main/java/com/android/tools/r8/retrace/RetraceApi.java
+++ b/src/main/java/com/android/tools/r8/retrace/RetraceApi.java
@@ -14,11 +14,15 @@
@Keep
public interface RetraceApi {
+ // TODO(b/170711681): Rename these to not have overloads.
+
RetraceClassResult retrace(ClassReference classReference);
RetraceMethodResult retrace(MethodReference methodReference);
RetraceFieldResult retrace(FieldReference fieldReference);
+ RetraceFrameResult retrace(MethodReference methodReference, int position);
+
RetraceTypeResult retrace(TypeReference typeReference);
}
diff --git a/src/main/java/com/android/tools/r8/retrace/RetraceClassMemberElement.java b/src/main/java/com/android/tools/r8/retrace/RetraceClassMemberElement.java
new file mode 100644
index 0000000..c21a100
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/retrace/RetraceClassMemberElement.java
@@ -0,0 +1,28 @@
+// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.retrace;
+
+import java.util.function.BiConsumer;
+
+public interface RetraceClassMemberElement<T extends RetracedClassMember> {
+
+ boolean isUnknown();
+
+ default boolean isFrameElement() {
+ return false;
+ }
+
+ default RetraceFrameResult.Element asFrameElement() {
+ return null;
+ }
+
+ RetraceClassResult.Element getClassElement();
+
+ T getMember();
+
+ void visitFrames(BiConsumer<T, Integer> consumer);
+
+ RetraceSourceFileResult retraceSourceFile(RetracedClassMember frame, String sourceFile);
+}
diff --git a/src/main/java/com/android/tools/r8/retrace/RetraceClassResult.java b/src/main/java/com/android/tools/r8/retrace/RetraceClassResult.java
index 9ea9614..795311e 100644
--- a/src/main/java/com/android/tools/r8/retrace/RetraceClassResult.java
+++ b/src/main/java/com/android/tools/r8/retrace/RetraceClassResult.java
@@ -14,6 +14,7 @@
import com.android.tools.r8.naming.mappinginformation.MappingInformation;
import com.android.tools.r8.references.ClassReference;
import com.android.tools.r8.references.Reference;
+import com.android.tools.r8.references.TypeReference;
import com.android.tools.r8.retrace.RetraceClassResult.Element;
import com.android.tools.r8.utils.Pair;
import com.google.common.collect.ImmutableList;
@@ -43,8 +44,28 @@
}
public RetraceFieldResult lookupField(String fieldName) {
+ return lookupField(FieldDefinition.create(obfuscatedReference, fieldName));
+ }
+
+ public RetraceFieldResult lookupField(String fieldName, TypeReference fieldType) {
+ return lookupField(
+ FieldDefinition.create(Reference.field(obfuscatedReference, fieldName, fieldType)));
+ }
+
+ public RetraceMethodResult lookupMethod(String methodName) {
+ return lookupMethod(MethodDefinition.create(obfuscatedReference, methodName));
+ }
+
+ public RetraceMethodResult lookupMethod(
+ String methodName, List<TypeReference> formalTypes, TypeReference returnType) {
+ return lookupMethod(
+ MethodDefinition.create(
+ Reference.method(obfuscatedReference, methodName, formalTypes, returnType)));
+ }
+
+ private RetraceFieldResult lookupField(FieldDefinition fieldDefinition) {
return lookup(
- fieldName,
+ fieldDefinition,
(mapper, name) -> {
List<MemberNaming> memberNamings = mapper.mappedFieldNamingsByName.get(name);
if (memberNamings == null || memberNamings.isEmpty()) {
@@ -55,9 +76,9 @@
RetraceFieldResult::new);
}
- public RetraceMethodResult lookupMethod(String methodName) {
+ private RetraceMethodResult lookupMethod(MethodDefinition methodDefinition) {
return lookup(
- methodName,
+ methodDefinition,
(mapper, name) -> {
MappedRangesOfName mappedRanges = mapper.mappedRangesByRenamedName.get(name);
if (mappedRanges == null || mappedRanges.getMappedRanges().isEmpty()) {
@@ -68,16 +89,16 @@
RetraceMethodResult::new);
}
- private <T, R> R lookup(
- String name,
+ private <T, R, D extends Definition> R lookup(
+ D definition,
BiFunction<ClassNamingForNameMapper, String, T> lookupFunction,
- ResultConstructor<T, R> constructor) {
+ ResultConstructor<T, R, D> constructor) {
List<Pair<Element, T>> mappings = new ArrayList<>();
forEach(
element -> {
if (mapper != null) {
assert element.mapper != null;
- T mappedElements = lookupFunction.apply(element.mapper, name);
+ T mappedElements = lookupFunction.apply(element.mapper, definition.getName());
if (mappedElements != null) {
mappings.add(new Pair<>(element, mappedElements));
return;
@@ -85,7 +106,7 @@
}
mappings.add(new Pair<>(element, null));
});
- return constructor.create(this, mappings, name, retracer);
+ return constructor.create(this, mappings, definition, retracer);
}
boolean hasRetraceResult() {
@@ -110,11 +131,11 @@
return this;
}
- private interface ResultConstructor<T, R> {
+ private interface ResultConstructor<T, R, D> {
R create(
RetraceClassResult classResult,
List<Pair<Element, T>> mappings,
- String obfuscatedName,
+ D definition,
RetraceApi retraceApi);
}
@@ -170,8 +191,12 @@
}
public RetraceFieldResult lookupField(String fieldName) {
+ return lookupField(FieldDefinition.create(classReference.getClassReference(), fieldName));
+ }
+
+ private RetraceFieldResult lookupField(FieldDefinition fieldDefinition) {
return lookup(
- fieldName,
+ fieldDefinition,
(mapper, name) -> {
List<MemberNaming> memberNamings = mapper.mappedFieldNamingsByName.get(name);
if (memberNamings == null || memberNamings.isEmpty()) {
@@ -183,8 +208,12 @@
}
public RetraceMethodResult lookupMethod(String methodName) {
+ return lookupMethod(MethodDefinition.create(classReference.getClassReference(), methodName));
+ }
+
+ private RetraceMethodResult lookupMethod(MethodDefinition methodDefinition) {
return lookup(
- methodName,
+ methodDefinition,
(mapper, name) -> {
MappedRangesOfName mappedRanges = mapper.mappedRangesByRenamedName.get(name);
if (mappedRanges == null || mappedRanges.getMappedRanges().isEmpty()) {
@@ -195,13 +224,13 @@
RetraceMethodResult::new);
}
- private <T, R> R lookup(
- String name,
+ private <T, R, D extends Definition> R lookup(
+ D definition,
BiFunction<ClassNamingForNameMapper, String, T> lookupFunction,
- ResultConstructor<T, R> constructor) {
+ ResultConstructor<T, R, D> constructor) {
List<Pair<Element, T>> mappings = ImmutableList.of();
if (mapper != null) {
- T result = lookupFunction.apply(mapper, name);
+ T result = lookupFunction.apply(mapper, definition.getName());
if (result != null) {
mappings = ImmutableList.of(new Pair<>(this, result));
}
@@ -209,7 +238,7 @@
if (mappings.isEmpty()) {
mappings = ImmutableList.of(new Pair<>(this, null));
}
- return constructor.create(classResult, mappings, name, classResult.retracer);
+ return constructor.create(classResult, mappings, definition, classResult.retracer);
}
}
}
diff --git a/src/main/java/com/android/tools/r8/retrace/RetraceFieldResult.java b/src/main/java/com/android/tools/r8/retrace/RetraceFieldResult.java
index 114f193..46f247d 100644
--- a/src/main/java/com/android/tools/r8/retrace/RetraceFieldResult.java
+++ b/src/main/java/com/android/tools/r8/retrace/RetraceFieldResult.java
@@ -19,17 +19,17 @@
private final RetraceClassResult classResult;
private final List<Pair<RetraceClassResult.Element, List<MemberNaming>>> memberNamings;
- private final String obfuscatedName;
+ private final FieldDefinition fieldDefinition;
private final RetraceApi retracer;
RetraceFieldResult(
RetraceClassResult classResult,
List<Pair<RetraceClassResult.Element, List<MemberNaming>>> memberNamings,
- String obfuscatedName,
+ FieldDefinition fieldDefinition,
RetraceApi retracer) {
this.classResult = classResult;
this.memberNamings = memberNamings;
- this.obfuscatedName = obfuscatedName;
+ this.fieldDefinition = fieldDefinition;
this.retracer = retracer;
assert classResult != null;
assert !memberNamings.isEmpty();
@@ -59,8 +59,9 @@
new RetraceFieldResult.Element(
this,
classElement,
- RetracedField.createUnknown(
- classElement.getRetracedClass(), obfuscatedName)));
+ RetracedField.create(
+ fieldDefinition.substituteHolder(
+ classElement.getRetracedClass().getClassReference()))));
}
return memberNamings.stream()
.map(
@@ -78,7 +79,6 @@
this,
classElement,
RetracedField.create(
- holder,
Reference.field(
holder.getClassReference(),
fieldSignature.isQualified()
diff --git a/src/main/java/com/android/tools/r8/retrace/RetraceFrameResult.java b/src/main/java/com/android/tools/r8/retrace/RetraceFrameResult.java
new file mode 100644
index 0000000..95dc9d5
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/retrace/RetraceFrameResult.java
@@ -0,0 +1,164 @@
+// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.retrace;
+
+import static com.android.tools.r8.retrace.RetraceUtils.methodReferenceFromMappedRange;
+
+import com.android.tools.r8.naming.ClassNamingForNameMapper.MappedRange;
+import com.android.tools.r8.references.MethodReference;
+import com.android.tools.r8.utils.Pair;
+import com.google.common.collect.ImmutableList;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.function.BiConsumer;
+import java.util.function.Consumer;
+import java.util.stream.Stream;
+
+public class RetraceFrameResult extends Result<RetraceFrameResult.Element, RetraceFrameResult> {
+
+ private final RetraceClassResult classResult;
+ private final MethodDefinition methodDefinition;
+ private final int obfuscatedPosition;
+ private final List<Pair<RetraceClassResult.Element, List<MappedRange>>> mappedRanges;
+ private final RetraceApi retracer;
+
+ public RetraceFrameResult(
+ RetraceClassResult classResult,
+ List<Pair<RetraceClassResult.Element, List<MappedRange>>> mappedRanges,
+ MethodDefinition methodDefinition,
+ int obfuscatedPosition,
+ RetraceApi retracer) {
+ this.classResult = classResult;
+ this.methodDefinition = methodDefinition;
+ this.obfuscatedPosition = obfuscatedPosition;
+ this.mappedRanges = mappedRanges;
+ this.retracer = retracer;
+ }
+
+ @Override
+ public boolean isAmbiguous() {
+ return mappedRanges.size() > 1;
+ }
+
+ @Override
+ public Stream<Element> stream() {
+ return mappedRanges.stream()
+ .map(
+ mappedRangePair -> {
+ RetraceClassResult.Element classElement = mappedRangePair.getFirst();
+ List<MappedRange> mappedRanges = mappedRangePair.getSecond();
+ if (mappedRanges == null || mappedRanges.isEmpty()) {
+ return new Element(
+ this,
+ classElement,
+ RetracedMethod.create(
+ methodDefinition.substituteHolder(
+ classElement.getRetracedClass().getClassReference())),
+ ImmutableList.of(),
+ obfuscatedPosition);
+ }
+ MappedRange mappedRange = mappedRanges.get(0);
+ MethodReference methodReference =
+ methodReferenceFromMappedRange(
+ mappedRange, classElement.getRetracedClass().getClassReference());
+ RetracedMethod retracedMethod =
+ RetracedMethod.create(
+ methodReference, mappedRange.getOriginalLineNumber(obfuscatedPosition));
+ return new Element(
+ this, classElement, retracedMethod, mappedRanges, obfuscatedPosition);
+ });
+ }
+
+ @Override
+ public RetraceFrameResult forEach(Consumer<Element> resultConsumer) {
+ stream().forEach(resultConsumer);
+ return this;
+ }
+
+ public static class Element implements RetraceClassMemberElement<RetracedMethod> {
+
+ private final RetracedMethod methodReference;
+ private final RetraceFrameResult retraceFrameResult;
+ private final RetraceClassResult.Element classElement;
+ private final List<MappedRange> mappedRanges;
+ private final int obfuscatedPosition;
+
+ public Element(
+ RetraceFrameResult retraceFrameResult,
+ RetraceClassResult.Element classElement,
+ RetracedMethod methodReference,
+ List<MappedRange> mappedRanges,
+ int obfuscatedPosition) {
+ this.methodReference = methodReference;
+ this.retraceFrameResult = retraceFrameResult;
+ this.classElement = classElement;
+ this.mappedRanges = mappedRanges;
+ this.obfuscatedPosition = obfuscatedPosition;
+ }
+
+ @Override
+ public boolean isUnknown() {
+ return methodReference.isUnknown();
+ }
+
+ @Override
+ public boolean isFrameElement() {
+ return true;
+ }
+
+ @Override
+ public Element asFrameElement() {
+ return this;
+ }
+
+ @Override
+ public RetracedMethod getMember() {
+ return methodReference;
+ }
+
+ public RetracedMethod getTopFrame() {
+ return methodReference;
+ }
+
+ @Override
+ public RetraceClassResult.Element getClassElement() {
+ return classElement;
+ }
+
+ @Override
+ public void visitFrames(BiConsumer<RetracedMethod, Integer> consumer) {
+ int counter = 0;
+ consumer.accept(methodReference, counter++);
+ for (RetracedMethod outerFrame : getOuterFrames()) {
+ consumer.accept(outerFrame, counter++);
+ }
+ }
+
+ @Override
+ public RetraceSourceFileResult retraceSourceFile(RetracedClassMember frame, String sourceFile) {
+ return RetraceUtils.getSourceFile(
+ classElement, frame.getHolderClass(), sourceFile, retraceFrameResult.retracer);
+ }
+
+ public List<RetracedMethod> getOuterFrames() {
+ if (mappedRanges == null) {
+ return Collections.emptyList();
+ }
+ List<RetracedMethod> outerFrames = new ArrayList<>();
+ for (int i = 1; i < mappedRanges.size(); i++) {
+ MappedRange mappedRange = mappedRanges.get(i);
+ MethodReference methodReference =
+ methodReferenceFromMappedRange(
+ mappedRange, classElement.getRetracedClass().getClassReference());
+ outerFrames.add(
+ RetracedMethod.create(
+ MethodDefinition.create(methodReference),
+ mappedRange.getOriginalLineNumber(obfuscatedPosition)));
+ }
+ return outerFrames;
+ }
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/retrace/RetraceMethodResult.java b/src/main/java/com/android/tools/r8/retrace/RetraceMethodResult.java
index 7a41f74..0906420 100644
--- a/src/main/java/com/android/tools/r8/retrace/RetraceMethodResult.java
+++ b/src/main/java/com/android/tools/r8/retrace/RetraceMethodResult.java
@@ -7,21 +7,19 @@
import com.android.tools.r8.Keep;
import com.android.tools.r8.naming.ClassNamingForNameMapper.MappedRange;
import com.android.tools.r8.naming.ClassNamingForNameMapper.MappedRangesOfName;
-import com.android.tools.r8.naming.MemberNaming.MethodSignature;
-import com.android.tools.r8.references.Reference;
-import com.android.tools.r8.references.TypeReference;
-import com.android.tools.r8.utils.DescriptorUtils;
+import com.android.tools.r8.references.MethodReference;
import com.android.tools.r8.utils.Pair;
import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
import java.util.List;
+import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.stream.Stream;
@Keep
public class RetraceMethodResult extends Result<RetraceMethodResult.Element, RetraceMethodResult> {
- private final String obfuscatedName;
+ private final MethodDefinition methodDefinition;
private final RetraceClassResult classResult;
private final List<Pair<RetraceClassResult.Element, List<MappedRange>>> mappedRanges;
private final RetraceApi retracer;
@@ -29,15 +27,14 @@
RetraceMethodResult(
RetraceClassResult classResult,
List<Pair<RetraceClassResult.Element, List<MappedRange>>> mappedRanges,
- String obfuscatedName,
+ MethodDefinition methodDefinition,
RetraceApi retracer) {
this.classResult = classResult;
this.mappedRanges = mappedRanges;
- this.obfuscatedName = obfuscatedName;
+ this.methodDefinition = methodDefinition;
this.retracer = retracer;
assert classResult != null;
- // TODO(mkroghj): Enable this when we have frame results.
- // assert !mappedRanges.isEmpty();
+ assert !mappedRanges.isEmpty();
}
@Override
@@ -60,7 +57,7 @@
return false;
}
- public RetraceMethodResult narrowByLine(int linePosition) {
+ public RetraceFrameResult narrowByPosition(int position) {
List<Pair<RetraceClassResult.Element, List<MappedRange>>> narrowedRanges = new ArrayList<>();
List<Pair<RetraceClassResult.Element, List<MappedRange>>> noMappingRanges = new ArrayList<>();
for (Pair<RetraceClassResult.Element, List<MappedRange>> mappedRange : mappedRanges) {
@@ -69,7 +66,7 @@
continue;
}
List<MappedRange> ranges =
- new MappedRangesOfName(mappedRange.getSecond()).allRangesForLine(linePosition, false);
+ new MappedRangesOfName(mappedRange.getSecond()).allRangesForLine(position, false);
boolean hasAddedRanges = false;
if (!ranges.isEmpty()) {
narrowedRanges.add(new Pair<>(mappedRange.getFirst(), ranges));
@@ -87,10 +84,11 @@
narrowedRanges.add(new Pair<>(mappedRange.getFirst(), null));
}
}
- return new RetraceMethodResult(
+ return new RetraceFrameResult(
classResult,
narrowedRanges.isEmpty() ? noMappingRanges : narrowedRanges,
- obfuscatedName,
+ methodDefinition,
+ position,
retracer);
}
@@ -101,45 +99,23 @@
mappedRangePair -> {
RetraceClassResult.Element classElement = mappedRangePair.getFirst();
List<MappedRange> mappedRanges = mappedRangePair.getSecond();
- if (mappedRanges == null) {
+ if (mappedRanges == null || mappedRanges.isEmpty()) {
return Stream.of(
new Element(
this,
classElement,
- RetracedMethod.createUnknown(
- classElement.getRetracedClass(), obfuscatedName),
- null));
+ RetracedMethod.create(
+ methodDefinition.substituteHolder(
+ classElement.getRetracedClass().getClassReference()))));
}
return mappedRanges.stream()
.map(
mappedRange -> {
- MethodSignature signature = mappedRange.signature;
- RetracedClass holder =
- mappedRange.signature.isQualified()
- ? RetracedClass.create(
- Reference.classFromDescriptor(
- DescriptorUtils.javaTypeToDescriptor(
- mappedRange.signature.toHolderFromQualified())))
- : classElement.getRetracedClass();
- List<TypeReference> formalTypes =
- new ArrayList<>(signature.parameters.length);
- for (String parameter : signature.parameters) {
- formalTypes.add(Reference.typeFromTypeName(parameter));
- }
- TypeReference returnType =
- Reference.returnTypeFromDescriptor(
- DescriptorUtils.javaTypeToDescriptor(signature.type));
- RetracedMethod retracedMethod =
- RetracedMethod.create(
- holder,
- Reference.method(
- holder.getClassReference(),
- signature.isQualified()
- ? signature.toUnqualifiedName()
- : signature.name,
- formalTypes,
- returnType));
- return new Element(this, classElement, retracedMethod, mappedRange);
+ MethodReference methodReference =
+ RetraceUtils.methodReferenceFromMappedRange(
+ mappedRange, classElement.getRetracedClass().getClassReference());
+ return new Element(
+ this, classElement, RetracedMethod.create(methodReference));
});
});
}
@@ -150,41 +126,28 @@
return this;
}
- public static class Element {
+ public static class Element implements RetraceClassMemberElement<RetracedMethod> {
private final RetracedMethod methodReference;
private final RetraceMethodResult retraceMethodResult;
private final RetraceClassResult.Element classElement;
- private final MappedRange mappedRange;
private Element(
RetraceMethodResult retraceMethodResult,
RetraceClassResult.Element classElement,
- RetracedMethod methodReference,
- MappedRange mappedRange) {
+ RetracedMethod methodReference) {
this.classElement = classElement;
this.retraceMethodResult = retraceMethodResult;
this.methodReference = methodReference;
- this.mappedRange = mappedRange;
}
+ @Override
public boolean isUnknown() {
return methodReference.isUnknown();
}
- public boolean hasNoLineNumberRange() {
- return mappedRange == null || mappedRange.minifiedRange == null;
- }
-
- public boolean containsMinifiedLineNumber(int linePosition) {
- if (hasNoLineNumberRange()) {
- return false;
- }
- return mappedRange.minifiedRange.from <= linePosition
- && linePosition <= mappedRange.minifiedRange.to;
- }
-
- public RetracedMethod getMethod() {
+ @Override
+ public RetracedMethod getMember() {
return methodReference;
}
@@ -192,22 +155,18 @@
return retraceMethodResult;
}
+ @Override
public RetraceClassResult.Element getClassElement() {
return classElement;
}
- public int getOriginalLineNumber(int linePosition) {
- return mappedRange != null ? mappedRange.getOriginalLineNumber(linePosition) : linePosition;
+ @Override
+ public void visitFrames(BiConsumer<RetracedMethod, Integer> consumer) {
+ consumer.accept(methodReference, 0);
}
- public int getFirstLineNumberOfOriginalRange() {
- if (hasNoLineNumberRange()) {
- return 0;
- }
- return mappedRange.getFirstLineNumberOfOriginalRange();
- }
-
- public RetraceSourceFileResult retraceSourceFile(String sourceFile) {
+ @Override
+ public RetraceSourceFileResult retraceSourceFile(RetracedClassMember frame, String sourceFile) {
return RetraceUtils.getSourceFile(
classElement, methodReference.getHolderClass(), sourceFile, retraceMethodResult.retracer);
}
diff --git a/src/main/java/com/android/tools/r8/retrace/RetraceRegularExpression.java b/src/main/java/com/android/tools/r8/retrace/RetraceRegularExpression.java
index bccb9dd..910db1a 100644
--- a/src/main/java/com/android/tools/r8/retrace/RetraceRegularExpression.java
+++ b/src/main/java/com/android/tools/r8/retrace/RetraceRegularExpression.java
@@ -4,6 +4,8 @@
package com.android.tools.r8.retrace;
+import static com.android.tools.r8.retrace.RetraceUtils.methodDescriptionFromRetraceMethod;
+
import com.android.tools.r8.DiagnosticsHandler;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.references.ClassReference;
@@ -14,7 +16,6 @@
import com.android.tools.r8.retrace.RetracedField.KnownRetracedField;
import com.android.tools.r8.utils.Box;
import com.android.tools.r8.utils.DescriptorUtils;
-import com.android.tools.r8.utils.StringDiagnostic;
import com.android.tools.r8.utils.StringUtils;
import com.google.common.collect.Lists;
import java.util.ArrayList;
@@ -133,7 +134,7 @@
case CLASS:
return line.getClassContext().getRetracedClass().getTypeName();
case METHOD:
- return line.getMethodContext().getMethod().getMethodName();
+ return line.getMethodContext().getMember().getMethodName();
case SOURCE:
return line.getSource();
case LINE:
@@ -241,9 +242,10 @@
static class RetraceStringContext {
private final Element classContext;
- private final RetracedClass qualifiedContext;
+ private final RetraceClassMemberElement<? extends RetracedMethod> methodContext;
+ private final RetracedClass qualifiedClassContext;
+ private final RetracedMethod qualifiedMethodContext;
private final String methodName;
- private final RetraceMethodResult.Element methodContext;
private final int minifiedLineNumber;
private final int originalLineNumber;
private final String source;
@@ -251,17 +253,19 @@
private RetraceStringContext(
Element classContext,
- RetracedClass qualifiedContext,
+ RetraceClassMemberElement<? extends RetracedMethod> methodContext,
+ RetracedClass qualifiedClassContext,
+ RetracedMethod qualifiedMethodContext,
String methodName,
- RetraceMethodResult.Element methodContext,
int minifiedLineNumber,
int originalLineNumber,
String source,
boolean isAmbiguous) {
this.classContext = classContext;
- this.qualifiedContext = qualifiedContext;
- this.methodName = methodName;
this.methodContext = methodContext;
+ this.qualifiedClassContext = qualifiedClassContext;
+ this.qualifiedMethodContext = qualifiedMethodContext;
+ this.methodName = methodName;
this.minifiedLineNumber = minifiedLineNumber;
this.originalLineNumber = originalLineNumber;
this.source = source;
@@ -269,16 +273,18 @@
}
private static RetraceStringContext empty() {
- return new RetraceStringContext(null, null, null, null, NO_MATCH, NO_MATCH, null, false);
+ return new RetraceStringContext(
+ null, null, null, null, null, NO_MATCH, NO_MATCH, null, false);
}
private RetraceStringContext withClassContext(
Element classContext, RetracedClass qualifiedContext) {
return new RetraceStringContext(
classContext,
- qualifiedContext,
- methodName,
methodContext,
+ qualifiedContext,
+ qualifiedMethodContext,
+ methodName,
minifiedLineNumber,
originalLineNumber,
source,
@@ -288,9 +294,10 @@
private RetraceStringContext withMethodName(String methodName) {
return new RetraceStringContext(
classContext,
- qualifiedContext,
- methodName,
methodContext,
+ qualifiedClassContext,
+ qualifiedMethodContext,
+ methodName,
minifiedLineNumber,
originalLineNumber,
source,
@@ -298,26 +305,39 @@
}
private RetraceStringContext withMethodContext(
- RetraceMethodResult.Element methodContext,
- RetracedClass qualifiedContext,
- boolean isAmbiguous) {
+ RetraceClassMemberElement<? extends RetracedMethod> methodContext, boolean isAmbiguous) {
return new RetraceStringContext(
classContext,
- qualifiedContext,
- methodName,
methodContext,
+ qualifiedClassContext,
+ qualifiedMethodContext,
+ methodName,
minifiedLineNumber,
originalLineNumber,
source,
isAmbiguous);
}
- private RetraceStringContext withQualifiedContext(RetracedClass qualifiedContext) {
+ private RetraceStringContext withQualifiedClassContext(RetracedClass qualifiedContext) {
return new RetraceStringContext(
classContext,
+ methodContext,
+ qualifiedContext,
+ qualifiedMethodContext,
+ methodName,
+ minifiedLineNumber,
+ originalLineNumber,
+ source,
+ isAmbiguous);
+ }
+
+ private RetraceStringContext withQualifiedMethodContext(RetracedMethod qualifiedContext) {
+ return new RetraceStringContext(
+ classContext,
+ methodContext,
+ qualifiedContext.getHolderClass(),
qualifiedContext,
methodName,
- methodContext,
minifiedLineNumber,
originalLineNumber,
source,
@@ -327,9 +347,10 @@
public RetraceStringContext withSource(String source) {
return new RetraceStringContext(
classContext,
- qualifiedContext,
- methodName,
methodContext,
+ qualifiedClassContext,
+ qualifiedMethodContext,
+ methodName,
minifiedLineNumber,
originalLineNumber,
source,
@@ -339,9 +360,10 @@
public RetraceStringContext withLineNumbers(int minifiedLineNumber, int originalLineNumber) {
return new RetraceStringContext(
classContext,
- qualifiedContext,
- methodName,
methodContext,
+ qualifiedClassContext,
+ qualifiedMethodContext,
+ methodName,
minifiedLineNumber,
originalLineNumber,
source,
@@ -385,7 +407,7 @@
return context.classContext;
}
- private RetraceMethodResult.Element getMethodContext() {
+ private RetraceClassMemberElement<? extends RetracedMethod> getMethodContext() {
return context.methodContext;
}
@@ -657,7 +679,7 @@
if (classNameGroupHandler != null) {
for (RetraceString string : strings) {
classNameGroupHandler.commitClassName(
- original, string, string.context.qualifiedContext, matcher);
+ original, string, string.context.qualifiedClassContext, matcher);
}
}
return strings;
@@ -669,20 +691,23 @@
retraceString,
methodName,
(element, newContext) -> {
- final RetraceString newRetraceString = retraceString.duplicate(newContext);
- if (classNameGroupHandler != null) {
- classNameGroupHandler.commitClassName(
- original, newRetraceString, element.getMethod().getHolderClass(), matcher);
- }
- retracedStrings.add(
- newRetraceString.appendRetracedString(
- original,
- printVerbose
- ? RetraceUtils.methodDescriptionFromMethodReference(
- element.getMethod(), false, true)
- : element.getMethod().getMethodName(),
- startOfGroup,
- matcher.end(captureGroup)));
+ element.visitFrames(
+ (method, ignoredPosition) -> {
+ RetraceString newRetraceString =
+ retraceString.duplicate(newContext.withQualifiedMethodContext(method));
+ if (classNameGroupHandler != null) {
+ classNameGroupHandler.commitClassName(
+ original, newRetraceString, method.getHolderClass(), matcher);
+ }
+ retracedStrings.add(
+ newRetraceString.appendRetracedString(
+ original,
+ printVerbose
+ ? methodDescriptionFromRetraceMethod(method, false, true)
+ : method.getMethodName(),
+ startOfGroup,
+ matcher.end(captureGroup)));
+ });
});
}
return retracedStrings;
@@ -703,24 +728,25 @@
private static void retraceMethodForString(
RetraceString retraceString,
String methodName,
- BiConsumer<RetraceMethodResult.Element, RetraceStringContext> process) {
+ BiConsumer<RetraceClassMemberElement<? extends RetracedMethod>, RetraceStringContext>
+ process) {
if (retraceString.context.classContext == null) {
return;
}
RetraceMethodResult retraceMethodResult =
retraceString.getClassContext().lookupMethod(methodName);
+ Result<? extends RetraceClassMemberElement<RetracedMethod>, ?> retraceResult;
if (retraceString.context.minifiedLineNumber > NO_MATCH) {
- retraceMethodResult =
- retraceMethodResult.narrowByLine(retraceString.context.minifiedLineNumber);
+ retraceResult =
+ retraceMethodResult.narrowByPosition(retraceString.context.minifiedLineNumber);
+ } else {
+ retraceResult = retraceMethodResult;
}
- retraceMethodResult.forEach(
+ retraceResult.forEach(
element ->
process.accept(
element,
- retraceString.context.withMethodContext(
- element,
- element.getMethod().getHolderClass(),
- element.getRetraceMethodResult().isAmbiguous())));
+ retraceString.context.withMethodContext(element, retraceResult.isAmbiguous())));
}
}
@@ -756,7 +782,7 @@
if (classNameGroupHandler != null) {
for (RetraceString string : strings) {
classNameGroupHandler.commitClassName(
- original, string, string.context.qualifiedContext, matcher);
+ original, string, string.context.qualifiedClassContext, matcher);
}
}
return strings;
@@ -781,7 +807,8 @@
retraceString
.updateContext(
context ->
- context.withQualifiedContext(element.getField().getHolderClass()))
+ context.withQualifiedClassContext(
+ element.getField().getHolderClass()))
.appendRetracedString(
original,
getFieldString(element.getField()),
@@ -829,10 +856,12 @@
}
RetraceSourceFileResult sourceFileResult =
retraceString.getMethodContext() != null
- ? retraceString.getMethodContext().retraceSourceFile(fileName)
+ ? retraceString
+ .getMethodContext()
+ .retraceSourceFile(retraceString.context.qualifiedMethodContext, fileName)
: RetraceUtils.getSourceFile(
retraceString.getClassContext(),
- retraceString.context.qualifiedContext,
+ retraceString.context.qualifiedClassContext,
fileName,
retracer);
retracedStrings.add(
@@ -873,7 +902,8 @@
int lineNumber = Integer.parseInt(lineNumberAsString);
List<RetraceString> retracedStrings = new ArrayList<>();
for (RetraceString retraceString : strings) {
- RetraceMethodResult.Element methodContext = retraceString.context.methodContext;
+ RetraceClassMemberElement<? extends RetracedMethod> methodContext =
+ retraceString.context.methodContext;
if (methodContext == null) {
if (retraceString.context.classContext == null
|| retraceString.context.methodName == null) {
@@ -889,34 +919,33 @@
(element, newContext) -> {
// The same method can be represented multiple times if it has multiple
// mappings.
- if (element.hasNoLineNumberRange()
- || !element.containsMinifiedLineNumber(lineNumber)) {
- diagnosticsHandler.info(
- new StringDiagnostic(
- "Pruning "
- + retraceString.builder.retracedString.toString()
- + " from result because method is not in range on line number "
- + lineNumber));
- }
- final int originalLineNumber = element.getOriginalLineNumber(lineNumber);
- retracedStrings.add(
- retraceString
- .updateContext(
- context -> context.withLineNumbers(lineNumber, originalLineNumber))
- .appendRetracedString(
- original,
- originalLineNumber + "",
- startOfGroup,
- matcher.end(captureGroup)));
+ element.visitFrames(
+ (method, ignoredPosition) -> {
+ int originalPosition = method.getOriginalPositionOrDefault(lineNumber);
+ retracedStrings.add(
+ retraceString
+ .duplicate(
+ retraceString
+ .context
+ .withQualifiedMethodContext(method)
+ .withLineNumbers(lineNumber, originalPosition))
+ .appendRetracedString(
+ original,
+ originalPosition + "",
+ startOfGroup,
+ matcher.end(captureGroup)));
+ });
});
continue;
}
// If the method context is unknown, do nothing.
- if (methodContext.isUnknown() || methodContext.hasNoLineNumberRange()) {
+ if (methodContext.isUnknown()) {
retracedStrings.add(retraceString);
continue;
}
- int originalLineNumber = methodContext.getOriginalLineNumber(lineNumber);
+ int originalLineNumber =
+ retraceString.context.qualifiedMethodContext.getOriginalPositionOrDefault(
+ lineNumber);
retracedStrings.add(
retraceString
.updateContext(
diff --git a/src/main/java/com/android/tools/r8/retrace/RetraceStackTrace.java b/src/main/java/com/android/tools/r8/retrace/RetraceStackTrace.java
index e2e3616..024f761 100644
--- a/src/main/java/com/android/tools/r8/retrace/RetraceStackTrace.java
+++ b/src/main/java/com/android/tools/r8/retrace/RetraceStackTrace.java
@@ -4,7 +4,7 @@
package com.android.tools.r8.retrace;
-import static com.android.tools.r8.retrace.RetraceUtils.methodDescriptionFromMethodReference;
+import static com.android.tools.r8.retrace.RetraceUtils.methodDescriptionFromRetraceMethod;
import static com.google.common.base.Predicates.not;
import com.android.tools.r8.DiagnosticsHandler;
@@ -418,28 +418,31 @@
RetraceApi retracer, boolean verbose, List<StackTraceLine> lines, String classLoaderName) {
ClassReference classReference = Reference.classFromTypeName(clazz);
RetraceClassResult classResult = retracer.retrace(classReference);
- RetraceMethodResult retraceResult = classResult.lookupMethod(method);
+ RetraceMethodResult retraceMethodResult = classResult.lookupMethod(method);
+ Result<? extends RetraceClassMemberElement<RetracedMethod>, ?> retraceResult;
if (linePosition != NO_POSITION && linePosition != INVALID_POSITION) {
- retraceResult = retraceResult.narrowByLine(linePosition);
+ retraceResult = retraceMethodResult.narrowByPosition(linePosition);
+ } else {
+ retraceResult = retraceMethodResult;
}
retraceResult.forEach(
- methodElement -> {
- RetracedMethod methodReference = methodElement.getMethod();
- lines.add(
- new AtLine(
- startingWhitespace,
- at,
- classLoaderName,
- moduleName,
- methodReference.getHolderClass().getTypeName(),
- methodReference.getMethodName(),
- methodDescriptionFromMethodReference(methodReference, true, verbose),
- methodElement.retraceSourceFile(fileName).getFilename(),
- hasLinePosition()
- ? methodElement.getOriginalLineNumber(linePosition)
- : linePosition,
- methodElement.getRetraceMethodResult().isAmbiguous()));
- });
+ methodElement ->
+ methodElement.visitFrames(
+ (methodReference, ignoredPosition) ->
+ lines.add(
+ new AtLine(
+ startingWhitespace,
+ at,
+ classLoaderName,
+ moduleName,
+ methodReference.getHolderClass().getTypeName(),
+ methodReference.getMethodName(),
+ methodDescriptionFromRetraceMethod(methodReference, true, verbose),
+ methodElement
+ .retraceSourceFile(methodReference, fileName)
+ .getFilename(),
+ methodReference.getOriginalPositionOrDefault(linePosition),
+ retraceResult.isAmbiguous()))));
}
@Override
diff --git a/src/main/java/com/android/tools/r8/retrace/RetraceUtils.java b/src/main/java/com/android/tools/r8/retrace/RetraceUtils.java
index 335059e..e402a80 100644
--- a/src/main/java/com/android/tools/r8/retrace/RetraceUtils.java
+++ b/src/main/java/com/android/tools/r8/retrace/RetraceUtils.java
@@ -4,11 +4,19 @@
package com.android.tools.r8.retrace;
+import com.android.tools.r8.naming.ClassNamingForNameMapper.MappedRange;
+import com.android.tools.r8.naming.MemberNaming.MethodSignature;
+import com.android.tools.r8.references.ClassReference;
+import com.android.tools.r8.references.MethodReference;
+import com.android.tools.r8.references.Reference;
import com.android.tools.r8.references.TypeReference;
import com.android.tools.r8.retrace.RetracedMethod.KnownRetracedMethod;
import com.android.tools.r8.utils.Box;
+import com.android.tools.r8.utils.DescriptorUtils;
import com.google.common.collect.Sets;
import com.google.common.io.Files;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Set;
public class RetraceUtils {
@@ -16,7 +24,7 @@
private static final Set<String> UNKNOWN_SOURCEFILE_NAMES =
Sets.newHashSet("", "SourceFile", "Unknown", "Unknown Source", "PG");
- public static String methodDescriptionFromMethodReference(
+ public static String methodDescriptionFromRetraceMethod(
RetracedMethod methodReference, boolean appendHolder, boolean verbose) {
StringBuilder sb = new StringBuilder();
if (appendHolder) {
@@ -115,4 +123,25 @@
String newFileName = getClassSimpleName(retracedClassName);
return newFileName + "." + extension;
}
+
+ static MethodReference methodReferenceFromMappedRange(
+ MappedRange mappedRange, ClassReference classReference) {
+ MethodSignature signature = mappedRange.signature;
+ ClassReference holder =
+ signature.isQualified()
+ ? Reference.classFromDescriptor(
+ DescriptorUtils.javaTypeToDescriptor(signature.toHolderFromQualified()))
+ : classReference;
+ List<TypeReference> formalTypes = new ArrayList<>(signature.parameters.length);
+ for (String parameter : signature.parameters) {
+ formalTypes.add(Reference.typeFromTypeName(parameter));
+ }
+ TypeReference returnType =
+ Reference.returnTypeFromDescriptor(DescriptorUtils.javaTypeToDescriptor(signature.type));
+ return Reference.method(
+ holder,
+ signature.isQualified() ? signature.toUnqualifiedName() : signature.name,
+ formalTypes,
+ returnType);
+ }
}
diff --git a/src/main/java/com/android/tools/r8/retrace/RetracedClassMember.java b/src/main/java/com/android/tools/r8/retrace/RetracedClassMember.java
new file mode 100644
index 0000000..e05be47
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/retrace/RetracedClassMember.java
@@ -0,0 +1,10 @@
+// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.retrace;
+
+public interface RetracedClassMember {
+
+ RetracedClass getHolderClass();
+}
diff --git a/src/main/java/com/android/tools/r8/retrace/RetracedField.java b/src/main/java/com/android/tools/r8/retrace/RetracedField.java
index b809cab..132d0c7 100644
--- a/src/main/java/com/android/tools/r8/retrace/RetracedField.java
+++ b/src/main/java/com/android/tools/r8/retrace/RetracedField.java
@@ -10,7 +10,7 @@
import java.util.Objects;
@Keep
-public abstract class RetracedField {
+public abstract class RetracedField implements RetracedClassMember {
private RetracedField() {}
@@ -26,17 +26,13 @@
return null;
}
- public abstract RetracedClass getHolderClass();
-
public abstract String getFieldName();
public static final class KnownRetracedField extends RetracedField {
- private final RetracedClass classReference;
private final FieldReference fieldReference;
- private KnownRetracedField(RetracedClass classReference, FieldReference fieldReference) {
- this.classReference = classReference;
+ private KnownRetracedField(FieldReference fieldReference) {
this.fieldReference = fieldReference;
}
@@ -52,7 +48,7 @@
@Override
public RetracedClass getHolderClass() {
- return classReference;
+ return RetracedClass.create(fieldReference.getHolderClass());
}
@Override
@@ -77,43 +73,56 @@
return false;
}
KnownRetracedField that = (KnownRetracedField) o;
- assert !fieldReference.equals(that.fieldReference)
- || classReference.equals(that.classReference);
return fieldReference.equals(that.fieldReference);
}
@Override
public int hashCode() {
- return Objects.hash(classReference, fieldReference);
+ return Objects.hash(fieldReference);
}
}
public static final class UnknownRetracedField extends RetracedField {
- private final RetracedClass classReference;
- private final String name;
+ private final FieldDefinition fieldDefinition;
- private UnknownRetracedField(RetracedClass classReference, String name) {
- this.classReference = classReference;
- this.name = name;
+ private UnknownRetracedField(FieldDefinition fieldDefinition) {
+ this.fieldDefinition = fieldDefinition;
}
@Override
public RetracedClass getHolderClass() {
- return classReference;
+ return RetracedClass.create(fieldDefinition.getHolderClass());
}
@Override
public String getFieldName() {
- return name;
+ return fieldDefinition.getName();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ UnknownRetracedField that = (UnknownRetracedField) o;
+ return fieldDefinition.equals(that.fieldDefinition);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(fieldDefinition);
}
}
- static RetracedField create(RetracedClass classReference, FieldReference fieldReference) {
- return new KnownRetracedField(classReference, fieldReference);
+ static RetracedField create(FieldReference fieldReference) {
+ return new KnownRetracedField(fieldReference);
}
- static RetracedField createUnknown(RetracedClass classReference, String name) {
- return new UnknownRetracedField(classReference, name);
+ static RetracedField create(FieldDefinition fieldDefinition) {
+ return new UnknownRetracedField(fieldDefinition);
}
}
diff --git a/src/main/java/com/android/tools/r8/retrace/RetracedMethod.java b/src/main/java/com/android/tools/r8/retrace/RetracedMethod.java
index ee3b792..937ded1 100644
--- a/src/main/java/com/android/tools/r8/retrace/RetracedMethod.java
+++ b/src/main/java/com/android/tools/r8/retrace/RetracedMethod.java
@@ -9,9 +9,12 @@
import com.android.tools.r8.references.TypeReference;
import java.util.List;
import java.util.Objects;
+import java.util.Optional;
@Keep
-public abstract class RetracedMethod {
+public abstract class RetracedMethod implements RetracedClassMember {
+
+ private static final int NO_POSITION = -1;
private RetracedMethod() {}
@@ -27,19 +30,21 @@
return null;
}
- public abstract RetracedClass getHolderClass();
-
public abstract String getMethodName();
+ public abstract boolean hasPosition();
+
+ public abstract int getOriginalPositionOrDefault(int defaultPosition);
+
public static final class KnownRetracedMethod extends RetracedMethod {
private final MethodReference methodReference;
- private final RetracedClass classReference;
+ private final int position;
- private KnownRetracedMethod(RetracedClass classReference, MethodReference methodReference) {
+ private KnownRetracedMethod(MethodReference methodReference, int position) {
assert methodReference != null;
- this.classReference = classReference;
this.methodReference = methodReference;
+ this.position = position;
}
@Override
@@ -58,7 +63,7 @@
@Override
public RetracedClass getHolderClass() {
- return classReference;
+ return RetracedClass.create(methodReference.getHolderClass());
}
@Override
@@ -66,6 +71,16 @@
return methodReference.getMethodName();
}
+ @Override
+ public boolean hasPosition() {
+ return position != NO_POSITION;
+ }
+
+ @Override
+ public int getOriginalPositionOrDefault(int defaultPosition) {
+ return hasPosition() ? position : defaultPosition;
+ }
+
public TypeReference getReturnType() {
assert !isVoid();
return methodReference.getReturnType();
@@ -75,14 +90,10 @@
return methodReference.getFormalTypes();
}
- public MethodReference getClassReference() {
+ public MethodReference getMethodReference() {
return methodReference;
}
- public boolean equalsMethodReference(MethodReference reference) {
- return methodReference.equals(reference);
- }
-
@Override
public boolean equals(Object o) {
if (this == o) {
@@ -92,43 +103,70 @@
return false;
}
KnownRetracedMethod that = (KnownRetracedMethod) o;
- assert !methodReference.equals(that.methodReference)
- || classReference.equals(that.classReference);
- return methodReference.equals(that.methodReference);
+ return position == that.position && methodReference.equals(that.methodReference);
}
@Override
public int hashCode() {
- return Objects.hash(methodReference, classReference);
+ return Objects.hash(methodReference, position);
}
}
public static final class UnknownRetracedMethod extends RetracedMethod {
- private final RetracedClass classReference;
- private final String name;
+ private final MethodDefinition methodDefinition;
+ private final int position;
- private UnknownRetracedMethod(RetracedClass classReference, String name) {
- this.classReference = classReference;
- this.name = name;
+ private UnknownRetracedMethod(MethodDefinition methodDefinition, int position) {
+ this.methodDefinition = methodDefinition;
+ this.position = position;
}
@Override
public RetracedClass getHolderClass() {
- return classReference;
+ return RetracedClass.create(methodDefinition.getHolderClass());
}
@Override
public String getMethodName() {
- return name;
+ return methodDefinition.getName();
+ }
+
+ @Override
+ public boolean hasPosition() {
+ return position != NO_POSITION;
+ }
+
+ @Override
+ public int getOriginalPositionOrDefault(int defaultPosition) {
+ return hasPosition() ? position : defaultPosition;
+ }
+
+ public Optional<MethodReference> getMethodReference() {
+ if (!methodDefinition.isFullMethodDefinition()) {
+ return Optional.empty();
+ }
+ return Optional.of(methodDefinition.asFullMethodDefinition().getMethodReference());
}
}
- static RetracedMethod create(RetracedClass classReference, MethodReference methodReference) {
- return new KnownRetracedMethod(classReference, methodReference);
+ static RetracedMethod create(MethodDefinition methodDefinition) {
+ return create(methodDefinition, NO_POSITION);
}
- static RetracedMethod createUnknown(RetracedClass classReference, String name) {
- return new UnknownRetracedMethod(classReference, name);
+ static RetracedMethod create(MethodDefinition methodDefinition, int position) {
+ if (methodDefinition.isFullMethodDefinition()) {
+ return new KnownRetracedMethod(
+ methodDefinition.asFullMethodDefinition().getMethodReference(), position);
+ }
+ return new UnknownRetracedMethod(methodDefinition, position);
+ }
+
+ static RetracedMethod create(MethodReference methodReference) {
+ return create(methodReference, NO_POSITION);
+ }
+
+ static RetracedMethod create(MethodReference methodReference, int position) {
+ return new KnownRetracedMethod(methodReference, position);
}
}
diff --git a/src/main/java/com/android/tools/r8/retrace/Retracer.java b/src/main/java/com/android/tools/r8/retrace/Retracer.java
index d38e203..279253c 100644
--- a/src/main/java/com/android/tools/r8/retrace/Retracer.java
+++ b/src/main/java/com/android/tools/r8/retrace/Retracer.java
@@ -50,6 +50,13 @@
}
@Override
+ public RetraceFrameResult retrace(MethodReference methodReference, int position) {
+ return retrace(methodReference.getHolderClass())
+ .lookupMethod(methodReference.getMethodName())
+ .narrowByPosition(position);
+ }
+
+ @Override
public RetraceClassResult retrace(ClassReference classReference) {
return RetraceClassResult.create(
classReference, classNameMapper.getClassNaming(classReference.getTypeName()), this);
diff --git a/src/test/java/com/android/tools/r8/debuginfo/DexPcWithDebugInfoForOverloadedMethodsTestRunner.java b/src/test/java/com/android/tools/r8/debuginfo/DexPcWithDebugInfoForOverloadedMethodsTestRunner.java
index 11dff7b..18913cc 100644
--- a/src/test/java/com/android/tools/r8/debuginfo/DexPcWithDebugInfoForOverloadedMethodsTestRunner.java
+++ b/src/test/java/com/android/tools/r8/debuginfo/DexPcWithDebugInfoForOverloadedMethodsTestRunner.java
@@ -22,7 +22,7 @@
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.ToolHelper.DexVm.Version;
import com.android.tools.r8.references.Reference;
-import com.android.tools.r8.retrace.RetraceMethodResult;
+import com.android.tools.r8.retrace.RetraceFrameResult;
import com.android.tools.r8.shaking.ProguardKeepAttributes;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
@@ -103,7 +103,7 @@
MINIFIED_LINE_POSITION,
20,
FILENAME_INLINE));
- RetraceMethodResult retraceResult =
+ RetraceFrameResult retraceResult =
throwingSubject
.streamInstructions()
.filter(InstructionSubject::isThrow)
diff --git a/src/test/java/com/android/tools/r8/debuginfo/EnsureNoDebugInfoEmittedForPcOnlyTestRunner.java b/src/test/java/com/android/tools/r8/debuginfo/EnsureNoDebugInfoEmittedForPcOnlyTestRunner.java
index ae533a4..8c2ef82 100644
--- a/src/test/java/com/android/tools/r8/debuginfo/EnsureNoDebugInfoEmittedForPcOnlyTestRunner.java
+++ b/src/test/java/com/android/tools/r8/debuginfo/EnsureNoDebugInfoEmittedForPcOnlyTestRunner.java
@@ -18,7 +18,7 @@
import com.android.tools.r8.TestParametersCollection;
import com.android.tools.r8.ToolHelper.DexVm.Version;
import com.android.tools.r8.references.Reference;
-import com.android.tools.r8.retrace.RetraceMethodResult;
+import com.android.tools.r8.retrace.RetraceFrameResult;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.InstructionSubject;
@@ -93,7 +93,7 @@
INLINED_DEX_PC,
23,
FILENAME_MAIN));
- RetraceMethodResult retraceResult =
+ RetraceFrameResult retraceResult =
mainSubject
.streamInstructions()
.filter(InstructionSubject::isThrow)
diff --git a/src/test/java/com/android/tools/r8/retrace/KotlinInlineFunctionInSameFileRetraceTests.java b/src/test/java/com/android/tools/r8/retrace/KotlinInlineFunctionInSameFileRetraceTests.java
index 1fa811a..0beee59 100644
--- a/src/test/java/com/android/tools/r8/retrace/KotlinInlineFunctionInSameFileRetraceTests.java
+++ b/src/test/java/com/android/tools/r8/retrace/KotlinInlineFunctionInSameFileRetraceTests.java
@@ -120,7 +120,7 @@
MethodSubject mainSubject,
LinePosition inlineStack) {
assertThat(mainSubject, isPresent());
- RetraceMethodResult retraceResult =
+ RetraceFrameResult retraceResult =
mainSubject
.streamInstructions()
.filter(InstructionSubject::isThrow)
diff --git a/src/test/java/com/android/tools/r8/retrace/KotlinInlineFunctionRetraceTest.java b/src/test/java/com/android/tools/r8/retrace/KotlinInlineFunctionRetraceTest.java
index 05b028a..3b0538d 100644
--- a/src/test/java/com/android/tools/r8/retrace/KotlinInlineFunctionRetraceTest.java
+++ b/src/test/java/com/android/tools/r8/retrace/KotlinInlineFunctionRetraceTest.java
@@ -225,7 +225,7 @@
MethodSubject mainSubject,
LinePosition inlineStack) {
assertThat(mainSubject, isPresent());
- RetraceMethodResult retraceResult =
+ RetraceFrameResult retraceResult =
mainSubject
.streamInstructions()
.filter(InstructionSubject::isThrow)
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 513de02..6f6bbf8 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
@@ -7,6 +7,7 @@
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.retrace.RetraceApi;
+import com.android.tools.r8.retrace.RetraceFrameResult;
import com.android.tools.r8.retrace.RetraceMethodResult;
public interface InstructionSubject {
@@ -137,11 +138,11 @@
return retracer.retrace(methodSubject.asFoundMethodSubject().asMethodReference());
}
- default RetraceMethodResult retraceLinePosition(RetraceApi retracer) {
- return retrace(retracer).narrowByLine(getLineNumber());
+ default RetraceFrameResult retraceLinePosition(RetraceApi retracer) {
+ return retrace(retracer).narrowByPosition(getLineNumber());
}
- default RetraceMethodResult retracePcPosition(RetraceApi retracer, MethodSubject methodSubject) {
- return retrace(retracer).narrowByLine(getOffset(methodSubject).offset);
+ default RetraceFrameResult retracePcPosition(RetraceApi retracer, MethodSubject methodSubject) {
+ return retrace(retracer).narrowByPosition(getOffset(methodSubject).offset);
}
}
diff --git a/src/test/java/com/android/tools/r8/utils/codeinspector/Matchers.java b/src/test/java/com/android/tools/r8/utils/codeinspector/Matchers.java
index 017a637..6f11640 100644
--- a/src/test/java/com/android/tools/r8/utils/codeinspector/Matchers.java
+++ b/src/test/java/com/android/tools/r8/utils/codeinspector/Matchers.java
@@ -6,6 +6,7 @@
import static org.hamcrest.CoreMatchers.not;
+import com.android.tools.r8.Collectors;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AccessFlags;
import com.android.tools.r8.graph.DexClass;
@@ -14,14 +15,11 @@
import com.android.tools.r8.naming.retrace.StackTrace;
import com.android.tools.r8.naming.retrace.StackTrace.StackTraceLine;
import com.android.tools.r8.references.MethodReference;
-import com.android.tools.r8.retrace.RetraceMethodResult;
-import com.android.tools.r8.retrace.RetraceMethodResult.Element;
-import com.android.tools.r8.retrace.RetracedMethod;
+import com.android.tools.r8.retrace.RetraceFrameResult;
import com.android.tools.r8.utils.Box;
import com.android.tools.r8.utils.Visibility;
import com.google.common.collect.ImmutableList;
import java.util.List;
-import java.util.stream.Collectors;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.TypeSafeMatcher;
@@ -483,11 +481,12 @@
};
}
- public static Matcher<RetraceMethodResult> isInlineFrame() {
- return new TypeSafeMatcher<RetraceMethodResult>() {
+ public static Matcher<RetraceFrameResult> isInlineFrame() {
+ return new TypeSafeMatcher<RetraceFrameResult>() {
@Override
- protected boolean matchesSafely(RetraceMethodResult item) {
- return !item.isAmbiguous() && item.stream().count() > 1;
+ protected boolean matchesSafely(RetraceFrameResult item) {
+ return !item.isAmbiguous()
+ && item.stream().mapToLong(method -> method.getOuterFrames().size()).sum() > 0;
}
@Override
@@ -497,28 +496,29 @@
};
}
- public static Matcher<RetraceMethodResult> isInlineStack(LinePosition startPosition) {
- return new TypeSafeMatcher<RetraceMethodResult>() {
+ public static Matcher<RetraceFrameResult> isInlineStack(LinePosition startPosition) {
+ return new TypeSafeMatcher<RetraceFrameResult>() {
@Override
- protected boolean matchesSafely(RetraceMethodResult item) {
+ protected boolean matchesSafely(RetraceFrameResult item) {
+ RetraceFrameResult.Element single = item.stream().collect(Collectors.toSingle());
Box<LinePosition> currentPosition = new Box<>(startPosition);
Box<Boolean> returnValue = new Box<>();
- item.forEach(
- element -> {
+ single.visitFrames(
+ (method, __) -> {
boolean sameMethod;
LinePosition currentInline = currentPosition.get();
if (currentInline == null) {
returnValue.set(false);
return;
}
+ if (method.isUnknown()) {
+ returnValue.set(false);
+ return;
+ }
sameMethod =
- element.getMethod().isKnown()
- && element
- .getMethod()
- .asKnown()
- .equalsMethodReference(currentInline.methodReference);
+ method.asKnown().getMethodReference().equals(currentInline.methodReference);
boolean samePosition =
- element.getOriginalLineNumber(currentInline.minifiedPosition)
+ method.getOriginalPositionOrDefault(currentInline.minifiedPosition)
== currentInline.originalPosition;
if (!returnValue.isSet() || returnValue.get()) {
returnValue.set(sameMethod & samePosition);
@@ -535,28 +535,24 @@
};
}
- public static Matcher<RetraceMethodResult> isTopOfStackTrace(
+ public static Matcher<RetraceFrameResult> isTopOfStackTrace(
StackTrace stackTrace, List<Integer> minifiedPositions) {
- return new TypeSafeMatcher<RetraceMethodResult>() {
+ return new TypeSafeMatcher<RetraceFrameResult>() {
@Override
- protected boolean matchesSafely(RetraceMethodResult item) {
- List<Element> retraceElements = item.stream().collect(Collectors.toList());
- if (retraceElements.size() > stackTrace.size()
- || retraceElements.size() != minifiedPositions.size()) {
- return false;
- }
- for (int i = 0; i < retraceElements.size(); i++) {
- Element retraceElement = retraceElements.get(i);
- StackTraceLine stackTraceLine = stackTrace.get(i);
- RetracedMethod methodReference = retraceElement.getMethod();
- if (!stackTraceLine.methodName.equals(methodReference.getMethodName())
- || !stackTraceLine.className.equals(methodReference.getHolderClass().getTypeName())
- || stackTraceLine.lineNumber
- != retraceElement.getOriginalLineNumber(minifiedPositions.get(i))) {
- return false;
- }
- }
- return true;
+ protected boolean matchesSafely(RetraceFrameResult item) {
+ RetraceFrameResult.Element single = item.stream().collect(Collectors.toSingle());
+ Box<Boolean> matches = new Box<>(true);
+ single.visitFrames(
+ (method, index) -> {
+ StackTraceLine stackTraceLine = stackTrace.get(index);
+ if (!stackTraceLine.methodName.equals(method.getMethodName())
+ || !stackTraceLine.className.equals(method.getHolderClass().getTypeName())
+ || stackTraceLine.lineNumber
+ != method.getOriginalPositionOrDefault(minifiedPositions.get(index))) {
+ matches.set(false);
+ }
+ });
+ return matches.get();
}
@Override