Unify synthetic dex debug events carrying position info

Bug: b/226699242
Change-Id: I9d116e50c7cd01b565c59333227bb093131f6eb7
diff --git a/src/main/java/com/android/tools/r8/R8.java b/src/main/java/com/android/tools/r8/R8.java
index afea47d..9584e69 100644
--- a/src/main/java/com/android/tools/r8/R8.java
+++ b/src/main/java/com/android/tools/r8/R8.java
@@ -975,7 +975,9 @@
       return true;
     }
     for (DexDebugEvent event : code.getDebugInfo().asEventBasedInfo().events) {
-      assert !event.isSetInlineFrame() || event.asSetInlineFrame().hasOuterPosition(originalMethod);
+      assert !event.isPositionFrame()
+          || event.asSetPositionFrame().getPosition().getOutermostCaller().getMethod()
+              == originalMethod;
     }
     return true;
   }
diff --git a/src/main/java/com/android/tools/r8/graph/DexCode.java b/src/main/java/com/android/tools/r8/graph/DexCode.java
index 6eb2f08..c99b310 100644
--- a/src/main/java/com/android/tools/r8/graph/DexCode.java
+++ b/src/main/java/com/android/tools/r8/graph/DexCode.java
@@ -13,7 +13,7 @@
 import com.android.tools.r8.dex.MixedSectionCollection;
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.DexCode.TryHandler.TypeAddrPair;
-import com.android.tools.r8.graph.DexDebugEvent.SetInlineFrame;
+import com.android.tools.r8.graph.DexDebugEvent.SetPositionFrame;
 import com.android.tools.r8.graph.DexDebugEvent.StartLocal;
 import com.android.tools.r8.graph.DexDebugInfo.EventBasedDebugInfo;
 import com.android.tools.r8.graph.bytecodemetadata.BytecodeInstructionMetadata;
@@ -279,6 +279,12 @@
       DexMethod caller, DexMethod callee, DexItemFactory factory) {
     Position callerPosition = SyntheticPosition.builder().setLine(0).setMethod(caller).build();
     EventBasedDebugInfo eventBasedInfo = DexDebugInfo.convertToEventBased(this, factory);
+    Position inlinePosition =
+        SyntheticPosition.builder()
+            .setMethod(caller)
+            .setCallerPosition(callerPosition)
+            .disableLineCheck()
+            .build();
     if (eventBasedInfo == null) {
       // If the method has no debug info we generate a preamble position to denote the inlining.
       // This is consistent with the building IR for inlining which will always ensure the method
@@ -287,22 +293,20 @@
           0,
           new DexString[callee.getArity()],
           new DexDebugEvent[] {
-            new DexDebugEvent.SetInlineFrame(callee, callerPosition), factory.zeroChangeDefaultEvent
+            new SetPositionFrame(inlinePosition), factory.zeroChangeDefaultEvent
           });
     }
     DexDebugEvent[] oldEvents = eventBasedInfo.events;
     DexDebugEvent[] newEvents = new DexDebugEvent[oldEvents.length + 1];
     int i = 0;
