OSDN Git Service

Use the original invoke type when inlining.
authorNicolas Geoffray <ngeoffray@google.com>
Thu, 26 Mar 2015 10:05:54 +0000 (10:05 +0000)
committerNicolas Geoffray <ngeoffray@google.com>
Thu, 26 Mar 2015 10:05:54 +0000 (10:05 +0000)
When resolving a method through the compiler driver, the code makes
sure the call in the DEX bytecode matches the kind of method found,
to check for IncompatibleClassChangeError. Because when we sharpen
an invoke virtual, we transform the invoke kind to direct, we must not
use the new kind, but the one in DEX.

Change-Id: Iaf77b27b529c659ea48ffb19f46427552c9e3654

compiler/optimizing/builder.cc
compiler/optimizing/inliner.cc
compiler/optimizing/nodes.h
test/464-checker-inline-sharpen-calls/expected.txt [new file with mode: 0644]
test/464-checker-inline-sharpen-calls/info.txt [new file with mode: 0644]
test/464-checker-inline-sharpen-calls/src/Main.java [new file with mode: 0644]

index 8786ed4..f81935a 100644 (file)
@@ -620,7 +620,7 @@ bool HGraphBuilder::BuildInvoke(const Instruction& instruction,
     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;
index 256e85b..4b990f1 100644 (file)
@@ -50,7 +50,9 @@ void HInliner::Run() {
       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());
index 08b16d9..9c751fb 100644 (file)
@@ -2131,8 +2131,10 @@ class HInvokeStaticOrDirect : public HInvoke {
                         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 @@ class HInvokeStaticOrDirect : public HInvoke {
     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 @@ class HInvokeStaticOrDirect : public HInvoke {
   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 (file)
index 0000000..e69de29
diff --git a/test/464-checker-inline-sharpen-calls/info.txt b/test/464-checker-inline-sharpen-calls/info.txt
new file mode 100644 (file)
index 0000000..9e56030
--- /dev/null
@@ -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 (file)
index 0000000..1b25b42
--- /dev/null
@@ -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");
+    }
+  }
+}