OSDN Git Service

Do a second check for testing intrinsic types.
authorNicolas Geoffray <ngeoffray@google.com>
Thu, 20 Aug 2015 13:05:14 +0000 (14:05 +0100)
committerNicolas Geoffray <ngeoffray@google.com>
Fri, 21 Aug 2015 10:01:38 +0000 (11:01 +0100)
This allows to intrinsify calls made in a different dex file.

Can't easily write a test because it depends on having inlined
a method from boot classpath that calls an intrinsic. Once
String.equals is implemented with the hybrid approach we can write one.

Change-Id: I591d9496e236429943d6bfa7f8b20f576b1cfb9a

compiler/optimizing/intrinsics.cc

index 075ec1e..feaaaf4 100644 (file)
 
 #include "intrinsics.h"
 
+#include "art_method.h"
+#include "class_linker.h"
 #include "dex/quick/dex_file_method_inliner.h"
 #include "dex/quick/dex_file_to_method_inliner_map.h"
 #include "driver/compiler_driver.h"
 #include "invoke_type.h"
+#include "mirror/dex_cache-inl.h"
 #include "nodes.h"
 #include "quick/inline_method_analyser.h"
+#include "scoped_thread_state_change.h"
 #include "utils.h"
 
 namespace art {
@@ -364,17 +368,34 @@ void IntrinsicsRecognizer::Run() {
       if (inst->IsInvoke()) {
         HInvoke* invoke = inst->AsInvoke();
         InlineMethod method;
-        DexFileMethodInliner* inliner =
-            driver_->GetMethodInlinerMap()->GetMethodInliner(&invoke->GetDexFile());
+        const DexFile& dex_file = invoke->GetDexFile();
+        DexFileMethodInliner* inliner = driver_->GetMethodInlinerMap()->GetMethodInliner(&dex_file);
         DCHECK(inliner != nullptr);
         if (inliner->IsIntrinsic(invoke->GetDexMethodIndex(), &method)) {
           Intrinsics intrinsic = GetIntrinsic(method, graph_->GetInstructionSet());
 
           if (intrinsic != Intrinsics::kNone) {
             if (!CheckInvokeType(intrinsic, invoke)) {
-              LOG(WARNING) << "Found an intrinsic with unexpected invoke type: "
-                           << intrinsic << " for "
-                           << PrettyMethod(invoke->GetDexMethodIndex(), invoke->GetDexFile());
+              // We might be in a situation where we have inlined a method that calls an intrinsic,
+              // but that method is in a different dex file on which we do not have a
+              // verified_method that would have helped the compiler driver sharpen the call.
+              // We can still ensure the invoke types match by checking whether the called method
+              // is final or is in a final class.
+              ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+              {
+                ScopedObjectAccess soa(Thread::Current());
+                ArtMethod* art_method = class_linker->FindDexCache(dex_file)->GetResolvedMethod(
+                    invoke->GetDexMethodIndex(), class_linker->GetImagePointerSize());
+                DCHECK(art_method != nullptr);
+                if (art_method->IsFinal() || art_method->GetDeclaringClass()->IsFinal()) {
+                  invoke->SetIntrinsic(intrinsic, NeedsEnvironmentOrCache(intrinsic));
+                } else {
+                  LOG(WARNING) << "Found an intrinsic with unexpected invoke type: "
+                               << intrinsic << " for "
+                               << PrettyMethod(invoke->GetDexMethodIndex(), invoke->GetDexFile())
+                               << invoke->DebugName();
+                }
+              }
             } else {
               invoke->SetIntrinsic(intrinsic, NeedsEnvironmentOrCache(intrinsic));
             }