Quick: Clean up temp use counting.
For the boot image on arm64 and x86-64 we're using true
PC-relative addressing, so pc_rel_temp_ is nullptr and
CanUsePcRelDexCacheArrayLoad() returns true, but we're not
actually using the ArtMethod* so fix the AnalyzeMIR() to
take it into account.
Also don't count intrinsic invokes towards ArtMethod* uses.
To avoid repeated method inliner inquiries about whether a
method is intrinsic or special (requiring lock acquisition),
cache that information in MirMethodLoweringInfo. As part of
that cleanup, take quickened invokes into account for
suspend check elimination.
Change-Id: I5b4ec124221c0db1314c8e72675976c110ebe7ca
diff --git a/compiler/dex/quick/dex_file_method_inliner.cc b/compiler/dex/quick/dex_file_method_inliner.cc
index 8e3f4ef..4ac6c0c 100644
--- a/compiler/dex/quick/dex_file_method_inliner.cc
+++ b/compiler/dex/quick/dex_file_method_inliner.cc
@@ -413,6 +413,17 @@
return success && AddInlineMethod(verifier->GetMethodReference().dex_method_index, method);
}
+InlineMethodFlags DexFileMethodInliner::IsIntrinsicOrSpecial(uint32_t method_index) {
+ ReaderMutexLock mu(Thread::Current(), lock_);
+ auto it = inline_methods_.find(method_index);
+ if (it != inline_methods_.end()) {
+ DCHECK_NE(it->second.flags & (kInlineIntrinsic | kInlineSpecial), 0);
+ return it->second.flags;
+ } else {
+ return kNoInlineMethodFlags;
+ }
+}
+
bool DexFileMethodInliner::IsIntrinsic(uint32_t method_index, InlineMethod* intrinsic) {
ReaderMutexLock mu(Thread::Current(), lock_);
auto it = inline_methods_.find(method_index);
diff --git a/compiler/dex/quick/dex_file_method_inliner.h b/compiler/dex/quick/dex_file_method_inliner.h
index cb521da..d1e5621 100644
--- a/compiler/dex/quick/dex_file_method_inliner.h
+++ b/compiler/dex/quick/dex_file_method_inliner.h
@@ -65,6 +65,11 @@
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) LOCKS_EXCLUDED(lock_);
/**
+ * Check whether a particular method index corresponds to an intrinsic or special function.
+ */
+ InlineMethodFlags IsIntrinsicOrSpecial(uint32_t method_index) LOCKS_EXCLUDED(lock_);
+
+ /**
* Check whether a particular method index corresponds to an intrinsic function.
*/
bool IsIntrinsic(uint32_t method_index, InlineMethod* intrinsic) LOCKS_EXCLUDED(lock_);
diff --git a/compiler/dex/quick/gen_invoke.cc b/compiler/dex/quick/gen_invoke.cc
index e747239..db7095d 100755
--- a/compiler/dex/quick/gen_invoke.cc
+++ b/compiler/dex/quick/gen_invoke.cc
@@ -1435,10 +1435,12 @@
void Mir2Lir::GenInvoke(CallInfo* info) {
DCHECK(cu_->compiler_driver->GetMethodInlinerMap() != nullptr);
- const DexFile* dex_file = info->method_ref.dex_file;
- if (cu_->compiler_driver->GetMethodInlinerMap()->GetMethodInliner(dex_file)
- ->GenIntrinsic(this, info)) {
- return;
+ if (mir_graph_->GetMethodLoweringInfo(info->mir).IsIntrinsic()) {
+ const DexFile* dex_file = info->method_ref.dex_file;
+ auto* inliner = cu_->compiler_driver->GetMethodInlinerMap()->GetMethodInliner(dex_file);
+ if (inliner->GenIntrinsic(this, info)) {
+ return;
+ }
}
GenInvokeNoInline(info);
}
diff --git a/compiler/dex/quick/ralloc_util.cc b/compiler/dex/quick/ralloc_util.cc
index 487d31c..e779479 100644
--- a/compiler/dex/quick/ralloc_util.cc
+++ b/compiler/dex/quick/ralloc_util.cc
@@ -1156,7 +1156,7 @@
mir_graph_->GetCurrentDexCompilationUnit(), mir->offset)) {
break; // No code generated.
}
- if (!needs_access_check && !use_declaring_class && pc_rel_temp_ != nullptr) {
+ if (!needs_access_check && !use_declaring_class && CanUseOpPcRelDexCacheArrayLoad()) {
uses_pc_rel_load = true; // And ignore method use in slow path.
dex_cache_array_offset = dex_cache_arrays_layout_.TypeOffset(type_idx);
} else {
@@ -1166,7 +1166,7 @@
}
case Instruction::CONST_CLASS:
- if (pc_rel_temp_ != nullptr &&
+ if (CanUseOpPcRelDexCacheArrayLoad() &&
cu_->compiler_driver->CanAccessTypeWithoutChecks(cu_->method_idx, *cu_->dex_file,
mir->dalvikInsn.vB)) {
uses_pc_rel_load = true; // And ignore method use in slow path.
@@ -1178,7 +1178,7 @@
case Instruction::CONST_STRING:
case Instruction::CONST_STRING_JUMBO:
- if (pc_rel_temp_ != nullptr) {
+ if (CanUseOpPcRelDexCacheArrayLoad()) {
uses_pc_rel_load = true; // And ignore method use in slow path.
dex_cache_array_offset = dex_cache_arrays_layout_.StringOffset(mir->dalvikInsn.vB);
} else {
@@ -1200,11 +1200,13 @@
case Instruction::INVOKE_VIRTUAL_RANGE_QUICK: {
const MirMethodLoweringInfo& info = mir_graph_->GetMethodLoweringInfo(mir);
InvokeType sharp_type = info.GetSharpType();
- if (!info.FastPath() || (sharp_type != kStatic && sharp_type != kDirect)) {
+ if (info.IsIntrinsic()) {
+ // Nothing to do, if an intrinsic uses ArtMethod* it's in the slow-path - don't count it.
+ } else if (!info.FastPath() || (sharp_type != kStatic && sharp_type != kDirect)) {
// Nothing to do, the generated code or entrypoint uses method from the stack.
} else if (info.DirectCode() != 0 && info.DirectMethod() != 0) {
// Nothing to do, the generated code uses method from the stack.
- } else if (pc_rel_temp_ != nullptr) {
+ } else if (CanUseOpPcRelDexCacheArrayLoad()) {
uses_pc_rel_load = true;
dex_cache_array_offset = dex_cache_arrays_layout_.MethodOffset(mir->dalvikInsn.vB);
} else {
@@ -1245,7 +1247,7 @@
? field_info.FastGet()
: field_info.FastPut();
if (fast && (cu_->enable_debug & (1 << kDebugSlowFieldPath)) == 0) {
- if (!field_info.IsReferrersClass() && pc_rel_temp_ != nullptr) {
+ if (!field_info.IsReferrersClass() && CanUseOpPcRelDexCacheArrayLoad()) {
uses_pc_rel_load = true; // And ignore method use in slow path.
dex_cache_array_offset = dex_cache_arrays_layout_.TypeOffset(field_info.StorageIndex());
} else {
@@ -1264,9 +1266,13 @@
core_counts[SRegToPMap(mir_graph_->GetMethodLoc().s_reg_low)].count += weight;
}
if (uses_pc_rel_load) {
- core_counts[SRegToPMap(pc_rel_temp_->s_reg_low)].count += weight;
- DCHECK_NE(dex_cache_array_offset, std::numeric_limits<uint32_t>::max());
- dex_cache_arrays_min_offset_ = std::min(dex_cache_arrays_min_offset_, dex_cache_array_offset);
+ if (pc_rel_temp_ != nullptr) {
+ core_counts[SRegToPMap(pc_rel_temp_->s_reg_low)].count += weight;
+ DCHECK_NE(dex_cache_array_offset, std::numeric_limits<uint32_t>::max());
+ dex_cache_arrays_min_offset_ = std::min(dex_cache_arrays_min_offset_, dex_cache_array_offset);
+ } else {
+ // Nothing to do, using PC-relative addressing without promoting base PC to register.
+ }
}
}