[Compose] Compose inlined outlines into outline callsites
Bug: b/284925475
Change-Id: Ib5f55f95849eaac319e8d8102168d5d057e3e75a
diff --git a/src/main/java/com/android/tools/r8/naming/ClassNamingForNameMapper.java b/src/main/java/com/android/tools/r8/naming/ClassNamingForNameMapper.java
index 76a188c..da66dfd 100644
--- a/src/main/java/com/android/tools/r8/naming/ClassNamingForNameMapper.java
+++ b/src/main/java/com/android/tools/r8/naming/ClassNamingForNameMapper.java
@@ -11,6 +11,7 @@
import com.android.tools.r8.naming.MemberNaming.Signature.SignatureKind;
import com.android.tools.r8.naming.mappinginformation.MappingInformation;
import com.android.tools.r8.naming.mappinginformation.OutlineCallsiteMappingInformation;
+import com.android.tools.r8.naming.mappinginformation.OutlineMappingInformation;
import com.android.tools.r8.naming.mappinginformation.RewriteFrameMappingInformation;
import com.android.tools.r8.utils.ChainableStringConsumer;
import com.android.tools.r8.utils.CollectionUtils;
@@ -632,6 +633,15 @@
MappingInformation::asRewriteFrameMappingInformation);
}
+ public OutlineMappingInformation getOutlineMappingInformation() {
+ List<OutlineMappingInformation> outlineMappingInformation =
+ filter(
+ MappingInformation::isOutlineMappingInformation,
+ MappingInformation::asOutlineMappingInformation);
+ assert outlineMappingInformation.size() <= 1;
+ return outlineMappingInformation.isEmpty() ? null : outlineMappingInformation.get(0);
+ }
+
public int getOriginalLineNumber(int lineNumberAfterMinification) {
if (minifiedRange == null) {
// General mapping without concrete line numbers: "a() -> b"
@@ -765,6 +775,11 @@
return Collections.unmodifiableList(additionalMappingInformation);
}
+ public void setAdditionalMappingInformationInternal(
+ List<MappingInformation> mappingInformation) {
+ this.additionalMappingInformation = mappingInformation;
+ }
+
public MappedRange partitionOnMinifiedRange(Range minifiedRange) {
if (minifiedRange.equals(this.minifiedRange)) {
return this;
@@ -784,5 +799,11 @@
public boolean isOriginalRangePreamble() {
return originalRange != null && originalRange.isPreamble();
}
+
+ public MappedRange withMinifiedRange(Range newMinifiedRange) {
+ return newMinifiedRange.equals(minifiedRange)
+ ? this
+ : new MappedRange(newMinifiedRange, signature, originalRange, renamedName);
+ }
}
}
diff --git a/src/main/java/com/android/tools/r8/naming/ComposingBuilder.java b/src/main/java/com/android/tools/r8/naming/ComposingBuilder.java
index b272aca..d87e036 100644
--- a/src/main/java/com/android/tools/r8/naming/ComposingBuilder.java
+++ b/src/main/java/com/android/tools/r8/naming/ComposingBuilder.java
@@ -27,6 +27,7 @@
import com.android.tools.r8.utils.Box;
import com.android.tools.r8.utils.ChainableStringConsumer;
import com.android.tools.r8.utils.ConsumerUtils;
+import com.android.tools.r8.utils.IntBox;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.ListUtils;
import com.android.tools.r8.utils.Pair;
@@ -42,12 +43,14 @@
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Set;
import java.util.TreeMap;
+import java.util.function.BiConsumer;
import java.util.function.Consumer;
public class ComposingBuilder {
@@ -640,7 +643,10 @@
if (composedInlineFrames.isEmpty()) {
splitOnNewMinifiedRange(
composeMappedRangesForMethod(
- existingMappedRanges, mappedRange, computedOutlineInformation),
+ existingClassBuilder,
+ existingMappedRanges,
+ mappedRange,
+ computedOutlineInformation),
Collections.emptyList(),
newComposedInlineFrames::add);
} else {
@@ -649,7 +655,10 @@
mappedRange.partitionOnMinifiedRange(composedInlineFrame.get(0).minifiedRange);
splitOnNewMinifiedRange(
composeMappedRangesForMethod(
- existingMappedRanges, splitMappedRange, computedOutlineInformation),
+ existingClassBuilder,
+ existingMappedRanges,
+ splitMappedRange,
+ computedOutlineInformation),
composedInlineFrame,
newComposedInlineFrames::add);
}
@@ -662,86 +671,195 @@
composedInlineFrames = Collections.emptyList();
}
}
- MappedRange lastComposedRange = ListUtils.last(composedRanges);
- if (computedOutlineInformation.seenOutlineMappingInformation != null) {
+ // Check if we could have inlined an outline which is true if we see both an outline and
+ // call site to patch up.
+ if (!computedOutlineInformation.seenOutlineMappingInformation.isEmpty()
+ && !computedOutlineInformation.outlineCallsiteMappingInformationToPatchUp.isEmpty()) {
+ Set<OutlineCallsiteMappingInformation> outlineCallSitesToRemove =
+ Sets.newIdentityHashSet();
+ Set<OutlineMappingInformation> outlinesToRemove = Sets.newIdentityHashSet();
+ // We patch up all ranges from top to bottom with the invariant that all at a given
+ // index, all above have been updated correctly. We will do expansion of frames
+ // when separating out single minified lines, but we keep the outline information
+ // present such that we can fix them when seeing them later.
+ int composedRangeIndex = 0;
+ while (composedRangeIndex < composedRanges.size() - 1) {
+ MappedRange outline = composedRanges.get(composedRangeIndex++);
+ if (outline.isOutlineFrame()
+ && outline.minifiedRange.equals(
+ composedRanges.get(composedRangeIndex).minifiedRange)) {
+ // We should replace the inlined outline frame positions with the synthesized
+ // positions from the outline call site.
+ MappedRange outlineCallSite = composedRanges.get(composedRangeIndex);
+ if (outlineCallSite.getOutlineCallsiteInformation().size() != 1) {
+ // If we have an inlined outline it must be such that the outer frame is an
+ // outline callsite.
+ throw new MappingComposeException(
+ "Expected exactly one outline call site for a mapped range with signature '"
+ + outlineCallSite.getOriginalSignature()
+ + "'.");
+ }
+ OutlineCallsiteMappingInformation outlineCallSiteInformation =
+ outlineCallSite.getOutlineCallsiteInformation().get(0);
+ // The original positions in the outline callsite have been composed, so we have to
+ // find the existing mapped range and iterate the original positions for that range.
+ ComputedMappedRangeForOutline computedInformationForCallSite =
+ computedOutlineInformation.getComputedRange(
+ outlineCallSiteInformation, outlineCallSite);
+ if (computedInformationForCallSite == null) {
+ continue;
+ }
+ Map<Integer, List<MappedRange>> mappedRangesForOutline =
+ new HashMap<>(outlineCallSiteInformation.getPositions().size());
+ visitOutlineMappedPositions(
+ outlineCallSiteInformation,
+ computedInformationForCallSite
+ .current
+ .getOriginalSignature()
+ .asMethodSignature(),
+ mappedRangesForOutline::put);
+ List<MappedRange> newComposedRanges = new ArrayList<>();
+ // Copy all previous handled mapped ranges into a new list.
+ for (MappedRange previousMappedRanges : composedRanges) {
+ if (previousMappedRanges == outline) {
+ break;
+ }
+ newComposedRanges.add(previousMappedRanges);
+ }
+ // The original positions in the outline have been composed, so we have to find the
+ // existing mapped range and iterate the original positions for that range.
+ ComputedMappedRangeForOutline computedInformationForOutline =
+ computedOutlineInformation.getComputedRange(
+ outline.getOutlineMappingInformation(), outline);
+ if (computedInformationForOutline == null) {
+ continue;
+ }
+ // The outline could have additional inlined positions in it, but we should be
+ // guaranteed to find call site information on all original line numbers. We
+ // therefore iterate one by one and amend the subsequent outer frames as well.
+ MappedRange current = computedInformationForOutline.current;
+ int minifiedLine = outline.minifiedRange.from;
+ for (int originalLine = current.getOriginalRangeOrIdentity().from;
+ originalLine <= current.getOriginalRangeOrIdentity().to;
+ originalLine++) {
+ // If the outline is itself an inline frame it is bound to only have one original
+ // position and we can simply insert all inline frames on that position with the
+ // existing minified range.
+ Range newMinifiedRange =
+ outline.originalRange.isCardinal
+ ? outline.minifiedRange
+ : new Range(minifiedLine, minifiedLine);
+ List<MappedRange> outlineMappedRanges = mappedRangesForOutline.get(originalLine);
+ if (outlineMappedRanges != null) {
+ outlineMappedRanges.forEach(
+ range -> {
+ if (range != ListUtils.last(outlineMappedRanges)) {
+ newComposedRanges.add(
+ new MappedRange(
+ newMinifiedRange,
+ range.getOriginalSignature().asMethodSignature(),
+ range.originalRange,
+ outlineCallSite.getRenamedName()));
+ }
+ });
+ newComposedRanges.add(
+ new MappedRange(
+ newMinifiedRange,
+ outlineCallSite.getOriginalSignature().asMethodSignature(),
+ ListUtils.last(outlineMappedRanges).originalRange,
+ outlineCallSite.getRenamedName()));
+ }
+ for (int tailInlineFrameIndex = composedRangeIndex + 1;
+ tailInlineFrameIndex < composedRanges.size();
+ tailInlineFrameIndex++) {
+ MappedRange originalMappedRange = composedRanges.get(tailInlineFrameIndex);
+ if (!originalMappedRange.minifiedRange.equals(outlineCallSite.minifiedRange)) {
+ break;
+ }
+ MappedRange newMappedRange =
+ originalMappedRange.withMinifiedRange(newMinifiedRange);
+ newMappedRange.setAdditionalMappingInformationInternal(
+ originalMappedRange.getAdditionalMappingInformation());
+ newComposedRanges.add(newMappedRange);
+ }
+ minifiedLine++;
+ }
+ // We have patched up the the inlined outline and all subsequent inline frames
+ // (although some of the subsequent frames above could also be inlined outlines). We
+ // therefore need to copy the remaining frames.
+ boolean seenMinifiedRange = false;
+ for (MappedRange range : composedRanges) {
+ if (range.minifiedRange.equals(outline.minifiedRange)) {
+ seenMinifiedRange = true;
+ } else if (seenMinifiedRange) {
+ newComposedRanges.add(range);
+ }
+ }
+ composedRanges = newComposedRanges;
+ outlineCallSitesToRemove.add(outlineCallSiteInformation);
+ outlinesToRemove.add(outline.getOutlineMappingInformation());
+ }
+ }
+ // If we removed any outlines or call site, remove the processing of them.
+ outlineCallSitesToRemove.forEach(
+ computedOutlineInformation.outlineCallsiteMappingInformationToPatchUp::remove);
+ outlinesToRemove.forEach(
+ computedOutlineInformation.seenOutlineMappingInformation::remove);
+ }
+ if (!computedOutlineInformation.seenOutlineMappingInformation.isEmpty()) {
+ MappedRange lastComposedRange = ListUtils.last(composedRanges);
current
.getUpdateOutlineCallsiteInformation(
committedPreviousClassBuilder.getRenamedName(),
ListUtils.last(newMappedRanges).signature.getName(),
lastComposedRange.getRenamedName())
.setNewMappedRanges(newMappedRanges);
- lastComposedRange.addMappingInformation(
- computedOutlineInformation.seenOutlineMappingInformation,
- ConsumerUtils.emptyConsumer());
}
if (!computedOutlineInformation.outlineCallsiteMappingInformationToPatchUp.isEmpty()) {
+ MappedRange lastComposedRange = ListUtils.last(composedRanges);
+ List<MappedRange> composedRangesFinal = composedRanges;
// Outline positions are synthetic positions and they have no position in the residual
// program. We therefore have to find the original positions and copy all inline frames
// and amend the outermost frame with the residual signature and the next free position.
List<OutlineCallsiteMappingInformation> outlineCallSites =
new ArrayList<>(
- computedOutlineInformation.outlineCallsiteMappingInformationToPatchUp);
+ computedOutlineInformation.outlineCallsiteMappingInformationToPatchUp.keySet());
outlineCallSites.sort(Comparator.comparing(mapping -> mapping.getOutline().toString()));
- int firstAvailableRange = lastComposedRange.minifiedRange.to + 1;
+ IntBox firstAvailableRange = new IntBox(lastComposedRange.minifiedRange.to + 1);
for (OutlineCallsiteMappingInformation outlineCallSite : outlineCallSites) {
- Int2IntSortedMap positionMap = outlineCallSite.getPositions();
- MethodSignature originalSignature =
- memberNaming.getOriginalSignature().asMethodSignature();
- ComposingClassBuilder existingClassBuilderForOutline =
- getExistingClassBuilder(originalSignature);
- if (existingClassBuilderForOutline == null) {
- assert false;
- continue;
- }
- SegmentTree<List<MappedRange>> outlineSegmentTree =
- existingClassBuilderForOutline.methodsWithPosition.get(originalSignature);
- if (outlineSegmentTree == null) {
- assert false;
- continue;
- }
- Int2IntSortedMap newPositionMap = new Int2IntLinkedOpenHashMap(positionMap.size());
- for (Integer keyPosition : positionMap.keySet()) {
- int keyPositionInt = keyPosition;
- int originalDestination = positionMap.get(keyPositionInt);
- ExistingMapping existingMapping =
- computeExistingMapping(outlineSegmentTree.find(originalDestination));
- List<MappedRange> mappedRangesForOutlinePosition =
- existingMapping.getMappedRangesForPosition(originalDestination);
- if (mappedRangesForOutlinePosition == null) {
- assert false;
- continue;
- }
- MappedRange outerMostOutlineFrame = ListUtils.last(mappedRangesForOutlinePosition);
- assert outerMostOutlineFrame.minifiedRange.span() == 1;
- Range newMinifiedRange = new Range(firstAvailableRange, firstAvailableRange);
- for (MappedRange inlineMappedRangeInOutlinePosition :
- mappedRangesForOutlinePosition) {
- if (inlineMappedRangeInOutlinePosition != outerMostOutlineFrame) {
- composedRanges.add(
+ Int2IntSortedMap newPositionMap =
+ new Int2IntLinkedOpenHashMap(outlineCallSite.getPositions().size());
+ visitOutlineMappedPositions(
+ outlineCallSite,
+ memberNaming.getOriginalSignature().asMethodSignature(),
+ (originalPosition, mappedRangesForOutlinePosition) -> {
+ int newIndex = firstAvailableRange.getAndIncrement();
+ Range newMinifiedRange = new Range(newIndex, newIndex);
+ MappedRange outerMostOutlineFrame =
+ ListUtils.last(mappedRangesForOutlinePosition);
+ for (MappedRange inlineMappedRangeInOutlinePosition :
+ mappedRangesForOutlinePosition) {
+ if (inlineMappedRangeInOutlinePosition != outerMostOutlineFrame) {
+ composedRangesFinal.add(
+ inlineMappedRangeInOutlinePosition.withMinifiedRange(newMinifiedRange));
+ }
+ }
+ composedRangesFinal.add(
new MappedRange(
newMinifiedRange,
- inlineMappedRangeInOutlinePosition.signature,
- inlineMappedRangeInOutlinePosition.getOriginalRangeOrIdentity(),
- inlineMappedRangeInOutlinePosition.getRenamedName()));
- }
- }
- composedRanges.add(
- new MappedRange(
- newMinifiedRange,
- lastComposedRange.signature,
- outerMostOutlineFrame.originalRange,
- lastComposedRange.getRenamedName()));
- newPositionMap.put(keyPositionInt, firstAvailableRange);
- firstAvailableRange = newMinifiedRange.to + 1;
- }
- outlineCallSite.setPositionsInternal(newPositionMap);
+ lastComposedRange.signature,
+ outerMostOutlineFrame.originalRange,
+ lastComposedRange.getRenamedName()));
+ newPositionMap.put((int) originalPosition, newIndex);
+ outlineCallSite.setPositionsInternal(newPositionMap);
+ });
}
}
MethodSignature residualSignature =
memberNaming
.computeResidualSignature(type -> inverseClassMapping.getOrDefault(type, type))
.asMethodSignature();
- if (lastComposedRange.minifiedRange != null) {
+ if (ListUtils.last(composedRanges).minifiedRange != null) {
SegmentTree<List<MappedRange>> listSegmentTree =
methodsWithPosition.computeIfAbsent(
residualSignature, ignored -> new SegmentTree<>(false));
@@ -749,12 +867,57 @@
minified.getStartOrNoRangeFrom(), minified.getEndOrNoRangeFrom(), composedRanges);
} else {
assert composedRanges.size() == 1;
- methodsWithoutPosition.put(residualSignature, lastComposedRange);
+ methodsWithoutPosition.put(residualSignature, ListUtils.last(composedRanges));
}
}
}
}
+ private void visitOutlineMappedPositions(
+ OutlineCallsiteMappingInformation outlineCallSite,
+ MethodSignature originalSignature,
+ BiConsumer<Integer, List<MappedRange>> outlinePositionConsumer)
+ throws MappingComposeException {
+ Int2IntSortedMap positionMap = outlineCallSite.getPositions();
+ ComposingClassBuilder existingClassBuilder = getExistingClassBuilder(originalSignature);
+ if (existingClassBuilder == null) {
+ throw new MappingComposeException(
+ "Could not find builder with original signature '" + originalSignature + "'.");
+ }
+ SegmentTree<List<MappedRange>> outlineSegmentTree =
+ existingClassBuilder.methodsWithPosition.get(
+ originalSignature.toUnqualifiedSignatureIfQualified().asMethodSignature());
+ if (outlineSegmentTree == null) {
+ throw new MappingComposeException(
+ "Could not find method positions for original signature '" + originalSignature + "'.");
+ }
+ for (Integer keyPosition : positionMap.keySet()) {
+ int keyPositionInt = keyPosition;
+ int originalDestination = positionMap.get(keyPositionInt);
+ List<MappedRange> mappedRanges = outlineSegmentTree.find(originalDestination);
+ if (mappedRanges == null) {
+ throw new MappingComposeException(
+ "Could not find ranges for outline position '"
+ + keyPosition
+ + "' with original signature '"
+ + originalSignature
+ + "'.");
+ }
+ ExistingMapping existingMapping = computeExistingMapping(mappedRanges);
+ List<MappedRange> mappedRangesForOutlinePosition =
+ existingMapping.getMappedRangesForPosition(originalDestination);
+ if (mappedRangesForOutlinePosition == null) {
+ throw new MappingComposeException(
+ "Could not find ranges for outline position '"
+ + keyPosition
+ + "' with original signature '"
+ + originalSignature
+ + "'.");
+ }
+ outlinePositionConsumer.accept(keyPositionInt, mappedRangesForOutlinePosition);
+ }
+ }
+
private void splitOnNewMinifiedRange(
List<MappedRange> mappedRanges,
List<MappedRange> previouslyMapped,
@@ -822,6 +985,7 @@
}
private List<MappedRange> composeMappedRangesForMethod(
+ ComposingClassBuilder existingClassBuilder,
List<MappedRange> existingRanges,
MappedRange newRange,
ComputedOutlineInformation computedOutlineInformation)
@@ -834,7 +998,13 @@
if (newRange.getOriginalRangeOrIdentity() == null) {
MappedRange newComposedRange =
new MappedRange(
- newRange.minifiedRange, lastExistingRange.signature, null, newRange.renamedName);
+ newRange.minifiedRange,
+ potentiallyQualifySignature(
+ newRange.signature,
+ lastExistingRange.signature,
+ existingClassBuilder.getOriginalName()),
+ null,
+ newRange.renamedName);
composeMappingInformation(
newComposedRange.getAdditionalMappingInformation(),
lastExistingRange.getAdditionalMappingInformation(),
@@ -858,7 +1028,10 @@
return Collections.singletonList(
new MappedRange(
newRange.minifiedRange,
- lastExistingRange.signature,
+ potentiallyQualifySignature(
+ newRange.signature,
+ lastExistingRange.signature,
+ existingClassBuilder.getOriginalName()),
lastExistingRange.originalRange != null
&& lastExistingRange.originalRange.span() == 1
? lastExistingRange.originalRange
@@ -882,6 +1055,7 @@
// then we have a perfect mapping that we can translate directly.
if (lastExistingMappedRange.minifiedRange.equals(newRange.getOriginalRangeOrIdentity())) {
computeComposedMappedRange(
+ existingClassBuilder,
newComposedRanges,
newRange,
existingMappedRanges,
@@ -907,6 +1081,7 @@
lastExistingMappedRangeForPosition.minifiedRange)) {
// We have seen an existing range we have to compute a splitting for.
computeComposedMappedRange(
+ existingClassBuilder,
newComposedRanges,
newRange,
existingMappedRanges,
@@ -949,6 +1124,7 @@
}
}
computeComposedMappedRange(
+ existingClassBuilder,
newComposedRanges,
newRange,
existingMappedRanges,
@@ -1038,6 +1214,7 @@
}
private void computeComposedMappedRange(
+ ComposingClassBuilder existingClassBuilder,
List<MappedRange> newComposedRanges,
MappedRange newMappedRange,
List<MappedRange> existingMappedRanges,
@@ -1071,7 +1248,10 @@
MappedRange computedRange =
new MappedRange(
newMinifiedRange,
- existingMappedRange.signature,
+ potentiallyQualifySignature(
+ newMappedRange.signature,
+ existingMappedRange.signature,
+ existingClassBuilder.getOriginalName()),
newOriginalRange,
newMappedRange.renamedName);
List<MappingInformation> mappingInformationToCompose = new ArrayList<>();
@@ -1080,13 +1260,17 @@
.forEach(
info -> {
if (info.isOutlineMappingInformation()) {
- computedOutlineInformation.seenOutlineMappingInformation =
- info.asOutlineMappingInformation();
- return;
- }
- if (info.isOutlineCallsiteInformation()) {
- computedOutlineInformation.outlineCallsiteMappingInformationToPatchUp.add(
- info.asOutlineCallsiteInformation());
+ computedOutlineInformation
+ .seenOutlineMappingInformation
+ .computeIfAbsent(
+ info.asOutlineMappingInformation(), ignoreArgument(ArrayList::new))
+ .add(new ComputedMappedRangeForOutline(newMappedRange, computedRange));
+ } else if (info.isOutlineCallsiteInformation()) {
+ computedOutlineInformation
+ .outlineCallsiteMappingInformationToPatchUp
+ .computeIfAbsent(
+ info.asOutlineCallsiteInformation(), ignoreArgument(ArrayList::new))
+ .add(new ComputedMappedRangeForOutline(newMappedRange, computedRange));
}
mappingInformationToCompose.add(info);
});
@@ -1229,6 +1413,14 @@
}
}
+ private MethodSignature potentiallyQualifySignature(
+ MethodSignature newSignature, MethodSignature signature, String originalHolder) {
+ return !newSignature.isQualified() || signature.isQualified()
+ ? signature
+ : new MethodSignature(
+ originalHolder + "." + signature.name, signature.type, signature.parameters);
+ }
+
private static class RangeBuilder {
private int start = Integer.MAX_VALUE;
@@ -1256,9 +1448,35 @@
}
private static class ComputedOutlineInformation {
- private final Set<OutlineCallsiteMappingInformation>
- outlineCallsiteMappingInformationToPatchUp = Sets.newIdentityHashSet();
- private OutlineMappingInformation seenOutlineMappingInformation = null;
+ private final Map<OutlineCallsiteMappingInformation, List<ComputedMappedRangeForOutline>>
+ outlineCallsiteMappingInformationToPatchUp = new IdentityHashMap<>();
+ private final Map<OutlineMappingInformation, List<ComputedMappedRangeForOutline>>
+ seenOutlineMappingInformation = new IdentityHashMap<>();
+
+ private ComputedMappedRangeForOutline getComputedRange(
+ MappingInformation outline, MappedRange current) {
+ List<ComputedMappedRangeForOutline> outlineMappingInformations =
+ outline.isOutlineMappingInformation()
+ ? seenOutlineMappingInformation.get(outline.asOutlineMappingInformation())
+ : outlineCallsiteMappingInformationToPatchUp.get(
+ outline.asOutlineCallsiteInformation());
+ if (outlineMappingInformations == null) {
+ return null;
+ }
+ return ListUtils.firstMatching(
+ outlineMappingInformations,
+ pair -> pair.composed.minifiedRange.contains(current.minifiedRange.from));
+ }
+ }
+
+ private static class ComputedMappedRangeForOutline {
+ private final MappedRange current;
+ private final MappedRange composed;
+
+ private ComputedMappedRangeForOutline(MappedRange current, MappedRange composed) {
+ this.current = current;
+ this.composed = composed;
+ }
}
}
}
diff --git a/src/main/java/com/android/tools/r8/naming/MemberNaming.java b/src/main/java/com/android/tools/r8/naming/MemberNaming.java
index d1bfb78..5ddf11e 100644
--- a/src/main/java/com/android/tools/r8/naming/MemberNaming.java
+++ b/src/main/java/com/android/tools/r8/naming/MemberNaming.java
@@ -510,6 +510,10 @@
return new MethodSignature(toUnqualifiedName(), type, parameters);
}
+ public Signature toUnqualifiedSignatureIfQualified() {
+ return isQualified() ? new MethodSignature(toUnqualifiedName(), type, parameters) : this;
+ }
+
@Override
public Signature toQualifiedSignature(String holder) {
return new MethodSignature(holder + "." + name, type, parameters);
diff --git a/src/test/java/com/android/tools/r8/mappingcompose/ComposeInlineFollowedByInlineTest.java b/src/test/java/com/android/tools/r8/mappingcompose/ComposeInlineFollowedByInlineTest.java
index 04ffc15..dbfcdb5 100644
--- a/src/test/java/com/android/tools/r8/mappingcompose/ComposeInlineFollowedByInlineTest.java
+++ b/src/test/java/com/android/tools/r8/mappingcompose/ComposeInlineFollowedByInlineTest.java
@@ -58,9 +58,9 @@
StringUtils.unixLines(
"# {'id':'com.android.tools.r8.mapping','version':'experimental'}",
"com.bar -> c:",
- " 2:2:void inlinee1():43:43 -> y",
+ " 2:2:void com.foo.inlinee1():43:43 -> y",
" 2:2:void foo.bar.baz.inlinee1():41 -> y",
- " 2:2:void caller():40 -> y",
+ " 2:2:void com.foo.caller():40 -> y",
" 2:2:void inlinee2():42:42 -> y",
" 2:2:void foo.bar.baz.inlinee1():41 -> y",
" 2:2:void caller():40 -> y",
diff --git a/src/test/java/com/android/tools/r8/mappingcompose/ComposeInlineResidualQualifiedTest.java b/src/test/java/com/android/tools/r8/mappingcompose/ComposeInlineResidualQualifiedTest.java
new file mode 100644
index 0000000..1912d84
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/mappingcompose/ComposeInlineResidualQualifiedTest.java
@@ -0,0 +1,62 @@
+// Copyright (c) 2023, 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.mappingcompose;
+
+import static com.android.tools.r8.mappingcompose.ComposeTestHelpers.doubleToSingleQuote;
+import static org.junit.Assert.assertEquals;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.naming.ClassNameMapper;
+import com.android.tools.r8.naming.MappingComposer;
+import com.android.tools.r8.utils.StringUtils;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class ComposeInlineResidualQualifiedTest extends TestBase {
+
+ @Parameter() public TestParameters parameters;
+
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withNoneRuntime().build();
+ }
+
+ private static final String mappingFoo =
+ StringUtils.unixLines(
+ "# {'id':'com.android.tools.r8.mapping','version':'2.2'}",
+ "com.foo -> A:",
+ " 1:3:void method1():42:44 -> x",
+ "com.bar -> B:",
+ " 4:6:void method2():104:106 -> x");
+ private static final String mappingBar =
+ StringUtils.unixLines(
+ "# {'id':'com.android.tools.r8.mapping','version':'2.2'}",
+ "B -> C:",
+ " 1:3:void A.x():2:2 -> y",
+ " 1:3:void x():4 -> y",
+ " 2:3:void x():5:6 -> y");
+ private static final String mappingResult =
+ StringUtils.unixLines(
+ "# {'id':'com.android.tools.r8.mapping','version':'2.2'}",
+ "com.bar -> C:",
+ " 1:3:void com.foo.method1():43:43 -> y",
+ " 1:3:void method2():104:104 -> y",
+ " 2:3:void method2():105:106 -> y",
+ "com.foo -> A:");
+
+ @Test
+ public void testCompose() throws Exception {
+ ClassNameMapper mappingForFoo = ClassNameMapper.mapperFromString(mappingFoo);
+ ClassNameMapper mappingForBar = ClassNameMapper.mapperFromString(mappingBar);
+ String composed = MappingComposer.compose(mappingForFoo, mappingForBar);
+ assertEquals(mappingResult, doubleToSingleQuote(composed));
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/mappingcompose/ComposeMovedMethodTest.java b/src/test/java/com/android/tools/r8/mappingcompose/ComposeMovedMethodTest.java
index 80c4dec..2991061 100644
--- a/src/test/java/com/android/tools/r8/mappingcompose/ComposeMovedMethodTest.java
+++ b/src/test/java/com/android/tools/r8/mappingcompose/ComposeMovedMethodTest.java
@@ -46,7 +46,7 @@
"# {'id':'com.android.tools.r8.mapping','version':'experimental'}",
"com.bar -> b:",
" int some.other.Class.f1() -> h1",
- " void f2() -> h2",
+ " void com.foo.f2() -> h2",
"com.foo -> a:");
@Test
diff --git a/src/test/java/com/android/tools/r8/mappingcompose/ComposeMovedMethodWithPositionTest.java b/src/test/java/com/android/tools/r8/mappingcompose/ComposeMovedMethodWithPositionTest.java
index 68d2c86..db17b8d 100644
--- a/src/test/java/com/android/tools/r8/mappingcompose/ComposeMovedMethodWithPositionTest.java
+++ b/src/test/java/com/android/tools/r8/mappingcompose/ComposeMovedMethodWithPositionTest.java
@@ -48,7 +48,7 @@
"com.bar -> b:",
" 12:14:int some.other.Class.f1():102:104 -> h11",
" 15:16:int some.other.Class.f1():102:103 -> h12",
- " 22:23:void f2():114:114 -> h2",
+ " 22:23:void com.foo.f2():114:114 -> h2",
"com.foo -> a:");
@Test
diff --git a/src/test/java/com/android/tools/r8/mappingcompose/ComposeOutlineHavingInlineInlinedTest.java b/src/test/java/com/android/tools/r8/mappingcompose/ComposeOutlineHavingInlineInlinedTest.java
new file mode 100644
index 0000000..03e93e6
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/mappingcompose/ComposeOutlineHavingInlineInlinedTest.java
@@ -0,0 +1,73 @@
+// Copyright (c) 2023, 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.mappingcompose;
+
+import static com.android.tools.r8.mappingcompose.ComposeTestHelpers.doubleToSingleQuote;
+import static org.junit.Assert.assertEquals;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.naming.ClassNameMapper;
+import com.android.tools.r8.naming.MappingComposer;
+import com.android.tools.r8.utils.StringUtils;
+import org.junit.Test;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+public class ComposeOutlineHavingInlineInlinedTest extends TestBase {
+
+ @Parameter() public TestParameters parameters;
+
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withNoneRuntime().build();
+ }
+
+ private static final String mappingFoo =
+ StringUtils.unixLines(
+ "# { id: 'com.android.tools.r8.mapping', version: '2.2' }",
+ "outline.Class -> A:",
+ " 1:2:int some.inlinee():75:76 -> a",
+ " 1:2:int outline():0 -> a",
+ " # { 'id':'com.android.tools.r8.outline' }",
+ "outline.Callsite -> X:",
+ " 1:2:int outlineCaller(int):41:42 -> s",
+ " 3:3:int outlineCaller(int):0:0 -> s",
+ " # { 'id':'com.android.tools.r8.outlineCallsite',"
+ + "'positions': { '1': 9, '2': 10 },"
+ + "'outline':'La;a()I' }",
+ " 9:9:int outlineCaller(int):23 -> s",
+ " 10:10:int foo.bar.baz.outlineCaller(int):98:98 -> s",
+ " 10:10:int outlineCaller(int):24 -> s");
+ private static final String mappingBar =
+ StringUtils.unixLines(
+ "# {'id':'com.android.tools.r8.mapping','version':'2.2'}",
+ "X -> Y:",
+ " 1:1:int A.a():1:1 -> s",
+ " 1:1:int s(int):3 -> s",
+ " 2:4:int another.inline():102:104 -> s",
+ " 2:4:int A.a():2 -> s",
+ " 2:4:int s(int):3 -> s");
+ private static final String mappingResult =
+ StringUtils.unixLines(
+ "# {'id':'com.android.tools.r8.mapping','version':'2.2'}",
+ "outline.Callsite -> Y:",
+ " 1:1:int some.inlinee():75:75 -> s",
+ " 1:1:int outlineCaller(int):23 -> s",
+ " 2:4:int another.inline():102:104 -> s",
+ " 2:4:int some.inlinee():76:76 -> s",
+ " 2:4:int foo.bar.baz.outlineCaller(int):98:98 -> s",
+ " 2:4:int outlineCaller(int):24 -> s",
+ "outline.Class -> A:");
+
+ @Test
+ public void testCompose() throws Exception {
+ ClassNameMapper mappingForFoo = ClassNameMapper.mapperFromString(mappingFoo);
+ ClassNameMapper mappingForBar = ClassNameMapper.mapperFromString(mappingBar);
+ String composed = MappingComposer.compose(mappingForFoo, mappingForBar);
+ assertEquals(mappingResult, doubleToSingleQuote(composed));
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/mappingcompose/ComposeOutlineInlineTest.java b/src/test/java/com/android/tools/r8/mappingcompose/ComposeOutlineInlineTest.java
index 9203fed..0c50e79 100644
--- a/src/test/java/com/android/tools/r8/mappingcompose/ComposeOutlineInlineTest.java
+++ b/src/test/java/com/android/tools/r8/mappingcompose/ComposeOutlineInlineTest.java
@@ -62,22 +62,10 @@
"package.Class -> package.new_internal.Y:",
"# {'id':'sourceFile','fileName':'FieldDefinition.java'}",
" 1:6:void foo():21:26 -> b",
- // TODO(b/284925475): We should put in the inline positions here instead of a reference to
- // the outline
- " 7:8:long package.Int2IntLinkedOpenHashMap$$InternalSyntheticOutline$HASH$0"
- + ".m(long,long,long):0:1 -> b",
- // TODO(b/284925475): This is not synthesized.
- " # {'id':'com.android.tools.r8.synthesized'}",
- " 7:8:void foo():0:0 -> b",
- " # {'id':'com.android.tools.r8.outlineCallsite',"
- + "'positions':{'1':11,'2':12},"
- + "'outline':'Lpackage/internal/X;a(JJJ)J'}",
+ " 7:7:void inlineeInOutline():1337:1337 -> b",
+ " 7:7:void foo():42 -> b",
+ " 8:8:void foo():44:44 -> b",
" 9:10:void foo():38:39 -> b",
- // TODO(b/284925475): This is not an outline or outline call site.
- " # {'id':'com.android.tools.r8.outline'}",
- " 11:11:void inlineeInOutline():1337:1337 -> a",
- " 11:11:void foo():42 -> b",
- " 12:12:void foo():44:44 -> b",
"package.Class$$ExternalSyntheticOutline0 -> package.internal.X:",
"# {'id':'sourceFile','fileName':'R8$$SyntheticClass'}",
"# {'id':'com.android.tools.r8.synthesized'}");
diff --git a/src/test/java/com/android/tools/r8/mappingcompose/ComposeOutlineInlinedIntoOutlineAndInlinedTest.java b/src/test/java/com/android/tools/r8/mappingcompose/ComposeOutlineInlinedIntoOutlineAndInlinedTest.java
new file mode 100644
index 0000000..9dc41ea
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/mappingcompose/ComposeOutlineInlinedIntoOutlineAndInlinedTest.java
@@ -0,0 +1,84 @@
+// Copyright (c) 2023, 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.mappingcompose;
+
+import static com.android.tools.r8.mappingcompose.ComposeTestHelpers.doubleToSingleQuote;
+import static org.junit.Assert.assertEquals;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.naming.ClassNameMapper;
+import com.android.tools.r8.naming.MappingComposer;
+import com.android.tools.r8.utils.StringUtils;
+import org.junit.Test;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+public class ComposeOutlineInlinedIntoOutlineAndInlinedTest extends TestBase {
+
+ @Parameter() public TestParameters parameters;
+
+ @Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withNoneRuntime().build();
+ }
+
+ private static final String mappingFoo =
+ StringUtils.unixLines(
+ "# { id: 'com.android.tools.r8.mapping', version: '2.2' }",
+ "Outline1 -> A:",
+ " 1:2:int outline1():0:1 -> a",
+ " # { 'id':'com.android.tools.r8.outline' }",
+ "Outline2 -> B:",
+ " 1:2:int outline2():0:1 -> a",
+ " # { 'id':'com.android.tools.r8.outline' }",
+ "outline.Callsite1 -> X:",
+ " 1:2:int caller1(int):41:42 -> s",
+ " 3:3:int caller1(int):0:0 -> s",
+ " # { 'id':'com.android.tools.r8.outlineCallsite',"
+ + "'positions': { '1': 9, '2': 10 },"
+ + "'outline':'La;a()I' }",
+ " 4:6:int caller1(int):48:49 -> s",
+ " 9:9:int caller1(int):23 -> s",
+ " 10:10:int caller1(int):24 -> s",
+ "outline.Callsite2 -> Y:",
+ " 1:1:int caller2(int):0:0 -> s",
+ " # { 'id':'com.android.tools.r8.outlineCallsite',"
+ + "'positions': { '1': 2, '2': 3 },"
+ + "'outline':'La;a()I' }",
+ " 2:2:int caller2(int):23:23 -> s",
+ " 3:3:int caller2(int):24:24 -> s");
+ private static final String mappingBar =
+ StringUtils.unixLines(
+ "# {'id':'com.android.tools.r8.mapping','version':'2.2'}",
+ "Y -> Z:",
+ " 1:2:int A.a():1:2 -> a",
+ " 1:2:int X.s(int):3 -> a",
+ " 1:2:int B.a():1 -> a",
+ " 1:2:int s(int):1 -> a",
+ " 3:3:int B.a():2:2 -> a",
+ " 3:3:int s(int):1 -> a");
+ private static final String mappingResult =
+ StringUtils.unixLines(
+ "# {'id':'com.android.tools.r8.mapping','version':'2.2'}",
+ "Outline1 -> A:",
+ "Outline2 -> B:",
+ "outline.Callsite1 -> X:",
+ "outline.Callsite2 -> Z:",
+ " 1:1:int outline.Callsite1.caller1(int):23 -> a",
+ " 1:1:int caller2(int):23:23 -> a",
+ " 2:2:int outline.Callsite1.caller1(int):24 -> a",
+ " 2:2:int caller2(int):23:23 -> a",
+ " 3:3:int caller2(int):24:24 -> a");
+
+ @Test
+ public void testCompose() throws Exception {
+ ClassNameMapper mappingForFoo = ClassNameMapper.mapperFromString(mappingFoo);
+ ClassNameMapper mappingForBar = ClassNameMapper.mapperFromString(mappingBar);
+ String composed = MappingComposer.compose(mappingForFoo, mappingForBar);
+ assertEquals(mappingResult, doubleToSingleQuote(composed));
+ }
+}