Add support for materializing line info from native pc methods
Bug: b/213411850
Bug: b/284954852
Bug: b/232212653
Change-Id: I84a1e903a6365f0693ad26c4c09a8f1dcec26d63
diff --git a/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java b/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
index 37fad8c..073cc8d 100644
--- a/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
+++ b/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
@@ -947,10 +947,7 @@
DexWritableCode code = method.getDefinition().getCode().asDexWritableCode();
DexWritableCode rewrittenCode =
code.rewriteCodeWithJumboStrings(
- method,
- mapping,
- application.dexItemFactory,
- options.testing.forceJumboStringProcessing);
+ method, mapping, appView, options.testing.forceJumboStringProcessing);
method.setCode(rewrittenCode.asCode(), appView);
});
}
diff --git a/src/main/java/com/android/tools/r8/dex/JumboStringRewriter.java b/src/main/java/com/android/tools/r8/dex/JumboStringRewriter.java
index a68f99f..13f6812 100644
--- a/src/main/java/com/android/tools/r8/dex/JumboStringRewriter.java
+++ b/src/main/java/com/android/tools/r8/dex/JumboStringRewriter.java
@@ -53,6 +53,7 @@
import java.util.ListIterator;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.function.BooleanSupplier;
public class JumboStringRewriter {
@@ -92,6 +93,7 @@
private final DexEncodedMethod method;
private final DexString firstJumboString;
+ private final BooleanSupplier materializeInfoForNativePc;
private final DexItemFactory factory;
private final Map<DexInstruction, List<DexInstruction>> instructionTargets =
new IdentityHashMap<>();
@@ -105,12 +107,20 @@
private final Map<TryHandler, List<DexInstruction>> handlerTargets = new IdentityHashMap<>();
public JumboStringRewriter(
- DexEncodedMethod method, DexString firstJumboString, DexItemFactory factory) {
+ DexEncodedMethod method,
+ DexString firstJumboString,
+ BooleanSupplier materializeInfoForNativePc,
+ DexItemFactory factory) {
this.method = method;
this.firstJumboString = firstJumboString;
+ this.materializeInfoForNativePc = materializeInfoForNativePc;
this.factory = factory;
}
+ private DexCode getCode() {
+ return method.getCode().asDexCode();
+ }
+
public DexCode rewrite() {
// Build maps from everything in the code that uses offsets or direct addresses to reference
// instructions to the actual instruction referenced.
@@ -124,7 +134,7 @@
TryHandler[] newHandlers = rewriteHandlerOffsets();
DexDebugInfo newDebugInfo = rewriteDebugInfoOffsets();
// Set the new code on the method.
- DexCode oldCode = method.getCode().asDexCode();
+ DexCode oldCode = getCode();
DexCode newCode =
new DexCode(
oldCode.registerSize,
@@ -185,7 +195,7 @@
}
private Try[] rewriteTryOffsets() {
- DexCode code = method.getCode().asDexCode();
+ DexCode code = getCode();
Try[] result = new Try[code.tries.length];
for (int i = 0; i < code.tries.length; i++) {
Try theTry = code.tries[i];
@@ -197,7 +207,7 @@
}
private TryHandler[] rewriteHandlerOffsets() {
- DexCode code = method.getCode().asDexCode();
+ DexCode code = getCode();
TryHandler[] result = new TryHandler[code.handlers.length];
for (int i = 0; i < code.handlers.length; i++) {
TryHandler handler = code.handlers[i];
@@ -218,7 +228,7 @@
}
private DexDebugInfo rewriteDebugInfoOffsets() {
- DexCode code = method.getCode().asDexCode();
+ DexCode code = getCode();
if (!debugEventTargets.isEmpty()) {
assert debugEventBasedInfo != null;
int lastOriginalOffset = 0;
@@ -256,7 +266,7 @@
@SuppressWarnings("JdkObsolete")
private List<DexInstruction> expandCode() {
LinkedList<DexInstruction> instructions = new LinkedList<>();
- Collections.addAll(instructions, method.getCode().asDexCode().instructions);
+ Collections.addAll(instructions, getCode().instructions);
int offsetDelta;
do {
ListIterator<DexInstruction> it = instructions.listIterator();
@@ -436,7 +446,7 @@
}
private void recordInstructionTargets(Int2ReferenceMap<DexInstruction> offsetToInstruction) {
- DexInstruction[] instructions = method.getCode().asDexCode().instructions;
+ DexInstruction[] instructions = getCode().instructions;
for (DexInstruction instruction : instructions) {
if (instruction instanceof DexFormat22t) { // IfEq, IfGe, IfGt, IfLe, IfLt, IfNe
DexFormat22t condition = (DexFormat22t) instruction;
@@ -486,14 +496,15 @@
}
private void recordDebugEventTargets(Int2ReferenceMap<DexInstruction> offsetToInstruction) {
- // TODO(b/213411850): Merging pc based D8 builds will map out of PC for any jumbo processed
- // method. Instead we should rather retain the PC encoding by bumping the max-pc and recording
- // the line number translation. We actually need to do so to support merging with native PC
- // support as in that case we can't reflect the change in the line table, only in the mapping.
- EventBasedDebugInfo eventBasedInfo =
- DexDebugInfo.convertToEventBased(method.getCode().asDexCode(), factory);
+ EventBasedDebugInfo eventBasedInfo = DexDebugInfo.convertToEventBased(getCode(), factory);
if (eventBasedInfo == null) {
- return;
+ if (materializeInfoForNativePc.getAsBoolean()) {
+ eventBasedInfo =
+ DexDebugInfo.createEventBasedDebugInfoForNativePc(
+ method.getParameters().size(), getCode(), factory);
+ } else {
+ return;
+ }
}
debugEventBasedInfo = eventBasedInfo;
int address = 0;
@@ -516,7 +527,7 @@
private void recordTryAndHandlerTargets(
Int2ReferenceMap<DexInstruction> offsetToInstruction, DexInstruction lastInstruction) {
- DexCode code = method.getCode().asDexCode();
+ DexCode code = getCode();
for (Try theTry : code.tries) {
DexInstruction start = offsetToInstruction.get(theTry.startAddress);
DexInstruction end = null;
@@ -553,7 +564,7 @@
private void recordTargets() {
Int2ReferenceMap<DexInstruction> offsetToInstruction = new Int2ReferenceOpenHashMap<>();
- DexInstruction[] instructions = method.getCode().asDexCode().instructions;
+ DexInstruction[] instructions = getCode().instructions;
boolean containsPayloads = false;
for (DexInstruction instruction : instructions) {
offsetToInstruction.put(instruction.getOffset(), instruction);
diff --git a/src/main/java/com/android/tools/r8/graph/DefaultInstanceInitializerCode.java b/src/main/java/com/android/tools/r8/graph/DefaultInstanceInitializerCode.java
index b0e0aba..31b2efe 100644
--- a/src/main/java/com/android/tools/r8/graph/DefaultInstanceInitializerCode.java
+++ b/src/main/java/com/android/tools/r8/graph/DefaultInstanceInitializerCode.java
@@ -324,7 +324,7 @@
@Override
public DexWritableCode rewriteCodeWithJumboStrings(
- ProgramMethod method, ObjectToOffsetMapping mapping, DexItemFactory factory, boolean force) {
+ ProgramMethod method, ObjectToOffsetMapping mapping, AppView<?> appView, boolean force) {
// Intentionally empty. This piece of code does not have any const-string instructions.
return this;
}
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 80a75b9..5932bb5 100644
--- a/src/main/java/com/android/tools/r8/graph/DexCode.java
+++ b/src/main/java/com/android/tools/r8/graph/DexCode.java
@@ -212,7 +212,7 @@
@Override
public DexWritableCode rewriteCodeWithJumboStrings(
- ProgramMethod method, ObjectToOffsetMapping mapping, DexItemFactory factory, boolean force) {
+ ProgramMethod method, ObjectToOffsetMapping mapping, AppView<?> appView, boolean force) {
DexString firstJumboString = null;
if (force) {
firstJumboString = mapping.getFirstString();
@@ -226,7 +226,12 @@
}
}
return firstJumboString != null
- ? new JumboStringRewriter(method.getDefinition(), firstJumboString, factory).rewrite()
+ ? new JumboStringRewriter(
+ method.getDefinition(),
+ firstJumboString,
+ () -> appView.options().shouldMaterializeLineInfoForNativePcEncoding(method),
+ appView.dexItemFactory())
+ .rewrite()
: this;
}
diff --git a/src/main/java/com/android/tools/r8/graph/DexDebugInfo.java b/src/main/java/com/android/tools/r8/graph/DexDebugInfo.java
index 8826ec4..1a0023a 100644
--- a/src/main/java/com/android/tools/r8/graph/DexDebugInfo.java
+++ b/src/main/java/com/android/tools/r8/graph/DexDebugInfo.java
@@ -314,11 +314,18 @@
code, pcBasedDebugInfo.maxPc);
// Generate a line event at each throwing instruction.
DexInstruction[] instructions = code.instructions;
- return forceConvertToEventBasedDebugInfo(pcBasedDebugInfo, instructions, factory);
+ return forceConvertToEventBasedDebugInfo(
+ PcBasedDebugInfo.START_LINE, pcBasedDebugInfo.getParameterCount(), instructions, factory);
}
- public static EventBasedDebugInfo forceConvertToEventBasedDebugInfo(
- PcBasedDebugInfo pcBasedDebugInfo, DexInstruction[] instructions, DexItemFactory factory) {
+ public static EventBasedDebugInfo createEventBasedDebugInfoForNativePc(
+ int parameterCount, DexCode code, DexItemFactory factory) {
+ assert code.getDebugInfo() == null;
+ return forceConvertToEventBasedDebugInfo(0, parameterCount, code.instructions, factory);
+ }
+
+ private static EventBasedDebugInfo forceConvertToEventBasedDebugInfo(
+ int startLine, int parameterCount, DexInstruction[] instructions, DexItemFactory factory) {
List<DexDebugEvent> events = new ArrayList<>(instructions.length);
int delta = 0;
for (DexInstruction instruction : instructions) {
@@ -329,9 +336,7 @@
delta += instruction.getSize();
}
return new EventBasedDebugInfo(
- PcBasedDebugInfo.START_LINE,
- new DexString[pcBasedDebugInfo.getParameterCount()],
- events.toArray(DexDebugEvent.EMPTY_ARRAY));
+ startLine, new DexString[parameterCount], events.toArray(DexDebugEvent.EMPTY_ARRAY));
}
public static DexDebugInfoForWriting convertToWritable(DexDebugInfo debugInfo) {
diff --git a/src/main/java/com/android/tools/r8/graph/DexWritableCode.java b/src/main/java/com/android/tools/r8/graph/DexWritableCode.java
index 99f8679..afe2afb 100644
--- a/src/main/java/com/android/tools/r8/graph/DexWritableCode.java
+++ b/src/main/java/com/android/tools/r8/graph/DexWritableCode.java
@@ -96,7 +96,7 @@
/** Rewrites the code to have JumboString bytecode if required by mapping. */
DexWritableCode rewriteCodeWithJumboStrings(
- ProgramMethod method, ObjectToOffsetMapping mapping, DexItemFactory factory, boolean force);
+ ProgramMethod method, ObjectToOffsetMapping mapping, AppView<?> appView, boolean force);
void setCallSiteContexts(ProgramMethod method);
diff --git a/src/main/java/com/android/tools/r8/graph/ThrowExceptionCode.java b/src/main/java/com/android/tools/r8/graph/ThrowExceptionCode.java
index 19d78c1..4905063 100644
--- a/src/main/java/com/android/tools/r8/graph/ThrowExceptionCode.java
+++ b/src/main/java/com/android/tools/r8/graph/ThrowExceptionCode.java
@@ -197,7 +197,7 @@
@Override
public DexWritableCode rewriteCodeWithJumboStrings(
- ProgramMethod method, ObjectToOffsetMapping mapping, DexItemFactory factory, boolean force) {
+ ProgramMethod method, ObjectToOffsetMapping mapping, AppView<?> appView, boolean force) {
// Intentionally empty. This piece of code does not have any const-string instructions.
return this;
}
diff --git a/src/main/java/com/android/tools/r8/graph/ThrowNullCode.java b/src/main/java/com/android/tools/r8/graph/ThrowNullCode.java
index 707e45a..90c6d8d 100644
--- a/src/main/java/com/android/tools/r8/graph/ThrowNullCode.java
+++ b/src/main/java/com/android/tools/r8/graph/ThrowNullCode.java
@@ -219,7 +219,7 @@
@Override
public DexWritableCode rewriteCodeWithJumboStrings(
- ProgramMethod method, ObjectToOffsetMapping mapping, DexItemFactory factory, boolean force) {
+ ProgramMethod method, ObjectToOffsetMapping mapping, AppView<?> appView, boolean force) {
// Intentionally empty. This piece of code does not have any const-string instructions.
return this;
}
diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
index b2ce050..89edec3 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -52,6 +52,7 @@
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexReference;
+import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.graph.classmerging.VerticallyMergedClasses;
@@ -2515,6 +2516,10 @@
throw new Unreachable();
}
+ public boolean canUseDexPc2PcAsDebugInformation() {
+ return isGeneratingDex() && lineNumberOptimization == LineNumberOptimization.ON;
+ }
+
// Debug entries may be dropped only if the source file content allows being omitted from
// stack traces, or if the VM will report the source file even with a null valued debug info.
public boolean allowDiscardingResidualDebugInfo() {
@@ -2522,8 +2527,10 @@
return sourceFileProvider != null && sourceFileProvider.allowDiscardingSourceFile();
}
- public boolean canUseDexPc2PcAsDebugInformation() {
- return isGeneratingDex() && lineNumberOptimization == LineNumberOptimization.ON;
+ public boolean allowDiscardingResidualDebugInfo(ProgramMethod method) {
+ // TODO(b/146565491): We can drop debug info once fixed at a known min-api.
+ DexString sourceFile = method.getHolder().getSourceFile();
+ return sourceFile == null || sourceFile.equals(itemFactory.defaultSourceFileAttribute);
}
public boolean canUseNativeDexPcInsteadOfDebugInfo() {
@@ -2532,6 +2539,19 @@
&& allowDiscardingResidualDebugInfo();
}
+ public boolean canUseNativeDexPcInsteadOfDebugInfo(ProgramMethod method) {
+ return canUseDexPc2PcAsDebugInformation()
+ && hasMinApi(AndroidApiLevel.O)
+ && allowDiscardingResidualDebugInfo(method);
+ }
+
+ public boolean shouldMaterializeLineInfoForNativePcEncoding(ProgramMethod method) {
+ assert method.getDefinition().getCode().asDexCode() != null;
+ assert method.getDefinition().getCode().asDexCode().getDebugInfo() == null;
+ return method.getHolder().originatesFromDexResource()
+ && canUseNativeDexPcInsteadOfDebugInfo(method);
+ }
+
public boolean isInterfaceMethodDesugaringEnabled() {
// This condition is to filter out tests that never set program consumer.
if (!hasConsumer()) {
diff --git a/src/test/java/com/android/tools/r8/debuginfo/composepc/ComposePcEncodingTest.java b/src/test/java/com/android/tools/r8/debuginfo/composepc/ComposePcEncodingTest.java
new file mode 100644
index 0000000..311ea41
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/debuginfo/composepc/ComposePcEncodingTest.java
@@ -0,0 +1,143 @@
+// 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.debuginfo.composepc;
+
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import com.android.tools.r8.R8TestCompileResult;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+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.references.Reference;
+import com.android.tools.r8.retrace.RetraceFrameElement;
+import com.android.tools.r8.retrace.RetraceFrameResult;
+import com.android.tools.r8.retrace.RetraceStackTraceContext;
+import com.android.tools.r8.retrace.RetracedMethodReference;
+import com.android.tools.r8.transformers.ClassFileTransformer.MethodPredicate;
+import com.android.tools.r8.utils.FileUtils;
+import com.android.tools.r8.utils.codeinspector.MethodSubject;
+import java.nio.file.Path;
+import java.util.OptionalInt;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class ComposePcEncodingTest extends TestBase {
+
+ private final TestParameters parameters;
+
+ @Parameterized.Parameters(name = "{0}")
+ public static TestParametersCollection data() {
+ return getTestParameters().withDexRuntimes().withAllApiLevels().build();
+ }
+
+ public ComposePcEncodingTest(TestParameters parameters) {
+ this.parameters = parameters;
+ }
+
+ private byte[] getTransformedClass() throws Exception {
+ return transformer(TestClass.class)
+ .removeLineNumberTable(MethodPredicate.onName("unusedKeptAndNoLineInfo"))
+ .transform();
+ }
+
+ private boolean isNativePcSupported() {
+ return parameters.getApiLevel().isGreaterThanOrEqualTo(apiLevelWithPcAsLineNumberSupport());
+ }
+
+ @Test
+ public void test() throws Exception {
+ MethodReference unusedKeptAndNoLineInfo =
+ Reference.methodFromMethod(TestClass.class.getDeclaredMethod("unusedKeptAndNoLineInfo"));
+
+ // R8 compiles to DEX with pc2pc encoding or native-pc encoding.
+ R8TestCompileResult compileResult =
+ testForR8(parameters.getBackend())
+ .addProgramClassFileData(getTransformedClass())
+ .addKeepMainRule(TestClass.class)
+ .addKeepMethodRules(unusedKeptAndNoLineInfo)
+ .setMinApi(parameters)
+ .addKeepAttributeLineNumberTable()
+ .compile()
+ .inspect(
+ inspector -> {
+ // Expected residual line info of 1 for pc2pc encoding and some value for native.
+ int residualLine = isNativePcSupported() ? 123 : 1;
+ // Check the expected status of the DEX debug info object for the "no lines".
+ MethodSubject methodNoLines = inspector.method(unusedKeptAndNoLineInfo);
+ assertThat(methodNoLines, isPresent());
+ // TODO(b/232212653): This should be true in pc2pc compilation with a single line.
+ assertFalse(methodNoLines.hasLineNumberTable());
+ // Check that "retracing" the pinned method with no lines maps to "noline/zero".
+ RetraceFrameResult retraceResult =
+ inspector
+ .retrace()
+ .retraceFrame(
+ RetraceStackTraceContext.empty(),
+ OptionalInt.of(residualLine),
+ unusedKeptAndNoLineInfo);
+ assertFalse(retraceResult.isAmbiguous());
+ RetraceFrameElement frameElement = retraceResult.stream().findFirst().get();
+ assertEquals(0, frameElement.getOuterFrames().size());
+ RetracedMethodReference topFrame = frameElement.getTopFrame();
+ assertTrue(topFrame.isKnown());
+ // TODO(b/232212653): Retrace should map back to the "no line" value of zero.
+ assertFalse(topFrame.hasPosition());
+ });
+
+ compileResult
+ .run(parameters.getRuntime(), TestClass.class)
+ .assertFailureWithErrorThatThrows(RuntimeException.class)
+ .inspectStackTrace(ComposePcEncodingTest::checkStackTrace);
+
+ Path r8OutputDex = compileResult.writeToZip();
+ Path r8OutputMap =
+ FileUtils.writeTextFile(
+ temp.newFolder().toPath().resolve("out.map"), compileResult.getProguardMap());
+
+ // D8 (re)merges DEX with an artificial jumbo-string to force a remapping of PC values.
+ testForD8(parameters.getBackend())
+ .addProgramFiles(r8OutputDex)
+ .setMinApi(parameters)
+ // We only optimize line info in release mode and with a mapping file output enabled.
+ .release()
+ .internalEnableMappingOutput()
+ .apply(b -> b.getBuilder().setProguardInputMapFile(r8OutputMap))
+ // Forcing jumbo processing will shift the PC values on the methods.
+ .addOptionsModification(o -> o.testing.forceJumboStringProcessing = true)
+ .compile()
+ .run(parameters.getRuntime(), TestClass.class)
+ .assertFailureWithErrorThatThrows(RuntimeException.class)
+ .inspectFailure(
+ inspector -> {
+ MethodSubject methodNoLines = inspector.method(unusedKeptAndNoLineInfo);
+ assertThat(methodNoLines, isPresent());
+ // TODO(b/213411850): This should depend on native pc support.
+ assertTrue(methodNoLines.hasLineNumberTable());
+ })
+ .inspectStackTrace(ComposePcEncodingTest::checkStackTrace);
+ }
+
+ private static void checkStackTrace(StackTrace stackTrace) {
+ StackTraceLine.Builder builder =
+ StackTraceLine.builder()
+ .setClassName(typeName(TestClass.class))
+ .setFileName(TestClass.class.getSimpleName() + ".java");
+ assertThat(
+ stackTrace,
+ StackTrace.isSame(
+ StackTrace.builder()
+ .add(builder.setMethodName("bar").setLineNumber(15).build())
+ .add(builder.setMethodName("main").setLineNumber(25).build())
+ .build()));
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/debuginfo/composepc/TestClass.java b/src/test/java/com/android/tools/r8/debuginfo/composepc/TestClass.java
new file mode 100644
index 0000000..caae028
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/debuginfo/composepc/TestClass.java
@@ -0,0 +1,33 @@
+// 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.debuginfo.composepc;
+
+class TestClass {
+
+ public static void foo() {
+ System.out.println("AAA");
+ }
+
+ public static void bar() {
+ System.out.println("BBB");
+ if (System.nanoTime() > 0) {
+ throw new RuntimeException(); // LINE 15 - update ComposePcEncodingTest if changed.
+ }
+ }
+
+ public static void baz() {
+ System.out.println("CCC");
+ }
+
+ public static void main(String[] args) {
+ foo();
+ bar(); // LINE 25 - update ComposePcEncodingTest if changed.
+ baz();
+ }
+
+ // Line removed by transform.
+ public static void unusedKeptAndNoLineInfo() {
+ System.out.println("DDDD");
+ }
+}
diff --git a/src/test/java/com/android/tools/r8/dex/JumboStringProcessing.java b/src/test/java/com/android/tools/r8/dex/JumboStringProcessing.java
index bf49805..ebf00c9 100644
--- a/src/test/java/com/android/tools/r8/dex/JumboStringProcessing.java
+++ b/src/test/java/com/android/tools/r8/dex/JumboStringProcessing.java
@@ -17,6 +17,7 @@
import com.android.tools.r8.dex.code.DexIfNez;
import com.android.tools.r8.dex.code.DexInstruction;
import com.android.tools.r8.dex.code.DexReturnVoid;
+import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.DexCode;
import com.android.tools.r8.graph.DexCode.Try;
import com.android.tools.r8.graph.DexCode.TryHandler;
@@ -158,6 +159,13 @@
.disableMethodNotNullCheck()
.disableAndroidApiLevelCheck()
.build();
- return new JumboStringRewriter(method, string, factory).rewrite();
+ return new JumboStringRewriter(
+ method,
+ string,
+ () -> {
+ throw new Unreachable();
+ },
+ factory)
+ .rewrite();
}
}