Do not place null check on unresolved method calls.

Rationale:
These invokes drop through the runtime anyway where various
checks are done, including null check. A few of these
checks need to occur before the null check.

With fail-before/pass-after smali test.

BUG=29068831

Change-Id: I260715e742365433a323598d97f7fdab321e8512
diff --git a/compiler/optimizing/instruction_builder.cc b/compiler/optimizing/instruction_builder.cc
index 135038b..f2286e4 100644
--- a/compiler/optimizing/instruction_builder.cc
+++ b/compiler/optimizing/instruction_builder.cc
@@ -833,7 +833,8 @@
                         register_index,
                         is_range,
                         descriptor,
-                        nullptr /* clinit_check */);
+                        nullptr, /* clinit_check */
+                        true /* is_unresolved */);
   }
 
   // Potential class initialization check, in the case of a static method call.
@@ -898,7 +899,8 @@
                       register_index,
                       is_range,
                       descriptor,
-                      clinit_check);
+                      clinit_check,
+                      false /* is_unresolved */);
 }
 
 bool HInstructionBuilder::BuildNewInstance(uint16_t type_index, uint32_t dex_pc) {
@@ -1091,14 +1093,17 @@
                                        uint32_t register_index,
                                        bool is_range,
                                        const char* descriptor,
-                                       HClinitCheck* clinit_check) {
+                                       HClinitCheck* clinit_check,
+                                       bool is_unresolved) {
   DCHECK(!invoke->IsInvokeStaticOrDirect() || !invoke->AsInvokeStaticOrDirect()->IsStringInit());
 
   size_t start_index = 0;
   size_t argument_index = 0;
   if (invoke->GetOriginalInvokeType() != InvokeType::kStatic) {  // Instance call.
-    HInstruction* arg = LoadNullCheckedLocal(is_range ? register_index : args[0],
-                                             invoke->GetDexPc());
+    uint32_t obj_reg = is_range ? register_index : args[0];
+    HInstruction* arg = is_unresolved
+        ? LoadLocal(obj_reg, Primitive::kPrimNot)
+        : LoadNullCheckedLocal(obj_reg, invoke->GetDexPc());
     invoke->SetArgumentAt(0, arg);
     start_index = 1;
     argument_index = 1;
diff --git a/compiler/optimizing/instruction_builder.h b/compiler/optimizing/instruction_builder.h
index 0e3e5a7..9cfc065 100644
--- a/compiler/optimizing/instruction_builder.h
+++ b/compiler/optimizing/instruction_builder.h
@@ -237,7 +237,8 @@
                     uint32_t register_index,
                     bool is_range,
                     const char* descriptor,
-                    HClinitCheck* clinit_check);
+                    HClinitCheck* clinit_check,
+                    bool is_unresolved);
 
   bool HandleStringInit(HInvoke* invoke,
                         uint32_t number_of_vreg_arguments,
diff --git a/test/529-checker-unresolved/src/Main.java b/test/529-checker-unresolved/src/Main.java
index a934377..5a36ba5 100644
--- a/test/529-checker-unresolved/src/Main.java
+++ b/test/529-checker-unresolved/src/Main.java
@@ -114,19 +114,31 @@
     expectEquals(o, c.instanceObject);
   }
 
+  /// CHECK-START: void Main.callUnresolvedNull(UnresolvedClass) register (before)
+  /// CHECK-NOT: NullCheck
   static public void callUnresolvedNull(UnresolvedClass c) {
     int x = 0;
     try {
       x = c.instanceInt;
       throw new Error("Expected NPE");
     } catch (NullPointerException e) {
+      x -= 1;
     }
-    expectEquals(0, x);
+    expectEquals(-1, x);
     try {
       c.instanceInt = -1;
       throw new Error("Expected NPE");
     } catch (NullPointerException e) {
+      x -= 1;
     }
+    expectEquals(-2, x);
+    try {
+      c.virtualMethod();
+      throw new Error("Expected NPE");
+    } catch (NullPointerException e) {
+      x -= 1;
+    }
+    expectEquals(-3, x);
   }
 
   static public void testInstanceOf(Object o) {
diff --git a/test/600-verifier-fails/expected.txt b/test/600-verifier-fails/expected.txt
index 8399969..eaa0c93 100644
--- a/test/600-verifier-fails/expected.txt
+++ b/test/600-verifier-fails/expected.txt
@@ -2,3 +2,4 @@
 passed B
 passed C
 passed D
+passed E
diff --git a/test/600-verifier-fails/info.txt b/test/600-verifier-fails/info.txt
index f77de05..df2396e 100644
--- a/test/600-verifier-fails/info.txt
+++ b/test/600-verifier-fails/info.txt
@@ -10,9 +10,11 @@
     bail immediately and not allow soft verification failures to pile up
     behind it to avoid fatal message later on
 (C) b/29068831:
-    access validation should occur prior to null reference check
+    access validation on field should occur prior to null reference check
 (D) b/29126870:
     soft verification failure (cannot access) should not hide the hard
     verification failure (non-reference type) to avoid a compiler crash
     later on
+(E) b/29068831:
+    access validation on method should occur prior to null reference check
 
diff --git a/test/600-verifier-fails/smali/invoke.smali b/test/600-verifier-fails/smali/invoke.smali
new file mode 100644
index 0000000..616d63c
--- /dev/null
+++ b/test/600-verifier-fails/smali/invoke.smali
@@ -0,0 +1,25 @@
+#
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+.class public LE;
+.super Ljava/lang/Object;
+
+.method public constructor <init>()V
+    .registers 2
+    invoke-direct {v1}, Ljava/lang/Object;-><init>()V
+    const v0, 0
+    invoke-virtual {v0}, LMain;->privateMethod()V
+    return-void
+.end method
diff --git a/test/600-verifier-fails/src/Main.java b/test/600-verifier-fails/src/Main.java
index a6a07fd..fa25d58 100644
--- a/test/600-verifier-fails/src/Main.java
+++ b/test/600-verifier-fails/src/Main.java
@@ -22,6 +22,8 @@
 
   private int privateField = 0;
 
+  private void privateMethod() { }
+
   private static void test(String name) throws Exception {
     try {
       Class<?> a = Class.forName(name);
@@ -36,5 +38,6 @@
     test("B");
     test("C");
     test("D");
+    test("E");
   }
 }