-    newEvents[i++] = new DexDebugEvent.SetInlineFrame(callee, callerPosition);
+    newEvents[i++] = new SetPositionFrame(inlinePosition);
     for (DexDebugEvent event : oldEvents) {
-      if (event instanceof SetInlineFrame) {
-        SetInlineFrame oldFrame = (SetInlineFrame) event;
+      if (event instanceof SetPositionFrame) {
+        SetPositionFrame oldFrame = (SetPositionFrame) event;
+        assert oldFrame.getPosition() != null;
         newEvents[i++] =
-            new SetInlineFrame(
-                oldFrame.callee,
-                oldFrame.caller == null
-                    ? callerPosition
-                    : oldFrame.caller.withOutermostCallerPosition(callerPosition));
+            new SetPositionFrame(
+                oldFrame.getPosition().withOutermostCallerPosition(callerPosition));
       } else {
         newEvents[i++] = event;
       }
diff --git a/src/main/java/com/android/tools/r8/graph/DexDebugEntryBuilder.java b/src/main/java/com/android/tools/r8/graph/DexDebugEntryBuilder.java
index d8b6a9b..2a67e34 100644
--- a/src/main/java/com/android/tools/r8/graph/DexDebugEntryBuilder.java
+++ b/src/main/java/com/android/tools/r8/graph/DexDebugEntryBuilder.java
@@ -3,8 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.graph;
 
-import com.android.tools.r8.graph.DexDebugEvent.SetOutlineCallerFrame;
-import com.android.tools.r8.graph.DexDebugEvent.SetOutlineFrame;
+import com.android.tools.r8.graph.DexDebugEvent.SetPositionFrame;
 import com.android.tools.r8.graph.DexDebugInfo.EventBasedDebugInfo;
 import com.android.tools.r8.ir.code.ValueType;
 import com.google.common.collect.ImmutableMap;
@@ -111,18 +110,8 @@
   }
 
   @Override
-  public void visit(DexDebugEvent.SetInlineFrame setInlineFrame) {
-    positionState.visit(setInlineFrame);
-  }
-
-  @Override
-  public void visit(SetOutlineFrame setOutlineFrame) {
-    positionState.visit(setOutlineFrame);
-  }
-
-  @Override
-  public void visit(SetOutlineCallerFrame setOutlineCallerFrame) {
-    positionState.visit(setOutlineCallerFrame);
+  public void visit(SetPositionFrame setPositionFrame) {
+    positionState.visit(setPositionFrame);
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/graph/DexDebugEvent.java b/src/main/java/com/android/tools/r8/graph/DexDebugEvent.java
index 60cc65a..27aacbe 100644
--- a/src/main/java/com/android/tools/r8/graph/DexDebugEvent.java
+++ b/src/main/java/com/android/tools/r8/graph/DexDebugEvent.java
@@ -9,7 +9,6 @@
 import com.android.tools.r8.dex.MixedSectionCollection;
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.ir.code.Position;
-import com.android.tools.r8.utils.Int2StructuralItemArrayMap;
 import com.android.tools.r8.utils.structural.CompareToVisitor;
 import com.android.tools.r8.utils.structural.HashingVisitor;
 import com.android.tools.r8.utils.structural.StructuralItem;
@@ -20,9 +19,7 @@
 public abstract class DexDebugEvent extends DexItem implements StructuralItem<DexDebugEvent> {
 
   // Compare ID(s) for virtual debug events.
-  private static final int DBG_SET_INLINE_FRAME_COMPARE_ID = Constants.DBG_LAST_SPECIAL + 1;
-  private static final int DBG_SET_OUTLINE_FRAME_COMPARE_ID = Constants.DBG_LAST_SPECIAL + 2;
-  private static final int DBG_SET_OUTLINE_CALLER_COMPARE_ID = Constants.DBG_LAST_SPECIAL + 3;
+  private static final int DBG_SET_POSITION_FRAME_COMPARE_ID = Constants.DBG_LAST_SPECIAL + 1;
 
   public static final DexDebugEvent[] EMPTY_ARRAY = {};
 
@@ -92,23 +89,11 @@
 
   public abstract void accept(DexDebugEventVisitor visitor);
 
-  public boolean isSetInlineFrame() {
+  public boolean isPositionFrame() {
     return false;
   }
 
-  public boolean isSetOutlineFrame() {
-    return false;
-  }
-
-  public boolean isSetOutlineCallerFrame() {
-    return false;
-  }
-
-  public SetInlineFrame asSetInlineFrame() {
-    return null;
-  }
-
-  public SetOutlineCallerFrame asSetOutlineCallerFrame() {
+  public SetPositionFrame asSetPositionFrame() {
     return null;
   }
 
@@ -575,19 +560,20 @@
     }
   }
 
-  public static class SetInlineFrame extends DexDebugEvent {
+  public static class SetPositionFrame extends DexDebugEvent {
 
-    final DexMethod callee;
-    final Position caller;
+    private final Position position;
 
-    private static void specify(StructuralSpecification<SetInlineFrame, ?> spec) {
-      spec.withItem(e -> e.callee).withNullableItem(e -> e.caller);
+    private static void specify(StructuralSpecification<SetPositionFrame, ?> spec) {
+      spec.withNullableItem(e -> e.position);
     }
 
-    SetInlineFrame(DexMethod callee, Position caller) {
-      assert callee != null;
-      this.callee = callee;
-      this.caller = caller;
+    SetPositionFrame(Position position) {
+      this.position = position;
+    }
+
+    public Position getPosition() {
+      return position;
     }
 
     @Override
@@ -597,140 +583,36 @@
 
     @Override
     public String toString() {
-      return String.format("SET_INLINE_FRAME %s %s", callee, caller);
+      return String.format("SET_POSITION_FRAME %s", position);
     }
 
     @Override
     public int hashCode() {
-      return 31 * callee.hashCode() + Objects.hashCode(caller);
+      return 31 * Objects.hashCode(position);
     }
 
     @Override
     int getCompareToId() {
-      return DBG_SET_INLINE_FRAME_COMPARE_ID;
+      return DBG_SET_POSITION_FRAME_COMPARE_ID;
     }
 
     @Override
     int internalAcceptCompareTo(DexDebugEvent other, CompareToVisitor visitor) {
-      return visitor.visit(this, (SetInlineFrame) other, SetInlineFrame::specify);
+      return visitor.visit(this, (SetPositionFrame) other, SetPositionFrame::specify);
     }
 
     @Override
     void internalAcceptHashing(HashingVisitor visitor) {
-      visitor.visit(this, SetInlineFrame::specify);
+      visitor.visit(this, SetPositionFrame::specify);
     }
 
     @Override
-    public boolean isSetInlineFrame() {
+    public boolean isPositionFrame() {
       return true;
     }
 
     @Override
-    public SetInlineFrame asSetInlineFrame() {
-      return this;
-    }
-
-    public boolean hasOuterPosition(DexMethod method) {
-      return (caller == null && callee == method)
-          || (caller != null && caller.getOutermostCaller().getMethod() == method);
-    }
-  }
-
-  public static class SetOutlineFrame extends DexDebugEvent {
-
-    @Override
-    public String toString() {
-      return "SET_OUTLINE_FRAME";
-    }
-
-    @Override
-    public int hashCode() {
-      return 7;
-    }
-
-    @Override
-    int getCompareToId() {
-      return DBG_SET_OUTLINE_FRAME_COMPARE_ID;
-    }
-
-    @Override
-    int internalAcceptCompareTo(DexDebugEvent other, CompareToVisitor visitor) {
-      return 0;
-    }
-
-    @Override
-    void internalAcceptHashing(HashingVisitor visitor) {
-      // Intentionally empty: no content besides the compare-id
-    }
-
-    @Override
-    public void accept(DexDebugEventVisitor visitor) {
-      visitor.visit(this);
-    }
-  }
-
-  public static class SetOutlineCallerFrame extends DexDebugEvent {
-
-    private final DexMethod outlineCallee;
-    private final Int2StructuralItemArrayMap<Position> outlinePositions;
-
-    private static void specify(StructuralSpecification<SetOutlineCallerFrame, ?> spec) {
-      spec.withItem(e -> e.outlineCallee).withNullableItem(e -> e.outlinePositions);
-    }
-
-    SetOutlineCallerFrame(
-        DexMethod outlineCallee, Int2StructuralItemArrayMap<Position> outlinePositions) {
-      assert outlineCallee != null;
-      assert !outlinePositions.isEmpty();
-      this.outlineCallee = outlineCallee;
-      this.outlinePositions = outlinePositions;
-    }
-
-    public DexMethod getOutlineCallee() {
-      return outlineCallee;
-    }
-
-    public Int2StructuralItemArrayMap<Position> getOutlinePositions() {
-      return outlinePositions;
-    }
-
-    @Override
-    public void accept(DexDebugEventVisitor visitor) {
-      visitor.visit(this);
-    }
-
-    @Override
-    public String toString() {
-      return String.format("SET_OUTLINE_CALLER_FRAME %s %s", outlineCallee, outlinePositions);
-    }
-
-    @Override
-    public int hashCode() {
-      return Objects.hash(outlineCallee, outlinePositions);
-    }
-
-    @Override
-    int getCompareToId() {
-      return DBG_SET_OUTLINE_CALLER_COMPARE_ID;
-    }
-
-    @Override
-    int internalAcceptCompareTo(DexDebugEvent other, CompareToVisitor visitor) {
-      return visitor.visit(this, (SetOutlineCallerFrame) other, SetOutlineCallerFrame::specify);
-    }
-
-    @Override
-    void internalAcceptHashing(HashingVisitor visitor) {
-      visitor.visit(this, SetOutlineCallerFrame::specify);
-    }
-
-    @Override
-    public boolean isSetOutlineCallerFrame() {
-      return true;
-    }
-
-    @Override
-    public SetOutlineCallerFrame asSetOutlineCallerFrame() {
+    public SetPositionFrame asSetPositionFrame() {
       return this;
     }
   }
diff --git a/src/main/java/com/android/tools/r8/graph/DexDebugEventBuilder.java b/src/main/java/com/android/tools/r8/graph/DexDebugEventBuilder.java
index dc90361..e4c29aa 100644
--- a/src/main/java/com/android/tools/r8/graph/DexDebugEventBuilder.java
+++ b/src/main/java/com/android/tools/r8/graph/DexDebugEventBuilder.java
@@ -249,18 +249,14 @@
         || previousPosition.hasCallerPosition()
         || nextPosition.getMethod() == previousPosition.getMethod()
         || optimizingLineNumbers;
-    if (nextPosition.getCallerPosition() != previousPosition.getCallerPosition()
-        || nextPosition.getMethod() != previousPosition.getMethod()) {
-      events.add(
-          factory.createSetInlineFrame(nextPosition.getMethod(), nextPosition.getCallerPosition()));
-    }
-    if (nextPosition.isOutline()) {
-      events.add(factory.createSetOutlineFrame());
-    }
-    if (nextPosition.getOutlineCallee() != null && !nextPosition.getOutlinePositions().isEmpty()) {
-      events.add(
-          factory.createSetOutlineCallerFrame(
-              nextPosition.getOutlineCallee(), nextPosition.getOutlinePositions()));
+    boolean isNewPosition =
+        nextPosition.getCallerPosition() != previousPosition.getCallerPosition()
+            || nextPosition.getMethod() != previousPosition.getMethod();
+    boolean isOutline = nextPosition.isOutline();
+    boolean isOutlineCallee =
+        nextPosition.getOutlineCallee() != null && !nextPosition.getOutlinePositions().isEmpty();
+    if (isNewPosition || isOutline || isOutlineCallee) {
+      events.add(factory.createPositionFrame(nextPosition));
     }
     addDefaultEventWithAdvancePcIfNecessary(lineDelta, pcDelta, events, factory);
   }
diff --git a/src/main/java/com/android/tools/r8/graph/DexDebugEventVisitor.java b/src/main/java/com/android/tools/r8/graph/DexDebugEventVisitor.java
index 165858b..b09f62d 100644
--- a/src/main/java/com/android/tools/r8/graph/DexDebugEventVisitor.java
+++ b/src/main/java/com/android/tools/r8/graph/DexDebugEventVisitor.java
@@ -10,9 +10,7 @@
 import com.android.tools.r8.graph.DexDebugEvent.RestartLocal;
 import com.android.tools.r8.graph.DexDebugEvent.SetEpilogueBegin;
 import com.android.tools.r8.graph.DexDebugEvent.SetFile;
-import com.android.tools.r8.graph.DexDebugEvent.SetInlineFrame;
-import com.android.tools.r8.graph.DexDebugEvent.SetOutlineCallerFrame;
-import com.android.tools.r8.graph.DexDebugEvent.SetOutlineFrame;
+import com.android.tools.r8.graph.DexDebugEvent.SetPositionFrame;
 import com.android.tools.r8.graph.DexDebugEvent.SetPrologueEnd;
 import com.android.tools.r8.graph.DexDebugEvent.StartLocal;
 
@@ -21,11 +19,7 @@
 
   void visit(AdvanceLine advanceLine);
 
-  void visit(SetInlineFrame setInlineFrame);
-
-  void visit(SetOutlineFrame setOutlineFrame);
-
-  void visit(SetOutlineCallerFrame setOutlineCallerFrame);
+  void visit(SetPositionFrame setPositionFrame);
 
   void visit(Default defaultEvent);
 
diff --git a/src/main/java/com/android/tools/r8/graph/DexDebugPositionState.java b/src/main/java/com/android/tools/r8/graph/DexDebugPositionState.java
index 9c5ffd6..10a06d5 100644
--- a/src/main/java/com/android/tools/r8/graph/DexDebugPositionState.java
+++ b/src/main/java/com/android/tools/r8/graph/DexDebugPositionState.java
@@ -11,9 +11,7 @@
 import com.android.tools.r8.graph.DexDebugEvent.RestartLocal;
 import com.android.tools.r8.graph.DexDebugEvent.SetEpilogueBegin;
 import com.android.tools.r8.graph.DexDebugEvent.SetFile;
-import com.android.tools.r8.graph.DexDebugEvent.SetInlineFrame;
-import com.android.tools.r8.graph.DexDebugEvent.SetOutlineCallerFrame;
-import com.android.tools.r8.graph.DexDebugEvent.SetOutlineFrame;
+import com.android.tools.r8.graph.DexDebugEvent.SetPositionFrame;
 import com.android.tools.r8.graph.DexDebugEvent.SetPrologueEnd;
 import com.android.tools.r8.graph.DexDebugEvent.StartLocal;
 import com.android.tools.r8.ir.code.Position;
@@ -51,20 +49,14 @@
   }
 
   @Override
-  public void visit(SetInlineFrame setInlineFrame) {
-    currentMethod = setInlineFrame.callee;
-    currentCallerPosition = setInlineFrame.caller;
-  }
-
-  @Override
-  public void visit(SetOutlineFrame setOutlineFrame) {
-    isOutline = true;
-  }
-
-  @Override
-  public void visit(SetOutlineCallerFrame setOutlineCallerFrame) {
-    outlineCallee = setOutlineCallerFrame.getOutlineCallee();
-    outlineCallerPositions = setOutlineCallerFrame.getOutlinePositions();
+  public void visit(SetPositionFrame setPositionFrame) {
+    assert setPositionFrame.getPosition() != null;
+    Position position = setPositionFrame.getPosition();
+    currentMethod = position.getMethod();
+    currentCallerPosition = position.getCallerPosition();
+    outlineCallee = position.getOutlineCallee();
+    outlineCallerPositions = position.getOutlinePositions();
+    isOutline = position.isOutline();
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/graph/DexItemFactory.java b/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
index c37e3ae..3e5150c 100644
--- a/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
+++ b/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
@@ -17,9 +17,7 @@
 import com.android.tools.r8.graph.DexDebugEvent.RestartLocal;
 import com.android.tools.r8.graph.DexDebugEvent.SetEpilogueBegin;
 import com.android.tools.r8.graph.DexDebugEvent.SetFile;
-import com.android.tools.r8.graph.DexDebugEvent.SetInlineFrame;
-import com.android.tools.r8.graph.DexDebugEvent.SetOutlineCallerFrame;
-import com.android.tools.r8.graph.DexDebugEvent.SetOutlineFrame;
+import com.android.tools.r8.graph.DexDebugEvent.SetPositionFrame;
 import com.android.tools.r8.graph.DexDebugEvent.SetPrologueEnd;
 import com.android.tools.r8.graph.DexMethodHandle.MethodHandleType;
 import com.android.tools.r8.ir.analysis.type.ArrayTypeElement;
@@ -38,7 +36,6 @@
 import com.android.tools.r8.synthesis.SyntheticNaming;
 import com.android.tools.r8.utils.ArrayUtils;
 import com.android.tools.r8.utils.DescriptorUtils;
-import com.android.tools.r8.utils.Int2StructuralItemArrayMap;
 import com.android.tools.r8.utils.IterableUtils;
 import com.android.tools.r8.utils.LRUCacheTable;
 import com.android.tools.r8.utils.ListUtils;
@@ -99,8 +96,7 @@
   private final SetEpilogueBegin setEpilogueBegin = new SetEpilogueBegin();
   private final SetPrologueEnd setPrologueEnd = new SetPrologueEnd();
   private final Map<DexString, SetFile> setFiles = new HashMap<>();
-  private final SetOutlineFrame setOutlineFrame = new SetOutlineFrame();
-  private final Map<SetInlineFrame, SetInlineFrame> setInlineFrames = new HashMap<>();
+  private final Map<SetPositionFrame, SetPositionFrame> setInlineFrames = new HashMap<>();
   public final DexDebugEvent.Default zeroChangeDefaultEvent = createDefault(0, 0);
   public final DexDebugEvent.Default oneChangeDefaultEvent = createDefault(1, 1);
 
@@ -2898,21 +2894,12 @@
   }
 
   // TODO(tamaskenez) b/69024229 Measure if canonicalization is worth it.
-  public SetInlineFrame createSetInlineFrame(DexMethod callee, Position caller) {
+  public SetPositionFrame createPositionFrame(Position position) {
     synchronized (setInlineFrames) {
-      return setInlineFrames.computeIfAbsent(new SetInlineFrame(callee, caller), p -> p);
+      return setInlineFrames.computeIfAbsent(new SetPositionFrame(position), p -> p);
     }
   }
 
-  public SetOutlineFrame createSetOutlineFrame() {
-    return setOutlineFrame;
-  }
-
-  public SetOutlineCallerFrame createSetOutlineCallerFrame(
-      DexMethod outlineCallee, Int2StructuralItemArrayMap<Position> outlinePositions) {
-    return new SetOutlineCallerFrame(outlineCallee, outlinePositions);
-  }
-
   public boolean isConstructor(DexMethod method) {
     return method.name == constructorMethodName;
   }