Maintain native pc encoded debug info for reoptimize dex.

Re-storing the native encoding is followup work (marked todo).

Bug: b/498336713
Change-Id: Id6139f19035bd84dfb435688bd968a5e23b1d2d6
diff --git a/src/main/java/com/android/tools/r8/D8.java b/src/main/java/com/android/tools/r8/D8.java
index 4806dea..e3055dd 100644
--- a/src/main/java/com/android/tools/r8/D8.java
+++ b/src/main/java/com/android/tools/r8/D8.java
@@ -8,13 +8,18 @@
 
 import com.android.tools.r8.androidapi.ApiReferenceStubber;
 import com.android.tools.r8.assistant.AssistantInstrumentation;
+import com.android.tools.r8.debuginfo.DebugRepresentation;
 import com.android.tools.r8.dex.ApplicationReader;
 import com.android.tools.r8.dex.ApplicationWriter;
 import com.android.tools.r8.dex.Marker;
+import com.android.tools.r8.dex.code.DexInstruction;
 import com.android.tools.r8.graph.AppInfo;
 import com.android.tools.r8.graph.AppServices;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexApplication;
+import com.android.tools.r8.graph.DexCode;
+import com.android.tools.r8.graph.DexDebugInfo.PcBasedDebugInfo;
+import com.android.tools.r8.graph.DexEncodedMethod;
 import com.android.tools.r8.graph.DexItemFactory;
 import com.android.tools.r8.graph.DexProgramClass;
 import com.android.tools.r8.graph.LazyLoadedDexApplication;
@@ -56,6 +61,8 @@
 import java.util.Collection;
 import java.util.List;
 import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.ExecutorService;
 import java.util.function.Consumer;
@@ -216,6 +223,7 @@
       timing.begin("Read input app");
       AppView<AppInfo> appView = readApp(inputApp, options, executor, timing);
       timing.end();
+      materializeMissingDebugInfo(appView, executor, timing);
       timing.begin("Initialize assume info collection");
       initializeAssumeInfoCollection(appView);
       timing.end();
@@ -352,6 +360,46 @@
     consumer.finished();
   }
 
+  private static void materializeMissingDebugInfo(
+      AppView<AppInfo> appView, ExecutorService executor, Timing timing) throws ExecutionException {
+    if (!appView.options().enableDexToDexCodeOptimizations) {
+      return;
+    }
+    timing.time(
+        "Materialize missing debug info",
+        () -> {
+          ConcurrentHashMap<PcBasedDebugInfo, PcBasedDebugInfo> cache = new ConcurrentHashMap<>();
+          // Methods without debug info is assumed to be native pc encoded debug info.
+          // Rematerialize into PcEncodedDebugInfo.
+          ThreadUtils.processItems(
+              appView.appInfo().classes(),
+              clazz -> materializeMissingDebugInfo(clazz, cache),
+              appView.options().getThreadingModule(),
+              executor);
+        });
+  }
+
+  private static void materializeMissingDebugInfo(
+      DexProgramClass clazz, ConcurrentMap<PcBasedDebugInfo, PcBasedDebugInfo> cache) {
+    for (DexEncodedMethod method : clazz.methods()) {
+      if (!method.hasCode() || !method.getCode().isDexCode()) {
+        continue;
+      }
+      DexCode code = method.getCode().asDexCode();
+      if (code.getDebugInfo() != null) {
+        continue;
+      }
+      DexInstruction lastInstruction = DebugRepresentation.getLastExecutableInstruction(code);
+      if (lastInstruction == null) {
+        continue;
+      }
+      int maxPc = lastInstruction.getOffset();
+      int parameterCount = method.getParameters().size();
+      PcBasedDebugInfo debugInfo = new PcBasedDebugInfo(parameterCount, maxPc);
+      code.setDebugInfo(cache.computeIfAbsent(debugInfo, k -> k));
+    }
+  }
+
   private static void writeApplication(
       AppView<AppInfo> appView,
       AndroidApp inputApp,
diff --git a/src/test/java/com/android/tools/r8/redex/NativeDebugPreservationTest.java b/src/test/java/com/android/tools/r8/redex/NativeDebugPreservationTest.java
index 7200e59..8ef65cd 100644
--- a/src/test/java/com/android/tools/r8/redex/NativeDebugPreservationTest.java
+++ b/src/test/java/com/android/tools/r8/redex/NativeDebugPreservationTest.java
@@ -4,6 +4,7 @@
 package com.android.tools.r8.redex;
 
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 
 import com.android.tools.r8.CompilationMode;
 import com.android.tools.r8.TestBase;
@@ -61,7 +62,8 @@
             inspector -> {
               ClassSubject clazz = inspector.clazz(TestClass.class);
               MethodSubject method = clazz.uniqueMethodWithOriginalName("main");
-              assertFalse("Expected no debug info", method.hasLineNumberTable());
+              // TODO(b/498336713): re-encode the pc debug info.
+              assertTrue("Expected no debug info", method.hasLineNumberTable());
             });
   }
 
diff --git a/src/test/java/com/android/tools/r8/redex/StacktracePreservationTest.java b/src/test/java/com/android/tools/r8/redex/StacktracePreservationTest.java
index 1cb4d1f..625f676 100644
--- a/src/test/java/com/android/tools/r8/redex/StacktracePreservationTest.java
+++ b/src/test/java/com/android/tools/r8/redex/StacktracePreservationTest.java
@@ -134,14 +134,7 @@
             stacktrace -> {
               assertThat(stacktrace, not(StackTrace.isSame(getExpectedStackTrace())));
               StackTrace retracedStackTrace = stacktrace.retrace(r8Mapping);
-              if (compilationApiLevel == AndroidApiLevel.CINNAMON_BUN
-                  && redexApiLevel == AndroidApiLevel.CINNAMON_BUN) {
-                // TODO(b/498336713): Fix trace preservation for native pc encoding, removing this
-                // special case.
-                assertThat(retracedStackTrace, not(StackTrace.isSame(getExpectedStackTrace())));
-              } else {
-                assertThat(retracedStackTrace, StackTrace.isSame(getExpectedStackTrace()));
-              }
+              assertThat(retracedStackTrace, StackTrace.isSame(getExpectedStackTrace()));
             });
   }