Merge "Only add keep rule when there is a default ctor"
diff --git a/src/main/java/com/android/tools/r8/Version.java b/src/main/java/com/android/tools/r8/Version.java
index c600144..24b2cc9 100644
--- a/src/main/java/com/android/tools/r8/Version.java
+++ b/src/main/java/com/android/tools/r8/Version.java
@@ -11,7 +11,7 @@
 
   // This field is accessed from release scripts using simple pattern matching.
   // Therefore, changing this field could break our release scripts.
-  public static final String LABEL = "1.2.18-dev";
+  public static final String LABEL = "1.2.19-dev";
 
   private Version() {
   }
diff --git a/src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java b/src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java
index bb27c08..ef247a0 100644
--- a/src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java
+++ b/src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java
@@ -390,10 +390,14 @@
         // Compute the final change in locals and insert it before nextInstruction.
         boolean localsChanged = !ending.isEmpty() || !starting.isEmpty();
         if (localsChanged) {
-          DebugLocalsChange change = createLocalsChange(ending, starting);
-          if (change != null) {
-            // Insert the DebugLocalsChange instruction before nextInstruction.
-            instructionIterator.add(change);
+          boolean skipChange =
+              nextInstruction == nextInstruction.getBlock().exit() && nextInstruction.isGoto();
+          if (!skipChange) {
+            DebugLocalsChange change = createLocalsChange(ending, starting);
+            if (change != null) {
+              // Insert the DebugLocalsChange instruction before nextInstruction.
+              instructionIterator.add(change);
+            }
           }
           // Create new maps for the next DebugLocalsChange instruction.
           ending = new Int2ReferenceOpenHashMap<>();
diff --git a/src/test/java/com/android/tools/r8/cf/DebugInfoTestRunner.java b/src/test/java/com/android/tools/r8/cf/DebugInfoTestRunner.java
index d6e0542..ad6a72b 100644
--- a/src/test/java/com/android/tools/r8/cf/DebugInfoTestRunner.java
+++ b/src/test/java/com/android/tools/r8/cf/DebugInfoTestRunner.java
@@ -4,6 +4,7 @@
 package com.android.tools.r8.cf;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 
 import com.android.tools.r8.ClassFileConsumer;
 import com.android.tools.r8.CompilationMode;
@@ -13,6 +14,8 @@
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.ToolHelper;
 import com.android.tools.r8.ToolHelper.ProcessResult;
+import com.android.tools.r8.errors.CompilationError;
+import com.android.tools.r8.errors.InvalidDebugInfoException;
 import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.utils.ThrowingConsumer;
 import java.nio.file.Path;
@@ -33,9 +36,18 @@
     ProcessResult run1 = ToolHelper.runJava(out1, CLASS.getCanonicalName());
     assertEquals(runInput.toString(), run1.toString());
     Path out2 = temp.getRoot().toPath().resolve("out2.zip");
-    build(builder -> builder.addProgramFiles(out1), new ClassFileConsumer.ArchiveConsumer(out2));
-    ProcessResult run2 = ToolHelper.runJava(out2, CLASS.getCanonicalName());
-    assertEquals(runInput.toString(), run2.toString());
+    boolean invalidDebugInfo = false;
+    try {
+      build(builder -> builder.addProgramFiles(out1), new ClassFileConsumer.ArchiveConsumer(out2));
+    } catch (CompilationError e) {
+      invalidDebugInfo = e.getCause() instanceof InvalidDebugInfoException;
+    }
+    // TODO(b/77522100): Change to assertFalse when fixed.
+    assertTrue(invalidDebugInfo);
+    if (!invalidDebugInfo) {
+      ProcessResult run2 = ToolHelper.runJava(out2, CLASS.getCanonicalName());
+      assertEquals(runInput.toString(), run2.toString());
+    }
   }
 
   private void build(ThrowingConsumer<Builder, Exception> input, ProgramConsumer consumer)
diff --git a/src/test/java/com/android/tools/r8/smali/RemoveWriteOfUnusedFieldsTest.java b/src/test/java/com/android/tools/r8/smali/RemoveWriteOfUnusedFieldsTest.java
index 7e03c9d..5270cd4 100644
--- a/src/test/java/com/android/tools/r8/smali/RemoveWriteOfUnusedFieldsTest.java
+++ b/src/test/java/com/android/tools/r8/smali/RemoveWriteOfUnusedFieldsTest.java
@@ -8,6 +8,7 @@
 
 import com.android.tools.r8.OutputMode;
 import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.ToolHelper.DexVm;
 import com.android.tools.r8.graph.DexCode;
 import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.utils.AndroidApp;
@@ -36,6 +37,10 @@
     builder.addStaticField("stringField", "Ljava/lang/String;");
     builder.addStaticField("testField", "LTest;");
 
+    boolean isDalvik = ToolHelper.getDexVm().isOlderThanOrEqual(DexVm.ART_4_4_4_HOST);
+    String additionalConstZero = isDalvik ? "const v0, 0" : "";
+    String additionalConstZeroWide = isDalvik ? "const-wide v0, 0" : "";
+
     builder.addStaticMethod("void", "test", ImmutableList.of(),
         2,
         "const               v0, 0",
@@ -43,7 +48,9 @@
         "sput-byte           v0, LTest;->byteField:B",
         "sput-short          v0, LTest;->shortField:S",
         "sput                v0, LTest;->intField:I",
+        // Dalvik 4.x. does not require a new const 0 here.
         "sput                v0, LTest;->floatField:F",
+        additionalConstZero,  // Required for Dalvik 4.x.
         "sput-char           v0, LTest;->charField:C",
         "const               v0, 0",
         "sput-object         v0, LTest;->objectField:Ljava/lang/Object;",
@@ -51,6 +58,7 @@
         "sput-object         v0, LTest;->testField:LTest;",
         "const-wide          v0, 0",
         "sput-wide           v0, LTest;->longField:J",
+        additionalConstZeroWide,  // Required for Dalvik 4.x.
         "sput-wide           v0, LTest;->doubleField:D",
         "return-void");
 
@@ -95,6 +103,10 @@
     builder.addInstanceField("stringField", "Ljava/lang/String;");
     builder.addInstanceField("testField", "LTest;");
 
+    boolean isDalvik = ToolHelper.getDexVm().isOlderThanOrEqual(DexVm.ART_4_4_4_HOST);
+    String additionalConstZero = isDalvik ? "const v0, 0" : "";
+    String additionalConstZeroWide = isDalvik ? "const-wide v0, 0" : "";
+
     builder.addInstanceMethod("void", "test", ImmutableList.of(),
         2,
         "const               v0, 0",
@@ -102,7 +114,9 @@
         "iput-byte           v0, p0, LTest;->byteField:B",
         "iput-short          v0, p0, LTest;->shortField:S",
         "iput                v0, p0, LTest;->intField:I",
+        // Dalvik 4.x. does not require a new const 0 here.
         "iput                v0, p0, LTest;->floatField:F",
+        additionalConstZero,  // Required for Dalvik 4.x.
         "iput-char           v0, p0, LTest;->charField:C",
         "const               v0, 0",
         "iput-object         v0, p0, LTest;->objectField:Ljava/lang/Object;",
@@ -110,9 +124,15 @@
         "iput-object         v0, p0, LTest;->testField:LTest;",
         "const-wide          v0, 0",
         "iput-wide           v0, p0, LTest;->longField:J",
+        additionalConstZeroWide,  // Required for Dalvik 4.x.
         "iput-wide           v0, p0, LTest;->doubleField:D",
         "return-void");
 
+    builder.addInitializer(ImmutableList.of(), 0,
+        "invoke-direct {p0}, Ljava/lang/Object;-><init>()V",
+        "return-void"
+    );
+
     builder.addMainMethod(
         1,
         "    new-instance         v0, LTest;",