Adding a black list of methods which are never supposed to be inlined.

Bug:
Change-Id: Idc52e433c02d338d38ca670f0741e30baf5c0ce3
diff --git a/src/main/java/com/android/tools/r8/graph/DexItemFactory.java b/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
index d674ccb..61881a8 100644
--- a/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
+++ b/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
@@ -194,6 +194,7 @@
   public final LongMethods longMethods = new LongMethods();
   public final ThrowableMethods throwableMethods = new ThrowableMethods();
   public final ClassMethods classMethods = new ClassMethods();
+  public final Kotlin kotlin = new Kotlin();
 
   // Dex system annotations.
   // See https://source.android.com/devices/tech/dalvik/dex-format.html#system-annotation
@@ -334,6 +335,23 @@
     }
   }
 
+  public class Kotlin {
+    private Kotlin() {
+    }
+
+    public final Intrinsics intrinsics = new Intrinsics();
+
+    // kotlin.jvm.internal.Intrinsics class
+    public class Intrinsics {
+      private Intrinsics() {
+      }
+
+      public final DexType type = createType(createString("Lkotlin/jvm/internal/Intrinsics;"));
+      public final DexMethod throwParameterIsNullException =
+          createMethod(type, createProto(voidType, stringType), "throwParameterIsNullException");
+    }
+  }
+
   private static <T extends DexItem> T canonicalize(ConcurrentHashMap<T, T> map, T item) {
     assert item != null;
     assert !DexItemFactory.isInternalSentinel(item);
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java b/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
index 2a8f7b0..4bb10d3 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
@@ -53,10 +53,21 @@
   private final Set<DexEncodedMethod> doubleInlineSelectedTargets = Sets.newIdentityHashSet();
   private final Map<DexEncodedMethod, DexEncodedMethod> doubleInlineeCandidates = new HashMap<>();
 
+  private final Set<DexMethod> blackList = Sets.newIdentityHashSet();
+
   public Inliner(AppInfoWithLiveness appInfo, GraphLense graphLense, InternalOptions options) {
     this.appInfo = appInfo;
     this.graphLense = graphLense;
     this.options = options;
+    fillInBlackList(appInfo);
+  }
+
+  private void fillInBlackList(AppInfoWithLiveness appInfo) {
+    blackList.add(appInfo.dexItemFactory.kotlin.intrinsics.throwParameterIsNullException);
+  }
+
+  public boolean isBlackListed(DexMethod method) {
+    return blackList.contains(method);
   }
 
   private Constraint instructionAllowedForInlining(
@@ -191,6 +202,14 @@
 
     public static Constraint classIsVisible(DexType context, DexType clazz,
         AppInfoWithSubtyping appInfo) {
+      if (clazz.isArrayType()) {
+        return classIsVisible(context, clazz.toArrayElementType(appInfo.dexItemFactory), appInfo);
+      }
+
+      if (clazz.isPrimitiveType()) {
+        return ALWAYS;
+      }
+
       DexClass definition = appInfo.definitionFor(clazz);
       return definition == null ? NEVER
           : deriveConstraint(context, clazz, definition.accessFlags, appInfo);
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/InliningOracle.java b/src/main/java/com/android/tools/r8/ir/optimize/InliningOracle.java
index 2f4ac93..0da6c30 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/InliningOracle.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/InliningOracle.java
@@ -206,7 +206,7 @@
   public InlineAction computeForInvokeWithReceiver(
       InvokeMethodWithReceiver invoke, DexType invocationContext) {
     DexEncodedMethod candidate = validateCandidate(invoke, invocationContext);
-    if (candidate == null) {
+    if (candidate == null || inliner.isBlackListed(candidate.method)) {
       return null;
     }
 
@@ -246,7 +246,7 @@
 
   public InlineAction computeForInvokeStatic(InvokeStatic invoke, DexType invocationContext) {
     DexEncodedMethod candidate = validateCandidate(invoke, invocationContext);
-    if (candidate == null) {
+    if (candidate == null || inliner.isBlackListed(candidate.method)) {
       return null;
     }
 
diff --git a/src/test/java/com/android/tools/r8/kotlin/R8KotlinDataClassTest.java b/src/test/java/com/android/tools/r8/kotlin/R8KotlinDataClassTest.java
index 4bd61e1..343fe9c 100644
--- a/src/test/java/com/android/tools/r8/kotlin/R8KotlinDataClassTest.java
+++ b/src/test/java/com/android/tools/r8/kotlin/R8KotlinDataClassTest.java
@@ -14,6 +14,7 @@
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Map;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
@@ -173,6 +174,7 @@
   }
 
   @Test
+  @Ignore("See b/72871423")
   public void test_dataclass_copyDefault() throws Exception {
     final String mainClassName = "dataclass.MainCopyWithDefaultKt";
     final MethodSignature testMethodSignature =
diff --git a/src/test/java/com/android/tools/r8/kotlin/R8KotlinIntrinsicsTest.java b/src/test/java/com/android/tools/r8/kotlin/R8KotlinIntrinsicsTest.java
new file mode 100644
index 0000000..fc2a7bb
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/kotlin/R8KotlinIntrinsicsTest.java
@@ -0,0 +1,57 @@
+// 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.kotlin;
+
+import com.android.tools.r8.naming.MemberNaming.MethodSignature;
+import com.android.tools.r8.utils.DexInspector;
+import com.android.tools.r8.utils.DexInspector.ClassSubject;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
+import java.util.Collection;
+import java.util.Collections;
+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 R8KotlinIntrinsicsTest extends AbstractR8KotlinTestBase {
+
+  private static final KotlinDataClass KOTLIN_INTRINSICS_CLASS =
+      new KotlinDataClass("kotlin.jvm.internal.Intrinsics");
+
+  @Parameters(name = "{0}")
+  public static Collection<Object> data() {
+    return ImmutableList.of(Boolean.TRUE, Boolean.FALSE);
+  }
+
+  public R8KotlinIntrinsicsTest(boolean allowAccessModification) {
+    super(allowAccessModification);
+  }
+
+  @Test
+  public void testParameterNullCheckIsInlined() throws Exception {
+    final String extraRules = keepClassMethod("intrinsics.IntrinsicsKt",
+        new MethodSignature("expectsNonNullParameters",
+            "java.lang.String", Lists.newArrayList("java.lang.String", "java.lang.String")));
+
+    runTest("intrinsics", "intrinsics.IntrinsicsKt", extraRules, (app) -> {
+      DexInspector dexInspector = new DexInspector(app);
+      ClassSubject intrinsicsClass = checkClassExists(
+          dexInspector, KOTLIN_INTRINSICS_CLASS.getClassName());
+
+      checkMethodsPresence(intrinsicsClass,
+          ImmutableMap.<MethodSignature, Boolean>builder()
+              .put(new MethodSignature("throwParameterIsNullException",
+                      "void", Collections.singletonList("java.lang.String")),
+                  true)
+              .put(new MethodSignature("checkParameterIsNotNull",
+                      "void", Lists.newArrayList("java.lang.Object", "java.lang.String")),
+                  allowAccessModification ? false /* should be inlined*/ : true)
+              .build());
+    });
+  }
+}
diff --git a/src/test/kotlinR8TestResources/intrinsics/Intrinsics.kt b/src/test/kotlinR8TestResources/intrinsics/Intrinsics.kt
new file mode 100644
index 0000000..90d26bf
--- /dev/null
+++ b/src/test/kotlinR8TestResources/intrinsics/Intrinsics.kt
@@ -0,0 +1,32 @@
+// 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 intrinsics
+
+import java.lang.reflect.InvocationTargetException
+
+fun main(args: Array<String>) {
+    testParameterNullCheck()
+}
+
+fun expectsNonNullParameters(a: String, b: String): String = a + b
+
+fun testParameterNullCheck() {
+    println("> ${expectsNonNullParameters("pre", "post")} <")
+
+    val intrinsics = Class.forName("intrinsics.IntrinsicsKt")
+    val method = intrinsics.getMethod(
+            "expectsNonNullParameters", String::class.java, String::class.java)
+
+    println("> ${method.invoke(null, "pre", "post")} <")
+
+    try {
+        println("> ${method.invoke(null, "pre", null)} <")
+    } catch (e: InvocationTargetException) {
+        println("> exception: ${e.targetException::javaClass} <")
+        return
+    }
+    throw AssertionError()
+}
+