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");
+ }
+ }
+}