Merge "Use the original invoke type when inlining."
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc
index 8786ed4..f81935a 100644
--- a/compiler/optimizing/builder.cc
+++ b/compiler/optimizing/builder.cc
@@ -620,7 +620,7 @@
     DCHECK(!is_recursive || (target_method.dex_file == dex_compilation_unit_->GetDexFile()));
     invoke = new (arena_) HInvokeStaticOrDirect(
         arena_, number_of_arguments, return_type, dex_pc, target_method.dex_method_index,
-        is_recursive, optimized_invoke_type);
+        is_recursive, invoke_type, optimized_invoke_type);
   }
 
   size_t start_index = 0;
diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc
index 256e85b..4b990f1 100644
--- a/compiler/optimizing/inliner.cc
+++ b/compiler/optimizing/inliner.cc
@@ -50,7 +50,9 @@
       HInstruction* next = instruction->GetNext();
       HInvokeStaticOrDirect* call = instruction->AsInvokeStaticOrDirect();
       if (call != nullptr) {
-        if (!TryInline(call, call->GetDexMethodIndex(), call->GetInvokeType())) {
+        // We use the original invoke type to ensure the resolution of the called method
+        // works properly.
+        if (!TryInline(call, call->GetDexMethodIndex(), call->GetOriginalInvokeType())) {
           if (kIsDebugBuild) {
             std::string callee_name =
                 PrettyMethod(call->GetDexMethodIndex(), *outer_compilation_unit_.GetDexFile());
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 08b16d9..9c751fb 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -2131,8 +2131,10 @@
                         uint32_t dex_pc,
                         uint32_t dex_method_index,
                         bool is_recursive,
+                        InvokeType original_invoke_type,
                         InvokeType invoke_type)
       : HInvoke(arena, number_of_arguments, return_type, dex_pc, dex_method_index),
+        original_invoke_type_(original_invoke_type),
         invoke_type_(invoke_type),
         is_recursive_(is_recursive) {}
 
@@ -2142,6 +2144,7 @@
     return false;
   }
 
+  InvokeType GetOriginalInvokeType() const { return original_invoke_type_; }
   InvokeType GetInvokeType() const { return invoke_type_; }
   bool IsRecursive() const { return is_recursive_; }
   bool NeedsDexCache() const OVERRIDE { return !IsRecursive(); }
@@ -2149,6 +2152,7 @@
   DECLARE_INSTRUCTION(InvokeStaticOrDirect);
 
  private:
+  const InvokeType original_invoke_type_;
   const InvokeType invoke_type_;
   const bool is_recursive_;
 
diff --git a/test/464-checker-inline-sharpen-calls/expected.txt b/test/464-checker-inline-sharpen-calls/expected.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/464-checker-inline-sharpen-calls/expected.txt
diff --git a/test/464-checker-inline-sharpen-calls/info.txt b/test/464-checker-inline-sharpen-calls/info.txt
new file mode 100644
index 0000000..9e56030
--- /dev/null
+++ b/test/464-checker-inline-sharpen-calls/info.txt
@@ -0,0 +1 @@
+Check that we inline sharpen calls.
diff --git a/test/464-checker-inline-sharpen-calls/src/Main.java b/test/464-checker-inline-sharpen-calls/src/Main.java
new file mode 100644
index 0000000..1b25b42
--- /dev/null
+++ b/test/464-checker-inline-sharpen-calls/src/Main.java
@@ -0,0 +1,54 @@
+/*
+* Copyright (C) 2015 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.
+*/
+
+public final class Main {
+
+  public void invokeVirtual() {
+  }
+
+  // CHECK-START: void Main.inlineSharpenInvokeVirtual(Main) inliner (before)
+  // CHECK-DAG:     [[Invoke:v\d+]]  InvokeStaticOrDirect
+  // CHECK-DAG:                      ReturnVoid
+
+  // CHECK-START: void Main.inlineSharpenInvokeVirtual(Main) inliner (after)
+  // CHECK-NOT:                      InvokeStaticOrDirect
+
+  public static void inlineSharpenInvokeVirtual(Main m) {
+    m.invokeVirtual();
+  }
+
+  // CHECK-START: int Main.inlineSharpenStringInvoke() inliner (before)
+  // CHECK-DAG:     [[Invoke:i\d+]]  InvokeStaticOrDirect
+  // CHECK-DAG:                      Return [ [[Invoke]] ]
+
+  // CHECK-START: int Main.inlineSharpenStringInvoke() inliner (after)
+  // CHECK-NOT:                      InvokeStaticOrDirect
+
+  // CHECK-START: int Main.inlineSharpenStringInvoke() inliner (after)
+  // CHECK-DAG:     [[Field:i\d+]]   InstanceFieldGet
+  // CHECK-DAG:                      Return [ [[Field]] ]
+
+  public static int inlineSharpenStringInvoke() {
+    return "Foo".length();
+  }
+
+  public static void main(String[] args) {
+    inlineSharpenInvokeVirtual(new Main());
+    if (inlineSharpenStringInvoke() != 3) {
+      throw new Error("Expected 3");
+    }
+  }
+}