Merge "Copy method access flags in LambdaClass"
diff --git a/src/main/java/com/android/tools/r8/ir/code/ValueType.java b/src/main/java/com/android/tools/r8/ir/code/ValueType.java
index 69618b3..c414342 100644
--- a/src/main/java/com/android/tools/r8/ir/code/ValueType.java
+++ b/src/main/java/com/android/tools/r8/ir/code/ValueType.java
@@ -48,10 +48,6 @@
     if (other == INT_OR_FLOAT_OR_NULL) {
       return other.meet(this);
     }
-    if (isPreciseType() && other.isPreciseType()) {
-      // Precise types must be identical, hitting the first check above.
-      throw new CompilationError("Cannot compute meet of types: " + this + " and " + other);
-    }
     switch (this) {
       case OBJECT:
         {
diff --git a/src/test/examples/inlining/A.java b/src/test/examples/inlining/A.java
index dd857c8..a7aa4d2 100644
--- a/src/test/examples/inlining/A.java
+++ b/src/test/examples/inlining/A.java
@@ -6,15 +6,21 @@
 class A {
 
   int a;
+  int b;
 
   A(int a) {
     this.a = a;
+    this.b = a + 1;
   }
 
   int a() {
     return a;
   }
 
+  int b() {
+    return b;
+  }
+
   int cannotInline(int v) {
     // Cannot inline due to recursion.
     if (v > 0) {
diff --git a/src/test/examples/inlining/Nullability.java b/src/test/examples/inlining/Nullability.java
index 74747d0..95422f0 100644
--- a/src/test/examples/inlining/Nullability.java
+++ b/src/test/examples/inlining/Nullability.java
@@ -43,8 +43,8 @@
   }
 
   int conditionalOperator(A a) {
-    // a is not null when a.a() is invoked.
-    return a != null ? a.a() : -1;
+    // a is not null when a.b() is invoked.
+    return a != null ? a.b() : -1;
   }
 
   int notInlinableOnThrow(Throwable t) throws Throwable {
@@ -97,8 +97,8 @@
     // instructions with side effects.
     if (a != null && result != 0) {
       // Thus, the invocation below is the first instruction with side effect.
-      // Also, a is not null here, hence a.a() is inlinable.
-      result *= a.a();
+      // Also, a is not null here, hence a.b() is inlinable.
+      result *= a.b();
     }
     return result;
   }
diff --git a/src/test/java/com/android/tools/r8/R8RunSmaliTestsTest.java b/src/test/java/com/android/tools/r8/R8RunSmaliTestsTest.java
index 11ad12b..0f3cadc 100644
--- a/src/test/java/com/android/tools/r8/R8RunSmaliTestsTest.java
+++ b/src/test/java/com/android/tools/r8/R8RunSmaliTestsTest.java
@@ -11,14 +11,12 @@
 import com.android.tools.r8.utils.TestDescriptionWatcher;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
@@ -91,11 +89,6 @@
       // This list is currently empty!
   );
 
-  private Set<String> failingOnX8 = ImmutableSet.of(
-      // Contains use of register as both an int and a float.
-      "regression/33336471"
-  );
-
   @Rule
   public TemporaryFolder temp = ToolHelper.getTemporaryFolderForTest();
 
@@ -168,10 +161,6 @@
         .addLibraryFiles(ToolHelper.getDefaultAndroidJar())
             .setOutput(Paths.get(outputPath), OutputMode.DexIndexed);
     ToolHelper.getAppBuilder(builder).addProgramFiles(originalDexFile);
-
-    if (failingOnX8.contains(directoryName)) {
-      thrown.expect(CompilationFailedException.class);
-    }
     R8.run(builder.build());
 
     if (!ToolHelper.artSupported()) {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/R8InliningTest.java b/src/test/java/com/android/tools/r8/ir/optimize/R8InliningTest.java
index 8e78784..7284384 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/R8InliningTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/R8InliningTest.java
@@ -27,6 +27,7 @@
 import com.android.tools.r8.code.Throw;
 import com.android.tools.r8.graph.DexCode;
 import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.utils.AndroidApiLevel;
 import com.android.tools.r8.utils.FileUtils;
 import com.android.tools.r8.utils.dexinspector.ClassSubject;
@@ -55,17 +56,26 @@
   private static final String DEFAULT_DEX_FILENAME = "classes.dex";
   private static final String DEFAULT_MAP_FILENAME = "proguard.map";
 
-  @Parameters(name = "{0}")
+  @Parameters(name = "{0}, minification={1}, allowaccessmodification={2}")
   public static Collection<Object[]> data() {
-    return Arrays.asList(new Object[][]{{"Inlining"}});
+    return Arrays.asList(new Object[][]{
+        {"Inlining", false, false},
+        {"Inlining", false, true},
+        {"Inlining", true, false},
+        {"Inlining", true, true}
+    });
   }
 
   private final String name;
   private final String keepRulesFile;
+  private final boolean minification;
+  private final boolean allowAccessModification;
 
-  public R8InliningTest(String name) {
+  public R8InliningTest(String name, boolean minification, boolean allowAccessModification) {
     this.name = name.toLowerCase();
     this.keepRulesFile = ToolHelper.EXAMPLES_DIR + this.name + "/keep-rules.txt";
+    this.minification = minification;
+    this.allowAccessModification = allowAccessModification;
   }
 
   private Path getInputFile() {
@@ -81,7 +91,7 @@
   }
 
   private String getGeneratedProguardMap() throws IOException {
-    Path mapFile = Paths.get(temp.getRoot().getCanonicalPath(), DEFAULT_MAP_FILENAME);
+    Path mapFile = temp.getRoot().toPath().resolve(DEFAULT_MAP_FILENAME);
     if (Files.exists(mapFile)) {
       return mapFile.toAbsolutePath().toString();
     }
@@ -94,19 +104,23 @@
   @Before
   public void generateR8Version() throws Exception {
     Path out = temp.getRoot().toPath();
-    R8Command command =
+    Path mapFile = out.resolve(DEFAULT_MAP_FILENAME);
+    R8Command.Builder commandBuilder =
         R8Command.builder()
             .addProgramFiles(getInputFile())
             .setMinApiLevel(AndroidApiLevel.M.getLevel())
             .setOutput(out, OutputMode.DexIndexed)
-            .addProguardConfigurationFiles(Paths.get(keepRulesFile))
-            .build();
-    // TODO(62048823): Enable minification.
-    ToolHelper.runR8(command, o -> {
-      o.enableMinification = false;
+            .setProguardMapOutputPath(mapFile)
+            .addProguardConfigurationFiles(Paths.get(keepRulesFile));
+    if (allowAccessModification) {
+      commandBuilder.addProguardConfiguration(
+          ImmutableList.of("-allowaccessmodification"), Origin.unknown());
+    }
+    ToolHelper.runR8(commandBuilder.build(), o -> {
+      o.enableMinification = minification;
     });
-    String artOutput = ToolHelper.runArtNoVerificationErrors(out + "/classes.dex",
-        "inlining.Inlining");
+    String artOutput =
+        ToolHelper.runArtNoVerificationErrors(out + "/classes.dex", "inlining.Inlining");
 
     // Compare result with Java to make sure we have the same behavior.
     ProcessResult javaResult = ToolHelper.runJava(getInputFile(), "inlining.Inlining");
@@ -179,17 +193,21 @@
         new DexInspector(getGeneratedDexFile().toAbsolutePath(), getGeneratedProguardMap());
     ClassSubject clazz = inspector.clazz("inlining.Nullability");
     MethodSubject m = clazz.method("int", "inlinable", ImmutableList.of("inlining.A"));
-    assertTrue(m.isPresent());
-    DexCode code = m.getMethod().getCode().asDexCode();
-    checkInstructions(
-        code,
-        ImmutableList.of(
-            Iget.class,
-            // TODO(b/70572176): below two could be replaced with Iget via inlining
-            InvokeVirtual.class,
-            MoveResult.class,
-            AddInt2Addr.class,
-            Return.class));
+    DexCode code;
+    if (allowAccessModification) {
+      assertFalse(m.isPresent());
+    } else {
+      assertTrue(m.isPresent());
+      code = m.getMethod().getCode().asDexCode();
+      checkInstructions(
+          code,
+          ImmutableList.of(
+              Iget.class,
+              InvokeVirtual.class,
+              MoveResult.class,
+              AddInt2Addr.class,
+              Return.class));
+    }
 
     m = clazz.method("int", "notInlinable", ImmutableList.of("inlining.A"));
     assertTrue(m.isPresent());
@@ -249,10 +267,7 @@
         code,
         ImmutableList.of(
             IfEqz.class,
-            // TODO(b/70794661): below two could be replaced with Iget via inlining if access
-            // modification is allowed.
-            InvokeVirtual.class,
-            MoveResult.class,
+            Iget.class,
             Goto.class,
             Const4.class,
             Return.class));
@@ -273,9 +288,7 @@
     builder.add(Const4.class);
     builder.add(IfEqz.class);
     builder.add(IfEqz.class);
-    // TODO(b/70794661): below two could be replaced with Iget via inlining
-    builder.add(InvokeVirtual.class);
-    builder.add(MoveResult.class);
+    builder.add(Iget.class);
     builder.add(MulInt2Addr.class);
     builder.add(Return.class);
     builder.add(PackedSwitchPayload.class);
diff --git a/src/test/java/com/android/tools/r8/naming/ApplyMappingTest.java b/src/test/java/com/android/tools/r8/naming/ApplyMappingTest.java
index 876a758..39d7f0b 100644
--- a/src/test/java/com/android/tools/r8/naming/ApplyMappingTest.java
+++ b/src/test/java/com/android/tools/r8/naming/ApplyMappingTest.java
@@ -6,6 +6,7 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
@@ -15,8 +16,6 @@
 import com.android.tools.r8.StringConsumer;
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.ToolHelper;
-import com.android.tools.r8.code.Instruction;
-import com.android.tools.r8.code.NewInstance;
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.shaking.ProguardRuleParserException;
@@ -26,14 +25,21 @@
 import com.android.tools.r8.utils.dexinspector.InstructionSubject;
 import com.android.tools.r8.utils.dexinspector.InvokeInstructionSubject;
 import com.android.tools.r8.utils.dexinspector.MethodSubject;
+import com.android.tools.r8.utils.dexinspector.NewInstanceInstructionSubject;
 import java.io.IOException;
 import java.nio.file.Path;
 import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.Collection;
 import java.util.Iterator;
 import java.util.concurrent.ExecutionException;
 import org.junit.Before;
 import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
 
+@RunWith(Parameterized.class)
 public class ApplyMappingTest extends TestBase {
 
   private static final String MAPPING = "test-mapping.txt";
@@ -52,9 +58,20 @@
 
   private Path out;
 
+  private Backend backend;
+
+  @Parameters(name = "Backend: {0}")
+  public static Collection<Backend> data() {
+    return Arrays.asList(Backend.values());
+  }
+
+  public ApplyMappingTest(Backend backend) {
+    this.backend = backend;
+  }
+
   @Before
   public void setup() throws IOException {
-    out = temp.newFolder("outdex").toPath();
+    out = temp.newFolder("out").toPath();
   }
 
   @Test
@@ -97,7 +114,7 @@
                     pgConfig -> pgConfig.setApplyMappingFile(proguardMap))
                 .build());
 
-    DexInspector inspector = new DexInspector(instrApp);
+    DexInspector inspector = createDexInspector(instrApp);
     MethodSubject main = inspector.clazz("applymapping044.Main").method(DexInspector.MAIN);
     Iterator<InvokeInstructionSubject> iterator =
         main.iterateInstructions(InstructionSubject::isInvoke);
@@ -152,7 +169,7 @@
                 .build());
 
     // Make sure the given proguard map is indeed applied.
-    DexInspector inspector = new DexInspector(outputApp);
+    DexInspector inspector = createDexInspector(outputApp);
     MethodSubject main = inspector.clazz("applymapping044.Main").method(DexInspector.MAIN);
     Iterator<InvokeInstructionSubject> iterator =
         main.iterateInstructions(InstructionSubject::isInvoke);
@@ -194,6 +211,15 @@
     assertEquals("p", original_f.invokedMethod().name.toString());
   }
 
+  private static DexInspector createDexInspector(AndroidApp outputApp)
+      throws IOException, ExecutionException {
+    return new DexInspector(
+        outputApp,
+        o -> {
+          o.enableCfFrontend = true;
+        });
+  }
+
   @Test
   public void test_naming001_rule105() throws Exception {
     // keep rules to reserve D and E, along with a proguard map.
@@ -210,7 +236,7 @@
                 .build());
 
     // Make sure the given proguard map is indeed applied.
-    DexInspector inspector = new DexInspector(outputApp);
+    DexInspector inspector = createDexInspector(outputApp);
     MethodSubject main = inspector.clazz("naming001.D").method(DexInspector.MAIN);
     Iterator<InvokeInstructionSubject> iterator =
         main.iterateInstructions(InstructionSubject::isInvoke);
@@ -242,13 +268,20 @@
                 .build());
 
     // Make sure the given proguard map is indeed applied.
-    DexInspector inspector = new DexInspector(outputApp);
+    DexInspector inspector = createDexInspector(outputApp);
     MethodSubject main = inspector.clazz("naming001.D").method(DexInspector.MAIN);
 
+    Iterator<InstructionSubject> iterator = main.iterateInstructions();
     // naming001.E is renamed to a.a, so first instruction must be: new-instance La/a;
-    Instruction[] instructions = main.getMethod().getCode().asDexCode().instructions;
-    assertTrue(instructions[0] instanceof NewInstance);
-    NewInstance newInstance = (NewInstance) instructions[0];
+    NewInstanceInstructionSubject newInstance = null;
+    while (iterator.hasNext()) {
+      InstructionSubject instruction = iterator.next();
+      if (instruction.isNewInstance()) {
+        newInstance = (NewInstanceInstructionSubject) instruction;
+        break;
+      }
+    }
+    assertNotNull(newInstance);
     assertEquals( "La/a;", newInstance.getType().toSmaliString());
   }
 
@@ -269,7 +302,7 @@
     return R8Command.builder()
         .addLibraryFiles(ToolHelper.getDefaultAndroidJar(), mainApp)
         .addProgramFiles(instrApp)
-        .setOutput(out, OutputMode.DexIndexed)
+        .setOutput(out, backend == Backend.DEX ? OutputMode.DexIndexed : OutputMode.ClassFile)
         .addProguardConfigurationFiles(flag);
   }
 
@@ -278,15 +311,17 @@
     return R8Command.builder()
         .addLibraryFiles(ToolHelper.getDefaultAndroidJar())
         .addProgramFiles(jars)
-        .setOutput(out, OutputMode.DexIndexed)
+        .setOutput(out, backend == Backend.DEX ? OutputMode.DexIndexed : OutputMode.ClassFile)
         .addProguardConfigurationFiles(flag);
   }
 
   private static AndroidApp runR8(R8Command command)
       throws ProguardRuleParserException, ExecutionException, IOException {
-    return ToolHelper.runR8(command, options -> {
-      // Disable inlining to make this test not depend on inlining decisions.
-      options.enableInlining = false;
-    });
+    return ToolHelper.runR8(
+        command,
+        options -> {
+          // Disable inlining to make this test not depend on inlining decisions.
+          options.enableInlining = false;
+        });
   }
 }
