Merge "Enhance visibility check when rebinding fields."
diff --git a/src/main/java/com/android/tools/r8/Version.java b/src/main/java/com/android/tools/r8/Version.java
index 6f062cf..5a0d2c4 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 = "v1.2.4-dev";
+  public static final String LABEL = "v1.2.6-dev";
 
   private Version() {
   }
diff --git a/src/main/java/com/android/tools/r8/cf/CfPrinter.java b/src/main/java/com/android/tools/r8/cf/CfPrinter.java
index 39d916a..181ebac 100644
--- a/src/main/java/com/android/tools/r8/cf/CfPrinter.java
+++ b/src/main/java/com/android/tools/r8/cf/CfPrinter.java
@@ -16,6 +16,9 @@
 import com.android.tools.r8.cf.code.CfConstString;
 import com.android.tools.r8.cf.code.CfFieldInstruction;
 import com.android.tools.r8.cf.code.CfFrame;
+import com.android.tools.r8.cf.code.CfFrame.Uninitialized;
+import com.android.tools.r8.cf.code.CfFrame.UninitializedNew;
+import com.android.tools.r8.cf.code.CfFrame.UninitializedThis;
 import com.android.tools.r8.cf.code.CfGoto;
 import com.android.tools.r8.cf.code.CfIf;
 import com.android.tools.r8.cf.code.CfIfCmp;
