Support GVN for HLoadClass::LoadKind::kJitTableAddress.
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
diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc
index 925d4f1..1e946d6 100644
--- a/compiler/optimizing/nodes.cc
+++ b/compiler/optimizing/nodes.cc
@@ -2440,6 +2440,17 @@
}
}
+// 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 @@
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());
}
}
diff --git a/compiler/optimizing/sharpening.cc b/compiler/optimizing/sharpening.cc
index bbbb1a1..91efb80 100644
--- a/compiler/optimizing/sharpening.cc
+++ b/compiler/optimizing/sharpening.cc
@@ -197,7 +197,9 @@
// 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;
}