Add a bit to position to track if the position is d8/r8 synthesized

Bug: b/261971803
Bug: b/169953605
Change-Id: I6978ae13f0b46c6e98d53d03125486384818a0bd
diff --git a/src/main/java/com/android/tools/r8/ir/code/Position.java b/src/main/java/com/android/tools/r8/ir/code/Position.java
index 5e88574..c3a705e 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Position.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Position.java
@@ -33,13 +33,19 @@
   protected final Position callerPosition;
 
   private final boolean removeInnerFramesIfThrowingNpe;
+  private final boolean isD8R8Synthesized;
 
   private Position(
-      int line, DexMethod method, Position callerPosition, boolean removeInnerFramesIfThrowingNpe) {
+      int line,
+      DexMethod method,
+      Position callerPosition,
+      boolean removeInnerFramesIfThrowingNpe,
+      boolean isD8R8Synthesized) {
     this.line = line;
     this.method = method;
     this.callerPosition = callerPosition;
     this.removeInnerFramesIfThrowingNpe = removeInnerFramesIfThrowingNpe;
+    this.isD8R8Synthesized = isD8R8Synthesized;
   }
 
   public boolean isSyntheticPosition() {
@@ -50,6 +56,10 @@
     return removeInnerFramesIfThrowingNpe;
   }
 
+  public boolean isD8R8Synthesized() {
+    return isD8R8Synthesized;
+  }
+
   public boolean isOutline() {
     return false;
   }
@@ -106,7 +116,8 @@
         .withInt(Position::getLine)
         .withNullableItem(Position::getMethod)
         .withNullableItem(Position::getCallerPosition)
-        .withBool(Position::isRemoveInnerFramesIfThrowingNpe);
+        .withBool(Position::isRemoveInnerFramesIfThrowingNpe)
+        .withBool(Position::isD8R8Synthesized);
   }
 
   public static Position syntheticNone() {
@@ -238,6 +249,7 @@
     protected DexMethod method;
     protected Position callerPosition;
     protected boolean removeInnerFramesIfThrowingNpe;
+    protected boolean isD8R8Synthesized;
 
     protected boolean noCheckOfPosition;
     protected boolean noCheckOfMethod;
@@ -268,6 +280,11 @@
       return self();
     }
 
+    public B setIsD8R8Synthesized(boolean isD8R8Synthesized) {
+      this.isD8R8Synthesized = isD8R8Synthesized;
+      return self();
+    }
+
     public B disableLineCheck() {
       noCheckOfPosition = true;
       return self();
@@ -286,7 +303,7 @@
     // A no-position marker. Not having a position means the position is implicitly defined by the
     // context, e.g., the marker does not materialize anything concrete.
     private static final SourcePosition NO_POSITION =
-        new SourcePosition(-1, null, null, false, null);
+        new SourcePosition(-1, null, null, false, false, null);
 
     public final DexString file;
 
@@ -299,8 +316,9 @@
         DexMethod method,
         Position callerPosition,
         boolean removeInnerFramesIfThrowingNpe,
+        boolean isD8R8Synthesized,
         DexString file) {
-      super(line, method, callerPosition, removeInnerFramesIfThrowingNpe);
+      super(line, method, callerPosition, removeInnerFramesIfThrowingNpe, isD8R8Synthesized);
       this.file = file;
       assert callerPosition == null || callerPosition.method != null;
     }
@@ -327,7 +345,8 @@
           .setFile(file)
           .setMethod(method)
           .setCallerPosition(callerPosition)
-          .setRemoveInnerFramesIfThrowingNpe(isRemoveInnerFramesIfThrowingNpe());
+          .setRemoveInnerFramesIfThrowingNpe(isRemoveInnerFramesIfThrowingNpe())
+          .setIsD8R8Synthesized(isD8R8Synthesized());
     }
 
     @Override
@@ -359,7 +378,7 @@
         assert noCheckOfPosition || line >= 0;
         assert noCheckOfMethod || method != null;
         return new SourcePosition(
-            line, method, callerPosition, removeInnerFramesIfThrowingNpe, file);
+            line, method, callerPosition, removeInnerFramesIfThrowingNpe, isD8R8Synthesized, file);
       }
     }
   }
@@ -370,14 +389,15 @@
     // This is used specifically to mark exceptional exit blocks from synchronized methods in
     // release.
     private static final Position NO_POSITION_SYNTHETIC =