@@ -240,7 +243,17 @@
     StringBuilder builder = new StringBuilder("frame: [");
     String separator = "";
     for (Entry<DexType> entry : frame.getLocals().int2ReferenceEntrySet()) {
-      builder.append(separator).append(entry.getIntKey()).append(':').append(entry.getValue());
+      builder.append(separator).append(entry.getIntKey()).append(':');
+      Uninitialized allocator = frame.getAllocators().get(entry.getIntKey());
+      if (allocator == null) {
+        builder.append(entry.getValue());
+      } else if (allocator instanceof UninitializedThis) {
+        builder.append("uninitialized this");
+      } else {
+        builder
+            .append("uninitialized ")
+            .append(getLabel(((UninitializedNew) allocator).getLabel()));
+      }
       separator = ", ";
     }
     builder.append("] ");
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfFrame.java b/src/main/java/com/android/tools/r8/cf/code/CfFrame.java
index 2818e44..b5e759c 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfFrame.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfFrame.java
@@ -17,11 +17,44 @@
 
 public class CfFrame extends CfInstruction {
 
+  public abstract static class Uninitialized {
+    abstract Object getAsmLabel();
+  }
+
+  public static class UninitializedNew extends Uninitialized {
+    private final CfLabel label;
+
+    public UninitializedNew(CfLabel label) {
+      this.label = label;
+    }
+
+    @Override
+    Object getAsmLabel() {
+      return label.getLabel();
+    }
+
+    public CfLabel getLabel() {
+      return label;
+    }
+  }
+
+  public static class UninitializedThis extends Uninitialized {
+    @Override
+    Object getAsmLabel() {
+      return Opcodes.UNINITIALIZED_THIS;
+    }
+  }
+
   private final Int2ReferenceSortedMap<DexType> locals;
+  private final Int2ReferenceSortedMap<Uninitialized> allocators;
   private final List<DexType> stack;
 
-  public CfFrame(Int2ReferenceSortedMap<DexType> locals, List<DexType> stack) {
+  public CfFrame(
+      Int2ReferenceSortedMap<DexType> locals,
+      Int2ReferenceSortedMap<Uninitialized> allocators,
+      List<DexType> stack) {
     this.locals = locals;
+    this.allocators = allocators;
     this.stack = stack;
   }
 
@@ -29,6 +62,10 @@
     return locals;
   }
 
+  public Int2ReferenceSortedMap<Uninitialized> getAllocators() {
+    return allocators;
+  }
+
   public List<DexType> getStack() {
     return stack;
   }
@@ -88,7 +125,8 @@
     int localIndex = 0;
     for (int i = 0; i <= maxRegister; i++) {
       DexType type = locals.get(i);
-      Object typeOpcode = getType(type, lens);
+      Uninitialized allocator = allocators.get(i);
+      Object typeOpcode = allocator == null ? getType(type, lens) : allocator.getAsmLabel();
       localsTypes[localIndex++] = typeOpcode;
       if (type != null && isWide(type)) {
         i++;
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfInvokeDynamic.java b/src/main/java/com/android/tools/r8/cf/code/CfInvokeDynamic.java
index a681943..f830427 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfInvokeDynamic.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfInvokeDynamic.java
@@ -46,8 +46,8 @@
     DexString methodName;
     if (lens.isIdentityLens()) {
       methodName = callSite.methodName;
-    } else if (callSite.interfaceMethod != null) {
-      methodName = lens.lookupName(callSite.interfaceMethod);
+    } else if (!callSite.interfaceMethods.isEmpty()) {
+      methodName = lens.lookupName(callSite.interfaceMethods.get(0));
     } else {
       throw new Unimplemented("Minification of non-lambda InvokeDynamic not supported");
     }
diff --git a/src/main/java/com/android/tools/r8/dexsplitter/DexSplitter.java b/src/main/java/com/android/tools/r8/dexsplitter/DexSplitter.java
index 45a62ef..e3753a7 100644
--- a/src/main/java/com/android/tools/r8/dexsplitter/DexSplitter.java
+++ b/src/main/java/com/android/tools/r8/dexsplitter/DexSplitter.java
@@ -14,6 +14,7 @@
 import com.android.tools.r8.utils.FeatureClassMapping.FeatureMappingException;
 import com.android.tools.r8.utils.OptionsParsing;
 import com.android.tools.r8.utils.OptionsParsing.ParseContext;
+import com.google.common.collect.ImmutableList;
 import java.io.IOException;
 import java.nio.file.Paths;
 import java.util.ArrayList;
@@ -27,40 +28,80 @@
   private static final boolean PRINT_ARGS = false;
 
   public static class Options {
-    List<String> inputArchives = new ArrayList<>();
-    List<String> featureJars = new ArrayList<>();
-    String splitBaseName = DEFAULT_OUTPUT_ARCHIVE_FILENAME;
-    String featureSplitMapping;
-    String proguardMap;
+    private List<String> inputArchives = new ArrayList<>();
+    private List<String> featureJars = new ArrayList<>();
+    private String splitBaseName = DEFAULT_OUTPUT_ARCHIVE_FILENAME;
+    private String featureSplitMapping;
+    private String proguardMap;
+
+    public String getSplitBaseName() {
+      return splitBaseName;
+    }
+
+    public void setSplitBaseName(String splitBaseName) {
+      this.splitBaseName = splitBaseName;
+    }
+
+    public String getFeatureSplitMapping() {
+      return featureSplitMapping;
+    }
+
+    public void setFeatureSplitMapping(String featureSplitMapping) {
+      this.featureSplitMapping = featureSplitMapping;
+    }
+
+    public String getProguardMap() {
+      return proguardMap;
+    }
+
+    public void setProguardMap(String proguardMap) {
+      this.proguardMap = proguardMap;
+    }
+
+    public void addInputArchive(String inputArchive) {
+      inputArchives.add(inputArchive);
+    }
+
+    public void addFeatureJar(String featureJar) {
+      featureJars.add(featureJar);
+    }
+
+    public ImmutableList<String> getInputArchives() {
+      return ImmutableList.copyOf(inputArchives);
+    }
+
+    public ImmutableList<String> getFeatureJars() {
+      return ImmutableList.copyOf(featureJars);
+    }
   }
 
   private static Options parseArguments(String[] args) throws IOException {
     Options options = new Options();
     ParseContext context = new ParseContext(args);
     while (context.head() != null) {
-      List<String> input = OptionsParsing.tryParseMulti(context, "--input");
-      if (input != null) {
-        options.inputArchives.addAll(input);
+      List<String> inputs = OptionsParsing.tryParseMulti(context, "--input");
+      if (inputs != null) {
+        inputs.stream().forEach(options::addInputArchive);
         continue;
       }
       List<String> featureJars = OptionsParsing.tryParseMulti(context, "--feature-jar");
       if (featureJars != null) {
-        options.featureJars.addAll(featureJars);
+        featureJars.stream().forEach(options::addFeatureJar);
         continue;
       }
       String output = OptionsParsing.tryParseSingle(context, "--output", "-o");
       if (output != null) {
-        options.splitBaseName = output;
+        options.setSplitBaseName(output);
         continue;
       }
       String proguardMap = OptionsParsing.tryParseSingle(context, "--proguard-map", null);
       if (proguardMap != null) {
-        options.proguardMap = proguardMap;
+        options.setProguardMap(proguardMap);
         continue;
       }
       String featureSplit = OptionsParsing.tryParseSingle(context, "--feature-splits", null);
       if (featureSplit != null) {
-        options.featureSplitMapping = featureSplit;
+        options.setFeatureSplitMapping(featureSplit);
         continue;
       }
       throw new RuntimeException(String.format("Unknown options: '%s'.", context.head()));
@@ -70,8 +111,8 @@
 
   private static FeatureClassMapping createFeatureClassMapping(Options options)
       throws IOException, FeatureMappingException, ResourceException {
-    if (options.featureSplitMapping != null) {
-      return FeatureClassMapping.fromSpecification(Paths.get(options.featureSplitMapping));
+    if (options.getFeatureSplitMapping() != null) {
+      return FeatureClassMapping.fromSpecification(Paths.get(options.getFeatureSplitMapping()));
     }
     assert !options.featureJars.isEmpty();
     return FeatureClassMapping.fromJarFiles(options.featureJars);
@@ -87,13 +128,13 @@
   public static void run(Options options)
       throws IOException, FeatureMappingException, ResourceException, CompilationException,
       ExecutionException, CompilationFailedException {
-    if (options.inputArchives.isEmpty()) {
+    if (options.getInputArchives().isEmpty()) {
       throw new RuntimeException("Need at least one --input");
     }
-    if (options.featureSplitMapping == null && options.featureJars.isEmpty()) {
+    if (options.getFeatureSplitMapping() == null && options.getFeatureJars().isEmpty()) {
       throw new RuntimeException("You must supply a feature split mapping or feature jars");
     }
-    if (options.featureSplitMapping != null && !options.featureJars.isEmpty()) {
+    if (options.getFeatureSplitMapping() != null && !options.getFeatureJars().isEmpty()) {
       throw new RuntimeException("You can't supply both a feature split mapping and feature jars");
     }
 
@@ -108,7 +149,7 @@
     FeatureClassMapping featureClassMapping = createFeatureClassMapping(options);
 
     DexSplitterHelper.run(
-        builder.build(), featureClassMapping, options.splitBaseName, options.proguardMap);
+        builder.build(), featureClassMapping, options.getSplitBaseName(), options.getProguardMap());
   }
 
   public static void main(String[] args) {
diff --git a/src/main/java/com/android/tools/r8/graph/DexCallSite.java b/src/main/java/com/android/tools/r8/graph/DexCallSite.java
index 9e22713..ac954f8 100644
--- a/src/main/java/com/android/tools/r8/graph/DexCallSite.java
+++ b/src/main/java/com/android/tools/r8/graph/DexCallSite.java
@@ -29,22 +29,27 @@
   public final DexMethodHandle bootstrapMethod;
   public final List<DexValue> bootstrapArgs;
 
-  public final DexMethod interfaceMethod;
+  public final List<DexMethod> interfaceMethods;
 
   private DexEncodedArray encodedArray = null;
 
-  DexCallSite(DexString methodName, DexProto methodProto,
-      DexMethodHandle bootstrapMethod, List<DexValue> bootstrapArgs, DexMethod interfaceMethod) {
+  DexCallSite(
+      DexString methodName,
+      DexProto methodProto,
+      DexMethodHandle bootstrapMethod,
+      List<DexValue> bootstrapArgs,
+      List<DexMethod> interfaceMethods) {
     assert methodName != null;
     assert methodProto != null;
     assert bootstrapMethod != null;
     assert bootstrapArgs != null;
+    assert interfaceMethods != null;
 
     this.methodName = methodName;
     this.methodProto = methodProto;
     this.bootstrapMethod = bootstrapMethod;
     this.bootstrapArgs = bootstrapArgs;
-    this.interfaceMethod = interfaceMethod;
+    this.interfaceMethods = interfaceMethods;
   }
 
   public static DexCallSite fromAsmInvokeDynamic(
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 75f2ee8..5fe9134 100644
--- a/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
+++ b/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
@@ -17,6 +17,7 @@
 import com.android.tools.r8.graph.DexMethodHandle.MethodHandleType;
 import com.android.tools.r8.graph.DexValue.DexValueMethodType;
 import com.android.tools.r8.ir.code.Position;
+import com.android.tools.r8.ir.desugar.LambdaDescriptor;
 import com.android.tools.r8.kotlin.Kotlin;
 import com.android.tools.r8.naming.NamingLens;
 import com.google.common.base.Strings;
@@ -26,6 +27,7 @@
 import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.IdentityHashMap;
 import java.util.List;
@@ -228,6 +230,33 @@
   public final DexType annotationSynthesizedClassMap =
       createType("Lcom/android/tools/r8/annotations/SynthesizedClassMap;");
 
+  private static final String METAFACTORY_METHOD_NAME = "metafactory";
+  private static final String METAFACTORY_ALT_METHOD_NAME = "altMetafactory";
+
+  public final DexType metafactoryType = createType("Ljava/lang/invoke/LambdaMetafactory;");
+  public final DexType callSiteType = createType("Ljava/lang/invoke/CallSite;");
+  public final DexType lookupType = createType("Ljava/lang/invoke/MethodHandles$Lookup;");
+  public final DexType serializableType = createType("Ljava/io/Serializable;");
+
+  public final DexMethod metafactoryMethod =
+      createMethod(
+          metafactoryType,
+          createProto(
+              callSiteType,
+              lookupType,
+              stringType,
+              methodTypeType,
+              methodTypeType,
+              methodHandleType,
+              methodTypeType),
+          createString(METAFACTORY_METHOD_NAME));
+
+  public final DexMethod metafactoryAltMethod =
+      createMethod(
+          metafactoryType,
+          createProto(callSiteType, lookupType, stringType, methodTypeType, objectArrayType),
+          createString(METAFACTORY_ALT_METHOD_NAME));
+
   private boolean skipNameValidationForTesting = false;
 
   public void setSkipNameValidationForTesting(boolean skipNameValidationForTesting) {
@@ -545,23 +574,46 @@
       DexString methodName, DexProto methodProto,
       DexMethodHandle bootstrapMethod, List<DexValue> bootstrapArgs) {
     assert !sorted;
-    String bootstrapClass = bootstrapMethod.asMethod().holder.toDescriptorString();
-    DexMethod interfaceMethod = null;
-    if (bootstrapClass.equals("Ljava/lang/invoke/LambdaMetafactory;")) {
-      if (methodName.toString().equals("metafactory")) {
-        DexType interfaceType = methodProto.returnType;
-        assert bootstrapArgs.size() == 3;
-        // bootstrapArgs contains samMethodType, implMethod and instantiatedMethodType.
-        DexValueMethodType samMethodType = (DexValueMethodType) bootstrapArgs.get(0);
-        interfaceMethod = createMethod(interfaceType, samMethodType.value, methodName);
-      }
-      // TODO(mathiasr): Support altMetafactory, possibly using ir.desugar.LambdaDescriptor
-    }
+    List<DexMethod> interfaceMethods =
+        getCallSiteInterfaceMethods(methodName, methodProto, bootstrapMethod, bootstrapArgs);
     DexCallSite callSite =
-        new DexCallSite(methodName, methodProto, bootstrapMethod, bootstrapArgs, interfaceMethod);
+        new DexCallSite(methodName, methodProto, bootstrapMethod, bootstrapArgs, interfaceMethods);
     return canonicalize(callSites, callSite);
   }
 
+  private List<DexMethod> getCallSiteInterfaceMethods(
+      DexString methodName,
+      DexProto methodProto,
+      DexMethodHandle bootstrapMethodHandle,
+      List<DexValue> bootstrapArgs) {
+    // TODO(mathiasr): Unify this with LambdaDescriptor.infer().
+    if (!bootstrapMethodHandle.type.isInvokeStatic()) {
+      return Collections.emptyList();
+    }
+    DexMethod bootstrapMethod = bootstrapMethodHandle.asMethod();
+    if (bootstrapMethod != metafactoryMethod && bootstrapMethod != metafactoryAltMethod) {
+      return Collections.emptyList();
+    }
+    DexType interfaceType = methodProto.returnType;
+    assert bootstrapMethod == metafactoryAltMethod || bootstrapArgs.size() == 3;
+    // Signature of main functional interface method.
+    // In Java docs, this argument is named 'samMethodType'.
+    DexValueMethodType funcErasedSignature = (DexValueMethodType) bootstrapArgs.get(0);
+    DexMethod mainMethod = createMethod(interfaceType, funcErasedSignature.value, methodName);
+    if (bootstrapMethod == metafactoryAltMethod) {
+      List<DexMethod> result = new ArrayList<>();
+      result.add(mainMethod);
+      LambdaDescriptor.extractAltMetafactory(
+          this,
+          bootstrapArgs,
+          type -> result.add(createMethod(type, funcErasedSignature.value, methodName)),
+          bridge -> {});
+      return result;
+    } else {
+      return Collections.singletonList(mainMethod);
+    }
+  }
+
   public DexMethod createMethod(DexString clazzDescriptor, DexString name,
       DexString returnTypeDescriptor,
       DexString[] parameterDescriptors) {
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/CfBuilder.java b/src/main/java/com/android/tools/r8/ir/conversion/CfBuilder.java
index 7c04392..8dd9162 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/CfBuilder.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/CfBuilder.java
@@ -7,6 +7,9 @@
 import com.android.tools.r8.cf.LoadStoreHelper;
 import com.android.tools.r8.cf.TypeVerificationHelper;
 import com.android.tools.r8.cf.code.CfFrame;
+import com.android.tools.r8.cf.code.CfFrame.Uninitialized;
+import com.android.tools.r8.cf.code.CfFrame.UninitializedNew;
+import com.android.tools.r8.cf.code.CfFrame.UninitializedThis;
 import com.android.tools.r8.cf.code.CfInstruction;
 import com.android.tools.r8.cf.code.CfLabel;
 import com.android.tools.r8.cf.code.CfPosition;
@@ -28,8 +31,10 @@
 import com.android.tools.r8.ir.code.Instruction;
 import com.android.tools.r8.ir.code.InstructionIterator;
 import com.android.tools.r8.ir.code.InstructionListIterator;
+import com.android.tools.r8.ir.code.InvokeDirect;
 import com.android.tools.r8.ir.code.JumpInstruction;
 import com.android.tools.r8.ir.code.Load;
+import com.android.tools.r8.ir.code.NewInstance;
 import com.android.tools.r8.ir.code.Position;
 import com.android.tools.r8.ir.code.StackValue;
 import com.android.tools.r8.ir.code.Store;
@@ -42,9 +47,11 @@
 import it.unimi.dsi.fastutil.ints.Int2ReferenceMap.Entry;
 import it.unimi.dsi.fastutil.ints.Int2ReferenceOpenHashMap;
 import it.unimi.dsi.fastutil.ints.Int2ReferenceSortedMap;
+import java.util.ArrayDeque;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Deque;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
@@ -77,6 +84,10 @@
 
   private AppInfoWithSubtyping appInfo;
 
+  private Map<NewInstance, List<InvokeDirect>> initializers;
+  private List<InvokeDirect> thisInitializers;
+  private Map<NewInstance, CfLabel> newInstanceLabels;
+
   // Internal abstraction of the stack values and height.
   private static class Stack {
     int maxHeight = 0;
@@ -110,6 +121,7 @@
 
   public CfCode build(
       CodeRewriter rewriter, InternalOptions options, AppInfoWithSubtyping appInfo) {
+    computeInitializers();
     types = new TypeVerificationHelper(code, factory, appInfo).computeVerificationTypes();
     splitExceptionalBlocks();
     LoadStoreHelper loadStoreHelper = new LoadStoreHelper(code, types);
@@ -133,6 +145,39 @@
     return resolvedField == null ? field : resolvedField.field;
   }
 
+  private void computeInitializers() {
+    assert initializers == null;
+    assert thisInitializers == null;
+    initializers = new HashMap<>();
+    for (BasicBlock block : code.blocks) {
+      for (Instruction insn : block.getInstructions()) {
+        if (insn.isNewInstance()) {
+          initializers.put(insn.asNewInstance(), computeInitializers(insn.outValue()));
+        } else if (insn.isArgument() && method.isInstanceInitializer()) {
+          if (insn.outValue().isThis()) {
+            // By JVM8 §4.10.1.9 (invokespecial), a this() or super() call in a constructor
+            // changes the type of `this` from uninitializedThis
+            // to the type of the class of the <init> method.
+            thisInitializers = computeInitializers(insn.outValue());
+          }
+        }
+      }
+    }
+    assert !(method.isInstanceInitializer() && thisInitializers == null);
+  }
+
+  private List<InvokeDirect> computeInitializers(Value value) {
+    List<InvokeDirect> initializers = new ArrayList<>();
+    for (Instruction user : value.uniqueUsers()) {
+      if (user instanceof InvokeDirect
+          && user.inValues().get(0) == value
+          && user.asInvokeDirect().getInvokedMethod().name == factory.constructorMethodName) {
+        initializers.add(user.asInvokeDirect());
+      }
+    }
+    return initializers;
+  }
+
   // Split all blocks with throwing instructions and exceptional edges such that any non-throwing
   // instructions that might define values prior to the throwing exception are excluded from the
   // try-catch range. Failure to do so will result in code that does not verify on the JVM.
@@ -203,6 +248,7 @@
     List<CfTryCatch> tryCatchRanges = new ArrayList<>();
     labels = new HashMap<>(code.blocks.size());
     emittedLabels = new HashSet<>(code.blocks.size());
+    newInstanceLabels = new HashMap<>(initializers.size());
     instructions = new ArrayList<>();
     ListIterator<BasicBlock> blockIterator = code.listIterator();
     BasicBlock block = blockIterator.next();
@@ -211,6 +257,7 @@
     BasicBlock pendingFrame = null;
     boolean previousFallthrough = false;
     do {
+      assert stack.isEmpty();
       CatchHandlers<BasicBlock> handlers = block.getCatchHandlers();
       if (!tryCatchHandlers.equals(handlers)) {
         if (!tryCatchHandlers.isEmpty()) {
@@ -230,7 +277,6 @@
       // If previousBlock is fallthrough, then it is counted in getPredecessors().size(), but
       // we only want to set a pendingFrame if we have a predecessor which is not previousBlock.
       if (block.getPredecessors().size() > (previousFallthrough ? 1 : 0)) {
-        assert stack.isEmpty();
         pendingFrame = block;
         emitLabel(getLabel(block));
       }
@@ -318,6 +364,9 @@
           pendingLocalChanges = true;
         }
       } else {
+        if (instruction.isNewInstance()) {
+          newInstanceLabels.put(instruction.asNewInstance(), ensureLabel());
+        }
         updatePositionAndLocals(instruction);
         instruction.buildCf(this);
       }
@@ -400,9 +449,11 @@
 
     Collection<Value> locals = registerAllocator.getLocalsAtBlockEntry(block);
     Int2ReferenceSortedMap<DexType> mapping = new Int2ReferenceAVLTreeMap<>();
+    Int2ReferenceSortedMap<Uninitialized> allocators = new Int2ReferenceAVLTreeMap<>();
 
     for (Value local : locals) {
       DexType type;
+      Uninitialized allocator = null;
       switch (local.outType()) {
         case INT:
           type = factory.intType;
@@ -418,14 +469,64 @@
           break;
         case OBJECT:
           type = types.get(local);
+          allocator = findAllocator(block, local);
           break;
         default:
           throw new Unreachable(
               "Unexpected local type: " + local.outType() + " for local: " + local);
       }
       mapping.put(getLocalRegister(local), type);
+      if (allocator != null) {
+        allocators.put(getLocalRegister(local), allocator);
+      }
     }
-    instructions.add(new CfFrame(mapping, stackTypes));
+    instructions.add(new CfFrame(mapping, allocators, stackTypes));
+  }
+
+  private Uninitialized findAllocator(BasicBlock liveBlock, Value value) {
+    Instruction definition = value.definition;
+    while (definition != null && (definition.isStore() || definition.isLoad())) {
+      definition = definition.inValues().get(0).definition;
+    }
+    if (definition == null) {
+      return null;
+    }
+    Uninitialized res;
+    if (definition.isNewInstance()) {
+      res = new UninitializedNew(newInstanceLabels.get(definition.asNewInstance()));
+    } else if (definition.isArgument()
+        && method.isInstanceInitializer()
+        && definition.outValue().isThis()) {
+      res = new UninitializedThis();
+    } else {
+      return null;
+    }
+    BasicBlock definitionBlock = definition.getBlock();
+    Set<BasicBlock> visited = new HashSet<>();
+    Deque<BasicBlock> toVisit = new ArrayDeque<>();
+    List<InvokeDirect> valueInitializers =
+        definition.isArgument() ? thisInitializers : initializers.get(definition.asNewInstance());
+    for (InvokeDirect initializer : valueInitializers) {
+      BasicBlock initializerBlock = initializer.getBlock();
+      if (initializerBlock == liveBlock) {
+        return res;
+      }
+      if (initializerBlock != definitionBlock && visited.add(initializerBlock)) {
+        toVisit.addLast(initializerBlock);
+      }
+    }
+    while (!toVisit.isEmpty()) {
+      BasicBlock block = toVisit.removeLast();
+      for (BasicBlock predecessor : block.getPredecessors()) {
+        if (predecessor == liveBlock) {
+          return res;
+        }
+        if (predecessor != definitionBlock && visited.add(predecessor)) {
+          toVisit.addLast(predecessor);
+        }
+      }
+    }
+    return null;
   }
 
   private void emitLabel(CfLabel label) {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/LambdaDescriptor.java b/src/main/java/com/android/tools/r8/ir/desugar/LambdaDescriptor.java
index 5d52523..49a797a 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/LambdaDescriptor.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/LambdaDescriptor.java
@@ -21,9 +21,10 @@
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Set;
+import java.util.function.Consumer;
 
 // Represents the lambda descriptor inferred from calls site.
-final class LambdaDescriptor {
+public final class LambdaDescriptor {
   private static final int LAMBDA_ALT_SERIALIZABLE = 1;
   private static final int LAMBDA_ALT_HAS_EXTRA_INTERFACES = 2;
   private static final int LAMBDA_ALT_HAS_BRIDGES = 4;
@@ -227,8 +228,8 @@
     }
 
     DexMethod bootstrapMethod = callSite.bootstrapMethod.asMethod();
-    boolean isMetafactoryMethod = bootstrapMethod == rewriter.metafactoryMethod;
-    boolean isAltMetafactoryMethod = bootstrapMethod == rewriter.metafactoryAltMethod;
+    boolean isMetafactoryMethod = bootstrapMethod == rewriter.factory.metafactoryMethod;
+    boolean isAltMetafactoryMethod = bootstrapMethod == rewriter.factory.metafactoryAltMethod;
     if (!isMetafactoryMethod && !isAltMetafactoryMethod) {
       // It is not a lambda, thus no need to manage this call site.
       return LambdaDescriptor.MATCH_FAILED;
@@ -240,18 +241,18 @@
 
     // Signature of main functional interface method.
     DexValue.DexValueMethodType funcErasedSignature =
-        getBootstrapArgument(callSite, 0, DexValue.DexValueMethodType.class);
+        getBootstrapArgument(callSite.bootstrapArgs, 0, DexValue.DexValueMethodType.class);
 
     // Method handle of the implementation method.
     DexMethodHandle lambdaImplMethodHandle =
-        getBootstrapArgument(callSite, 1, DexValue.DexValueMethodHandle.class).value;
+        getBootstrapArgument(callSite.bootstrapArgs, 1, DexValue.DexValueMethodHandle.class).value;
     // Even though there are some limitations on which method handle kinds are
     // allowed for lambda impl-methods, there is no way to detect unsupported
     // handle kinds after they are transformed into DEX method handle.
 
     // Signature to be enforced on main method.
     DexValue.DexValueMethodType funcEnforcedSignature =
-        getBootstrapArgument(callSite, 2, DexValue.DexValueMethodType.class);
+        getBootstrapArgument(callSite.bootstrapArgs, 2, DexValue.DexValueMethodType.class);
     if (!isEnforcedSignatureValid(
         rewriter, funcEnforcedSignature.value, funcErasedSignature.value)) {
       throw new Unreachable(
@@ -277,67 +278,70 @@
             "Unexpected number of metafactory method arguments in " + callSite.toString());
       }
     } else {
-      extractExtraLambdaInfo(rewriter, callSite, match);
+      extractAltMetafactory(
+          rewriter.factory,
+          callSite.bootstrapArgs,
+          interfaceType -> {
+            if (!match.interfaces.contains(interfaceType)) {
+              match.interfaces.add(interfaceType);
+            }
+          },
+          match.bridges::add);
     }
 
     return match;
   }
 
-  private static void extractExtraLambdaInfo(
-      LambdaRewriter rewriter, DexCallSite callSite, LambdaDescriptor match) {
+  public static void extractAltMetafactory(
+      DexItemFactory dexItemFactory,
+      List<DexValue> bootstrapArgs,
+      Consumer<DexType> interfaceConsumer,
+      Consumer<DexProto> bridgeConsumer) {
     int argIndex = 3;
-    int flagsArg = getBootstrapArgument(
-        callSite, argIndex++, DexValue.DexValueInt.class).value;
+    int flagsArg =
+        getBootstrapArgument(bootstrapArgs, argIndex++, DexValue.DexValueInt.class).value;
     assert (flagsArg & ~LAMBDA_ALT_MASK) == 0;
 
     // Load extra interfaces if any.
     if ((flagsArg & LAMBDA_ALT_HAS_EXTRA_INTERFACES) != 0) {
-      int count = getBootstrapArgument(
-          callSite, argIndex++, DexValue.DexValueInt.class).value;
+      int count = getBootstrapArgument(bootstrapArgs, argIndex++, DexValue.DexValueInt.class).value;
       for (int i = 0; i < count; i++) {
-        DexType type = getBootstrapArgument(
-            callSite, argIndex++, DexValue.DexValueType.class).value;
-        if (!match.interfaces.contains(type)) {
-          match.interfaces.add(type);
-        }
+        DexType interfaceType =
+            getBootstrapArgument(bootstrapArgs, argIndex++, DexValue.DexValueType.class).value;
+        interfaceConsumer.accept(interfaceType);
       }
     }
 
     // If the lambda is serializable, add it.
     if ((flagsArg & LAMBDA_ALT_SERIALIZABLE) != 0) {
-      if (!match.interfaces.contains(rewriter.serializableType)) {
-        match.interfaces.add(rewriter.serializableType);
-      }
+      interfaceConsumer.accept(dexItemFactory.serializableType);
     }
 
     // Load bridges if any.
     if ((flagsArg & LAMBDA_ALT_HAS_BRIDGES) != 0) {
-      int count = getBootstrapArgument(
-          callSite, argIndex++, DexValue.DexValueInt.class).value;
+      int count = getBootstrapArgument(bootstrapArgs, argIndex++, DexValue.DexValueInt.class).value;
       for (int i = 0; i < count; i++) {
-        DexProto bridgeProto = getBootstrapArgument(
-            callSite, argIndex++, DexValue.DexValueMethodType.class).value;
-        match.bridges.add(bridgeProto);
+        DexProto bridgeProto =
+            getBootstrapArgument(bootstrapArgs, argIndex++, DexValue.DexValueMethodType.class)
+                .value;
+        bridgeConsumer.accept(bridgeProto);
       }
     }
 
-    if (callSite.bootstrapArgs.size() != argIndex) {
-      throw new Unreachable(
-          "Unexpected number of metafactory method arguments in " + callSite.toString());
+    if (bootstrapArgs.size() != argIndex) {
+      throw new Unreachable("Unexpected number of metafactory method arguments in DexCallSite");
     }
   }
 
   @SuppressWarnings("unchecked")
-  private static <T> T getBootstrapArgument(DexCallSite callSite, int i, Class<T> clazz) {
-    List<DexValue> bootstrapArgs = callSite.bootstrapArgs;
+  private static <T> T getBootstrapArgument(List<DexValue> bootstrapArgs, int i, Class<T> clazz) {
     if (bootstrapArgs.size() < i) {
-      throw new Unreachable("Expected to find at least "
-          + i + " bootstrap arguments in " + callSite.toString());
+      throw new Unreachable(
+          "Expected to find at least " + i + " bootstrap arguments in DexCallSite");
     }
     DexValue value = bootstrapArgs.get(i);
     if (!clazz.isAssignableFrom(value.getClass())) {
-      throw new Unreachable("Unexpected type of "
-          + "bootstrap arguments #" + i + " in " + callSite.toString());
+      throw new Unreachable("Unexpected type of bootstrap arguments #" + i + " in DexCallSite");
     }
     return (T) value;
   }
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/LambdaRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/LambdaRewriter.java
index aad7961..82792df 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/LambdaRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/LambdaRewriter.java
@@ -41,16 +41,8 @@
  * lambda class generation, and instruction patching.
  */
 public class LambdaRewriter {
-  private static final String METAFACTORY_TYPE_DESCR = "Ljava/lang/invoke/LambdaMetafactory;";
-  private static final String CALLSITE_TYPE_DESCR = "Ljava/lang/invoke/CallSite;";
-  private static final String LOOKUP_TYPE_DESCR = "Ljava/lang/invoke/MethodHandles$Lookup;";
-  private static final String METHODTYPE_TYPE_DESCR = "Ljava/lang/invoke/MethodType;";
-  private static final String METHODHANDLE_TYPE_DESCR = "Ljava/lang/invoke/MethodHandle;";
-  private static final String SERIALIZABLE_TYPE_DESCR = "Ljava/io/Serializable;";
   private static final String SERIALIZED_LAMBDA_TYPE_DESCR = "Ljava/lang/invoke/SerializedLambda;";
 
-  private static final String METAFACTORY_METHOD_NAME = "metafactory";
-  private static final String METAFACTORY_ALT_METHOD_NAME = "altMetafactory";
   private static final String DESERIALIZE_LAMBDA_METHOD_NAME = "$deserializeLambda$";
 
   // Public for testing.
@@ -62,12 +54,8 @@
   final AppInfo appInfo;
   final DexItemFactory factory;
 
-  final DexMethod metafactoryMethod;
   final DexMethod objectInitMethod;
 
-  final DexMethod metafactoryAltMethod;
-  final DexType serializableType;
-
   final DexString constructorName;
   final DexString classConstructorName;
   final DexString instanceFieldName;
@@ -97,28 +85,11 @@
     this.factory = converter.appInfo.dexItemFactory;
     this.appInfo = converter.appInfo;
 
-    DexType metafactoryType = factory.createType(METAFACTORY_TYPE_DESCR);
-    DexType callSiteType = factory.createType(CALLSITE_TYPE_DESCR);
-    DexType lookupType = factory.createType(LOOKUP_TYPE_DESCR);
-    DexType methodTypeType = factory.createType(METHODTYPE_TYPE_DESCR);
-    DexType methodHandleType = factory.createType(METHODHANDLE_TYPE_DESCR);
-
-    this.metafactoryMethod = factory.createMethod(metafactoryType,
-        factory.createProto(callSiteType, lookupType, factory.stringType, methodTypeType,
-            methodTypeType, methodHandleType, methodTypeType),
-        factory.createString(METAFACTORY_METHOD_NAME));
-
-    this.metafactoryAltMethod = factory.createMethod(metafactoryType,
-        factory.createProto(callSiteType, lookupType, factory.stringType, methodTypeType,
-            factory.objectArrayType),
-        factory.createString(METAFACTORY_ALT_METHOD_NAME));
-
     this.constructorName = factory.createString(Constants.INSTANCE_INITIALIZER_NAME);
     DexProto initProto = factory.createProto(factory.voidType);
     this.objectInitMethod = factory.createMethod(factory.objectType, initProto, constructorName);
     this.classConstructorName = factory.createString(Constants.CLASS_INITIALIZER_NAME);
     this.instanceFieldName = factory.createString(LAMBDA_INSTANCE_FIELD_NAME);
-    this.serializableType = factory.createType(SERIALIZABLE_TYPE_DESCR);
 
     this.deserializeLambdaMethodName = factory.createString(DESERIALIZE_LAMBDA_METHOD_NAME);
     this.deserializeLambdaMethodProto = factory.createProto(
diff --git a/src/main/java/com/android/tools/r8/naming/MethodNameMinifier.java b/src/main/java/com/android/tools/r8/naming/MethodNameMinifier.java
index ce37763..25a84b6 100644
--- a/src/main/java/com/android/tools/r8/naming/MethodNameMinifier.java
+++ b/src/main/java/com/android/tools/r8/naming/MethodNameMinifier.java
@@ -12,7 +12,6 @@
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.shaking.RootSetBuilder.RootSet;
 import com.android.tools.r8.utils.InternalOptions;
-import com.android.tools.r8.utils.MethodJavaSignatureEquivalence;
 import com.android.tools.r8.utils.MethodSignatureEquivalence;
 import com.android.tools.r8.utils.Timing;
 import com.google.common.base.Equivalence;
@@ -88,13 +87,10 @@
  */
 class MethodNameMinifier extends MemberNameMinifier<DexMethod, DexProto> {
 
-  private final Equivalence<DexMethod> equivalence;
+  private final Equivalence<DexMethod> equivalence = MethodSignatureEquivalence.get();
 
   MethodNameMinifier(AppInfoWithSubtyping appInfo, RootSet rootSet, InternalOptions options) {
     super(appInfo, rootSet, options);
-    equivalence = overloadAggressively
-        ? MethodSignatureEquivalence.get()
-        : MethodJavaSignatureEquivalence.get();
   }
 
   @Override
diff --git a/src/test/java/com/android/tools/r8/cf/UninitializedInFrameDump.java b/src/test/java/com/android/tools/r8/cf/UninitializedInFrameDump.java
new file mode 100644
index 0000000..bac896e
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/cf/UninitializedInFrameDump.java
@@ -0,0 +1,179 @@
+// Copyright (c) 2018, 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.cf;
+
+import java.util.*;
+import org.objectweb.asm.*;
+
+public class UninitializedInFrameDump implements Opcodes {
+
+  public static byte[] dump() throws Exception {
+
+    ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
+    FieldVisitor fv;
+    MethodVisitor mv;
+    AnnotationVisitor av0;
+
+    cw.visit(
+        V1_8,
+        ACC_PUBLIC + ACC_SUPER,
+        "com/android/tools/r8/cf/UninitializedInFrameTest",
+        null,
+        "java/lang/Object",
+        null);
+
+    // The constructor UninitializedInFrameTest(int i) has been modified
+    // to add a jump back to the entry block.
+    {
+      mv = cw.visitMethod(ACC_PUBLIC, "<init>", "(I)V", null, null);
+      mv.visitCode();
+      Label l = new Label(); // Added
+      mv.visitLabel(l); // Added
+      mv.visitVarInsn(ALOAD, 0);
+      mv.visitVarInsn(ILOAD, 1);
+      mv.visitInsn(ICONST_1);
+      mv.visitInsn(ISUB);
+      mv.visitInsn(DUP); // Added
+      mv.visitIntInsn(BIPUSH, 42);
+      Label l0 = new Label();
+      mv.visitJumpInsn(IF_ICMPLT, l0);
+      // mv.visitInsn(ICONST_1);
+      mv.visitVarInsn(ISTORE, 1); // Added
+      mv.visitInsn(POP); // Added
+      mv.visitJumpInsn(GOTO, l); // Added
+      Label l1 = new Label();
+      mv.visitJumpInsn(GOTO, l1);
+      mv.visitLabel(l0);
+      mv.visitInsn(POP); // Added
+      mv.visitInsn(ICONST_0);
+      mv.visitLabel(l1);
+      mv.visitMethodInsn(
+          INVOKESPECIAL,
+          "com/android/tools/r8/cf/UninitializedInFrameTest",
+          "<init>",
+          "(Z)V",
+          false);
+      mv.visitInsn(RETURN);
+      mv.visitMaxs(-1, -1);
+      // mv.visitMaxs(3, 2);
+      mv.visitEnd();
+    }
+    {
+      mv = cw.visitMethod(ACC_PRIVATE, "<init>", "(Z)V", null, null);
+      mv.visitCode();
+      mv.visitVarInsn(ALOAD, 0);
+      mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
+      mv.visitInsn(RETURN);
+      mv.visitMaxs(-1, -1);
+      // mv.visitMaxs(1, 2);
+      mv.visitEnd();
+    }
+    {
+      mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "main", "([Ljava/lang/String;)V", null, null);
+      mv.visitCode();
+      mv.visitVarInsn(ALOAD, 0);
+      mv.visitInsn(ARRAYLENGTH);
+      Label l0 = new Label();
+      mv.visitJumpInsn(IFEQ, l0);
+      mv.visitTypeInsn(NEW, "java/lang/RuntimeException");
+      mv.visitInsn(DUP);
+      mv.visitVarInsn(ALOAD, 0);
+      mv.visitInsn(ARRAYLENGTH);
+      mv.visitIntInsn(BIPUSH, 42);
+      Label l1 = new Label();
+      mv.visitJumpInsn(IF_ICMPNE, l1);
+      // mv.visitTypeInsn(NEW, "java/lang/RuntimeException");
+      // mv.visitInsn(DUP);
+      mv.visitTypeInsn(NEW, "java/lang/IllegalArgumentException");
+      mv.visitInsn(DUP);
+      mv.visitMethodInsn(
+          INVOKESPECIAL, "java/lang/IllegalArgumentException", "<init>", "()V", false);
+      mv.visitMethodInsn(
+          INVOKESPECIAL, "java/lang/RuntimeException", "<init>", "(Ljava/lang/Throwable;)V", false);
+      mv.visitVarInsn(ASTORE, 1);
+      // At this point, stack is empty.
+      Label l2 = new Label();
+      mv.visitJumpInsn(GOTO, l2);
+      mv.visitLabel(l1);
+      // At this point, stack contains two copies of uninitialized RuntimeException.
+      // mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
+      // mv.visitTypeInsn(NEW, "java/lang/RuntimeException");
+      // mv.visitInsn(DUP);
+      mv.visitTypeInsn(NEW, "java/lang/StringBuilder");
+      mv.visitInsn(DUP);
+      mv.visitMethodInsn(INVOKESPECIAL, "java/lang/StringBuilder", "<init>", "()V", false);
+      mv.visitLdcInsn("You supplied ");
+      mv.visitMethodInsn(
+          INVOKEVIRTUAL,
+          "java/lang/StringBuilder",
+          "append",
+          "(Ljava/lang/String;)Ljava/lang/StringBuilder;",
+          false);
+      mv.visitVarInsn(ALOAD, 0);
+      mv.visitInsn(ARRAYLENGTH);
+      mv.visitMethodInsn(
+          INVOKEVIRTUAL,
+          "java/lang/StringBuilder",
+          "append",
+          "(I)Ljava/lang/StringBuilder;",
+          false);
+      mv.visitVarInsn(ALOAD, 0);
+      mv.visitInsn(ARRAYLENGTH);
+      mv.visitInsn(ICONST_1);
+      Label l3 = new Label();
+      mv.visitJumpInsn(IF_ICMPNE, l3);
+      mv.visitLdcInsn(" arg");
+      Label l4 = new Label();
+      mv.visitJumpInsn(GOTO, l4);
+      mv.visitLabel(l3);
+      // At this point, stack contains two copies of uninitialized RuntimeException.
+      // Note that asmifier seems to produce incorrect labels for the uninitialized type.
+      // mv.visitFrame(Opcodes.F_FULL, 1, new Object[] {"[Ljava/lang/String;"}, 3, new Object[] {l1,
+      // l1, "java/lang/StringBuilder"});
+      mv.visitLdcInsn(" args");
+      mv.visitLabel(l4);
+      // At this point, stack contains two copies of uninitialized RuntimeException.
+      // mv.visitFrame(Opcodes.F_FULL, 1, new Object[] {"[Ljava/lang/String;"}, 4, new Object[] {l1,
+      // l1, "java/lang/StringBuilder", "java/lang/String"});
+      mv.visitMethodInsn(
+          INVOKEVIRTUAL,
+          "java/lang/StringBuilder",
+          "append",
+          "(Ljava/lang/String;)Ljava/lang/StringBuilder;",
+          false);
+      mv.visitMethodInsn(
+          INVOKEVIRTUAL, "java/lang/StringBuilder", "toString", "()Ljava/lang/String;", false);
+      mv.visitMethodInsn(
+          INVOKESPECIAL, "java/lang/RuntimeException", "<init>", "(Ljava/lang/String;)V", false);
+      mv.visitVarInsn(ASTORE, 1);
+      mv.visitLabel(l2);
+      // At this point, stack is empty, and local 1 contains an initialized RuntimeException.
+      // mv.visitFrame(Opcodes.F_APPEND,1, new Object[] {"java/lang/RuntimeException"}, 0, null);
+      mv.visitVarInsn(ALOAD, 0);
+      mv.visitInsn(ARRAYLENGTH);
+      mv.visitInsn(ICONST_2);
+      mv.visitInsn(IREM);
+      Label l5 = new Label();
+      mv.visitJumpInsn(IFNE, l5);
+      mv.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
+      mv.visitVarInsn(ALOAD, 1);
+      mv.visitMethodInsn(
+          INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/Object;)V", false);
+      mv.visitLabel(l5);
+      // mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
+      mv.visitVarInsn(ALOAD, 1);
+      mv.visitInsn(ATHROW);
+      mv.visitLabel(l0);
+      // mv.visitFrame(Opcodes.F_CHOP,1, null, 0, null);
+      mv.visitInsn(RETURN);
+      mv.visitMaxs(-1, -1);
+      // mv.visitMaxs(5, 2);
+      mv.visitEnd();
+    }
+    cw.visitEnd();
+
+    return cw.toByteArray();
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/cf/UninitializedInFrameTest.java b/src/test/java/com/android/tools/r8/cf/UninitializedInFrameTest.java
new file mode 100644
index 0000000..4479796
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/cf/UninitializedInFrameTest.java
@@ -0,0 +1,54 @@
+// Copyright (c) 2018, 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.cf;
+
+public class UninitializedInFrameTest {
+  int v;
+
+  public UninitializedInFrameTest(int i) {
+    // In UninitializedInFrameDump, this method is changed to:
+    //     while (i-1 >= 42) {i = i-1;} this(i-1 >= 42);
+    // ...which is invalid in Java source since this() must be the first statement.
+    // Put "i-1 >= 42" in the code here to aid the manual editing in UninitializedInFrameDump.
+    this(i - 1 >= 42);
+  }
+
+  public UninitializedInFrameTest(boolean b) {
+    v = b ? 42 : 0;
+    System.out.println(this);
+    // Add an InvokeDirect that has 'this' as argument to ensure we don't consider it to be
+    // an initialization for 'this'.
+    if (!b) {
+      throw new AssertionError(this);
+    }
+  }
+
+  @Override
+  public String toString() {
+    return "Hello world! " + v;
+  }
+
+  public static void main(String[] args) {
+    try {
+      new UninitializedInFrameTest(true);
+      new UninitializedInFrameTest(45);
+    } catch (AssertionError e) {
+    }
+    if (args.length != 0) {
+      RuntimeException e;
+      if (args.length == 42) {
+        e = new RuntimeException(new IllegalArgumentException());
+      } else {
+        e =
+            new RuntimeException(
+                "You supplied " + args.length + (args.length == 1 ? " arg" : " args"));
+      }
+      if (args.length % 2 == 0) {
+        System.out.println(e);
+      }
+      throw e;
+    }
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/cf/UninitializedInFrameTestRunner.java b/src/test/java/com/android/tools/r8/cf/UninitializedInFrameTestRunner.java
new file mode 100644
index 0000000..f433a9d
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/cf/UninitializedInFrameTestRunner.java
@@ -0,0 +1,64 @@
+// Copyright (c) 2018, 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.cf;
+
+import com.android.tools.r8.ClassFileConsumer.ArchiveConsumer;
+import com.android.tools.r8.CompilationFailedException;
+import com.android.tools.r8.CompilationMode;
+import com.android.tools.r8.R8;
+import com.android.tools.r8.R8Command;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.ToolHelper.ProcessResult;
+import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.utils.DescriptorUtils;
+import java.io.IOException;
+import java.nio.file.Path;
+import org.junit.Assert;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+public class UninitializedInFrameTestRunner {
+  static final Class CLASS = UninitializedInFrameTest.class;
+
+  @Rule
+  public TemporaryFolder temp = ToolHelper.getTemporaryFolderForTest();
+
+  @Test
+  public void test() throws Exception {
+    test(ToolHelper.getClassAsBytes(CLASS));
+  }
+
+  @Test
+  public void testDump() throws Exception {
+    test(UninitializedInFrameDump.dump());
+  }
+
+  private void test(byte[] clazz) throws CompilationFailedException, IOException {
+    Path input = temp.getRoot().toPath().resolve("input.jar");
+    Path output = temp.getRoot().toPath().resolve("output.jar");
+
+    ArchiveConsumer inputConsumer = new ArchiveConsumer(input);
+    inputConsumer.accept(clazz, DescriptorUtils.javaTypeToDescriptor(CLASS.getName()), null);
+    inputConsumer.finished(null);
+    ProcessResult runInput = ToolHelper.runJava(input, CLASS.getCanonicalName());
+    if (runInput.exitCode != 0) {
+      System.out.println(runInput);
+    }
+    Assert.assertEquals(0, runInput.exitCode);
+
+    R8.run(
+        R8Command.builder()
+            .setMode(CompilationMode.DEBUG)
+            .addClassProgramData(clazz, Origin.unknown())
+            .addLibraryFiles(ToolHelper.getAndroidJar(ToolHelper.getMinApiLevelForDexVm()))
+            .setProgramConsumer(new ArchiveConsumer(output))
+            .build());
+    ProcessResult runOutput = ToolHelper.runJava(output, CLASS.getCanonicalName());
+    if (runOutput.exitCode != 0) {
+      System.out.println(runOutput);
+    }
+    Assert.assertEquals(runInput.toString(), runOutput.toString());
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/dexsplitter/DexSplitterTests.java b/src/test/java/com/android/tools/r8/dexsplitter/DexSplitterTests.java
index 19a5ee2..cf87d46 100644
--- a/src/test/java/com/android/tools/r8/dexsplitter/DexSplitterTests.java
+++ b/src/test/java/com/android/tools/r8/dexsplitter/DexSplitterTests.java
@@ -89,9 +89,9 @@
 
     if (useOptions) {
       Options options = new Options();
-      options.inputArchives.add(inputZip.toString());
-      options.featureSplitMapping = splitSpec.toString();
-      options.splitBaseName = output.toString();
+      options.addInputArchive(inputZip.toString());
+      options.setFeatureSplitMapping(splitSpec.toString());
+      options.setSplitBaseName(output.toString());
       DexSplitter.run(options);
     } else {
       DexSplitter.main(
@@ -235,12 +235,12 @@
     featureStream.close();
     if (useOptions) {
       Options options = new Options();
-      options.inputArchives.add(inputZip.toString());
-      options.splitBaseName = output.toString();
+      options.addInputArchive(inputZip.toString());
+      options.setSplitBaseName(output.toString());
       if (explicitBase) {
-        options.featureJars.add(baseJar.toString());
+        options.addFeatureJar(baseJar.toString());
       }
-      options.featureJars.add(featureJar.toString());
+      options.addFeatureJar(featureJar.toString());
       DexSplitter.run(options);
     } else {
       List<String> args = Lists.newArrayList(
diff --git a/src/test/java/com/android/tools/r8/ir/regalloc/B77240639.java b/src/test/java/com/android/tools/r8/ir/regalloc/B77240639.java
new file mode 100644
index 0000000..440f4f3
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/regalloc/B77240639.java
@@ -0,0 +1,820 @@
+// Copyright (c) 2018, 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.ir.regalloc;
+
+import static com.android.tools.r8.utils.DexInspectorMatchers.isPresent;
+import static org.junit.Assert.assertThat;
+
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.utils.AndroidApp;
+import com.android.tools.r8.utils.DexInspector;
+import com.android.tools.r8.utils.DexInspector.ClassSubject;
+import java.util.List;
+import java.util.Map;
+import org.junit.Ignore;
+import org.junit.Test;
+
+public class B77240639 extends TestBase {
+  @Ignore("b/77240639")
+  @Test
+  public void test() throws Exception {
+    AndroidApp app = compileWithD8(readClasses(TestClass.class));
+    DexInspector inspector = new DexInspector(app);
+    ClassSubject clazz = inspector.clazz(TestClass.class);
+    assertThat(clazz, isPresent());
+  }
+}
+
+class TestClass {
+  private boolean b;
+  private boolean b_flag = false;
+  private Boolean ob;
+  private boolean ob_flag = false;
+  private List<Boolean> vb;
+  private boolean vb_flag = false;
+  private List<Boolean> vob;
+  private boolean vob_flag = false;
+  private Map<String, Boolean> db;
+  private boolean db_flag = false;
+  private Map<String, Boolean> dob;
+  private boolean dob_flag = false;
+  private int i;
+  private boolean i_flag = false;
+  private Integer oi;
+  private boolean oi_flag = false;
+  private List<Boolean> vi;
+  private boolean vi_flag = false;
+  private List<Boolean> voi;
+  private boolean voi_flag = false;
+  private Map<String, Boolean> di;
+  private boolean di_flag = false;
+  private Map<String, Boolean> doi;
+  private boolean doi_flag = false;
+  private int ui;
+  private boolean ui_flag = false;
+  private Integer oui;
+  private boolean oui_flag = false;
+  private List<Boolean> vui;
+  private boolean vui_flag = false;
+  private List<Boolean> voui;
+  private boolean voui_flag = false;
+  private Map<String, Boolean> dui;
+  private boolean dui_flag = false;
+  private Map<String, Boolean> doui;
+  private boolean doui_flag = false;
+  private long i64;
+  private boolean i64_flag = false;
+  private Long oi64;
+  private boolean oi64_flag = false;
+  private List<Boolean> vi64;
+  private boolean vi64_flag = false;
+  private List<Boolean> voi64;
+  private boolean voi64_flag = false;
+  private Map<String, Boolean> di64;
+  private boolean di64_flag = false;
+  private Map<String, Boolean> doi64;
+  private boolean doi64_flag = false;
+  private float fl;
+  private boolean fl_flag = false;
+  private Float ofl;
+  private boolean ofl_flag = false;
+  private List<Boolean> vfl;
+  private boolean vfl_flag = false;
+  private List<Boolean> vofl;
+  private boolean vofl_flag = false;
+  private Map<String, Boolean> dfl;
+  private boolean dfl_flag = false;
+  private Map<String, Boolean> dofl;
+  private boolean dofl_flag = false;
+  private double d;
+  private boolean d_flag = false;
+  private Double od;
+  private boolean od_flag = false;
+  private List<Boolean> vd;
+  private boolean vd_flag = false;
+  private List<Boolean> vod;
+  private boolean vod_flag = false;
+  private Map<String, Boolean> dd;
+  private boolean dd_flag = false;
+  private Map<String, Boolean> dod;
+  private boolean dod_flag = false;
+  private String s;
+  private boolean s_flag = false;
+  private String os;
+  private boolean os_flag = false;
+  private List<Boolean> vs;
+  private boolean vs_flag = false;
+  private List<Boolean> vos;
+  private boolean vos_flag = false;
+  private Map<String, Boolean> ds;
+  private boolean ds_flag = false;
+  private Map<String, Boolean> dos;
+  private boolean dos_flag = false;
+  private long ti;
+  private boolean ti_flag = false;
+  private Long oti;
+  private boolean oti_flag = false;
+  private List<Boolean> vti;
+  private boolean vti_flag = false;
+  private List<Boolean> voti;
+  private boolean voti_flag = false;
+  private Map<String, Boolean> dti;
+  private boolean dti_flag = false;
+  private Map<String, Boolean> doti;
+  private boolean doti_flag = false;
+  private long at;
+  private boolean at_flag = false;
+  private Long oat;
+  private boolean oat_flag = false;
+  private List<Boolean> vat;
+  private boolean vat_flag = false;
+  private List<Boolean> voat;
+  private boolean voat_flag = false;
+  private Map<String, Boolean> dat;
+  private boolean dat_flag = false;
+  private Map<String, Boolean> doat;
+  private boolean doat_flag = false;
+  private long rt;
+  private boolean rt_flag = false;
+  private Long ort;
+  private boolean ort_flag = false;
+  private List<Boolean> vrt;
+  private boolean vrt_flag = false;
+  private List<Boolean> vort;
+  private boolean vort_flag = false;
+  private Map<String, Boolean> drt;
+  private boolean drt_flag = false;
+  private Map<String, Boolean> dort;
+  private boolean dort_flag = false;
+  private byte[] by;
+  private boolean by_flag = false;
+  private byte[] oby;
+  private boolean oby_flag = false;
+  private int c;
+  private boolean c_flag = false;
+  private Integer oc;
+  private boolean oc_flag = false;
+  private List<Integer> vc;
+  private boolean vc_flag = false;
+  private List<Integer> voc;
+  private boolean voc_flag = false;
+  private Map<String, Integer> dc;
+  private boolean dc_flag = false;
+  private Map<String, Integer> doc;
+  private boolean doc_flag = false;
+  private Object p;
+  private boolean p_flag = false;
+  private Object op;
+  private boolean op_flag = false;
+  private List<Object> vp;
+  private boolean vp_flag = false;
+  private List<Object> vop;
+  private boolean vop_flag = false;
+  private Map<String, Object> dp;
+  private boolean dp_flag = false;
+  private Map<String, Object> dop;
+  private boolean dop_flag = false;
+  private Object e;
+  private boolean e_flag = false;
+  private Object oe;
+  private boolean oe_flag = false;
+  private List<Object> ve;
+  private boolean ve_flag = false;
+  private List<Object> voe;
+  private boolean voe_flag = false;
+  private Map<String, Object> de;
+  private boolean de_flag = false;
+  private Map<String, Object> doe;
+  private boolean doe_flag = false;
+  private int be;
+  private boolean be_flag = false;
+  private Integer obe;
+  private boolean obe_flag = false;
+  private List<Object> vbe;
+  private boolean vbe_flag = false;
+  private List<Object> vobe;
+  private boolean vobe_flag = false;
+  private Map<String, Object> dbe;
+  private boolean dbe_flag = false;
+  private Map<String, Object> dobe;
+  private boolean dobe_flag = false;
+  private Object ts;
+  private boolean ts_flag = false;
+  private Object ots;
+  private boolean ots_flag = false;
+  private List<Object> vts;
+  private boolean vts_flag = false;
+  private List<Object> vots;
+  private boolean vots_flag = false;
+  private Map<String, Object> dts;
+  private boolean dts_flag = false;
+  private Map<String, Object> dots;
+  private boolean dots_flag = false;
+  private Object lts;
+  private boolean lts_flag = false;
+  private Object olts;
+  private boolean olts_flag = false;
+  private List<Object> vlts;
+  private boolean vlts_flag = false;
+  private List<Object> volts;
+  private boolean volts_flag = false;
+  private Map<String, Object> dlts;
+  private boolean dlts_flag = false;
+  private Map<String, Object> dolts;
+  private boolean dolts_flag = false;
+  private Object opts;
+  private boolean opts_flag = false;
+  private Object oopts;
+  private boolean oopts_flag = false;
+  private List<Object> vopts;
+  private boolean vopts_flag = false;
+  private List<Object> voopts;
+  private boolean voopts_flag = false;
+  private Map<String, Object> dopts;
+  private boolean dopts_flag = false;
+  private Map<String, Object> doopts;
+  private boolean doopts_flag = false;
+  private Object nativeObject;
+
+  public TestClass() {}
+
+  public TestClass(
+      boolean b,
+      Boolean ob,
+      List<Boolean> vb,
+      List<Boolean> vob,
+      Map<String, Boolean> db,
+      Map<String, Boolean> dob,
+      int i,
+      Integer oi,
+      List<Boolean> vi,
+      List<Boolean> voi,
+      Map<String, Boolean> di,
+      Map<String, Boolean> doi,
+      int ui,
+      Integer oui,
+      List<Boolean> vui,
+      List<Boolean> voui,
+      Map<String, Boolean> dui,
+      Map<String, Boolean> doui,
+      long i64,
+      Long oi64,
+      List<Boolean> vi64,
+      List<Boolean> voi64,
+      Map<String, Boolean> di64,
+      Map<String, Boolean> doi64,
+      float fl,
+      Float ofl,
+      List<Boolean> vfl,
+      List<Boolean> vofl,
+      Map<String, Boolean> dfl,
+      Map<String, Boolean> dofl,
+      double d,
+      Double od,
+      List<Boolean> vd,
+      List<Boolean> vod,
+      Map<String, Boolean> dd,
+      Map<String, Boolean> dod,
+      String s,
+      String os,
+      List<Boolean> vs,
+      List<Boolean> vos,
+      Map<String, Boolean> ds,
+      Map<String, Boolean> dos,
+      long ti,
+      Long oti,
+      List<Boolean> vti,
+      List<Boolean> voti,
+      Map<String, Boolean> dti,
+      Map<String, Boolean> doti,
+      long at,
+      Long oat,
+      List<Boolean> vat,
+      List<Boolean> voat,
+      Map<String, Boolean> dat,
+      Map<String, Boolean> doat,
+      long rt,
+      Long ort,
+      List<Boolean> vrt,
+      List<Boolean> vort,
+      Map<String, Boolean> drt,
+      Map<String, Boolean> dort,
+      byte[] by,
+      byte[] oby,
+      int c,
+      Integer oc,
+      List<Integer> vc,
+      List<Integer> voc,
+      Map<String, Integer> dc,
+      Map<String, Integer> doc,
+      Object p,
+      Object op,
+      List<Object> vp,
+      List<Object> vop,
+      Map<String, Object> dp,
+      Map<String, Object> dop,
+      Object e,
+      Object oe,
+      List<Object> ve,
+      List<Object> voe,
+      Map<String, Object> de,
+      Map<String, Object> doe,
+      int be,
+      Integer obe,
+      List<Object> vbe,
+      List<Object> vobe,
+      Map<String, Object> dbe,
+      Map<String, Object> dobe,
+      Object ts,
+      Object ots,
+      List<Object> vts,
+      List<Object> vots,
+      Map<String, Object> dts,
+      Map<String, Object> dots,
+      Object lts,
+      Object olts,
+      List<Object> vlts,
+      List<Object> volts,
+      Map<String, Object> dlts,
+      Map<String, Object> dolts,
+      Object opts,
+      Object oopts,
+      List<Object> vopts,
+      List<Object> voopts,
+      Map<String, Object> dopts,
+      Map<String, Object> doopts) {
+    if (vb == null) {
+      throw new IllegalArgumentException("vb");
+    } else if (vob == null) {
+      throw new IllegalArgumentException("vob");
+    } else if (db == null) {
+      throw new IllegalArgumentException("db");
+    } else if (dob == null) {
+      throw new IllegalArgumentException("dob");
+    } else if (vi == null) {
+      throw new IllegalArgumentException("vi");
+    } else if (voi == null) {
+      throw new IllegalArgumentException("voi");
+    } else if (di == null) {
+      throw new IllegalArgumentException("di");
+    } else if (doi == null) {
+      throw new IllegalArgumentException("doi");
+    } else if (vui == null) {
+      throw new IllegalArgumentException("vui");
+    } else if (voui == null) {
+      throw new IllegalArgumentException("voui");
+    } else if (dui == null) {
+      throw new IllegalArgumentException("dui");
+    } else if (doui == null) {
+      throw new IllegalArgumentException("doui");
+    } else if (vi64 == null) {
+      throw new IllegalArgumentException("vi64");
+    } else if (voi64 == null) {
+      throw new IllegalArgumentException("voi64");
+    } else if (di64 == null) {
+      throw new IllegalArgumentException("di64");
+    } else if (doi64 == null) {
+      throw new IllegalArgumentException("doi64");
+    } else if (vfl == null) {
+      throw new IllegalArgumentException("vfl");
+    } else if (vofl == null) {
+      throw new IllegalArgumentException("vofl");
+    } else if (dfl == null) {
+      throw new IllegalArgumentException("dfl");
+    } else if (dofl == null) {
+      throw new IllegalArgumentException("dofl");
+    } else if (vd == null) {
+      throw new IllegalArgumentException("vd");
+    } else if (vod == null) {
+      throw new IllegalArgumentException("vod");
+    } else if (dd == null) {
+      throw new IllegalArgumentException("dd");
+    } else if (dod == null) {
+      throw new IllegalArgumentException("dod");
+    } else if (s == null) {
+      throw new IllegalArgumentException("s");
+    } else if (vs == null) {
+      throw new IllegalArgumentException("vs");
+    } else if (vos == null) {
+      throw new IllegalArgumentException("vos");
+    } else if (ds == null) {
+      throw new IllegalArgumentException("ds");
+    } else if (dos == null) {
+      throw new IllegalArgumentException("dos");
+    } else if (vti == null) {
+      throw new IllegalArgumentException("vti");
+    } else if (voti == null) {
+      throw new IllegalArgumentException("voti");
+    } else if (dti == null) {
+      throw new IllegalArgumentException("dti");
+    } else if (doti == null) {
+      throw new IllegalArgumentException("doti");
+    } else if (vat == null) {
+      throw new IllegalArgumentException("vat");
+    } else if (voat == null) {
+      throw new IllegalArgumentException("voat");
+    } else if (dat == null) {
+      throw new IllegalArgumentException("dat");
+    } else if (doat == null) {
+      throw new IllegalArgumentException("doat");
+    } else if (vrt == null) {
+      throw new IllegalArgumentException("vrt");
+    } else if (vort == null) {
+      throw new IllegalArgumentException("vort");
+    } else if (drt == null) {
+      throw new IllegalArgumentException("drt");
+    } else if (dort == null) {
+      throw new IllegalArgumentException("dort");
+    } else if (by == null) {
+      throw new IllegalArgumentException("by");
+    } else if (vc == null) {
+      throw new IllegalArgumentException("vc");
+    } else if (voc == null) {
+      throw new IllegalArgumentException("voc");
+    } else if (dc == null) {
+      throw new IllegalArgumentException("dc");
+    } else if (doc == null) {
+      throw new IllegalArgumentException("doc");
+    } else if (p == null) {
+      throw new IllegalArgumentException("p");
+    } else if (vp == null) {
+      throw new IllegalArgumentException("vp");
+    } else if (vop == null) {
+      throw new IllegalArgumentException("vop");
+    } else if (dp == null) {
+      throw new IllegalArgumentException("dp");
+    } else if (dop == null) {
+      throw new IllegalArgumentException("dop");
+    } else if (e == null) {
+      throw new IllegalArgumentException("e");
+    } else if (ve == null) {
+      throw new IllegalArgumentException("ve");
+    } else if (voe == null) {
+      throw new IllegalArgumentException("voe");
+    } else if (de == null) {
+      throw new IllegalArgumentException("de");
+    } else if (doe == null) {
+      throw new IllegalArgumentException("doe");
+    } else if (vbe == null) {
+      throw new IllegalArgumentException("vbe");
+    } else if (vobe == null) {
+      throw new IllegalArgumentException("vobe");
+    } else if (dbe == null) {
+      throw new IllegalArgumentException("dbe");
+    } else if (dobe == null) {
+      throw new IllegalArgumentException("dobe");
+    } else if (ts == null) {
+      throw new IllegalArgumentException("ts");
+    } else if (vts == null) {
+      throw new IllegalArgumentException("vts");
+    } else if (vots == null) {
+      throw new IllegalArgumentException("vots");
+    } else if (dts == null) {
+      throw new IllegalArgumentException("dts");
+    } else if (dots == null) {
+      throw new IllegalArgumentException("dots");
+    } else if (lts == null) {
+      throw new IllegalArgumentException("lts");
+    } else if (vlts == null) {
+      throw new IllegalArgumentException("vlts");
+    } else if (volts == null) {
+      throw new IllegalArgumentException("volts");
+    } else if (dlts == null) {
+      throw new IllegalArgumentException("dlts");
+    } else if (dolts == null) {
+      throw new IllegalArgumentException("dolts");
+    } else if (opts == null) {
+      throw new IllegalArgumentException("opts");
+    } else if (vopts == null) {
+      throw new IllegalArgumentException("vopts");
+    } else if (voopts == null) {
+      throw new IllegalArgumentException("voopts");
+    } else if (dopts == null) {
+      throw new IllegalArgumentException("dopts");
+    } else if (doopts == null) {
+      throw new IllegalArgumentException("doopts");
+    } else {
+      this.nativeObject =
+          this.init(
+              b, ob, vb, vob, db, dob, i, oi, vi, voi, di, doi, ui, oui, vui, voui, dui, doui, i64,
+              oi64, vi64, voi64, di64, doi64, fl, ofl, vfl, vofl, dfl, dofl, d, od, vd, vod, dd,
+              dod, s, os, vs, vos, ds, dos, ti, oti, vti, voti, dti, doti, at, oat, vat, voat, dat,
+              doat, rt, ort, vrt, vort, drt, dort, by, oby, c, oc, vc, voc, dc, doc, p, op, vp, vop,
+              dp, dop, e, oe, ve, voe, de, doe, be, obe, vbe, vobe, dbe, dobe, ts, ots, vts, vots,
+              dts, dots, lts, olts, vlts, volts, dlts, dolts, opts, oopts, vopts, voopts, dopts,
+              doopts);
+      this.b = b;
+      this.b_flag = true;
+      this.ob = ob;
+      this.ob_flag = true;
+      this.vb = vb;
+      this.vb_flag = true;
+      this.vob = vob;
+      this.vob_flag = true;
+      this.db = db;
+      this.db_flag = true;
+      this.dob = dob;
+      this.dob_flag = true;
+      this.i = i;
+      this.i_flag = true;
+      this.oi = oi;
+      this.oi_flag = true;
+      this.vi = vi;
+      this.vi_flag = true;
+      this.voi = voi;
+      this.voi_flag = true;
+      this.di = di;
+      this.di_flag = true;
+      this.doi = doi;
+      this.doi_flag = true;
+      this.ui = ui;
+      this.ui_flag = true;
+      this.oui = oui;
+      this.oui_flag = true;
+      this.vui = vui;
+      this.vui_flag = true;
+      this.voui = voui;
+      this.voui_flag = true;
+      this.dui = dui;
+      this.dui_flag = true;
+      this.doui = doui;
+      this.doui_flag = true;
+      this.i64 = i64;
+      this.i64_flag = true;
+      this.oi64 = oi64;
+      this.oi64_flag = true;
+      this.vi64 = vi64;
+      this.vi64_flag = true;
+      this.voi64 = voi64;
+      this.voi64_flag = true;
+      this.di64 = di64;
+      this.di64_flag = true;
+      this.doi64 = doi64;
+      this.doi64_flag = true;
+      this.fl = fl;
+      this.fl_flag = true;
+      this.ofl = ofl;
+      this.ofl_flag = true;
+      this.vfl = vfl;
+      this.vfl_flag = true;
+      this.vofl = vofl;
+      this.vofl_flag = true;
+      this.dfl = dfl;
+      this.dfl_flag = true;
+      this.dofl = dofl;
+      this.dofl_flag = true;
+      this.d = d;
+      this.d_flag = true;
+      this.od = od;
+      this.od_flag = true;
+      this.vd = vd;
+      this.vd_flag = true;
+      this.vod = vod;
+      this.vod_flag = true;
+      this.dd = dd;
+      this.dd_flag = true;
+      this.dod = dod;
+      this.dod_flag = true;
+      this.s = s;
+      this.s_flag = true;
+      this.os = os;
+      this.os_flag = true;
+      this.vs = vs;
+      this.vs_flag = true;
+      this.vos = vos;
+      this.vos_flag = true;
+      this.ds = ds;
+      this.ds_flag = true;
+      this.dos = dos;
+      this.dos_flag = true;
+      this.ti = ti;
+      this.ti_flag = true;
+      this.oti = oti;
+      this.oti_flag = true;
+      this.vti = vti;
+      this.vti_flag = true;
+      this.voti = voti;
+      this.voti_flag = true;
+      this.dti = dti;
+      this.dti_flag = true;
+      this.doti = doti;
+      this.doti_flag = true;
+      this.at = at;
+      this.at_flag = true;
+      this.oat = oat;
+      this.oat_flag = true;
+      this.vat = vat;
+      this.vat_flag = true;
+      this.voat = voat;
+      this.voat_flag = true;
+      this.dat = dat;
+      this.dat_flag = true;
+      this.doat = doat;
+      this.doat_flag = true;
+      this.rt = rt;
+      this.rt_flag = true;
+      this.ort = ort;
+      this.ort_flag = true;
+      this.vrt = vrt;
+      this.vrt_flag = true;
+      this.vort = vort;
+      this.vort_flag = true;
+      this.drt = drt;
+      this.drt_flag = true;
+      this.dort = dort;
+      this.dort_flag = true;
+      this.by = by;
+      this.by_flag = true;
+      this.oby = oby;
+      this.oby_flag = true;
+      this.c = c;
+      this.c_flag = true;
+      this.oc = oc;
+      this.oc_flag = true;
+      this.vc = vc;
+      this.vc_flag = true;
+      this.voc = voc;
+      this.voc_flag = true;
+      this.dc = dc;
+      this.dc_flag = true;
+      this.doc = doc;
+      this.doc_flag = true;
+      this.p = p;
+      this.p_flag = true;
+      this.op = op;
+      this.op_flag = true;
+      this.vp = vp;
+      this.vp_flag = true;
+      this.vop = vop;
+      this.vop_flag = true;
+      this.dp = dp;
+      this.dp_flag = true;
+      this.dop = dop;
+      this.dop_flag = true;
+      this.e = e;
+      this.e_flag = true;
+      this.oe = oe;
+      this.oe_flag = true;
+      this.ve = ve;
+      this.ve_flag = true;
+      this.voe = voe;
+      this.voe_flag = true;
+      this.de = de;
+      this.de_flag = true;
+      this.doe = doe;
+      this.doe_flag = true;
+      this.be = be;
+      this.be_flag = true;
+      this.obe = obe;
+      this.obe_flag = true;
+      this.vbe = vbe;
+      this.vbe_flag = true;
+      this.vobe = vobe;
+      this.vobe_flag = true;
+      this.dbe = dbe;
+      this.dbe_flag = true;
+      this.dobe = dobe;
+      this.dobe_flag = true;
+      this.ts = ts;
+      this.ts_flag = true;
+      this.ots = ots;
+      this.ots_flag = true;
+      this.vts = vts;
+      this.vts_flag = true;
+      this.vots = vots;
+      this.vots_flag = true;
+      this.dts = dts;
+      this.dts_flag = true;
+      this.dots = dots;
+      this.dots_flag = true;
+      this.lts = lts;
+      this.lts_flag = true;
+      this.olts = olts;
+      this.olts_flag = true;
+      this.vlts = vlts;
+      this.vlts_flag = true;
+      this.volts = volts;
+      this.volts_flag = true;
+      this.dlts = dlts;
+      this.dlts_flag = true;
+      this.dolts = dolts;
+      this.dolts_flag = true;
+      this.opts = opts;
+      this.opts_flag = true;
+      this.oopts = oopts;
+      this.oopts_flag = true;
+      this.vopts = vopts;
+      this.vopts_flag = true;
+      this.voopts = voopts;
+      this.voopts_flag = true;
+      this.dopts = dopts;
+      this.dopts_flag = true;
+      this.doopts = doopts;
+      this.doopts_flag = true;
+    }
+  }
+
+  private native Object init(
+      boolean v1,
+      Boolean v2,
+      List<Boolean> v3,
+      List<Boolean> v4,
+      Map<String, Boolean> v5,
+      Map<String, Boolean> v6,
+      int v7, Integer var8,
+      List<Boolean> v9,
+      List<Boolean> v10,
+      Map<String, Boolean> v11,
+      Map<String, Boolean> v12,
+      int v13,
+      Integer v14,
+      List<Boolean> v15,
+      List<Boolean> v16,
+      Map<String, Boolean> v17,
+      Map<String, Boolean> v18,
+      long v19, Long var21,
+      List<Boolean> v22,
+      List<Boolean> v23,
+      Map<String, Boolean> v24,
+      Map<String, Boolean> v25,
+      float v26,
+      Float v27,
+      List<Boolean> v28,
+      List<Boolean> v29,
+      Map<String, Boolean> v30,
+      Map<String, Boolean> v31,
+      double v32,
+      Double v34,
+      List<Boolean> v35,
+      List<Boolean> v36,
+      Map<String, Boolean> v37,
+      Map<String, Boolean> v38,
+      String v39,
+      String v40,
+      List<Boolean> v41,
+      List<Boolean> v42,
+      Map<String, Boolean> v43,
+      Map<String, Boolean> v44,
+      long v45, Long var47,
+      List<Boolean> v48,
+      List<Boolean> v49,
+      Map<String, Boolean> v50,
+      Map<String, Boolean> v51,
+      long v52,
+      Long v54,
+      List<Boolean> v55,
+      List<Boolean> v56,
+      Map<String, Boolean> v57,
+      Map<String, Boolean> v58,
+      long v59,
+      Long v61,
+      List<Boolean> v62,
+      List<Boolean> v63,
+      Map<String, Boolean> v64,
+      Map<String, Boolean> v65,
+      byte[] v66,
+      byte[] v67,
+      int v68,
+      Integer v69,
+      List<Integer> v70,
+      List<Integer> v71,
+      Map<String, Integer> v72,
+      Map<String, Integer> v73,
+      Object v74,
+      Object v75,
+      List<Object> v76,
+      List<Object> v77,
+      Map<String, Object> v78,
+      Map<String, Object> v79,
+      Object v80,
+      Object v81,
+      List<Object> v82,
+      List<Object> v83,
+      Map<String, Object> v84,
+      Map<String, Object> v85,
+      int v86,
+      Integer v87,
+      List<Object> v88,
+      List<Object> v89,
+      Map<String, Object> v90,
+      Map<String, Object> v91,
+      Object v92,
+      Object v93,
+      List<Object> v94,
+      List<Object> v95,
+      Map<String, Object> v96,
+      Map<String, Object> v97,
+      Object v98,
+      Object v99,
+      List<Object> v100,
+      List<Object> v101,
+      Map<String, Object> v102,
+      Map<String, Object> v103,
+      Object v104,
+      Object v105,
+      List<Object> v106,
+      List<Object> v107,
+      Map<String, Object> v108,
+      Map<String, Object> v109);
+}
diff --git a/src/test/java/com/android/tools/r8/naming/InterfaceRenamingTestRunner.java b/src/test/java/com/android/tools/r8/naming/InterfaceRenamingTestRunner.java
index d25c061..6c054e5 100644
--- a/src/test/java/com/android/tools/r8/naming/InterfaceRenamingTestRunner.java
+++ b/src/test/java/com/android/tools/r8/naming/InterfaceRenamingTestRunner.java
@@ -24,7 +24,6 @@
 public class InterfaceRenamingTestRunner extends TestBase {
   static final Class CLASS = InterfaceRenamingTest.class;
   static final Class[] CLASSES = InterfaceRenamingTest.CLASSES;
-  private boolean bug = false;
 
   @Test
   public void testCfNoMinify() throws Exception {
@@ -33,7 +32,6 @@
 
   @Test
   public void testCfMinify() throws Exception {
-    bug = true;
     testCf(MinifyMode.JAVA);
   }
 
@@ -49,7 +47,6 @@
 
   @Test
   public void testDexMinify() throws Exception {
-    bug = true;
     testDex(MinifyMode.JAVA);
   }
 
@@ -65,11 +62,6 @@
     Path outCf = temp.getRoot().toPath().resolve("cf.zip");
     build(new ClassFileConsumer.ArchiveConsumer(outCf), minify);
     ProcessResult runCf = ToolHelper.runJava(outCf, CLASS.getCanonicalName());
-    if (bug) {
-      assertNotEquals(-1, runCf.stderr.indexOf("java.lang.AbstractMethodError"));
-      assertNotEquals(0, runCf.exitCode);
-      return;
-    }
     assertEquals(runInput.toString(), runCf.toString());
   }
 
@@ -79,12 +71,6 @@
     assertEquals(0, runInput.exitCode);
     Path outDex = temp.getRoot().toPath().resolve("dex.zip");
     build(new DexIndexedConsumer.ArchiveConsumer(outDex), minify);
-    if (bug) {
-      ProcessResult runDex = ToolHelper.runArtRaw(outDex.toString(), CLASS.getCanonicalName());
-      assertNotEquals(-1, runDex.stderr.indexOf("java.lang.AbstractMethodError"));
-      assertNotEquals(0, runDex.exitCode);
-      return;
-    }
     ProcessResult runDex =
         ToolHelper.runArtNoVerificationErrorsRaw(outDex.toString(), CLASS.getCanonicalName());
     assertEquals(runInput.stdout, runDex.stdout);