From 9b1583e7d799a3bb3c0036abb8a0b9fcbfad360a Mon Sep 17 00:00:00 2001 From: Nicolas Geoffray Date: Tue, 13 Dec 2016 13:43:31 +0000 Subject: [PATCH] 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 --- compiler/optimizing/nodes.cc | 29 +++++++++++++++++++---------- compiler/optimizing/sharpening.cc | 4 +++- 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc index 925d4f1fd..1e946d67b 100644 --- a/compiler/optimizing/nodes.cc +++ b/compiler/optimizing/nodes.cc @@ -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*>(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()); } } diff --git a/compiler/optimizing/sharpening.cc b/compiler/optimizing/sharpening.cc index bbbb1a18c..91efb8001 100644 --- a/compiler/optimizing/sharpening.cc +++ b/compiler/optimizing/sharpening.cc @@ -197,7 +197,9 @@ void HSharpening::ProcessLoadClass(HLoadClass* load_class) { // out which class loader to use. address = reinterpret_cast(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; } -- 2.11.0