-        new SyntheticPosition(-1, null, null, false);
+        new SyntheticPosition(-1, null, null, false, false);
 
     private SyntheticPosition(
         int line,
         DexMethod method,
         Position callerPosition,
-        boolean removeInnerFramesIfThrowingNpe) {
-      super(line, method, callerPosition, removeInnerFramesIfThrowingNpe);
+        boolean removeInnerFramesIfThrowingNpe,
+        boolean isD8R8Synthesized) {
+      super(line, method, callerPosition, removeInnerFramesIfThrowingNpe, isD8R8Synthesized);
     }
 
     @Override
@@ -396,7 +416,8 @@
           .setLine(line)
           .setMethod(method)
           .setCallerPosition(callerPosition)
-          .setRemoveInnerFramesIfThrowingNpe(isRemoveInnerFramesIfThrowingNpe());
+          .setRemoveInnerFramesIfThrowingNpe(isRemoveInnerFramesIfThrowingNpe())
+          .setIsD8R8Synthesized(isD8R8Synthesized());
     }
 
     @Override
@@ -422,7 +443,8 @@
       public SyntheticPosition build() {
         assert noCheckOfPosition || line >= 0;
         assert noCheckOfMethod || method != null;
-        return new SyntheticPosition(line, method, callerPosition, removeInnerFramesIfThrowingNpe);
+        return new SyntheticPosition(
+            line, method, callerPosition, removeInnerFramesIfThrowingNpe, isD8R8Synthesized);
       }
     }
   }
@@ -433,8 +455,9 @@
         int line,
         DexMethod method,
         Position callerPosition,
-        boolean removeInnerFramesIfThrowingNpe) {
-      super(line, method, callerPosition, removeInnerFramesIfThrowingNpe);
+        boolean removeInnerFramesIfThrowingNpe,
+        boolean isD8R8Synthesized) {
+      super(line, method, callerPosition, removeInnerFramesIfThrowingNpe, isD8R8Synthesized);
     }
 
     @Override
@@ -453,7 +476,8 @@
           .setLine(line)
           .setMethod(method)
           .setCallerPosition(callerPosition)
-          .setRemoveInnerFramesIfThrowingNpe(isRemoveInnerFramesIfThrowingNpe());
+          .setRemoveInnerFramesIfThrowingNpe(isRemoveInnerFramesIfThrowingNpe())
+          .setIsD8R8Synthesized(isD8R8Synthesized());
     }
 
     @Override
@@ -477,7 +501,8 @@
 
       @Override
       public OutlinePosition build() {
-        return new OutlinePosition(line, method, callerPosition, removeInnerFramesIfThrowingNpe);
+        return new OutlinePosition(
+            line, method, callerPosition, removeInnerFramesIfThrowingNpe, isD8R8Synthesized);
       }
     }
   }
@@ -500,10 +525,11 @@
         DexMethod method,
         Position callerPosition,
         boolean removeInnerFramesIfThrowingNpe,
+        boolean isD8R8Synthesized,
         Int2StructuralItemArrayMap<Position> outlinePositions,
         DexMethod outlineCallee,
         boolean isOutline) {
-      super(line, method, callerPosition, removeInnerFramesIfThrowingNpe);
+      super(line, method, callerPosition, removeInnerFramesIfThrowingNpe, isD8R8Synthesized);
       this.outlinePositions = outlinePositions;
       this.outlineCallee = outlineCallee;
       this.isOutline = isOutline;
@@ -528,7 +554,8 @@
               .setCallerPosition(callerPosition)
               .setOutlineCallee(outlineCallee)
               .setIsOutline(isOutline)
-              .setRemoveInnerFramesIfThrowingNpe(isRemoveInnerFramesIfThrowingNpe());
+              .setRemoveInnerFramesIfThrowingNpe(isRemoveInnerFramesIfThrowingNpe())
+              .setIsD8R8Synthesized(isD8R8Synthesized());
       outlinePositions.forEach(outlineCallerPositionBuilder::addOutlinePosition);
       return outlineCallerPositionBuilder;
     }
@@ -600,6 +627,7 @@
             method,
             callerPosition,
             removeInnerFramesIfThrowingNpe,
+            isD8R8Synthesized,
             outlinePositionsBuilder.build(),
             outlineCallee,
             isOutline);
