OSDN Git Service

Support GVN for HLoadClass::LoadKind::kJitTableAddress.
authorNicolas Geoffray <ngeoffray@google.com>
Tue, 13 Dec 2016 13:43:31 +0000 (13:43 +0000)
committerNicolas Geoffray <ngeoffray@google.com>
Tue, 13 Dec 2016 22:14:02 +0000 (22:14 +0000)
Fixes performance regressions seen in eg Dhrystone.

Also add comment on why a class may not be found when sharpening.

Test: manual Dhrystone run, performance recovers
Test: ART_TEST_JIT=true test-art-host-run-test-jit
Change-Id: I8e879f1c390f83e8bc930f343beb7b4a41c2f190

compiler/optimizing/nodes.cc
compiler/optimizing/sharpening.cc

index 925d4f1..1e946d6 100644 (file)
@@ -2440,6 +2440,17 @@ std::ostream& operator<<(std::ostream& os, HInvokeStaticOrDirect::ClinitCheckReq
   }
 }
 
+// Helper for InstructionDataEquals to fetch the mirror Class out
+// from a kJitTableAddress LoadClass kind.
+// NO_THREAD_SAFETY_ANALYSIS because even though we're accessing
+// mirrors, they are stored in a variable size handle scope which is always
+// visited during a pause. Also, the only caller of this helper
+// only uses the mirror for pointer comparison.
+static inline mirror::Class* AsMirrorInternal(uint64_t address)
+    NO_THREAD_SAFETY_ANALYSIS {
+  return reinterpret_cast<StackReference<mirror::Class>*>(address)->AsMirrorPtr();
+}
+
 bool HLoadClass::InstructionDataEquals(const HInstruction* other) const {
   const HLoadClass* other_load_class = other->AsLoadClass();
   // TODO: To allow GVN for HLoadClass from different dex files, we should compare the type
@@ -2448,16 +2459,14 @@ bool HLoadClass::InstructionDataEquals(const HInstruction* other) const {
       GetPackedFields() != other_load_class->GetPackedFields()) {
     return false;
   }
-  LoadKind load_kind = GetLoadKind();
-  if (HasAddress(load_kind)) {
-    return GetAddress() == other_load_class->GetAddress();
-  } else if (HasTypeReference(load_kind)) {
-    return IsSameDexFile(GetDexFile(), other_load_class->GetDexFile());
-  } else {
-    DCHECK(HasDexCacheReference(load_kind)) << load_kind;
-    // If the type indexes and dex files are the same, dex cache element offsets
-    // must also be the same, so we don't need to compare them.
-    return IsSameDexFile(GetDexFile(), other_load_class->GetDexFile());
+  switch (GetLoadKind()) {
+    case LoadKind::kBootImageAddress:
+      return GetAddress() == other_load_class->GetAddress();
+    case LoadKind::kJitTableAddress:
+      return AsMirrorInternal(GetAddress()) == AsMirrorInternal(other_load_class->GetAddress());
+    default:
+      DCHECK(HasTypeReference(GetLoadKind()) || HasDexCacheReference(GetLoadKind()));
+      return IsSameDexFile(GetDexFile(), other_load_class->GetDexFile());
   }
 }
 
index bbbb1a1..91efb80 100644 (file)
@@ -197,7 +197,9 @@ void HSharpening::ProcessLoadClass(HLoadClass* load_class) {
           // out which class loader to use.
           address = reinterpret_cast<uint64_t>(handles_->NewHandle(klass).GetReference());
         } else {
-          // Class not loaded yet. Fallback to the dex cache.
+          // Class not loaded yet. This happens when the dex code requesting
+          // this `HLoadClass` hasn't been executed in the interpreter.
+          // Fallback to the dex cache.
           // TODO(ngeoffray): Generate HDeoptimize instead.
           desired_load_kind = HLoadClass::LoadKind::kDexCacheViaMethod;
         }