diff --git a/src/test/java/com/android/tools/r8/regress/b111080693/B111080693.java b/src/test/java/com/android/tools/r8/regress/b111080693/B111080693.java
new file mode 100644
index 0000000..d424c39
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/regress/b111080693/B111080693.java
@@ -0,0 +1,51 @@
+// 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.regress.b111080693;
+
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.CoreMatchers.not;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+
+import com.android.tools.r8.DexIndexedConsumer;
+import com.android.tools.r8.R8Command;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.ToolHelper.ProcessResult;
+import com.android.tools.r8.VmTestRunner;
+import com.android.tools.r8.origin.Origin;
+import com.android.tools.r8.regress.b111080693.a.Observable;
+import com.android.tools.r8.regress.b111080693.b.RecyclerView;
+import com.android.tools.r8.utils.AndroidApp;
+import com.google.common.collect.ImmutableList;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(VmTestRunner.class)
+public class B111080693 extends TestBase {
+  @Ignore("b/111080693")
+  @Test
+  public void test() throws Exception {
+    R8Command.Builder builder = R8Command.builder();
+    builder.addProgramFiles(
+        ToolHelper.getClassFilesForTestPackage(Observable.class.getPackage()));
+    builder.addProgramFiles(
+        ToolHelper.getClassFilesForTestPackage(RecyclerView.class.getPackage()));
+    builder.addProgramFiles(ToolHelper.getClassFileForTestClass(TestMain.class));
+    builder.addProgramFiles(ToolHelper.getClassFileForTestClass(TestMain.TestAdapter.class));
+    builder.setProgramConsumer(DexIndexedConsumer.emptyConsumer());
+    builder.setMinApiLevel(ToolHelper.getMinApiLevelForDexVm().getLevel());
+    String config = keepMainProguardConfiguration(TestMain.class);
+    builder.addProguardConfiguration(
+        ImmutableList.of(config,
+            "-keepattributes Signature, InnerClasses, EnclosingMethod, *Annotation*"),
+        Origin.unknown());
+    AndroidApp app = ToolHelper.runR8(builder.build());
+    ProcessResult result = runOnArtRaw(app, TestMain.class);
+    assertEquals(0, result.exitCode);
+    assertThat(result.stderr, not(containsString("IllegalAccessError")));
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/regress/b111080693/TestMain.java b/src/test/java/com/android/tools/r8/regress/b111080693/TestMain.java
new file mode 100644
index 0000000..8979250
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/regress/b111080693/TestMain.java
@@ -0,0 +1,22 @@
+// 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.regress.b111080693;
+
+import com.android.tools.r8.regress.b111080693.b.RecyclerView;
+import com.android.tools.r8.regress.b111080693.b.RecyclerView.Adapter;
+
+public class TestMain {
+  static final class TestAdapter extends Adapter {
+    TestAdapter() {
+    }
+  }
+
+  public static void main(String[] args) {
+    TestAdapter adapter = new TestAdapter();
+    RecyclerView view = new RecyclerView();
+    view.setAdapter(adapter);
+    adapter.notifyDataSetChanged();
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/regress/b111080693/a/Observable.java b/src/test/java/com/android/tools/r8/regress/b111080693/a/Observable.java
new file mode 100644
index 0000000..c7a4858
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/regress/b111080693/a/Observable.java
@@ -0,0 +1,15 @@
+// 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.regress.b111080693.a;
+
+import java.util.ArrayList;
+
+public abstract class Observable<T> {
+  /**
+   * The list of observers.  An observer can be in the list at most
+   * once and will never be null.
+   */
+  protected final ArrayList<T> mObservers = new ArrayList<T>();
+}
diff --git a/src/test/java/com/android/tools/r8/regress/b111080693/b/RecyclerView.java b/src/test/java/com/android/tools/r8/regress/b111080693/b/RecyclerView.java
new file mode 100644
index 0000000..06347fe
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/regress/b111080693/b/RecyclerView.java
@@ -0,0 +1,78 @@
+// 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.regress.b111080693.b;
+
+import com.android.tools.r8.regress.b111080693.a.Observable;
+
+public class RecyclerView {
+
+  final State mState = new State();
+
+  public static class State {
+    boolean mStructureChanged = false;
+  }
+
+  public abstract static class AdapterDataObserver {
+    public void onChanged() {
+      // Do nothing
+    }
+  }
+
+  private class RecyclerViewDataObserver extends AdapterDataObserver {
+    RecyclerViewDataObserver() {
+    }
+
+    @Override
+    public void onChanged() {
+      // This is the single target of AdapterDataObserver#onChanged(), and could be inlined to
+      // AdapterDataObservable#notifyChanged() as long as this preserves null check of the receiver.
+      // To do so, access the enclosing class' member to use the receiver.
+      mState.mStructureChanged = true;
+    }
+  }
+
+  static class AdapterDataObservable extends Observable<AdapterDataObserver> {
+    public void registerObserver(AdapterDataObserver observer) {
+      mObservers.add(observer);
+    }
+    public void notifyChanged() {
+      for (int i = mObservers.size() - 1; i >= 0; i--) {
+        // The single target, RecyclerViewDataObserver#onChange is inlined, along with check-cast:
+        //    AdapterDataObserver observer_i = mObservers.get(i);
+        //    RecyclerViewDataObserver casted_obs = (RecyclerViewDataObserver) observer_i;
+        //    // inlining RecyclerViewDataObserver#onChanged():
+        mObservers.get(i).onChanged();
+      }
+    }
+  }
+
+  public abstract static class Adapter {
+    private final AdapterDataObservable mObservable = new AdapterDataObservable();
+
+    public void registerAdapterDataObserver(AdapterDataObserver observer) {
+      mObservable.registerObserver(observer);
+    }
+
+    public final void notifyDataSetChanged() {
+      // Single callee, AdapterDataObservable#notifyChanged(), could be inlined, but should not.
+      // Accessing AdapterDataObservable.mObservers, which is a protected field in Observable,
+      // results in an illegal access error.
+      //
+      // Without the above inlining, the inlining constraint for the target here is SUBCLASS due to
+      // that protected field, and thus decline to inline because the holder, Adapter, is not a
+      // subtype of the target holder, AdapterDataObservable.
+      // However, after the above inlining, check-cast to RecyclerViewDataObserver overrides that
+      // condition to PACKAGE, which accidentally allows the target to be inlined here.
+      mObservable.notifyChanged();
+    }
+  }
+
+  private final RecyclerViewDataObserver mObserver = new RecyclerViewDataObserver();
+
+  public void setAdapter(Adapter adapter) {
+    adapter.registerAdapterDataObserver(mObserver);
+  }
+
+}
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 b6ec9c3..c8713e3 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,23 +37,28 @@
     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", // single non-float typed zero (ie, int type)
+        "const               v0, 0",
         "sput-boolean        v0, LTest;->booleanField:Z",
         "sput-byte           v0, LTest;->byteField:B",
-        "sput-char           v0, LTest;->charField:C",
         "sput-short          v0, LTest;->shortField:S",
         "sput                v0, LTest;->intField:I",
-        "const               v0, 0", // float typed zero
+        // Dalvik 4.x. does not require a new const 0 here.
         "sput                v0, LTest;->floatField:F",
-        "const               v0, 0", // reference typed null
+        additionalConstZero,  // Required for Dalvik 4.x.
+        "sput-char           v0, LTest;->charField:C",
+        "const               v0, 0",
         "sput-object         v0, LTest;->objectField:Ljava/lang/Object;",
         "sput-object         v0, LTest;->stringField:Ljava/lang/String;",
         "sput-object         v0, LTest;->testField:LTest;",
-        "const-wide          v0, 0", // wide typed long
+        "const-wide          v0, 0",
         "sput-wide           v0, LTest;->longField:J",
-        "const-wide          v0, 0", // wide typed double
+        additionalConstZeroWide,  // Required for Dalvik 4.x.
         "sput-wide           v0, LTest;->doubleField:D",
         "return-void");
 
@@ -97,23 +103,28 @@
     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",
         "iput-boolean        v0, p0, LTest;->booleanField:Z",
         "iput-byte           v0, p0, LTest;->byteField:B",
-        "iput-char           v0, p0, LTest;->charField:C",
         "iput-short          v0, p0, LTest;->shortField:S",
         "iput                v0, p0, LTest;->intField:I",
-        "const               v0, 0",
+        // 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;",
         "iput-object         v0, p0, LTest;->stringField:Ljava/lang/String;",
         "iput-object         v0, p0, LTest;->testField:LTest;",
         "const-wide          v0, 0",
         "iput-wide           v0, p0, LTest;->longField:J",
-        "const-wide          v0, 0",
+        additionalConstZeroWide,  // Required for Dalvik 4.x.
         "iput-wide           v0, p0, LTest;->doubleField:D",
         "return-void");
 
diff --git a/src/test/java/com/android/tools/r8/utils/dexinspector/AbsentClassSubject.java b/src/test/java/com/android/tools/r8/utils/dexinspector/AbsentClassSubject.java
index 7213a54..e2fa906 100644
--- a/src/test/java/com/android/tools/r8/utils/dexinspector/AbsentClassSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/dexinspector/AbsentClassSubject.java
@@ -10,12 +10,6 @@
 
 public class AbsentClassSubject extends ClassSubject {
 
-  private DexInspector dexInspector;
-
-  public AbsentClassSubject(DexInspector dexInspector) {
-    this.dexInspector = dexInspector;
-  }
-
   @Override
   public boolean isPresent() {
     return false;
diff --git a/src/test/java/com/android/tools/r8/utils/dexinspector/CfInstructionIterator.java b/src/test/java/com/android/tools/r8/utils/dexinspector/CfInstructionIterator.java
new file mode 100644
index 0000000..d000250
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/utils/dexinspector/CfInstructionIterator.java
@@ -0,0 +1,33 @@
+// 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.utils.dexinspector;
+
+import com.android.tools.r8.cf.code.CfInstruction;
+import com.android.tools.r8.graph.Code;
+import java.util.Iterator;
+
+class CfInstructionIterator implements InstructionIterator {
+
+  private final DexInspector dexInspector;
+  private final Iterator<CfInstruction> iterator;
+
+  CfInstructionIterator(DexInspector dexInspector, MethodSubject method) {
+    this.dexInspector = dexInspector;
+    assert method.isPresent();
+    Code code = method.getMethod().getCode();
+    assert code != null && code.isCfCode();
+    iterator = code.asCfCode().getInstructions().iterator();
+  }
+
+  @Override
+  public boolean hasNext() {
+    return iterator.hasNext();
+  }
+
+  @Override
+  public InstructionSubject next() {
+    return dexInspector.createInstructionSubject(iterator.next());
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/utils/dexinspector/CfInstructionSubject.java b/src/test/java/com/android/tools/r8/utils/dexinspector/CfInstructionSubject.java
new file mode 100644
index 0000000..ae900f3
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/utils/dexinspector/CfInstructionSubject.java
@@ -0,0 +1,118 @@
+// 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.utils.dexinspector;
+
+import com.android.tools.r8.cf.code.CfConstString;
+import com.android.tools.r8.cf.code.CfFieldInstruction;
+import com.android.tools.r8.cf.code.CfGoto;
+import com.android.tools.r8.cf.code.CfIf;
+import com.android.tools.r8.cf.code.CfInstruction;
+import com.android.tools.r8.cf.code.CfInvoke;
+import com.android.tools.r8.cf.code.CfInvokeDynamic;
+import com.android.tools.r8.cf.code.CfLabel;
+import com.android.tools.r8.cf.code.CfNew;
+import com.android.tools.r8.cf.code.CfNop;
+import com.android.tools.r8.cf.code.CfPosition;
+import com.android.tools.r8.cf.code.CfReturnVoid;
+import com.android.tools.r8.cf.code.CfThrow;
+import org.objectweb.asm.Opcodes;
+
+public class CfInstructionSubject implements InstructionSubject {
+  protected final CfInstruction instruction;
+
+  public CfInstructionSubject(CfInstruction instruction) {
+    this.instruction = instruction;
+  }
+
+  @Override
+  public boolean isFieldAccess() {
+    return instruction instanceof CfFieldInstruction;
+  }
+
+  @Override
+  public boolean isInvokeVirtual() {
+    return instruction instanceof CfInvoke
+        && ((CfInvoke) instruction).getOpcode() == Opcodes.INVOKEVIRTUAL;
+  }
+
+  @Override
+  public boolean isInvokeInterface() {
+    return instruction instanceof CfInvoke
+        && ((CfInvoke) instruction).getOpcode() == Opcodes.INVOKEINTERFACE;
+  }
+
+  @Override
+  public boolean isInvokeStatic() {
+    return instruction instanceof CfInvoke
+        && ((CfInvoke) instruction).getOpcode() == Opcodes.INVOKESTATIC;
+  }
+
+  @Override
+  public boolean isNop() {
+    return instruction instanceof CfNop;
+  }
+
+  @Override
+  public boolean isConstString() {
+    return instruction instanceof CfConstString;
+  }
+
+  @Override
+  public boolean isConstString(String value) {
+    return isConstString() && ((CfConstString) instruction).getString().toString().equals(value);
+  }
+
+  @Override
+  public boolean isGoto() {
+    return instruction instanceof CfGoto;
+  }
+
+  @Override
+  public boolean isIfNez() {
+    return instruction instanceof CfIf && ((CfIf) instruction).getOpcode() == Opcodes.IFNE;
+  }
+
+  @Override
+  public boolean isIfEqz() {
+    return instruction instanceof CfIf && ((CfIf) instruction).getOpcode() == Opcodes.IFEQ;
+  }
+
+  @Override
+  public boolean isReturnVoid() {
+    return instruction instanceof CfReturnVoid;
+  }
+
+  @Override
+  public boolean isThrow() {
+    return instruction instanceof CfThrow;
+  }
+
+  @Override
+  public boolean isInvoke() {
+    return instruction instanceof CfInvoke || instruction instanceof CfInvokeDynamic;
+  }
+
+  @Override
+  public boolean isNewInstance() {
+    return instruction instanceof CfNew;
+  }
+
+  public boolean isInvokeSpecial() {
+    return instruction instanceof CfInvoke
+        && ((CfInvoke) instruction).getOpcode() == Opcodes.INVOKESPECIAL;
+  }
+
+  public boolean isInvokeDynamic() {
+    return instruction instanceof CfInvokeDynamic;
+  }
+
+  public boolean isLabel() {
+    return instruction instanceof CfLabel;
+  }
+
+  public boolean isPosition() {
+    return instruction instanceof CfPosition;
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/utils/dexinspector/DexInspector.java b/src/test/java/com/android/tools/r8/utils/dexinspector/DexInspector.java
index 51e4ce2..c67a560 100644
--- a/src/test/java/com/android/tools/r8/utils/dexinspector/DexInspector.java
+++ b/src/test/java/com/android/tools/r8/utils/dexinspector/DexInspector.java
@@ -6,8 +6,10 @@
 import static org.junit.Assert.assertTrue;
 
 import com.android.tools.r8.StringResource;
+import com.android.tools.r8.cf.code.CfInstruction;
 import com.android.tools.r8.code.Instruction;
 import com.android.tools.r8.dex.ApplicationReader;
+import com.android.tools.r8.errors.Unimplemented;
 import com.android.tools.r8.graph.Code;
 import com.android.tools.r8.graph.DexAnnotation;
 import com.android.tools.r8.graph.DexAnnotationElement;
@@ -205,7 +207,7 @@
     }
     DexClass clazz = application.definitionFor(toDexTypeIgnorePrimitives(name));
     if (clazz == null) {
-      return new AbsentClassSubject(this);
+      return new AbsentClassSubject();
     }
     return new FoundClassSubject(this, clazz, naming);
   }
@@ -250,15 +252,36 @@
       return new InvokeDexInstructionSubject(this, instruction);
     } else if (dexInst.isFieldAccess()) {
       return new FieldAccessDexInstructionSubject(this, instruction);
+    } else if (dexInst.isNewInstance()) {
+      return new NewInstanceDexInstructionSubject(instruction);
     } else {
       return dexInst;
     }
   }
 
+  InstructionSubject createInstructionSubject(CfInstruction instruction) {
+    CfInstructionSubject cfInst = new CfInstructionSubject(instruction);
+    if (cfInst.isInvoke()) {
+      return new InvokeCfInstructionSubject(this, instruction);
+    } else if (cfInst.isFieldAccess()) {
+      return new FieldAccessCfInstructionSubject(this, instruction);
+    } else if (cfInst.isNewInstance()) {
+      return new NewInstanceCfInstructionSubject(instruction);
+    } else {
+      return cfInst;
+    }
+  }
+
   InstructionIterator createInstructionIterator(MethodSubject method) {
     Code code = method.getMethod().getCode();
-    assert code != null && code.isDexCode();
-    return new DexInstructionIterator(this, method);
+    assert code != null;
+    if (code.isDexCode()) {
+      return new DexInstructionIterator(this, method);
+    } else if (code.isCfCode()) {
+      return new CfInstructionIterator(this, method);
+    } else {
+      throw new Unimplemented("InstructionIterator is implemented for DexCode and CfCode only.");
+    }
   }
 
   // Build the generic signature using the current mapping if any.
diff --git a/src/test/java/com/android/tools/r8/utils/dexinspector/DexInstructionIterator.java b/src/test/java/com/android/tools/r8/utils/dexinspector/DexInstructionIterator.java
index eaff010..9ed4de1 100644
--- a/src/test/java/com/android/tools/r8/utils/dexinspector/DexInstructionIterator.java
+++ b/src/test/java/com/android/tools/r8/utils/dexinspector/DexInstructionIterator.java
@@ -10,7 +10,7 @@
 
 class DexInstructionIterator implements InstructionIterator {
 
-  private DexInspector dexInspector;
+  private final DexInspector dexInspector;
   private final DexCode code;
   private int index;
 
diff --git a/src/test/java/com/android/tools/r8/utils/dexinspector/DexInstructionSubject.java b/src/test/java/com/android/tools/r8/utils/dexinspector/DexInstructionSubject.java
index b2320d3..82d725a 100644
--- a/src/test/java/com/android/tools/r8/utils/dexinspector/DexInstructionSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/dexinspector/DexInstructionSubject.java
@@ -34,6 +34,7 @@
 import com.android.tools.r8.code.IputObject;
 import com.android.tools.r8.code.IputShort;
 import com.android.tools.r8.code.IputWide;
+import com.android.tools.r8.code.NewInstance;
 import com.android.tools.r8.code.Nop;
 import com.android.tools.r8.code.ReturnVoid;
 import com.android.tools.r8.code.Sget;
@@ -53,7 +54,7 @@
 import com.android.tools.r8.code.Throw;
 
 public class DexInstructionSubject implements InstructionSubject {
-  protected Instruction instruction;
+  protected final Instruction instruction;
 
   public DexInstructionSubject(Instruction instruction) {
     this.instruction = instruction;
@@ -75,16 +76,6 @@
   }
 
   @Override
-  public boolean isInvokeDirect() {
-    return instruction instanceof InvokeDirect || instruction instanceof InvokeDirectRange;
-  }
-
-  @Override
-  public boolean isInvokeSuper() {
-    return instruction instanceof InvokeSuper || instruction instanceof InvokeSuperRange;
-  }
-
-  @Override
   public boolean isInvokeStatic() {
     return instruction instanceof InvokeStatic || instruction instanceof InvokeStaticRange;
   }
@@ -131,6 +122,28 @@
     return instruction instanceof Throw;
   }
 
+  @Override
+  public boolean isInvoke() {
+    return isInvokeVirtual()
+        || isInvokeInterface()
+        || isInvokeDirect()
+        || isInvokeSuper()
+        || isInvokeStatic();
+  }
+
+  @Override
+  public boolean isNewInstance() {
+    return instruction instanceof NewInstance;
+  }
+
+  public boolean isInvokeSuper() {
+    return instruction instanceof InvokeSuper || instruction instanceof InvokeSuperRange;
+  }
+
+  public boolean isInvokeDirect() {
+    return instruction instanceof InvokeDirect || instruction instanceof InvokeDirectRange;
+  }
+
   public boolean isConst4() {
     return instruction instanceof Const4;
   }
diff --git a/src/test/java/com/android/tools/r8/utils/dexinspector/FieldAccessCfInstructionSubject.java b/src/test/java/com/android/tools/r8/utils/dexinspector/FieldAccessCfInstructionSubject.java
new file mode 100644
index 0000000..a2103e6
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/utils/dexinspector/FieldAccessCfInstructionSubject.java
@@ -0,0 +1,23 @@
+// 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.utils.dexinspector;
+
+import com.android.tools.r8.cf.code.CfFieldInstruction;
+import com.android.tools.r8.cf.code.CfInstruction;
+
+public class FieldAccessCfInstructionSubject extends CfInstructionSubject
+    implements FieldAccessInstructionSubject {
+  private final DexInspector dexInspector;
+
+  public FieldAccessCfInstructionSubject(DexInspector dexInspector, CfInstruction instruction) {
+    super(instruction);
+    this.dexInspector = dexInspector;
+    assert isFieldAccess();
+  }
+
+  public TypeSubject holder() {
+    return new TypeSubject(dexInspector, ((CfFieldInstruction) instruction).getField().getHolder());
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/utils/dexinspector/FieldAccessDexInstructionSubject.java b/src/test/java/com/android/tools/r8/utils/dexinspector/FieldAccessDexInstructionSubject.java
index c3ea3fc..ed54f90 100644
--- a/src/test/java/com/android/tools/r8/utils/dexinspector/FieldAccessDexInstructionSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/dexinspector/FieldAccessDexInstructionSubject.java
@@ -9,7 +9,7 @@
 public class FieldAccessDexInstructionSubject extends DexInstructionSubject
     implements FieldAccessInstructionSubject {
 
-  private DexInspector dexInspector;
+  private final DexInspector dexInspector;
 
   public FieldAccessDexInstructionSubject(DexInspector dexInspector, Instruction instruction) {
     super(instruction);
diff --git a/src/test/java/com/android/tools/r8/utils/dexinspector/FilteredInstructionIterator.java b/src/test/java/com/android/tools/r8/utils/dexinspector/FilteredInstructionIterator.java
index 33ac77f..5f3c078 100644
--- a/src/test/java/com/android/tools/r8/utils/dexinspector/FilteredInstructionIterator.java
+++ b/src/test/java/com/android/tools/r8/utils/dexinspector/FilteredInstructionIterator.java
@@ -10,14 +10,12 @@
 
 class FilteredInstructionIterator<T extends InstructionSubject> implements Iterator<T> {
 
-  private DexInspector dexInspector;
   private final InstructionIterator iterator;
   private final Predicate<InstructionSubject> predicate;
   private InstructionSubject pendingNext = null;
 
   FilteredInstructionIterator(
       DexInspector dexInspector, MethodSubject method, Predicate<InstructionSubject> predicate) {
-    this.dexInspector = dexInspector;
     this.iterator = dexInspector.createInstructionIterator(method);
     this.predicate = predicate;
     hasNext();
diff --git a/src/test/java/com/android/tools/r8/utils/dexinspector/FoundClassSubject.java b/src/test/java/com/android/tools/r8/utils/dexinspector/FoundClassSubject.java
index 12dbaeb..2202f89 100644
--- a/src/test/java/com/android/tools/r8/utils/dexinspector/FoundClassSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/dexinspector/FoundClassSubject.java
@@ -25,7 +25,7 @@
 
 public class FoundClassSubject extends ClassSubject {
 
-  private DexInspector dexInspector;
+  private final DexInspector dexInspector;
   private final DexClass dexClass;
   final ClassNamingForNameMapper naming;
 
diff --git a/src/test/java/com/android/tools/r8/utils/dexinspector/FoundFieldSubject.java b/src/test/java/com/android/tools/r8/utils/dexinspector/FoundFieldSubject.java
index 52aa0ce..5dfa4f1 100644
--- a/src/test/java/com/android/tools/r8/utils/dexinspector/FoundFieldSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/dexinspector/FoundFieldSubject.java
@@ -12,7 +12,7 @@
 
 public class FoundFieldSubject extends FieldSubject {
 
-  private DexInspector dexInspector;
+  private final DexInspector dexInspector;
   private final FoundClassSubject clazz;
   private final DexEncodedField dexField;
 
diff --git a/src/test/java/com/android/tools/r8/utils/dexinspector/FoundMethodSubject.java b/src/test/java/com/android/tools/r8/utils/dexinspector/FoundMethodSubject.java
index e245258..6eb3858 100644
--- a/src/test/java/com/android/tools/r8/utils/dexinspector/FoundMethodSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/dexinspector/FoundMethodSubject.java
@@ -13,7 +13,7 @@
 
 public class FoundMethodSubject extends MethodSubject {
 
-  private DexInspector dexInspector;
+  private final DexInspector dexInspector;
   private final FoundClassSubject clazz;
   private final DexEncodedMethod dexMethod;
 
diff --git a/src/test/java/com/android/tools/r8/utils/dexinspector/InstructionSubject.java b/src/test/java/com/android/tools/r8/utils/dexinspector/InstructionSubject.java
index 00102e5..b6f1e52 100644
--- a/src/test/java/com/android/tools/r8/utils/dexinspector/InstructionSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/dexinspector/InstructionSubject.java
@@ -11,10 +11,6 @@
 
   boolean isInvokeInterface();
 
-  boolean isInvokeDirect();
-
-  boolean isInvokeSuper();
-
   boolean isInvokeStatic();
 
   boolean isNop();
@@ -33,11 +29,7 @@
 
   boolean isThrow();
 
-  default boolean isInvoke() {
-    return isInvokeVirtual()
-        || isInvokeInterface()
-        || isInvokeDirect()
-        || isInvokeSuper()
-        || isInvokeStatic();
-  }
+  boolean isInvoke();
+
+  boolean isNewInstance();
 }
diff --git a/src/test/java/com/android/tools/r8/utils/dexinspector/InvokeCfInstructionSubject.java b/src/test/java/com/android/tools/r8/utils/dexinspector/InvokeCfInstructionSubject.java
new file mode 100644
index 0000000..4d245b2
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/utils/dexinspector/InvokeCfInstructionSubject.java
@@ -0,0 +1,33 @@
+// 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.utils.dexinspector;
+
+import com.android.tools.r8.cf.code.CfInstruction;
+import com.android.tools.r8.cf.code.CfInvoke;
+import com.android.tools.r8.errors.Unimplemented;
+import com.android.tools.r8.graph.DexMethod;
+
+public class InvokeCfInstructionSubject extends CfInstructionSubject
+    implements InvokeInstructionSubject {
+  private final DexInspector dexInspector;
+
+  public InvokeCfInstructionSubject(DexInspector dexInspector, CfInstruction instruction) {
+    super(instruction);
+    assert isInvoke();
+    this.dexInspector = dexInspector;
+  }
+
+  public TypeSubject holder() {
+    return new TypeSubject(dexInspector, invokedMethod().getHolder());
+  }
+
+  public DexMethod invokedMethod() {
+    if (isInvokeDynamic()) {
+      throw new Unimplemented(
+          "invokeMethod is not implemented for the INVOKEDYNAMIC CF instruction.");
+    }
+    return ((CfInvoke) instruction).getMethod();
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/utils/dexinspector/InvokeDexInstructionSubject.java b/src/test/java/com/android/tools/r8/utils/dexinspector/InvokeDexInstructionSubject.java
index a4f5636..51d0767 100644
--- a/src/test/java/com/android/tools/r8/utils/dexinspector/InvokeDexInstructionSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/dexinspector/InvokeDexInstructionSubject.java
@@ -10,7 +10,7 @@
 public class InvokeDexInstructionSubject extends DexInstructionSubject
     implements InvokeInstructionSubject {
 
-  private DexInspector dexInspector;
+  private final DexInspector dexInspector;
 
   public InvokeDexInstructionSubject(DexInspector dexInspector, Instruction instruction) {
     super(instruction);
diff --git a/src/test/java/com/android/tools/r8/utils/dexinspector/NewInstanceCfInstructionSubject.java b/src/test/java/com/android/tools/r8/utils/dexinspector/NewInstanceCfInstructionSubject.java
new file mode 100644
index 0000000..71a1dfc
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/utils/dexinspector/NewInstanceCfInstructionSubject.java
@@ -0,0 +1,17 @@
+package com.android.tools.r8.utils.dexinspector;
+
+import com.android.tools.r8.cf.code.CfInstruction;
+import com.android.tools.r8.cf.code.CfNew;
+import com.android.tools.r8.graph.DexType;
+
+public class NewInstanceCfInstructionSubject extends CfInstructionSubject
+    implements NewInstanceInstructionSubject {
+  public NewInstanceCfInstructionSubject(CfInstruction instruction) {
+    super(instruction);
+  }
+
+  @Override
+  public DexType getType() {
+    return ((CfNew) instruction).getType();
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/utils/dexinspector/NewInstanceDexInstructionSubject.java b/src/test/java/com/android/tools/r8/utils/dexinspector/NewInstanceDexInstructionSubject.java
new file mode 100644
index 0000000..675ded2
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/utils/dexinspector/NewInstanceDexInstructionSubject.java
@@ -0,0 +1,17 @@
+package com.android.tools.r8.utils.dexinspector;
+
+import com.android.tools.r8.code.Instruction;
+import com.android.tools.r8.code.NewInstance;
+import com.android.tools.r8.graph.DexType;
+
+public class NewInstanceDexInstructionSubject extends DexInstructionSubject
+    implements NewInstanceInstructionSubject {
+  public NewInstanceDexInstructionSubject(Instruction instruction) {
+    super(instruction);
+  }
+
+  @Override
+  public DexType getType() {
+    return ((NewInstance) instruction).getType();
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/utils/dexinspector/NewInstanceInstructionSubject.java b/src/test/java/com/android/tools/r8/utils/dexinspector/NewInstanceInstructionSubject.java
new file mode 100644
index 0000000..98a10ec
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/utils/dexinspector/NewInstanceInstructionSubject.java
@@ -0,0 +1,7 @@
+package com.android.tools.r8.utils.dexinspector;
+
+import com.android.tools.r8.graph.DexType;
+
+public interface NewInstanceInstructionSubject extends InstructionSubject {
+  DexType getType();
+}
diff --git a/src/test/java/com/android/tools/r8/utils/dexinspector/TypeSubject.java b/src/test/java/com/android/tools/r8/utils/dexinspector/TypeSubject.java
index 6a911eb..5b21c41 100644
--- a/src/test/java/com/android/tools/r8/utils/dexinspector/TypeSubject.java
+++ b/src/test/java/com/android/tools/r8/utils/dexinspector/TypeSubject.java
@@ -8,7 +8,7 @@
 
 public class TypeSubject extends Subject {
 
-  private DexInspector dexInspector;
+  private final DexInspector dexInspector;
   private final DexType dexType;
 
   TypeSubject(DexInspector dexInspector, DexType dexType) {