diff --git a/src/main/java/com/android/tools/r8/utils/positions/MappedPositionToClassNameMapperBuilder.java b/src/main/java/com/android/tools/r8/utils/positions/MappedPositionToClassNameMapperBuilder.java
index 2915d14..189367d 100644
--- a/src/main/java/com/android/tools/r8/utils/positions/MappedPositionToClassNameMapperBuilder.java
+++ b/src/main/java/com/android/tools/r8/utils/positions/MappedPositionToClassNameMapperBuilder.java
@@ -198,7 +198,9 @@
 
       OneShotCollectionConsumer<MappingInformation> methodSpecificMappingInformation =
           OneShotCollectionConsumer.wrap(new ArrayList<>());
-      if (method.getDefinition().isD8R8Synthesized()) {
+      if (method.getDefinition().isD8R8Synthesized()
+          || (!mappedPositions.isEmpty()
+              && mappedPositions.get(0).getPosition().isD8R8Synthesized())) {
         methodSpecificMappingInformation.add(
             CompilerSynthesizedMappingInformation.builder().build());
       }
@@ -309,11 +311,10 @@
                 appView,
                 getOriginalMethodSignature,
                 getBuilder(),
-                firstPosition.getMethod(),
+                firstPosition,
                 residualSignature,
                 obfuscatedRange,
                 originalRange,
-                firstPosition.getCallerPosition(),
                 prunedInlinedClasses,
                 cardinalRangeCache);
         methodSpecificMappingInformation.consume(
@@ -338,12 +339,11 @@
                         appView,
                         getOriginalMethodSignature,
                         getBuilder(),
-                        position.getMethod(),
+                        position,
                         residualSignature,
                         nonCardinalRangeCache.get(
                             placeHolderLineToBeFixed, placeHolderLineToBeFixed),
                         nonCardinalRangeCache.get(position.getLine(), position.getLine()),
-                        position.getCallerPosition(),
                         prunedInlinedClasses,
                         cardinalRangeCache);
                   });
@@ -370,37 +370,36 @@
         AppView<?> appView,
         Function<DexMethod, MethodSignature> getOriginalMethodSignature,
         ClassNaming.Builder classNamingBuilder,
-        DexMethod method,
+        Position position,
         MethodSignature residualSignature,
         Range obfuscatedRange,
         Range originalLine,
-        Position caller,
         Map<DexType, String> prunedInlineHolder,
         CardinalPositionRangeAllocator cardinalRangeCache) {
-      MappedRange lastMappedRange =
-          classNamingBuilder.addMappedRange(
-              obfuscatedRange,
-              getOriginalMethodSignature.apply(method),
-              originalLine,
-              residualSignature.getName());
-      int inlineFramesCount = 0;
-      while (caller != null) {
+      MappedRange lastMappedRange = null;
+      int inlineFramesCount = -1;
+      do {
+        if (position.isD8R8Synthesized() && position.hasCallerPosition()) {
+          position = position.getCallerPosition();
+          continue;
+        }
         inlineFramesCount += 1;
-        String prunedClassSourceFileInfo =
-            appView.getPrunedClassSourceFileInfo(method.getHolderType());
+        DexType holderType = position.getMethod().getHolderType();
+        String prunedClassSourceFileInfo = appView.getPrunedClassSourceFileInfo(holderType);
         if (prunedClassSourceFileInfo != null) {
-          String originalValue =
-              prunedInlineHolder.put(method.getHolderType(), prunedClassSourceFileInfo);
+          String originalValue = prunedInlineHolder.put(holderType, prunedClassSourceFileInfo);
           assert originalValue == null || originalValue.equals(prunedClassSourceFileInfo);
         }
         lastMappedRange =
             classNamingBuilder.addMappedRange(
                 obfuscatedRange,
-                getOriginalMethodSignature.apply(caller.getMethod()),
-                cardinalRangeCache.get(
-                    Math.max(caller.getLine(), 0)), // Prevent against "no-position".
+                getOriginalMethodSignature.apply(position.getMethod()),
+                inlineFramesCount == 0
+                    ? originalLine
+                    : cardinalRangeCache.get(
+                        Math.max(position.getLine(), 0)), // Prevent against "no-position".
                 residualSignature.getName());
-        if (caller.isRemoveInnerFramesIfThrowingNpe()) {
+        if (position.isRemoveInnerFramesIfThrowingNpe()) {
           lastMappedRange.addMappingInformation(
               RewriteFrameMappingInformation.builder()
                   .addCondition(
@@ -411,8 +410,9 @@
                   .build(),
               Unreachable::raise);
         }
-        caller = caller.getCallerPosition();
-      }
+        position = position.getCallerPosition();
+      } while (position != null);
+      assert lastMappedRange != null;
       return lastMappedRange;
     }