Initial push.
diff --git a/src/test/examplesAndroidO/invokecustom/InvokeCustom.java b/src/test/examplesAndroidO/invokecustom/InvokeCustom.java
new file mode 100644
index 0000000..0d4d5c5
--- /dev/null
+++ b/src/test/examplesAndroidO/invokecustom/InvokeCustom.java
@@ -0,0 +1,177 @@
+// Copyright (c) 2017, 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 invokecustom;
+
+import java.lang.invoke.CallSite;
+import java.lang.invoke.ConstantCallSite;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+
+interface J {
+
+  default void targetMethodTest8() {
+    System.out.println("targetMethodTest8 from J");
+  }
+
+  default void targetMethodTest7() {
+    System.out.println("targetMethodTest7 from J");
+  }
+
+  default void targetMethodTest6() {
+    System.out.println("targetMethodTest6 from J");
+  }
+}
+
+interface I extends J {
+  void targetMethodTest8();
+
+  default void targetMethodTest6() {
+    System.out.println("targetMethodTest6 from I");
+  }
+
+  default void targetMethodTest9() {
+    System.out.println("targetMethodTest9 from I");
+  }
+
+  default void targetMethodTest10() {
+    System.out.println("targetMethodTest10 from I");
+  }
+}
+
+abstract class Super {
+  public void targetMethodTest5() {
+    System.out.println("targetMethodTest5 from Super");
+  }
+
+  abstract void targetMethodTest10();
+}
+
+public class InvokeCustom extends Super implements I {
+
+  private static String staticField1 = "StaticField1";
+
+  private String instanceField1 = "instanceField1";
+
+  private static void targetMethodTest1() {
+    System.out.println("Hello World!");
+  }
+
+  private static void targetMethodTest2(boolean z, byte b, char c, short s, int i, float f, long l,
+      double d, String str) {
+    System.out.println(z);
+    System.out.println(b);
+    System.out.println(c);
+    System.out.println(s);
+    System.out.println(i);
+    System.out.println(f);
+    System.out.println(l);
+    System.out.println(d);
+    System.out.println(str);
+  }
+
+  private static void targetMethodTest3() {
+  }
+
+  public static CallSite bsmLookupStatic(MethodHandles.Lookup caller, String name, MethodType type)
+      throws NoSuchMethodException, IllegalAccessException {
+    final MethodHandles.Lookup lookup = MethodHandles.lookup();
+    final MethodHandle targetMH = lookup.findStatic(lookup.lookupClass(), name, type);
+    return new ConstantCallSite(targetMH.asType(type));
+  }
+
+  public static CallSite bsmLookupStaticWithExtraArgs(
+      MethodHandles.Lookup caller, String name, MethodType type, int i, long l, float f, double d)
+      throws NoSuchMethodException, IllegalAccessException {
+    System.out.println(i);
+    System.out.println(l);
+    System.out.println(f);
+    System.out.println(d);
+    final MethodHandles.Lookup lookup = MethodHandles.lookup();
+    final MethodHandle targetMH = lookup.findStatic(lookup.lookupClass(), name, type);
+    return new ConstantCallSite(targetMH.asType(type));
+  }
+
+  @Override
+  public void targetMethodTest5() {
+    System.out.println("targetMethodTest5 from InvokeCustom");
+  }
+
+  private static void targetMethodTest4() {
+    System.out.println("targetMethodTest4");
+  }
+
+  public static CallSite bsmCreateCallSite(
+      MethodHandles.Lookup caller, String name, MethodType type, MethodHandle mh)
+      throws Throwable {
+    // Using mh to create the call site fails when run on Art. See b/36957105 for details.
+    final MethodHandle targetMH = MethodHandles.lookup().findSpecial(Super.class,
+                "targetMethodTest5", MethodType.methodType(void.class), InvokeCustom.class);
+    return new ConstantCallSite(targetMH);
+  }
+
+  public static CallSite bsmCreateCallCallingtargetMethodTest6(
+      MethodHandles.Lookup caller, String name, MethodType type, MethodHandle mh)
+      throws Throwable {
+    // Using mh to create the call site fails when run on Art. See b/36957105 for details.
+    final MethodHandle targetMH =
+        MethodHandles.lookup().findVirtual(
+            I.class, "targetMethodTest6", MethodType.methodType(void.class));
+    return new ConstantCallSite(targetMH);
+  }
+
+  public static CallSite bsmCreateCallCallingtargetMethodTest7(
+      MethodHandles.Lookup caller, String name, MethodType type, MethodHandle mh)
+      throws Throwable {
+    // Using mh to create the call site fails when run on Art. See b/36957105 for details.
+    final MethodHandle targetMH =
+        MethodHandles.lookup().findVirtual(
+            J.class, "targetMethodTest7", MethodType.methodType(void.class));
+    return new ConstantCallSite(targetMH);
+  }
+
+  public void targetMethodTest8() {
+    System.out.println("targetMethodTest8 from InvokeCustom");
+  }
+
+  public static CallSite bsmCreateCallCallingtargetMethodTest8(
+      MethodHandles.Lookup caller, String name, MethodType type, MethodHandle mh)
+      throws Throwable {
+    // Using mh to create the call site fails when run on Art. See b/36957105 for details.
+    final MethodHandle targetMH =
+        MethodHandles.lookup().findVirtual(
+            J.class, "targetMethodTest8", MethodType.methodType(void.class));
+    return new ConstantCallSite(targetMH);
+  }
+
+  public static CallSite bsmCreateCallCallingtargetMethodTest9(
+      MethodHandles.Lookup caller, String name, MethodType type, MethodHandle mh)
+      throws Throwable {
+    // Using mh to create the call site fails when run on Art. See b/36957105 for details.
+    final MethodHandle targetMH =
+        MethodHandles.lookup().findVirtual(
+            InvokeCustom.class, "targetMethodTest9", MethodType.methodType(void.class));
+    return new ConstantCallSite(targetMH);
+  }
+
+  public void targetMethodTest10() {
+    System.out.println("targetMethodTest10 from InvokeCustom");
+  }
+
+  public static CallSite bsmCreateCallCallingtargetMethodTest10(
+      MethodHandles.Lookup caller, String name, MethodType type, MethodHandle mh)
+      throws Throwable {
+    // Using mh to create the call site fails when run on Art. See b/36957105 for details.
+    final MethodHandle targetMH =
+        MethodHandles.lookup().findVirtual(
+            InvokeCustom.class, "targetMethodTest10", MethodType.methodType(void.class));
+    return new ConstantCallSite(targetMH);
+  }
+
+  public static CallSite bsmCreateCallCallingtargetMethod(
+      MethodHandles.Lookup caller, String name, MethodType type, MethodHandle mh)
+      throws Throwable {
+    return new ConstantCallSite(mh);
+  }
+}
diff --git a/src/test/examplesAndroidO/invokecustom/TestGenerator.java b/src/test/examplesAndroidO/invokecustom/TestGenerator.java
new file mode 100644
index 0000000..883106f
--- /dev/null
+++ b/src/test/examplesAndroidO/invokecustom/TestGenerator.java
@@ -0,0 +1,422 @@
+// Copyright (c) 2017, 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 invokecustom;
+
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.lang.invoke.CallSite;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.Handle;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+
+public class TestGenerator {
+
+  private final Path classNamePath;
+
+  public static void main(String[] args) throws IOException {
+    assert args.length == 1;
+    TestGenerator testGenerator = new TestGenerator(Paths.get(args[0],
+        TestGenerator.class.getPackage().getName(), InvokeCustom.class.getSimpleName() + ".class"));
+    testGenerator.generateTests();
+  }
+
+  public TestGenerator(Path classNamePath) {
+    this.classNamePath = classNamePath;
+  }
+
+  private void generateTests() throws IOException {
+    ClassReader cr = new ClassReader(new FileInputStream(classNamePath.toFile()));
+    ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
+    cr.accept(
+        new ClassVisitor(Opcodes.ASM5, cw) {
+          @Override
+          public void visitEnd() {
+            generateMethodTest1(cw);
+            generateMethodTest2(cw);
+            generateMethodTest3(cw);
+            generateMethodTest4(cw);
+            generateMethodTest5(cw);
+            generateMethodTest6(cw);
+            generateMethodTest7(cw);
+            generateMethodTest8(cw);
+            generateMethodTest9(cw);
+            generateMethodTest10(cw);
+            generateMethodTest11(cw);
+            generateMethodTest12(cw);
+            generateMethodTest13(cw);
+            generateMethodMain(cw);
+            super.visitEnd();
+          }
+        }, 0);
+    new FileOutputStream(classNamePath.toFile()).write(cw.toByteArray());
+  }
+
+  /* generate main method that only call all test methods. */
+  private void generateMethodMain(ClassVisitor cv) {
+    MethodVisitor mv = cv.visitMethod(
+            Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, "main", "([Ljava/lang/String;)V", null, null);
+    mv.visitMethodInsn(
+        Opcodes.INVOKESTATIC, Type.getInternalName(InvokeCustom.class), "test1", "()V", false);
+    mv.visitMethodInsn(
+        Opcodes.INVOKESTATIC, Type.getInternalName(InvokeCustom.class), "test2", "()V", false);
+    mv.visitMethodInsn(
+        Opcodes.INVOKESTATIC, Type.getInternalName(InvokeCustom.class), "test3", "()V", false);
+    mv.visitMethodInsn(
+        Opcodes.INVOKESTATIC, Type.getInternalName(InvokeCustom.class), "test4", "()V", false);
+    mv.visitMethodInsn(
+        Opcodes.INVOKESTATIC, Type.getInternalName(InvokeCustom.class), "test5", "()V", false);
+    mv.visitMethodInsn(
+        Opcodes.INVOKESTATIC, Type.getInternalName(InvokeCustom.class), "test6", "()V", false);
+    mv.visitMethodInsn(
+        Opcodes.INVOKESTATIC, Type.getInternalName(InvokeCustom.class), "test7", "()V", false);
+    mv.visitMethodInsn(
+        Opcodes.INVOKESTATIC, Type.getInternalName(InvokeCustom.class), "test8", "()V", false);
+    mv.visitMethodInsn(
+        Opcodes.INVOKESTATIC, Type.getInternalName(InvokeCustom.class), "test9", "()V", false);
+    mv.visitMethodInsn(
+        Opcodes.INVOKESTATIC, Type.getInternalName(InvokeCustom.class), "test10", "()V", false);
+    mv.visitMethodInsn(
+        Opcodes.INVOKESTATIC, Type.getInternalName(InvokeCustom.class), "test11", "()V", false);
+    mv.visitMethodInsn(
+        Opcodes.INVOKESTATIC, Type.getInternalName(InvokeCustom.class), "test12", "()V", false);
+    mv.visitMethodInsn(
+        Opcodes.INVOKESTATIC, Type.getInternalName(InvokeCustom.class), "test13", "()V", false);
+    mv.visitInsn(Opcodes.RETURN);
+    mv.visitMaxs(-1, -1);
+  }
+
+  /**
+   *  Generate test with an invokedynamic, a static bootstrap method without extra args and no arg
+   *  to the target method.
+   */
+  private void generateMethodTest1(ClassVisitor cv) {
+    MethodVisitor mv = cv.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, "test1", "()V",
+            null, null);
+    MethodType mt =
+        MethodType.methodType(
+            CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class);
+    Handle bootstrap = new Handle( Opcodes.H_INVOKESTATIC, Type.getInternalName(InvokeCustom.class),
+        "bsmLookupStatic", mt.toMethodDescriptorString(), false);
+    mv.visitInvokeDynamicInsn("targetMethodTest1", "()V", bootstrap);
+    mv.visitInsn(Opcodes.RETURN);
+    mv.visitMaxs(-1, -1);
+  }
+
+  /**
+   *  Generate test with an invokedynamic, a static bootstrap method without extra args and
+   *  args to the target method.
+   */
+  private void generateMethodTest2(ClassVisitor cv) {
+    MethodVisitor mv = cv.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, "test2", "()V",
+        null, null);
+    MethodType mt = MethodType.methodType(
+            CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class);
+    Handle bootstrap = new Handle( Opcodes.H_INVOKESTATIC, Type.getInternalName(InvokeCustom.class),
+        "bsmLookupStatic", mt.toMethodDescriptorString(), false);
+    mv.visitLdcInsn(new Boolean(true));
+    mv.visitLdcInsn(new Byte((byte) 127));
+    mv.visitLdcInsn(new Character('c'));
+    mv.visitLdcInsn(new Short((short) 1024));
+    mv.visitLdcInsn(new Integer(123456));
+    mv.visitLdcInsn(new Float(1.2f));
+    mv.visitLdcInsn(new Long(123456789));
+    mv.visitLdcInsn(new Double(3.5123456789));
+    mv.visitLdcInsn("String");
+    mv.visitInvokeDynamicInsn("targetMethodTest2", "(ZBCSIFJDLjava/lang/String;)V", bootstrap);
+    mv.visitInsn(Opcodes.RETURN);
+    mv.visitMaxs(-1, -1);
+  }
+
+  /**
+   *  Generate test with an invokedynamic, a static bootstrap method with extra args and no arg
+   *  to the target method.
+   */
+  private void generateMethodTest3(ClassVisitor cv) {
+    MethodVisitor mv = cv.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, "test3", "()V",
+        null, null);
+    MethodType mt = MethodType.methodType(
+            CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class, int.class,
+        long.class, float.class, double.class);
+    Handle bootstrap = new Handle( Opcodes.H_INVOKESTATIC, Type.getInternalName(InvokeCustom.class),
+        "bsmLookupStaticWithExtraArgs", mt.toMethodDescriptorString(), false);
+    mv.visitInvokeDynamicInsn("targetMethodTest3", "()V", bootstrap, new Integer(1),
+        new Long(123456789), new Float(123.456), new Double(123456.789123));
+    mv.visitInsn(Opcodes.RETURN);
+    mv.visitMaxs(-1, -1);
+  }
+
+  /**
+   *  Generate test with an invokedynamic, a static bootstrap method with an extra arg that is a
+   *  MethodHandle of kind invokespecial.
+   */
+  private void generateMethodTest4(ClassVisitor cv) {
+    MethodVisitor mv = cv.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, "test4", "()V",
+        null, null);
+    MethodType mt = MethodType.methodType(CallSite.class, MethodHandles.Lookup.class, String.class,
+        MethodType.class, MethodHandle.class);
+    Handle bootstrap = new Handle( Opcodes.H_INVOKESTATIC, Type.getInternalName(InvokeCustom.class),
+        "bsmCreateCallSite", mt.toMethodDescriptorString(), false);
+    mv.visitTypeInsn(Opcodes.NEW, Type.getInternalName(InvokeCustom.class));
+    mv.visitInsn(Opcodes.DUP);
+    mv.visitMethodInsn(
+        Opcodes.INVOKESPECIAL, Type.getInternalName(InvokeCustom.class), "<init>", "()V", false);
+    mv.visitInvokeDynamicInsn("targetMethodTest5", "(Linvokecustom/InvokeCustom;)V", bootstrap,
+        new Handle( Opcodes.H_INVOKESPECIAL, Type.getInternalName(Super.class),
+            "targetMethodTest5", "()V", false));
+    mv.visitInsn(Opcodes.RETURN);
+    mv.visitMaxs(-1, -1);
+  }
+
+  /**
+   *  Generate test with an invokedynamic, a static bootstrap method with an extra arg that is a
+   *  MethodHandle of kind invoke interface. The target method is a default method into an interface
+   *  that shadows another default method from a super interface.
+   */
+  private void generateMethodTest5(ClassVisitor cv) {
+    MethodVisitor mv = cv.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, "test5", "()V",
+        null, null);
+    MethodType mt = MethodType.methodType(CallSite.class, MethodHandles.Lookup.class, String.class,
+        MethodType.class, MethodHandle.class);
+    Handle bootstrap = new Handle(Opcodes.H_INVOKESTATIC, Type.getInternalName(InvokeCustom.class),
+        "bsmCreateCallCallingtargetMethodTest6", mt.toMethodDescriptorString(), false);
+    mv.visitTypeInsn(Opcodes.NEW, Type.getInternalName(InvokeCustom.class));
+    mv.visitInsn(Opcodes.DUP);
+    mv.visitMethodInsn(
+        Opcodes.INVOKESPECIAL, Type.getInternalName(InvokeCustom.class), "<init>", "()V", false);
+    mv.visitInvokeDynamicInsn("targetMethodTest6", "(Linvokecustom/I;)V", bootstrap,
+        new Handle(Opcodes.H_INVOKEINTERFACE, Type.getInternalName(I.class),
+            "targetMethodTest6", "()V", true));
+    mv.visitInsn(Opcodes.RETURN);
+    mv.visitMaxs(-1, -1);
+  }
+
+  /**
+   *  Generate test with an invokedynamic, a static bootstrap method with an extra arg that is a
+   *  MethodHandle of kind invoke interface. The target method is a default method into an interface
+   *  that is at the end of a chain of interfaces.
+   */
+  private void generateMethodTest6(ClassVisitor cv) {
+    MethodVisitor mv = cv.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, "test6", "()V",
+        null, null);
+    MethodType mt = MethodType.methodType(CallSite.class, MethodHandles.Lookup.class, String.class,
+        MethodType.class, MethodHandle.class);
+    Handle bootstrap = new Handle(Opcodes.H_INVOKESTATIC, Type.getInternalName(InvokeCustom.class),
+        "bsmCreateCallCallingtargetMethodTest7", mt.toMethodDescriptorString(), false);
+    mv.visitTypeInsn(Opcodes.NEW, Type.getInternalName(InvokeCustom.class));
+    mv.visitInsn(Opcodes.DUP);
+    mv.visitMethodInsn(
+        Opcodes.INVOKESPECIAL, Type.getInternalName(InvokeCustom.class), "<init>", "()V", false);
+    mv.visitInvokeDynamicInsn("targetMethodTest7", "(Linvokecustom/J;)V", bootstrap,
+        new Handle(Opcodes.H_INVOKEINTERFACE, Type.getInternalName(J.class),
+            "targetMethodTest7", "()V", true));
+    mv.visitInsn(Opcodes.RETURN);
+    mv.visitMaxs(-1, -1);
+  }
+
+  /**
+   *  Generate test with an invokedynamic, a static bootstrap method with an extra arg that is a
+   *  MethodHandle of kind invoke interface. The target method is a method into an interface
+   *  that is shadowed by another definition into a sub interfaces.
+   */
+  private void generateMethodTest7(ClassVisitor cv) {
+    MethodVisitor mv = cv.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, "test7", "()V",
+        null, null);
+    MethodType mt = MethodType.methodType(CallSite.class, MethodHandles.Lookup.class, String.class,
+        MethodType.class, MethodHandle.class);
+    Handle bootstrap = new Handle(Opcodes.H_INVOKESTATIC, Type.getInternalName(InvokeCustom.class),
+        "bsmCreateCallCallingtargetMethodTest8", mt.toMethodDescriptorString(), false);
+    mv.visitTypeInsn(Opcodes.NEW, Type.getInternalName(InvokeCustom.class));
+    mv.visitInsn(Opcodes.DUP);
+    mv.visitMethodInsn(
+        Opcodes.INVOKESPECIAL, Type.getInternalName(InvokeCustom.class), "<init>", "()V", false);
+    mv.visitInvokeDynamicInsn("targetMethodTest8", "(Linvokecustom/J;)V", bootstrap,
+        new Handle(Opcodes.H_INVOKEINTERFACE, Type.getInternalName(J.class),
+            "targetMethodTest8", "()V", true));
+    mv.visitInsn(Opcodes.RETURN);
+    mv.visitMaxs(-1, -1);
+  }
+
+  /**
+   *  Generate test with an invokedynamic, a static bootstrap method with an extra arg that is a
+   *  MethodHandle of kind invoke virtual. The target method is a method into an interface that is
+   *  not shadowed by an implementation into a classes implementing the interface.
+   */
+  private void generateMethodTest8(ClassVisitor cv) {
+    MethodVisitor mv = cv.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, "test8", "()V",
+        null, null);
+    MethodType mt = MethodType.methodType(CallSite.class, MethodHandles.Lookup.class, String.class,
+        MethodType.class, MethodHandle.class);
+    Handle bootstrap = new Handle(Opcodes.H_INVOKESTATIC, Type.getInternalName(InvokeCustom.class),
+        "bsmCreateCallCallingtargetMethodTest9", mt.toMethodDescriptorString(), false);
+    mv.visitTypeInsn(Opcodes.NEW, Type.getInternalName(InvokeCustom.class));
+    mv.visitInsn(Opcodes.DUP);
+    mv.visitMethodInsn(
+        Opcodes.INVOKESPECIAL, Type.getInternalName(InvokeCustom.class), "<init>", "()V", false);
+    mv.visitInvokeDynamicInsn("targetMethodTest9", "(Linvokecustom/InvokeCustom;)V", bootstrap,
+        new Handle(Opcodes.H_INVOKEVIRTUAL, Type.getInternalName(InvokeCustom.class),
+            "targetMethodTest9", "()V", false));
+    mv.visitInsn(Opcodes.RETURN);
+    mv.visitMaxs(-1, -1);
+  }
+
+  /**
+   *  Generate test with an invokedynamic, a static bootstrap method with an extra arg that is a
+   *  MethodHandle of kind invoke virtual. The target method is a method into a class implementing
+   *  an abstract method and that shadows a default method from an interface.
+   */
+  private void generateMethodTest9(ClassVisitor cv) {
+    MethodVisitor mv = cv.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, "test9", "()V",
+        null, null);
+    MethodType mt = MethodType.methodType(CallSite.class, MethodHandles.Lookup.class, String.class,
+        MethodType.class, MethodHandle.class);
+    Handle bootstrap = new Handle(Opcodes.H_INVOKESTATIC, Type.getInternalName(InvokeCustom.class),
+        "bsmCreateCallCallingtargetMethodTest10", mt.toMethodDescriptorString(), false);
+    mv.visitTypeInsn(Opcodes.NEW, Type.getInternalName(InvokeCustom.class));
+    mv.visitInsn(Opcodes.DUP);
+    mv.visitMethodInsn(
+        Opcodes.INVOKESPECIAL, Type.getInternalName(InvokeCustom.class), "<init>", "()V", false);
+    mv.visitInvokeDynamicInsn("targetMethodTest10", "(Linvokecustom/InvokeCustom;)V", bootstrap,
+        new Handle(Opcodes.H_INVOKEVIRTUAL, Type.getInternalName(InvokeCustom.class),
+            "targetMethodTest10", "()V", false));
+    mv.visitInsn(Opcodes.RETURN);
+    mv.visitMaxs(-1, -1);
+  }
+
+  /**
+   *  Generate test with an invokedynamic, a static bootstrap method with an extra arg that is a
+   *  MethodHandle of kind get static. The method handle read a static field from a class.
+   */
+  private void generateMethodTest10(ClassVisitor cv) {
+    MethodVisitor mv = cv.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, "test10", "()V",
+        null, null);
+    MethodType mt = MethodType.methodType(CallSite.class, MethodHandles.Lookup.class, String.class,
+        MethodType.class, MethodHandle.class);
+    Handle bootstrap = new Handle(Opcodes.H_INVOKESTATIC, Type.getInternalName(InvokeCustom.class),
+        "bsmCreateCallCallingtargetMethod", mt.toMethodDescriptorString(), false);
+    mv.visitFieldInsn(Opcodes.GETSTATIC,
+        "java/lang/System",
+        "out",
+        "Ljava/io/PrintStream;");
+    mv.visitInvokeDynamicInsn("staticField1", "()Ljava/lang/String;", bootstrap,
+        new Handle(Opcodes.H_GETSTATIC, Type.getInternalName(InvokeCustom.class),
+            "staticField1", "Ljava/lang/String;", false));
+    mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
+        "java/io/PrintStream",
+        "println",
+        "(Ljava/lang/String;)V", false);
+    mv.visitInsn(Opcodes.RETURN);
+    mv.visitMaxs(-1, -1);
+  }
+
+  /**
+   * Generate test with an invokedynamic, a static bootstrap method with an extra arg that is a
+   * MethodHandle of kind put static. The method handle write a static field in a class and then
+   * print its value.
+   */
+  private void generateMethodTest11(ClassVisitor cv) {
+    MethodVisitor mv = cv.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, "test11", "()V",
+        null, null);
+    MethodType mt = MethodType.methodType(CallSite.class, MethodHandles.Lookup.class, String.class,
+            MethodType.class, MethodHandle.class);
+    Handle bootstrap = new Handle(Opcodes.H_INVOKESTATIC, Type.getInternalName(InvokeCustom.class),
+        "bsmCreateCallCallingtargetMethod", mt.toMethodDescriptorString(), false);
+    mv.visitLdcInsn("Write static field");
+    mv.visitInvokeDynamicInsn("staticField1", "(Ljava/lang/String;)V", bootstrap,
+        new Handle(Opcodes.H_PUTSTATIC, Type.getInternalName(InvokeCustom.class),
+            "staticField1", "Ljava/lang/String;", false));
+    mv.visitFieldInsn(Opcodes.GETSTATIC,
+        "java/lang/System",
+        "out",
+        "Ljava/io/PrintStream;");
+    mv.visitFieldInsn(Opcodes.GETSTATIC,
+        Type.getInternalName(InvokeCustom.class),
+        "staticField1",
+        "Ljava/lang/String;");
+    mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
+        "java/io/PrintStream",
+        "println",
+        "(Ljava/lang/String;)V", false);
+    mv.visitInsn(Opcodes.RETURN);
+    mv.visitMaxs(-1, -1);
+  }
+
+  /**
+   *  Generate test with an invokedynamic, a static bootstrap method with an extra arg that is a
+   *  MethodHandle of kind get instance. The method handle read an instance field from a class.
+   */
+  private void generateMethodTest12(ClassVisitor cv) {
+    MethodVisitor mv = cv.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, "test12", "()V",
+        null, null);
+    MethodType mt = MethodType.methodType(CallSite.class, MethodHandles.Lookup.class, String.class,
+        MethodType.class, MethodHandle.class);
+    Handle bootstrap = new Handle(Opcodes.H_INVOKESTATIC, Type.getInternalName(InvokeCustom.class),
+        "bsmCreateCallCallingtargetMethod", mt.toMethodDescriptorString(), false);
+    mv.visitFieldInsn(Opcodes.GETSTATIC,
+        "java/lang/System",
+        "out",
+        "Ljava/io/PrintStream;");
+    mv.visitTypeInsn(Opcodes.NEW, Type.getInternalName(InvokeCustom.class));
+    mv.visitInsn(Opcodes.DUP);
+    mv.visitMethodInsn(
+        Opcodes.INVOKESPECIAL, Type.getInternalName(InvokeCustom.class), "<init>", "()V", false);
+    mv.visitInvokeDynamicInsn("instanceField1", "(Linvokecustom/InvokeCustom;)Ljava/lang/String;",
+        bootstrap, new Handle(Opcodes.H_GETFIELD, Type.getInternalName(InvokeCustom.class),
+            "instanceField1", "Ljava/lang/String;", false));
+    mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
+        "java/io/PrintStream",
+        "println",
+        "(Ljava/lang/String;)V", false);
+    mv.visitInsn(Opcodes.RETURN);
+    mv.visitMaxs(-1, -1);
+  }
+
+  /**
+   * Generate test with an invokedynamic, a static bootstrap method with an extra arg that is a
+   * MethodHandle of kind put instance. The method handle write an instance field in a class and
+   * then print its value.
+   */
+  private void generateMethodTest13(ClassVisitor cv) {
+    MethodVisitor mv = cv.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, "test13", "()V",
+        null, null);
+    MethodType mt = MethodType.methodType(CallSite.class, MethodHandles.Lookup.class, String.class,
+        MethodType.class, MethodHandle.class);
+    Handle bootstrap = new Handle(Opcodes.H_INVOKESTATIC, Type.getInternalName(InvokeCustom.class),
+        "bsmCreateCallCallingtargetMethod", mt.toMethodDescriptorString(), false);
+    mv.visitTypeInsn(Opcodes.NEW, Type.getInternalName(InvokeCustom.class));
+    mv.visitInsn(Opcodes.DUP);
+    mv.visitMethodInsn(
+        Opcodes.INVOKESPECIAL, Type.getInternalName(InvokeCustom.class), "<init>", "()V", false);
+    mv.visitVarInsn(Opcodes.ASTORE, 0);
+    mv.visitVarInsn(Opcodes.ALOAD, 0);
+    mv.visitLdcInsn("Write instance field");
+    mv.visitInvokeDynamicInsn("instanceField1", "(Linvokecustom/InvokeCustom;Ljava/lang/String;)V",
+        bootstrap, new Handle(Opcodes.H_PUTFIELD, Type.getInternalName(InvokeCustom.class),
+            "instanceField1", "Ljava/lang/String;", false));
+    mv.visitFieldInsn(Opcodes.GETSTATIC,
+        "java/lang/System",
+        "out",
+        "Ljava/io/PrintStream;");
+    mv.visitVarInsn(Opcodes.ALOAD, 0);
+    mv.visitFieldInsn(Opcodes.GETFIELD,
+        Type.getInternalName(InvokeCustom.class),
+        "instanceField1",
+        "Ljava/lang/String;");
+    mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
+        "java/io/PrintStream",
+        "println",
+        "(Ljava/lang/String;)V", false);
+    mv.visitInsn(Opcodes.RETURN);
+    mv.visitMaxs(-1, -1);
+  }
+}
diff --git a/src/test/examplesAndroidO/invokecustom/keep-rules.txt b/src/test/examplesAndroidO/invokecustom/keep-rules.txt
new file mode 100644
index 0000000..52fa2a7
--- /dev/null
+++ b/src/test/examplesAndroidO/invokecustom/keep-rules.txt
@@ -0,0 +1,17 @@
+# Copyright (c) 2017, 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.
+
+# Keep the application entry point and the target methods of invoke-custom because these methods
+# can not be known at compile time. Get rid of everything that is not reachable from there.
+-keep public class invokecustom.InvokeCustom {
+  public static void main(...);
+}
+
+-keepclassmembers  class * {
+  *** targetMethodTest*(...);
+}
+
+# allow access modification to enable minification
+-allowaccessmodification
+
diff --git a/src/test/examplesAndroidO/invokepolymorphic/InvokePolymorphic.java b/src/test/examplesAndroidO/invokepolymorphic/InvokePolymorphic.java
new file mode 100644
index 0000000..90cb064
--- /dev/null
+++ b/src/test/examplesAndroidO/invokepolymorphic/InvokePolymorphic.java
@@ -0,0 +1,104 @@
+// Copyright (c) 2017, 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 invokepolymorphic;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+
+class Data {
+}
+
+public class InvokePolymorphic {
+
+  public String buildString(Integer i1, int i2, String s) {
+    return (i1 == null ? "N" : "!N") + "-" + i2 + "-" + s;
+  }
+
+  public void testInvokePolymorphic() {
+    MethodType mt = MethodType.methodType(String.class, Integer.class, int.class, String.class);
+    MethodHandles.Lookup lk = MethodHandles.lookup();
+
+    try {
+      MethodHandle mh = lk.findVirtual(getClass(), "buildString", mt);
+      System.out.println(mh.invoke(this, null, 1, "string"));
+    } catch (Throwable t) {
+      t.printStackTrace();
+    }
+  }
+
+  public String buildString(
+      byte b, char c, short s, float f, double d, long l, Integer i1, int i2, String str) {
+    return b + "-" + c + "-" + s + "-" + f + "-" + d + "-" + l + "-" + (i1 == null ? "N" : "!N")
+        + "-" + i2 + "-" + str;
+  }
+
+  public void testInvokePolymorphicRange() {
+    MethodType mt = MethodType.methodType(String.class, byte.class, char.class, short.class,
+        float.class, double.class, long.class, Integer.class, int.class, String.class);
+    MethodHandles.Lookup lk = MethodHandles.lookup();
+
+    try {
+      MethodHandle mh = lk.findVirtual(getClass(), "buildString", mt);
+      System.out.println(
+          mh.invoke(this, (byte) 2, 'a', (short) 0xFFFF, 1.1f, 2.24d, 12345678L, null,
+              1, "string"));
+    } catch (Throwable t) {
+      t.printStackTrace();
+    }
+  }
+
+  public static void testWithAllTypes(
+      boolean z, char a, short b, int c, long d, float e, double f, String g, Object h) {
+    System.out.println(z);
+    System.out.println(a);
+    System.out.println(b);
+    System.out.println(c);
+    System.out.println(d);
+    System.out.println(e);
+    System.out.println(f);
+    System.out.println(g);
+    System.out.println(h);
+  }
+
+  public void testInvokePolymorphicWithAllTypes() {
+    try {
+      MethodHandle mth =
+          MethodHandles.lookup()
+              .findStatic(
+                  InvokePolymorphic.class,
+                  "testWithAllTypes",
+                  MethodType.methodType(
+                      void.class, boolean.class, char.class, short.class, int.class, long.class,
+                      float.class, double.class, String.class, Object.class));
+      mth.invokeExact(false,'h', (short) 56, 72, Integer.MAX_VALUE + 42l,
+          0.56f, 100.0d, "hello", (Object) "goodbye");
+    } catch (Throwable t) {
+      t.printStackTrace();
+    }
+  }
+
+  public MethodHandle testInvokePolymorphicWithConstructor() {
+    MethodHandle mh = null;
+    MethodType mt = MethodType.methodType(void.class);
+    MethodHandles.Lookup lk = MethodHandles.lookup();
+
+    try {
+      mh = lk.findConstructor(Data.class, mt);
+      System.out.println(mh.invoke().getClass() == Data.class);
+    } catch (Throwable t) {
+      t.printStackTrace();
+    }
+
+    return mh;
+  }
+
+  public static void main(String[] args) {
+    InvokePolymorphic invokePolymorphic = new InvokePolymorphic();
+    invokePolymorphic.testInvokePolymorphic();
+    invokePolymorphic.testInvokePolymorphicRange();
+    invokePolymorphic.testInvokePolymorphicWithAllTypes();
+    invokePolymorphic.testInvokePolymorphicWithConstructor();
+  }
+}
diff --git a/src/test/examplesAndroidO/lambdadesugaring/LambdaDesugaring.java b/src/test/examplesAndroidO/lambdadesugaring/LambdaDesugaring.java
new file mode 100644
index 0000000..4b7ebd9
--- /dev/null
+++ b/src/test/examplesAndroidO/lambdadesugaring/LambdaDesugaring.java
@@ -0,0 +1,529 @@
+// Copyright (c) 2017, 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 lambdadesugaring;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import lambdadesugaring.legacy.Legacy;
+import lambdadesugaring.other.OtherRefs;
+
+public class LambdaDesugaring {
+  interface I {
+    String foo();
+  }
+
+  interface V {
+    void foo();
+  }
+
+  interface VT<T> {
+    void foo(T t);
+  }
+
+  interface P1<X> {
+    X foo(int i);
+  }
+
+  interface I2 extends I {
+  }
+
+  interface I3 {
+    String foo();
+  }
+
+  interface M1 {
+  }
+
+  interface M2 {
+  }
+
+  interface J {
+    String foo(String a, int b, boolean c);
+  }
+
+  interface G {
+    A foo();
+  }
+
+  interface H<T extends A> {
+    T foo(T o);
+  }
+
+  interface K {
+    Object foo(String a, String b, String c);
+  }
+
+  interface ObjectProvider {
+    Object act();
+  }
+
+  interface S2Z {
+    boolean foo(String a);
+  }
+
+  interface SS2Z {
+    boolean foo(String a, String b);
+  }
+
+  interface ArrayTransformerA<T> {
+    T[] transform(T[] a);
+  }
+
+  @SuppressWarnings("unchecked")
+  interface ArrayTransformerB<T> {
+    T[] transform(T... a);
+  }
+
+  static <T> void print(T[] a) {
+    StringBuilder builder = new StringBuilder("{");
+    String sep = "";
+    for (T s : a) {
+      builder.append(sep).append(s.toString());
+      sep = ", ";
+    }
+    builder.append("}");
+    System.out.println(builder.toString());
+  }
+
+  <T> T[] reorder(T[] a) {
+    int size = a.length;
+    for (int x = 0; x < size / 2; x++) {
+      T t = a[x];
+      a[x] = a[size - 1 - x];
+      a[size - 1 - x] = t;
+    }
+    return a;
+  }
+
+  static void atA(ArrayTransformerA<Integer> f) {
+    print(f.transform(new Integer[] { 1, 2, 3 }));
+  }
+
+  static void atB(ArrayTransformerB<String> f) {
+    print(f.transform("A", "B", "C"));
+  }
+
+  public static String staticUnused() {
+    return "ReleaseTests::staticUnused";
+  }
+
+  public static void testUnusedLambdas() {
+    System.out.print("Before unused ... ");
+    Object o = (I) LambdaDesugaring::staticUnused;
+    System.out.println("after unused.");
+  }
+
+  class A {
+    final String toString;
+
+    A(String toString) {
+      this.toString = toString;
+    }
+
+    @Override
+    public String toString() {
+      return toString;
+    }
+  }
+
+  class B extends A {
+    B(String toString) {
+      super(toString);
+    }
+  }
+
+  class C extends B {
+    C(String toString) {
+      super(toString);
+    }
+  }
+
+  class D extends C {
+    D(String toString) {
+      super(toString);
+    }
+  }
+
+  public static class Refs {
+    public static String f(I i) {
+      return i.foo();
+    }
+
+    public static void v(V v) {
+      v.foo();
+    }
+
+    public static void vt(VT<String> v) {
+      v.foo(null);
+    }
+
+    public static String p1(P1 p) {
+      return p.foo(123).getClass().getCanonicalName();
+    }
+
+    public static String pSS2Z(SS2Z p) {
+      return "" + p.foo("123", "321");
+    }
+
+    public static String pS2Z(S2Z p) {
+      return "" + p.foo("123");
+    }
+
+    public static String p3(K k) {
+      return k.foo("A", "B", "C").toString();
+    }
+
+    public static String g(ObjectProvider op) {
+      return op.act().toString();
+    }
+
+    static class A extends OtherRefs {
+      String fooInternal() {
+        return "Refs::A::fooInternal()";
+      }
+
+      protected String fooProtected() {
+        return "Refs::A::fooProtected()";
+      }
+
+      protected String fooProtectedOverridden() {
+        return "Refs::A::fooProtectedOverridden()";
+      }
+
+      protected static String staticProtected() {
+        return "Refs::A::staticProtected()";
+      }
+
+      static String staticInternal() {
+        return "Refs::A::staticInternal()";
+      }
+    }
+
+    public static class B extends A {
+      public void test() {
+        System.out.println(f(new A()::fooInternal));
+        System.out.println(f(this::fooInternal));
+        System.out.println(f(this::fooProtected));
+        System.out.println(f(this::fooProtectedOverridden));
+        System.out.println(f(this::fooPublic));
+        System.out.println(f(this::fooInternal));
+
+        System.out.println(f(super::fooProtectedOverridden));
+        System.out.println(f(this::fooOtherProtected));
+        System.out.println(f(this::fooOtherPublic));
+
+        System.out.println(g(this::fooPrivate));
+        System.out.println(g(new Integer(123)::toString));
+        System.out.println(g(System::lineSeparator));
+
+        System.out.println(f(A::staticInternal));
+        System.out.println(f(A::staticProtected));
+        System.out.println(f(B::staticPrivate));
+        System.out.println(f(OtherRefs::staticOtherPublic));
+        System.out.println(f(OtherRefs::staticOtherProtected));
+
+        System.out.println(g(StringBuilder::new));
+        System.out.println(g(OtherRefs.PublicInit::new));
+        System.out.println(ProtectedInit.testProtected());
+        System.out.println(g(ProtectedInit::new));
+        System.out.println(g(InternalInit::new));
+        System.out.println(PrivateInit.testPrivate());
+        System.out.println(g(PrivateInit::new));
+
+        System.out.println(p1(D[]::new));
+        System.out.println(p1(Integer::new));
+        System.out.println(p1(B::staticArray));
+
+        System.out.println(pSS2Z(String::equalsIgnoreCase));
+        System.out.println(pS2Z("123321"::contains));
+        System.out.println(pS2Z(String::isEmpty));
+
+        System.out.println(p3(B::fooConcat));
+
+        v(D::new); // Discarding the return value
+        vt((new ArrayList<String>())::add);
+
+        I3 i3 = this::fooPrivate;
+        System.out.println(f(i3::foo));
+      }
+
+      private static String staticPrivate() {
+        return "Refs::B::staticPrivate()";
+      }
+
+      private String fooPrivate() {
+        return "Refs::B::fooPrivate()";
+      }
+
+      String fooInternal() {
+        return "Refs::B::fooInternal()";
+      }
+
+      public static StringBuilder fooConcat(Object... objs) {
+        StringBuilder builder = new StringBuilder("Refs::B::fooConcat(");
+        String sep = "";
+        for (Object obj : objs) {
+          builder.append(sep).append(obj.toString());
+          sep = ", ";
+        }
+        return builder.append(")");
+      }
+
+      @Override
+      protected String fooProtectedOverridden() {
+        return "Refs::B::fooProtectedOverridden()";
+      }
+
+      public String fooPublic() {
+        return "Refs::B::fooPublic()";
+      }
+
+      static int[] staticArray(int size) {
+        return new int[size];
+      }
+    }
+
+    static class D {
+      D() {
+        System.out.println("Refs::D::init()");
+      }
+    }
+
+    public static class ProtectedInit extends OtherRefs.PublicInit {
+      protected ProtectedInit() {
+      }
+
+      static String testProtected() {
+        return g(ProtectedInit::new);
+      }
+
+      @Override
+      public String toString() {
+        return "OtherRefs::ProtectedInit::init()";
+      }
+    }
+
+    static class InternalInit extends ProtectedInit {
+      InternalInit() {
+      }
+
+      @Override
+      public String toString() {
+        return "Refs::InternalInit::init()";
+      }
+    }
+
+    static class PrivateInit extends InternalInit {
+      private PrivateInit() {
+      }
+
+      static String testPrivate() {
+        return g(PrivateInit::new);
+      }
+
+      @Override
+      public String toString() {
+        return "Refs::PrivateInit::init()";
+      }
+    }
+  }
+
+  public void testLambdasSimple() {
+    System.out.println(f(() -> "testLambdasSimple#1"));
+    System.out.println(
+        g((a, b, c) -> "{" + a + ":" + b + ":" + c + "}",
+            "testLambdasSimple#2", 123, true));
+  }
+
+  public void testLambdasSimpleWithCaptures() {
+    String s = "<stirng>";
+    long l = 1234567890123456789L;
+    char c = '#';
+
+    System.out.println(
+        g((x, y, z) -> "{" + s + ":" + l + ":" + c + ":" + x + ":" + y + ":" + z + "}",
+            "param1", 2, false));
+
+    I i1 = () -> "i1";
+    I i2 = () -> i1.foo() + ":i2";
+    I i3 = () -> i2.foo() + ":i3";
+    System.out.println(f(() -> "{" + i3.foo() + ":anonymous}"));
+  }
+
+  public void testInstructionPatchingWithCatchHandlers() {
+    try {
+      int a = 1, b = 0;
+      System.out.println(f(() -> "testInstructionPatchingWithCatchHandlers:1"));
+      System.out.println(f(() -> ("does not matter " + (a / b))));
+    } catch (IndexOutOfBoundsException | ArithmeticException e) {
+      System.out.println("testInstructionPatchingWithCatchHandlers:Divide By Zero");
+    } catch (RuntimeException re) {
+      throw re;
+    } catch (Exception e) {
+      throw new RuntimeException(e);
+    }
+
+    int changes = -1;
+    try {
+      if (f(() -> "").isEmpty()) {
+        changes = 32;
+        System.out.println(f(() -> "testInstructionPatchingWithCatchHandlers:lambda"));
+        throw new RuntimeException();
+      } else {
+        changes = 42;
+        throw new RuntimeException();
+      }
+    } catch (Throwable t) {
+      System.out.println("testInstructionPatchingWithCatchHandlers:changes=" + changes);
+    }
+  }
+
+  public void testInstanceLambdaMethods() {
+    Integer i = 12345;
+    System.out.println(h(() -> new A("{testInstanceLambdaMethods:" + i + "}")));
+  }
+
+  @SuppressWarnings("unchecked")
+  private void testEnforcedSignatureHelper() {
+    H h = ((H<B>) x -> new B("{testEnforcedSignature:" + x + "}"));
+    System.out.println(h.foo(new A("A")).toString());
+  }
+
+  public void testEnforcedSignature() {
+    String capture = "capture";
+    System.out.println(i(x -> new B("{testEnforcedSignature:" + x + "}")));
+    System.out.println(i(x -> new B("{testEnforcedSignature:" + capture + "}")));
+
+    try {
+      testEnforcedSignatureHelper();
+    } catch (Exception e) {
+      System.out.println(e.getMessage());
+    }
+
+    atA(t -> new LambdaDesugaring().reorder(t));
+    atB(t -> new LambdaDesugaring().reorder(t));
+  }
+
+  public void testMultipleInterfaces() {
+    System.out.println(j((I2 & M1 & I3 & M2) () -> "{testMultipleInterfaces:1}"));
+
+    Object o = (I2 & M1 & I3 & M2) () -> "{testMultipleInterfaces:2}";
+    M1 m1 = (M1) o;
+    M2 m2 = (M2) m1;
+    I i = (I) m2;
+    System.out.println(((I3) i).foo());
+
+    o = (I2 & Serializable & M2) () -> "{testMultipleInterfaces:3}";
+    m2 = (M2) o;
+    Serializable s = (Serializable) m2;
+    System.out.println(((I) s).foo());
+  }
+
+  public void testBridges() {
+    k((Legacy.BH) (x -> x), "{testBridges:1}");
+    k((Legacy.BK<Legacy.D> & Serializable) (x -> x), new Legacy.D("{testBridges:2}"));
+    // k((Legacy.BL) (x -> x), new Legacy.B("{testBridges:3}")); crashes javac
+    k((Legacy.BM) (x -> x), new Legacy.C("{testBridges:4}"));
+  }
+
+  public String f(I i) {
+    return i.foo();
+  }
+
+  String g(J j, String a, int b, boolean c) {
+    return j.foo(a, b, c);
+  }
+
+  String h(G g) {
+    return g.foo().toString();
+  }
+
+  String i(H<B> h) {
+    return h.foo(new B("i(H<B>)")).toString();
+  }
+
+  <T extends I2 & M1 & M2 & I3> String j(T l) {
+    return ((I3) ((M2) ((M1) (((I2) l))))).foo();
+  }
+
+  static <T> void k(Legacy.BI<T> i, T v) {
+    System.out.println(i.foo(v).toString());
+  }
+
+  static I statelessLambda() {
+    return InstanceAndClassChecks::staticProvider;
+  }
+
+  static I statefulLambda() {
+    return InstanceAndClassChecks.INSTANCE::instanceProvider;
+  }
+
+  static class InstanceAndClassChecks {
+    static final InstanceAndClassChecks INSTANCE = new InstanceAndClassChecks();
+
+    static void test() {
+      assertSameInstance(
+          InstanceAndClassChecks::staticProvider,
+          InstanceAndClassChecks::staticProvider,
+          "Instances must be same");
+      assertSameInstance(
+          InstanceAndClassChecks::staticProvider,
+          statelessLambda(),
+          "Instances must be same");
+
+      assertDifferentInstance(
+          INSTANCE::instanceProvider,
+          INSTANCE::instanceProvider,
+          "Instances must be different");
+      assertDifferentInstance(
+          INSTANCE::instanceProvider,
+          statefulLambda(), "Instances must be different");
+    }
+
+    public static String staticProvider() {
+      return "staticProvider";
+    }
+
+    public String instanceProvider() {
+      return "instanceProvider";
+    }
+
+    static void assertSameInstance(I a, I b, String msg) {
+      if (a != b) {
+        throw new AssertionError(msg);
+      }
+    }
+
+    static void assertDifferentInstance(I a, I b, String msg) {
+      if (a == b) {
+        throw new AssertionError(msg);
+      }
+    }
+  }
+
+  public static void main(String[] args) {
+    LambdaDesugaring tests = new LambdaDesugaring();
+    tests.testLambdasSimple();
+    LambdaDesugaring.testUnusedLambdas();
+    tests.testLambdasSimpleWithCaptures();
+    tests.testInstructionPatchingWithCatchHandlers();
+    tests.testInstanceLambdaMethods();
+    tests.testEnforcedSignature();
+    tests.testMultipleInterfaces();
+    tests.testBridges();
+    new Refs.B().test();
+    if (isAndroid()) {
+      InstanceAndClassChecks.test();
+    }
+  }
+
+  static boolean isAndroid() {
+    try {
+      Class.forName("dalvik.system.VMRuntime");
+      return true;
+    } catch (Exception ignored) {
+    }
+    return false;
+  }
+}
diff --git a/src/test/examplesAndroidO/lambdadesugaring/ValueAdjustments.java b/src/test/examplesAndroidO/lambdadesugaring/ValueAdjustments.java
new file mode 100644
index 0000000..b9d2752
--- /dev/null
+++ b/src/test/examplesAndroidO/lambdadesugaring/ValueAdjustments.java
@@ -0,0 +1,330 @@
+// Copyright (c) 2017, 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 lambdadesugaring;
+
+public class ValueAdjustments {
+  interface B2i {
+    int foo(Byte i);
+  }
+
+  interface BnUnB {
+    Object foo(boolean z, Boolean Z, byte b, Byte B, char c, Character C, short s, Short S,
+        int i, Integer I, long l, Long L, float f, Float F, double d, Double D);
+  }
+
+  interface iz {
+    boolean f();
+  }
+
+  interface iZ {
+    Boolean f();
+  }
+
+  interface ib {
+    byte f();
+  }
+
+  interface iO {
+    Object f();
+  }
+
+  interface iN {
+    Number f();
+  }
+
+  interface iB {
+    Byte f();
+  }
+
+  interface ic {
+    char f();
+  }
+
+  interface iC {
+    Character f();
+  }
+
+  interface is {
+    short f();
+  }
+
+  interface iS {
+    Short f();
+  }
+
+  interface ii {
+    int f();
+  }
+
+  interface iI {
+    Integer f();
+  }
+
+  interface ij {
+    long f();
+  }
+
+  interface iJ {
+    Long f();
+  }
+
+  interface if_ {
+    float f();
+  }
+
+  interface iF {
+    Float f();
+  }
+
+  interface id {
+    double f();
+  }
+
+  interface iD {
+    Double f();
+  }
+
+  private static void checkObject(StringBuffer builder) {
+    builder
+        .append(((iO) ValueAdjustments::z).f()).append(' ')
+        .append(((iO) ValueAdjustments::Z).f()).append(' ')
+        .append(((iO) ValueAdjustments::b).f()).append(' ')
+        .append(((iO) ValueAdjustments::B).f()).append(' ')
+        .append(((iO) ValueAdjustments::c).f()).append(' ')
+        .append(((iO) ValueAdjustments::C).f()).append(' ')
+        .append(((iO) ValueAdjustments::s).f()).append(' ')
+        .append(((iO) ValueAdjustments::S).f()).append(' ')
+        .append(((iO) ValueAdjustments::i).f()).append(' ')
+        .append(((iO) ValueAdjustments::I).f()).append(' ')
+        .append(((iO) ValueAdjustments::j).f()).append(' ')
+        .append(((iO) ValueAdjustments::J).f()).append(' ')
+        .append(((iO) ValueAdjustments::f).f()).append(' ')
+        .append(((iO) ValueAdjustments::F).f()).append(' ')
+        .append(((iO) ValueAdjustments::d).f()).append(' ')
+        .append(((iO) ValueAdjustments::D).f()).append('\n');
+  }
+
+  private static void checkNumber(StringBuffer builder) {
+    builder
+        .append(((iN) ValueAdjustments::b).f()).append(' ')
+        .append(((iN) ValueAdjustments::B).f()).append(' ')
+        .append(((iN) ValueAdjustments::s).f()).append(' ')
+        .append(((iN) ValueAdjustments::S).f()).append(' ')
+        .append(((iN) ValueAdjustments::i).f()).append(' ')
+        .append(((iN) ValueAdjustments::I).f()).append(' ')
+        .append(((iN) ValueAdjustments::j).f()).append(' ')
+        .append(((iN) ValueAdjustments::J).f()).append(' ')
+        .append(((iN) ValueAdjustments::f).f()).append(' ')
+        .append(((iN) ValueAdjustments::F).f()).append(' ')
+        .append(((iN) ValueAdjustments::d).f()).append(' ')
+        .append(((iN) ValueAdjustments::D).f()).append('\n');
+  }
+
+  private static void checkBoxes(StringBuffer builder) {
+    builder
+        .append(((iZ) ValueAdjustments::z).f()).append(' ')
+        .append(((iB) ValueAdjustments::b).f()).append(' ')
+        .append(((iC) ValueAdjustments::c).f()).append(' ')
+        .append(((iS) ValueAdjustments::s).f()).append(' ')
+        .append(((iI) ValueAdjustments::i).f()).append(' ')
+        .append(((iJ) ValueAdjustments::j).f()).append(' ')
+        .append(((iF) ValueAdjustments::f).f()).append(' ')
+        .append(((iD) ValueAdjustments::d).f()).append('\n');
+  }
+
+  private static void checkDouble(StringBuffer builder) {
+    builder
+        .append(((id) ValueAdjustments::b).f()).append(' ')
+        .append(((id) ValueAdjustments::B).f()).append(' ')
+        .append(((id) ValueAdjustments::s).f()).append(' ')
+        .append(((id) ValueAdjustments::S).f()).append(' ')
+        .append(((id) ValueAdjustments::c).f()).append(' ')
+        .append(((id) ValueAdjustments::C).f()).append(' ')
+        .append(((id) ValueAdjustments::i).f()).append(' ')
+        .append(((id) ValueAdjustments::I).f()).append(' ')
+        .append(((id) ValueAdjustments::j).f()).append(' ')
+        .append(((id) ValueAdjustments::J).f()).append(' ')
+        .append(((id) ValueAdjustments::f).f()).append(' ')
+        .append(((id) ValueAdjustments::F).f()).append(' ')
+        .append(((id) ValueAdjustments::d).f()).append(' ')
+        .append(((id) ValueAdjustments::D).f()).append('\n');
+  }
+
+  private static void checkFloat(StringBuffer builder) {
+    builder
+        .append(((if_) ValueAdjustments::b).f()).append(' ')
+        .append(((if_) ValueAdjustments::B).f()).append(' ')
+        .append(((if_) ValueAdjustments::s).f()).append(' ')
+        .append(((if_) ValueAdjustments::S).f()).append(' ')
+        .append(((if_) ValueAdjustments::c).f()).append(' ')
+        .append(((if_) ValueAdjustments::C).f()).append(' ')
+        .append(((if_) ValueAdjustments::i).f()).append(' ')
+        .append(((if_) ValueAdjustments::I).f()).append(' ')
+        .append(((if_) ValueAdjustments::j).f()).append(' ')
+        .append(((if_) ValueAdjustments::J).f()).append(' ')
+        .append(((if_) ValueAdjustments::f).f()).append(' ')
+        .append(((if_) ValueAdjustments::F).f()).append('\n');
+  }
+
+  private static void checkLong(StringBuffer builder) {
+    builder
+        .append(((ij) ValueAdjustments::b).f()).append(' ')
+        .append(((ij) ValueAdjustments::B).f()).append(' ')
+        .append(((ij) ValueAdjustments::s).f()).append(' ')
+        .append(((ij) ValueAdjustments::S).f()).append(' ')
+        .append(((ij) ValueAdjustments::c).f()).append(' ')
+        .append(((ij) ValueAdjustments::C).f()).append(' ')
+        .append(((ij) ValueAdjustments::i).f()).append(' ')
+        .append(((ij) ValueAdjustments::I).f()).append(' ')
+        .append(((ij) ValueAdjustments::j).f()).append(' ')
+        .append(((ij) ValueAdjustments::J).f()).append('\n');
+  }
+
+  private static void checkInt(StringBuffer builder) {
+    builder
+        .append(((ii) ValueAdjustments::b).f()).append(' ')
+        .append(((ii) ValueAdjustments::B).f()).append(' ')
+        .append(((ii) ValueAdjustments::s).f()).append(' ')
+        .append(((ii) ValueAdjustments::S).f()).append(' ')
+        .append(((ii) ValueAdjustments::c).f()).append(' ')
+        .append(((ii) ValueAdjustments::C).f()).append(' ')
+        .append(((ii) ValueAdjustments::i).f()).append(' ')
+        .append(((ii) ValueAdjustments::I).f()).append('\n');
+  }
+
+  private static void checkShort(StringBuffer builder) {
+    builder
+        .append(((is) ValueAdjustments::b).f()).append(' ')
+        .append(((is) ValueAdjustments::B).f()).append(' ')
+        .append(((is) ValueAdjustments::s).f()).append(' ')
+        .append(((is) ValueAdjustments::S).f()).append('\n');
+  }
+
+  private static void checkChar(StringBuffer builder) {
+    builder
+        .append(((ic) ValueAdjustments::c).f()).append(' ')
+        .append(((ic) ValueAdjustments::C).f()).append('\n');
+  }
+
+  private static void checkByte(StringBuffer builder) {
+    builder
+        .append(((ib) ValueAdjustments::b).f()).append(' ')
+        .append(((ib) ValueAdjustments::B).f()).append('\n');
+  }
+
+  private static void checkBoolean(StringBuffer builder) {
+    builder
+        .append(((iz) ValueAdjustments::z).f()).append(' ')
+        .append(((iz) ValueAdjustments::Z).f()).append('\n');
+  }
+
+  private static void checkMisc(StringBuffer builder) {
+    builder
+        .append(((BnUnB) ValueAdjustments::boxingAndUnboxing).foo(true, false, (byte) 1, (byte) 2,
+            (char) 33, (char) 44, (short) 5, (short) 6, 7, 8, 9, 10L, 11, 12f, 13, 14d))
+        .append('\n')
+        .append(((BnUnB) ValueAdjustments::boxingAndUnboxingW).foo(true, false, (byte) 1, (byte) 2,
+            (char) 33, (char) 44, (short) 5, (short) 6, 7, 8, 9, 10L, 11, 12f, 13, 14d))
+        .append('\n')
+        .append(((B2i) (Integer::new)).foo(Byte.valueOf((byte) 44))).append('\n');
+  }
+
+  static String boxingAndUnboxing(Boolean Z, boolean z, Byte B, byte b, Character C, char c,
+      Short S, short s, Integer I, int i, Long L, long l, Float F, float f, Double D, double d) {
+    return "" + Z + ":" + z + ":" + B + ":" + b + ":" + C + ":" + c + ":" + S + ":" + s
+        + ":" + I + ":" + i + ":" + L + ":" + l + ":" + F + ":" + f + ":" + D + ":" + d;
+  }
+
+  static String boxingAndUnboxingW(boolean Z, boolean z, double B, double b,
+      double C, double c, double S, double s, double I, double i, double L, double l,
+      double F, double f, double D, double d) {
+    return "" + Z + ":" + z + ":" + B + ":" + b + ":" + C + ":" + c + ":" + S + ":" + s
+        + ":" + I + ":" + i + ":" + L + ":" + l + ":" + F + ":" + f + ":" + D + ":" + d;
+  }
+
+  static boolean z() {
+    return true;
+  }
+
+  static byte b() {
+    return 8;
+  }
+
+  static char c() {
+    return 'c';
+  }
+
+  static short s() {
+    return 16;
+  }
+
+  static int i() {
+    return 32;
+  }
+
+  static long j() {
+    return 64;
+  }
+
+  static float f() {
+    return 0.32f;
+  }
+
+  static double d() {
+    return 0.64;
+  }
+
+  static Boolean Z() {
+    return false;
+  }
+
+  static Byte B() {
+    return -8;
+  }
+
+  static Character C() {
+    return 'C';
+  }
+
+  static Short S() {
+    return -16;
+  }
+
+  static Integer I() {
+    return -32;
+  }
+
+  static Long J() {
+    return -64L;
+  }
+
+  static Float F() {
+    return -0.32f;
+  }
+
+  static Double D() {
+    return -0.64;
+  }
+
+  public static void main(String[] args) {
+    StringBuffer builder = new StringBuffer();
+
+    checkBoolean(builder);
+    checkByte(builder);
+    checkChar(builder);
+    checkShort(builder);
+    checkInt(builder);
+    checkLong(builder);
+    checkFloat(builder);
+    checkDouble(builder);
+
+    checkBoxes(builder);
+    checkNumber(builder);
+    checkObject(builder);
+
+    checkMisc(builder);
+
+    System.out.println(builder.toString());
+  }
+}
diff --git a/src/test/examplesAndroidO/lambdadesugaring/legacy/Legacy.java b/src/test/examplesAndroidO/lambdadesugaring/legacy/Legacy.java
new file mode 100644
index 0000000..aabd8d8
--- /dev/null
+++ b/src/test/examplesAndroidO/lambdadesugaring/legacy/Legacy.java
@@ -0,0 +1,56 @@
+// Copyright (c) 2017, 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 lambdadesugaring.legacy;
+
+public class Legacy {
+  public static class A {
+    private final String toString;
+
+    public A(String toString) {
+      this.toString = toString;
+    }
+
+    @Override
+    public String toString() {
+      return toString;
+    }
+  }
+
+  public static class B extends A {
+    public B(String toString) {
+      super(toString);
+    }
+  }
+
+  public static class C extends B {
+    public C(String toString) {
+      super(toString);
+    }
+  }
+
+  public static class D extends C {
+    public D(String toString) {
+      super(toString);
+    }
+  }
+
+  public interface BI<T> {
+    T foo(T o1);
+  }
+
+  public interface BH extends BI<String> {
+  }
+
+  public interface BK<T extends A> extends BI<T> {
+    T foo(T o1);
+  }
+
+  public interface BL<T extends B> extends BK<T> {
+    T foo(T o1);
+  }
+
+  public interface BM extends BK<C> {
+    C foo(C o1);
+  }
+}
diff --git a/src/test/examplesAndroidO/lambdadesugaring/other/OtherRefs.java b/src/test/examplesAndroidO/lambdadesugaring/other/OtherRefs.java
new file mode 100644
index 0000000..e783be3
--- /dev/null
+++ b/src/test/examplesAndroidO/lambdadesugaring/other/OtherRefs.java
@@ -0,0 +1,32 @@
+// Copyright (c) 2017, 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 lambdadesugaring.other;
+
+public class OtherRefs {
+  public static class PublicInit {
+    public PublicInit() {
+    }
+
+    @Override
+    public String toString() {
+      return "OtherRefs::PublicInit::init()";
+    }
+  }
+
+  protected String fooOtherProtected() {
+    return "OtherRefs::fooOtherProtected()";
+  }
+
+  public String fooOtherPublic() {
+    return "OtherRefs::fooOtherPublic()";
+  }
+
+  protected static String staticOtherProtected() {
+    return "OtherRefs::staticOtherProtected()";
+  }
+
+  public static String staticOtherPublic() {
+    return "OtherRefs::staticOtherPublic()";
+  }
+}
diff --git a/src/test/examplesAndroidO/lambdadesugaringnplus/LambdasWithStaticAndDefaultMethods.java b/src/test/examplesAndroidO/lambdadesugaringnplus/LambdasWithStaticAndDefaultMethods.java
new file mode 100644
index 0000000..d2e738d
--- /dev/null
+++ b/src/test/examplesAndroidO/lambdadesugaringnplus/LambdasWithStaticAndDefaultMethods.java
@@ -0,0 +1,405 @@
+// Copyright (c) 2017, 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 lambdadesugaringnplus;
+
+import java.lang.annotation.Annotation;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import lambdadesugaringnplus.other.ClassWithDefaultPackagePrivate;
+import lambdadesugaringnplus.other.InterfaceWithDefaultPackagePrivate;
+
+public class LambdasWithStaticAndDefaultMethods {
+  interface I {
+    String iRegular();
+
+    static String iStatic() {
+      return "I::iStatic()";
+    }
+
+    default String iDefault() {
+      return "I::iDefault()";
+    }
+
+    default String iDefaultOverridden() {
+      return "I::iDefaultOverridden()";
+    }
+
+    default II stateless() {
+      return () -> "I::stateless()";
+    }
+
+    default II stateful() {
+      return () -> "I::captureThis(" + stateless().iRegular() + ")";
+    }
+  }
+
+  static class C implements I {
+    @Override
+    public String iRegular() {
+      return "C::iRegular()";
+    }
+
+    @Override
+    public String iDefaultOverridden() {
+      return "C::iDefaultOverridden()";
+    }
+  }
+
+  interface II extends I {
+    static String iStatic() {
+      II ii = I::iStatic;
+      return "II::iStatic(" + ((I) I::iStatic).iRegular() +
+          "|" + ((II) ii::iDefaultOverridden).iRegular() +
+          "|" + ((II) String::new).iRegular() +
+          "|" + ((II) ii::iRegular).iRegular() + ")";
+    }
+
+    default String iDefaultOverridden() {
+      return "II::iDefault(" + ((I) this::iDefault).iRegular() +
+          "|" + ((II) "One-Two-Three"::intern).iRegular() +
+          "|" + ((II) this::iDefault).iRegular() + ")";
+    }
+  }
+
+  interface P {
+    String get();
+  }
+
+  static void p(P p) {
+    System.out.println(p.get());
+  }
+
+  interface X<T> {
+    String foo(T t);
+  }
+
+  interface Y<T extends I> extends X<T> {
+    String foo(T t);
+  }
+
+  interface Z extends Y<II> {
+    String foo(II t);
+  }
+
+  interface G<T> {
+    T foo(T t);
+  }
+
+  interface B38257361_I1<T extends Number> {
+    default T copy(T t) {
+      return t;
+    }
+  }
+
+  interface B38257361_I2 extends B38257361_I1<Integer> {
+    @Override
+    default Integer copy(Integer t) {
+      return B38257361_I1.super.copy(t);
+    }
+  }
+
+  static class B38257361_C implements B38257361_I2 {
+  }
+
+  static class B38257361 {
+    private B38257361_C c = new B38257361_C();
+
+    public Integer test(Integer i) {
+      return c.copy(i);
+    }
+
+    @SuppressWarnings({"rawtypes", "unchecked"})
+    public Number test(Number n) {
+      return ((B38257361_I1) c).copy(n);
+    }
+
+    public static void test() {
+      B38257361 l = new B38257361();
+      Integer i = new Integer(1);
+      if (i.equals(l.test(i))) {
+        System.out.println("Check 1: OK");
+      } else {
+        System.out.println("Check 1: NOT OK");
+      }
+      if (i.equals(l.test((Number) i))) {
+        System.out.println("Check 2: OK");
+      } else {
+        System.out.println("Check 2: NOT OK");
+      }
+      try {
+        Double d = new Double(1);
+        if (d.equals(l.test((Number) d))) {
+          System.out.println("Check 3: NOT OK, classCastException expected");
+        } else {
+          System.out.println("Check 3: NOT OK, classCastException expected");
+        }
+        System.out.println("Error, ClassCastException is expected");
+      } catch (ClassCastException e) {
+        // Class cast into the bridge method is expected
+        System.out.println("OK, ClassCastException is expected");
+      }
+    }
+  }
+
+  interface B38257037_I1 {
+    default Number getNumber() {
+      return new Integer(1);
+    }
+  }
+
+  interface B38257037_I2 extends B38257037_I1 {
+    @Override
+    default Double getNumber() {
+      return new Double(2.3);
+    }
+  }
+
+  static class B38257037_C implements B38257037_I2 {
+  }
+
+  /**
+   * Check that bridges are generated.
+   */
+  static class B38257037 {
+    private B38257037_C c = new B38257037_C();
+
+    public Double test1() {
+      return c.getNumber();
+    }
+
+    public Number test2() {
+      return ((B38257037_I1) c).getNumber();
+    }
+
+    public static void test() {
+      B38257037 l = new B38257037();
+      if (l.test1() == 2.3) {
+        System.out.println("Check 1: OK");
+      } else {
+        System.out.println("Check 1: NOT OK");
+      }
+      if (l.test2().equals(new Double(2.3))) {
+        System.out.println("Check 2: OK");
+      } else {
+        System.out.println("Check 2: NOT OK");
+      }
+    }
+  }
+
+  interface B38306708_I {
+    class $CC{
+      static void print() {
+        System.out.println("$CC");
+      }
+    }
+
+    default String m() {
+      return "ITop.m()";
+    }
+  }
+
+  static class B38306708 {
+    public static void test() {
+      B38306708_I.$CC.print();
+    }
+  }
+
+  interface B38308515_I {
+    default String m() {
+      return "m instance";
+    }
+
+    static String m(B38308515_I i) {
+      return "m static";
+    }
+  }
+
+  static class B38308515_C implements B38308515_I {
+  }
+
+  static class B38308515 {
+    static void test() {
+      B38308515_C c = new B38308515_C();
+      System.out.println(c.m());
+      System.out.println(B38308515_I.m(c));
+    }
+  }
+
+  static class B38302860 {
+
+    @SomeAnnotation(1)
+    private interface AnnotatedInterface {
+
+      @SomeAnnotation(2)
+      void annotatedAbstractMethod();
+
+      @SomeAnnotation(3)
+      default void annotatedDefaultMethod() {
+      }
+
+      @SomeAnnotation(4)
+      static void annotatedStaticMethod() {
+      }
+    }
+
+    @Retention(value = RetentionPolicy.RUNTIME)
+    private @interface SomeAnnotation {
+      int value();
+    }
+
+    private static boolean checkAnnotationValue(Annotation[] annotations, int value) {
+      if (annotations.length != 1) {
+        return false;
+      }
+      return annotations[0] instanceof SomeAnnotation
+          && ((SomeAnnotation) annotations[0]).value() == value;
+    }
+
+    @SuppressWarnings("unchecked")
+    static void test() throws Exception {
+      if (checkAnnotationValue(AnnotatedInterface.class.getAnnotations(), 1)) {
+        System.out.println("Check 1: OK");
+      } else {
+        System.out.println("Check 1: NOT OK");
+      }
+
+      if (checkAnnotationValue(
+          AnnotatedInterface.class.getMethod("annotatedAbstractMethod").getAnnotations(), 2)) {
+        System.out.println("Check 2: OK");
+      } else {
+        System.out.println("Check 2: NOT OK");
+      }
+
+      if (checkAnnotationValue(
+          AnnotatedInterface.class.getMethod("annotatedDefaultMethod").getAnnotations(), 3)) {
+        System.out.println("Check 3: OK");
+      } else {
+        System.out.println("Check 3: NOT OK");
+      }
+
+      if (checkAnnotationValue(
+          getCompanionClassOrInterface().getMethod("annotatedStaticMethod").getAnnotations(), 4)) {
+        System.out.println("Check 4: OK");
+      } else {
+        System.out.println("Check 4: NOT OK");
+      }
+    }
+
+    private static Class getCompanionClassOrInterface() {
+      try {
+        return Class.forName("lambdadesugaringnplus."
+            + "LambdasWithStaticAndDefaultMethods$B38302860$AnnotatedInterface-CC");
+      } catch (Exception e) {
+        return AnnotatedInterface.class;
+      }
+    }
+  }
+
+  static void z(Z p) {
+    System.out.println(p.foo(null));
+  }
+
+  static void g(G<String[]> g) {
+    StringBuilder builder = new StringBuilder("{");
+    String sep = "";
+    for (String s : g.foo(new String[] { "Arg0", "Arg1", "Arg2" })) {
+      builder.append(sep).append(s);
+      sep = ", ";
+    }
+    builder.append("}");
+    System.out.println(builder.toString());
+  }
+
+  interface SuperChain {
+    default String iMain() {
+      return "SuperChain::iMain()";
+    }
+  }
+
+  interface SuperChainDerived extends SuperChain {
+    default String iMain() {
+      return "SuperChainDerived::iMain(" + SuperChain.super.iMain() + ")";
+    }
+  }
+
+  interface OtherSuperChain {
+    default String iMain() {
+      return "OtherSuperChain::iMain()";
+    }
+  }
+
+  static class ClassWithSuperChain implements SuperChainDerived, OtherSuperChain {
+    public String iMain() {
+      return "ClassWithSuperChain::iMain(" + SuperChainDerived.super.iMain() + ")" + iMainImpl();
+    }
+
+    public String iMainImpl() {
+      return "ClassWithSuperChain::iMain(" + SuperChainDerived.super.iMain() +
+          " + " + OtherSuperChain.super.iMain() + ")";
+    }
+  }
+
+  public static void main(String[] args) throws Exception {
+    C c = new C();
+    I i = c;
+
+    c.iRegular();
+    c.iDefault();
+    c.iDefaultOverridden();
+    I.iStatic();
+    i.iRegular();
+    i.iDefault();
+    i.iDefaultOverridden();
+
+    p(i.stateless()::iRegular);
+    p(i.stateful()::iRegular);
+
+    g(a -> a);
+    g(a -> {
+      int size = a.length;
+      for (int x = 0; x < size / 2; x++) {
+        String t = a[x];
+        a[x] = a[size - 1 - x];
+        a[size - 1 - x] = t;
+      }
+      return a;
+    });
+
+    p(c::iRegular);
+    p(c::iDefault);
+    p(c::iDefaultOverridden);
+    p(I::iStatic);
+    p(i::iRegular);
+    p(i::iDefault);
+    p(i::iDefaultOverridden);
+
+    II ii = i::iRegular;
+    p(II::iStatic);
+    p(ii::iRegular);
+    p(ii::iDefault);
+    p(ii::iDefaultOverridden);
+
+    z(s -> "From Interface With Bridges");
+
+    System.out.println(new ClassWithSuperChain().iMain());
+
+    ClassWithDefaultPackagePrivate c2 = new ClassWithDefaultPackagePrivate();
+    InterfaceWithDefaultPackagePrivate i2 = c2;
+
+    c2.defaultFoo();
+    i2.defaultFoo();
+    InterfaceWithDefaultPackagePrivate.staticFoo();
+
+    p(c2::defaultFoo);
+    p(i2::defaultFoo);
+    p(InterfaceWithDefaultPackagePrivate::staticFoo);
+    p(c2.lambda()::foo);
+
+    B38257361.test();
+    B38257037.test();
+    B38306708.test();
+    B38308515.test();
+    B38302860.test();
+  }
+}
diff --git a/src/test/examplesAndroidO/lambdadesugaringnplus/other/ClassWithDefaultPackagePrivate.java b/src/test/examplesAndroidO/lambdadesugaringnplus/other/ClassWithDefaultPackagePrivate.java
new file mode 100644
index 0000000..102b13b
--- /dev/null
+++ b/src/test/examplesAndroidO/lambdadesugaringnplus/other/ClassWithDefaultPackagePrivate.java
@@ -0,0 +1,15 @@
+// Copyright (c) 2017, 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 lambdadesugaringnplus.other;
+
+public class ClassWithDefaultPackagePrivate implements InterfaceWithDefaultPackagePrivate {
+  public InterfaceWithDefaultPackagePrivate lambda() {
+    return () -> ("lambda(" + InterfaceWithDefaultPackagePrivate.super.defaultFoo() + ")");
+  }
+
+  @Override
+  public String foo() {
+    throw new RuntimeException("Don't call me!");
+  }
+}
diff --git a/src/test/examplesAndroidO/lambdadesugaringnplus/other/InterfaceWithDefaultPackagePrivate.java b/src/test/examplesAndroidO/lambdadesugaringnplus/other/InterfaceWithDefaultPackagePrivate.java
new file mode 100644
index 0000000..536bc29
--- /dev/null
+++ b/src/test/examplesAndroidO/lambdadesugaringnplus/other/InterfaceWithDefaultPackagePrivate.java
@@ -0,0 +1,23 @@
+// Copyright (c) 2017, 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 lambdadesugaringnplus.other;
+
+class PackagePrivate {
+  @Override
+  public String toString() {
+    return "PackagePrivate::toString()";
+  }
+}
+
+public interface InterfaceWithDefaultPackagePrivate {
+  String foo();
+
+  default String defaultFoo() {
+    return "defaultFoo: " + new PackagePrivate().toString();
+  }
+
+  static String staticFoo() {
+    return "staticFoo: " + new PackagePrivate().toString();
+  }
+}
diff --git a/src/test/examplesAndroidO/paramnames/ParameterNames.java b/src/test/examplesAndroidO/paramnames/ParameterNames.java
new file mode 100644
index 0000000..e9d9334
--- /dev/null
+++ b/src/test/examplesAndroidO/paramnames/ParameterNames.java
@@ -0,0 +1,56 @@
+// Copyright (c) 2017, 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 paramnames;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.lang.reflect.Parameter;
+
+public class ParameterNames {
+
+  private static final int MODIFIER_NONE = 0;
+  private static final int MODIFIER_FINAL = 0X10;
+
+  public ParameterNames(int a, final int b) {
+  }
+
+  public static void check(String expected, String checked) {
+    if (!expected.equals(checked)) {
+      throw new RuntimeException("Found '" + checked + "' while expecting '" + expected + "'");
+    }
+  }
+
+  public static void check(int expected, int checked) {
+    if (expected != checked) {
+      throw new RuntimeException("Found '" + checked + "' while expecting '" + expected + "'");
+    }
+  }
+
+  public static void myMethod(int a, final int b) throws NoSuchMethodException {
+    Class<ParameterNames> clazz = ParameterNames.class;
+    Method myMethod = clazz.getDeclaredMethod("myMethod", int.class, int.class);
+    Parameter[] parameters = myMethod.getParameters();
+    check(2, parameters.length);
+    check("a", parameters[0].getName());
+    check("b", parameters[1].getName());
+    check(MODIFIER_NONE, parameters[0].getModifiers());
+    check(MODIFIER_FINAL, parameters[1].getModifiers());
+  }
+
+  public static void myConstructor() throws NoSuchMethodException {
+    Class<ParameterNames> clazz = ParameterNames.class;
+    Constructor<?> myConstructor = clazz.getDeclaredConstructor(int.class, int.class);
+    Parameter[] parameters = myConstructor.getParameters();
+    check(2, parameters.length);
+    check("a", parameters[0].getName());
+    check("b", parameters[1].getName());
+    check(MODIFIER_NONE, parameters[0].getModifiers());
+    check(MODIFIER_FINAL, parameters[1].getModifiers());
+  }
+
+  public static void main(String[] args) throws NoSuchMethodException {
+    myMethod(0, 1);
+    myConstructor();
+  }
+}
diff --git a/src/test/examplesAndroidO/repeat_annotations/NumberAnnotation.java b/src/test/examplesAndroidO/repeat_annotations/NumberAnnotation.java
new file mode 100644
index 0000000..7e304b9
--- /dev/null
+++ b/src/test/examplesAndroidO/repeat_annotations/NumberAnnotation.java
@@ -0,0 +1,14 @@
+// Copyright (c) 2017, 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 repeat_annotations;
+
+import java.lang.annotation.Repeatable;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Repeatable(NumberAnnotations.class)
+public @interface NumberAnnotation {
+  int number() default 32;
+}
diff --git a/src/test/examplesAndroidO/repeat_annotations/NumberAnnotations.java b/src/test/examplesAndroidO/repeat_annotations/NumberAnnotations.java
new file mode 100644
index 0000000..a70587a
--- /dev/null
+++ b/src/test/examplesAndroidO/repeat_annotations/NumberAnnotations.java
@@ -0,0 +1,12 @@
+// Copyright (c) 2017, 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 repeat_annotations;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@Retention(RetentionPolicy.RUNTIME)
+public @interface NumberAnnotations {
+  NumberAnnotation[] value();
+}
diff --git a/src/test/examplesAndroidO/repeat_annotations/RepeatAnnotations.java b/src/test/examplesAndroidO/repeat_annotations/RepeatAnnotations.java
new file mode 100644
index 0000000..d55de94
--- /dev/null
+++ b/src/test/examplesAndroidO/repeat_annotations/RepeatAnnotations.java
@@ -0,0 +1,22 @@
+// Copyright (c) 2017, 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 repeat_annotations;
+
+// Simple test of Java 8 repeated annotations.
+public class RepeatAnnotations {
+
+  @NumberAnnotation(number = 1)
+  @NumberAnnotation(number = 2)
+  @NumberAnnotation(number = 3)
+  class Inner {
+  }
+
+  public static void main(String[] args) {
+    NumberAnnotations annotations = Inner.class.getAnnotation(NumberAnnotations.class);
+    System.out.println(annotations.value().length);
+    for (NumberAnnotation annotation : annotations.value()) {
+      System.out.println("Number annotation value: " + annotation.number());
+    }
+  }
+}
diff --git a/src/test/examplesAndroidO/repeat_annotations/RepeatAnnotationsNewApi.java b/src/test/examplesAndroidO/repeat_annotations/RepeatAnnotationsNewApi.java
new file mode 100644
index 0000000..6d23706
--- /dev/null
+++ b/src/test/examplesAndroidO/repeat_annotations/RepeatAnnotationsNewApi.java
@@ -0,0 +1,23 @@
+// Copyright (c) 2017, 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 repeat_annotations;
+
+// Simple test of Java 8 repeated annotations using the new getAnnotationsByType
+// API to access them.
+public class RepeatAnnotationsNewApi {
+
+  @NumberAnnotation(number = 1)
+  @NumberAnnotation(number = 2)
+  @NumberAnnotation(number = 3)
+  class Inner {
+  }
+
+  public static void main(String[] args) {
+    NumberAnnotation[] annotations = Inner.class.getAnnotationsByType(NumberAnnotation.class);
+    System.out.println(annotations.length);
+    for (NumberAnnotation annotation : annotations) {
+      System.out.println("Number annotation value: " + annotation.number());
+    }
+  }
+}