summaryrefslogtreecommitdiff
path: root/compiler/optimizing
diff options
context:
space:
mode:
author Mythri Alle <mythria@google.com> 2023-04-24 09:12:54 +0000
committer Mythri Alle <mythria@google.com> 2023-04-25 08:46:29 +0000
commitcb008914fbc5a2334e3c00366afdb5f8af5a23ba (patch)
tree8d3776e8021da39b32ad377a5f0eda20c9490c93 /compiler/optimizing
parente834f1ec604e4c8e15dabfa9685de0eb646f3824 (diff)
Don't enable intrinsic optimizations in debuggable runtime
We have optimizations that generate code inline for intrinsics instead of leaving them as invoke for better performance. Some debug features like method entry / exit or setting a breakpoint on intrinsics wouldn't work if intrinsics are inlined. So disable those optimizations in debuggable runtimes. Also update 988-method-trace test to test intrinsics on JITed code. Test: art/test.py -t 988 Bug: 279547861 Change-Id: Ic7c61d1b1541ff534faa24ccec5c2d0b574b0537
Diffstat (limited to 'compiler/optimizing')
-rw-r--r--compiler/optimizing/critical_native_abi_fixup_arm.cc3
-rw-r--r--compiler/optimizing/inliner.cc6
-rw-r--r--compiler/optimizing/instruction_builder.cc35
-rw-r--r--compiler/optimizing/instruction_simplifier.cc2
-rw-r--r--compiler/optimizing/load_store_analysis_test.cc30
-rw-r--r--compiler/optimizing/nodes.cc4
-rw-r--r--compiler/optimizing/nodes.h40
-rw-r--r--compiler/optimizing/optimizing_unit_test.h3
8 files changed, 83 insertions, 40 deletions
diff --git a/compiler/optimizing/critical_native_abi_fixup_arm.cc b/compiler/optimizing/critical_native_abi_fixup_arm.cc
index 03fb26bf1e..77e156608b 100644
--- a/compiler/optimizing/critical_native_abi_fixup_arm.cc
+++ b/compiler/optimizing/critical_native_abi_fixup_arm.cc
@@ -74,7 +74,8 @@ static void FixUpArguments(HInvokeStaticOrDirect* invoke) {
dispatch_info,
kStatic,
target_method,
- HInvokeStaticOrDirect::ClinitCheckRequirement::kNone);
+ HInvokeStaticOrDirect::ClinitCheckRequirement::kNone,
+ !block->GetGraph()->IsDebuggable());
// The intrinsic has no side effects and does not need environment or dex cache on ARM.
new_input->SetSideEffects(SideEffects::None());
IntrinsicOptimizations opt(new_input);
diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc
index da498d4277..4bf62f3c26 100644
--- a/compiler/optimizing/inliner.cc
+++ b/compiler/optimizing/inliner.cc
@@ -1321,7 +1321,8 @@ bool HInliner::TryDevirtualize(HInvoke* invoke_instruction,
dispatch_info,
kDirect,
MethodReference(method->GetDexFile(), method->GetDexMethodIndex()),
- HInvokeStaticOrDirect::ClinitCheckRequirement::kNone);
+ HInvokeStaticOrDirect::ClinitCheckRequirement::kNone,
+ !graph_->IsDebuggable());
HInputsRef inputs = invoke_instruction->GetInputs();
DCHECK_EQ(inputs.size(), invoke_instruction->GetNumberOfArguments());
for (size_t index = 0; index != inputs.size(); ++index) {
@@ -1527,7 +1528,8 @@ bool HInliner::TryBuildAndInline(HInvoke* invoke_instruction,
invoke_instruction->GetMethodReference(), // Use existing invoke's method's reference.
method,
MethodReference(method->GetDexFile(), method->GetDexMethodIndex()),
- method->GetMethodIndex());
+ method->GetMethodIndex(),
+ !graph_->IsDebuggable());
DCHECK_NE(new_invoke->GetIntrinsic(), Intrinsics::kNone);
HInputsRef inputs = invoke_instruction->GetInputs();
for (size_t index = 0; index != inputs.size(); ++index) {
diff --git a/compiler/optimizing/instruction_builder.cc b/compiler/optimizing/instruction_builder.cc
index f9a513804c..fee9091145 100644
--- a/compiler/optimizing/instruction_builder.cc
+++ b/compiler/optimizing/instruction_builder.cc
@@ -469,6 +469,9 @@ void HInstructionBuilder::BuildIntrinsic(ArtMethod* method) {
current_block_ = graph_->GetEntryBlock();
InitializeBlockLocals();
InitializeParameters();
+ if (graph_->IsDebuggable() && code_generator_->GetCompilerOptions().IsJitCompiler()) {
+ AppendInstruction(new (allocator_) HMethodEntryHook(0u));
+ }
AppendInstruction(new (allocator_) HGoto(0u));
// Fill the body.
@@ -504,14 +507,21 @@ void HInstructionBuilder::BuildIntrinsic(ArtMethod* method) {
dispatch_info,
invoke_type,
target_method,
- HInvokeStaticOrDirect::ClinitCheckRequirement::kNone);
+ HInvokeStaticOrDirect::ClinitCheckRequirement::kNone,
+ !graph_->IsDebuggable());
HandleInvoke(invoke, operands, shorty, /* is_unresolved= */ false);
}
// Add the return instruction.
if (return_type_ == DataType::Type::kVoid) {
+ if (graph_->IsDebuggable() && code_generator_->GetCompilerOptions().IsJitCompiler()) {
+ AppendInstruction(new (allocator_) HMethodExitHook(graph_->GetNullConstant(), kNoDexPc));
+ }
AppendInstruction(new (allocator_) HReturnVoid());
} else {
+ if (graph_->IsDebuggable() && code_generator_->GetCompilerOptions().IsJitCompiler()) {
+ AppendInstruction(new (allocator_) HMethodExitHook(latest_result_, kNoDexPc));
+ }
AppendInstruction(new (allocator_) HReturn(latest_result_));
}
@@ -1050,7 +1060,8 @@ bool HInstructionBuilder::BuildInvoke(const Instruction& instruction,
dispatch_info,
invoke_type,
resolved_method_reference,
- HInvokeStaticOrDirect::ClinitCheckRequirement::kImplicit);
+ HInvokeStaticOrDirect::ClinitCheckRequirement::kImplicit,
+ !graph_->IsDebuggable());
return HandleStringInit(invoke, operands, shorty);
}
@@ -1063,7 +1074,7 @@ bool HInstructionBuilder::BuildInvoke(const Instruction& instruction,
}
// Try to build an HIR replacement for the intrinsic.
- if (UNLIKELY(resolved_method->IsIntrinsic())) {
+ if (UNLIKELY(resolved_method->IsIntrinsic()) && !graph_->IsDebuggable()) {
// All intrinsics are in the primary boot image, so their class can always be referenced
// and we do not need to rely on the implicit class initialization check. The class should
// be initialized but we do not require that here.
@@ -1114,7 +1125,8 @@ bool HInstructionBuilder::BuildInvoke(const Instruction& instruction,
dispatch_info,
invoke_type,
resolved_method_reference,
- clinit_check_requirement);
+ clinit_check_requirement,
+ !graph_->IsDebuggable());
if (clinit_check != nullptr) {
// Add the class initialization check as last input of `invoke`.
DCHECK_EQ(clinit_check_requirement, HInvokeStaticOrDirect::ClinitCheckRequirement::kExplicit);
@@ -1130,7 +1142,8 @@ bool HInstructionBuilder::BuildInvoke(const Instruction& instruction,
method_reference,
resolved_method,
resolved_method_reference,
- /*vtable_index=*/ imt_or_vtable_index);
+ /*vtable_index=*/ imt_or_vtable_index,
+ !graph_->IsDebuggable());
} else {
DCHECK_EQ(invoke_type, kInterface);
if (kIsDebugBuild) {
@@ -1151,7 +1164,8 @@ bool HInstructionBuilder::BuildInvoke(const Instruction& instruction,
resolved_method,
resolved_method_reference,
/*imt_index=*/ imt_or_vtable_index,
- load_kind);
+ load_kind,
+ !graph_->IsDebuggable());
}
return HandleInvoke(invoke, operands, shorty, /* is_unresolved= */ false);
}
@@ -1350,12 +1364,14 @@ bool HInstructionBuilder::BuildInvokePolymorphic(uint32_t dex_pc,
method_reference,
resolved_method,
resolved_method_reference,
- proto_idx);
+ proto_idx,
+ !graph_->IsDebuggable());
if (!HandleInvoke(invoke, operands, shorty, /* is_unresolved= */ false)) {
return false;
}
- if (invoke->GetIntrinsic() != Intrinsics::kMethodHandleInvoke &&
+ if (invoke->GetIntrinsic() != Intrinsics::kNone &&
+ invoke->GetIntrinsic() != Intrinsics::kMethodHandleInvoke &&
invoke->GetIntrinsic() != Intrinsics::kMethodHandleInvokeExact &&
VarHandleAccessorNeedsReturnTypeCheck(invoke, return_type)) {
// Type check is needed because VarHandle intrinsics do not type check the retrieved reference.
@@ -1388,7 +1404,8 @@ bool HInstructionBuilder::BuildInvokeCustom(uint32_t dex_pc,
call_site_idx,
return_type,
dex_pc,
- method_reference);
+ method_reference,
+ !graph_->IsDebuggable());
return HandleInvoke(invoke, operands, shorty, /* is_unresolved= */ false);
}
diff --git a/compiler/optimizing/instruction_simplifier.cc b/compiler/optimizing/instruction_simplifier.cc
index bf51b5dcf4..0c2fd5de56 100644
--- a/compiler/optimizing/instruction_simplifier.cc
+++ b/compiler/optimizing/instruction_simplifier.cc
@@ -2465,7 +2465,7 @@ void InstructionSimplifierVisitor::SimplifySystemArrayCopy(HInvoke* instruction)
DCHECK(method != nullptr);
DCHECK(method->IsStatic());
DCHECK(method->GetDeclaringClass() == system);
- invoke->SetResolvedMethod(method);
+ invoke->SetResolvedMethod(method, !codegen_->GetGraph()->IsDebuggable());
// Sharpen the new invoke. Note that we do not update the dex method index of
// the invoke, as we would need to look it up in the current dex file, and it
// is unlikely that it exists. The most usual situation for such typed
diff --git a/compiler/optimizing/load_store_analysis_test.cc b/compiler/optimizing/load_store_analysis_test.cc
index 17e7f1fb15..865febbd31 100644
--- a/compiler/optimizing/load_store_analysis_test.cc
+++ b/compiler/optimizing/load_store_analysis_test.cc
@@ -894,7 +894,8 @@ TEST_F(LoadStoreAnalysisTest, PartialEscape) {
{},
InvokeType::kStatic,
{ nullptr, 0 },
- HInvokeStaticOrDirect::ClinitCheckRequirement::kNone);
+ HInvokeStaticOrDirect::ClinitCheckRequirement::kNone,
+ !graph_->IsDebuggable());
HInstruction* goto_left = new (GetAllocator()) HGoto();
call_left->AsInvoke()->SetRawInputAt(0, new_inst);
left->AddInstruction(call_left);
@@ -1003,7 +1004,8 @@ TEST_F(LoadStoreAnalysisTest, PartialEscape2) {
{},
InvokeType::kStatic,
{ nullptr, 0 },
- HInvokeStaticOrDirect::ClinitCheckRequirement::kNone);
+ HInvokeStaticOrDirect::ClinitCheckRequirement::kNone,
+ !graph_->IsDebuggable());
HInstruction* goto_left = new (GetAllocator()) HGoto();
call_left->AsInvoke()->SetRawInputAt(0, new_inst);
left->AddInstruction(call_left);
@@ -1126,7 +1128,8 @@ TEST_F(LoadStoreAnalysisTest, PartialEscape3) {
{},
InvokeType::kStatic,
{ nullptr, 0 },
- HInvokeStaticOrDirect::ClinitCheckRequirement::kNone);
+ HInvokeStaticOrDirect::ClinitCheckRequirement::kNone,
+ !graph_->IsDebuggable());
HInstruction* goto_left = new (GetAllocator()) HGoto();
call_left->AsInvoke()->SetRawInputAt(0, new_inst);
left->AddInstruction(call_left);
@@ -1406,7 +1409,8 @@ TEST_F(LoadStoreAnalysisTest, TotalEscapeAdjacentNoPredicated) {
{},
InvokeType::kStatic,
{nullptr, 0},
- HInvokeStaticOrDirect::ClinitCheckRequirement::kNone);
+ HInvokeStaticOrDirect::ClinitCheckRequirement::kNone,
+ !graph_->IsDebuggable());
HInstruction* goto_left = new (GetAllocator()) HGoto();
call_left->AsInvoke()->SetRawInputAt(0, new_inst);
left->AddInstruction(call_left);
@@ -1507,7 +1511,8 @@ TEST_F(LoadStoreAnalysisTest, TotalEscapeAdjacent) {
{},
InvokeType::kStatic,
{ nullptr, 0 },
- HInvokeStaticOrDirect::ClinitCheckRequirement::kNone);
+ HInvokeStaticOrDirect::ClinitCheckRequirement::kNone,
+ !graph_->IsDebuggable());
HInstruction* goto_left = new (GetAllocator()) HGoto();
call_left->AsInvoke()->SetRawInputAt(0, new_inst);
left->AddInstruction(call_left);
@@ -1618,7 +1623,8 @@ TEST_F(LoadStoreAnalysisTest, TotalEscape) {
{},
InvokeType::kStatic,
{ nullptr, 0 },
- HInvokeStaticOrDirect::ClinitCheckRequirement::kNone);
+ HInvokeStaticOrDirect::ClinitCheckRequirement::kNone,
+ !graph_->IsDebuggable());
HInstruction* goto_left = new (GetAllocator()) HGoto();
call_left->AsInvoke()->SetRawInputAt(0, new_inst);
left->AddInstruction(call_left);
@@ -1634,7 +1640,8 @@ TEST_F(LoadStoreAnalysisTest, TotalEscape) {
{},
InvokeType::kStatic,
{ nullptr, 0 },
- HInvokeStaticOrDirect::ClinitCheckRequirement::kNone);
+ HInvokeStaticOrDirect::ClinitCheckRequirement::kNone,
+ !graph_->IsDebuggable());
HInstruction* write_right = new (GetAllocator()) HInstanceFieldSet(new_inst,
c0,
nullptr,
@@ -1803,7 +1810,8 @@ TEST_F(LoadStoreAnalysisTest, DoubleDiamondEscape) {
{},
InvokeType::kStatic,
{ nullptr, 0 },
- HInvokeStaticOrDirect::ClinitCheckRequirement::kNone);
+ HInvokeStaticOrDirect::ClinitCheckRequirement::kNone,
+ !graph_->IsDebuggable());
HInstruction* goto_left = new (GetAllocator()) HGoto();
call_left->AsInvoke()->SetRawInputAt(0, new_inst);
high_left->AddInstruction(call_left);
@@ -1859,7 +1867,8 @@ TEST_F(LoadStoreAnalysisTest, DoubleDiamondEscape) {
{},
InvokeType::kStatic,
{ nullptr, 0 },
- HInvokeStaticOrDirect::ClinitCheckRequirement::kNone);
+ HInvokeStaticOrDirect::ClinitCheckRequirement::kNone,
+ !graph_->IsDebuggable());
HInstruction* goto_low_left = new (GetAllocator()) HGoto();
call_low_left->AsInvoke()->SetRawInputAt(0, new_inst);
low_left->AddInstruction(call_low_left);
@@ -2016,7 +2025,8 @@ TEST_F(LoadStoreAnalysisTest, PartialPhiPropagation1) {
{},
InvokeType::kStatic,
{nullptr, 0},
- HInvokeStaticOrDirect::ClinitCheckRequirement::kNone);
+ HInvokeStaticOrDirect::ClinitCheckRequirement::kNone,
+ !graph_->IsDebuggable());
HInstruction* goto_left_merge = new (GetAllocator()) HGoto();
left_phi->SetRawInputAt(0, obj_param);
left_phi->SetRawInputAt(1, new_inst);
diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc
index c99cfab05f..3790058879 100644
--- a/compiler/optimizing/nodes.cc
+++ b/compiler/optimizing/nodes.cc
@@ -3571,8 +3571,8 @@ static inline IntrinsicExceptions GetExceptionsIntrinsic(Intrinsics i) {
return kCanThrow;
}
-void HInvoke::SetResolvedMethod(ArtMethod* method) {
- if (method != nullptr && method->IsIntrinsic()) {
+void HInvoke::SetResolvedMethod(ArtMethod* method, bool enable_intrinsic_opt) {
+ if (method != nullptr && method->IsIntrinsic() && enable_intrinsic_opt) {
Intrinsics intrinsic = static_cast<Intrinsics>(method->GetIntrinsic());
SetIntrinsic(intrinsic,
NeedsEnvironmentIntrinsic(intrinsic),
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index fc5d2196da..28112d176a 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -4756,7 +4756,7 @@ class HInvoke : public HVariableInputSizeInstruction {
bool IsIntrinsic() const { return intrinsic_ != Intrinsics::kNone; }
ArtMethod* GetResolvedMethod() const { return resolved_method_; }
- void SetResolvedMethod(ArtMethod* method);
+ void SetResolvedMethod(ArtMethod* method, bool enable_intrinsic_opt);
MethodReference GetMethodReference() const { return method_reference_; }
@@ -4785,7 +4785,8 @@ class HInvoke : public HVariableInputSizeInstruction {
MethodReference method_reference,
ArtMethod* resolved_method,
MethodReference resolved_method_reference,
- InvokeType invoke_type)
+ InvokeType invoke_type,
+ bool enable_intrinsic_opt)
: HVariableInputSizeInstruction(
kind,
return_type,
@@ -4801,7 +4802,7 @@ class HInvoke : public HVariableInputSizeInstruction {
intrinsic_optimizations_(0) {
SetPackedField<InvokeTypeField>(invoke_type);
SetPackedFlag<kFlagCanThrow>(true);
- SetResolvedMethod(resolved_method);
+ SetResolvedMethod(resolved_method, enable_intrinsic_opt);
}
DEFAULT_COPY_CONSTRUCTOR(Invoke);
@@ -4834,7 +4835,8 @@ class HInvokeUnresolved final : public HInvoke {
method_reference,
nullptr,
MethodReference(nullptr, 0u),
- invoke_type) {
+ invoke_type,
+ /* enable_intrinsic_opt= */ false) {
}
bool IsClonable() const override { return true; }
@@ -4857,7 +4859,8 @@ class HInvokePolymorphic final : public HInvoke {
// to pass intrinsic information to the HInvokePolymorphic node.
ArtMethod* resolved_method,
MethodReference resolved_method_reference,
- dex::ProtoIndex proto_idx)
+ dex::ProtoIndex proto_idx,
+ bool enable_intrinsic_opt)
: HInvoke(kInvokePolymorphic,
allocator,
number_of_arguments,
@@ -4867,7 +4870,8 @@ class HInvokePolymorphic final : public HInvoke {
method_reference,
resolved_method,
resolved_method_reference,
- kPolymorphic),
+ kPolymorphic,
+ enable_intrinsic_opt),
proto_idx_(proto_idx) {
}
@@ -4889,7 +4893,8 @@ class HInvokeCustom final : public HInvoke {
uint32_t call_site_index,
DataType::Type return_type,
uint32_t dex_pc,
- MethodReference method_reference)
+ MethodReference method_reference,
+ bool enable_intrinsic_opt)
: HInvoke(kInvokeCustom,
allocator,
number_of_arguments,
@@ -4899,7 +4904,8 @@ class HInvokeCustom final : public HInvoke {
method_reference,
/* resolved_method= */ nullptr,
MethodReference(nullptr, 0u),
- kStatic),
+ kStatic,
+ enable_intrinsic_opt),
call_site_index_(call_site_index) {
}
@@ -4946,7 +4952,8 @@ class HInvokeStaticOrDirect final : public HInvoke {
DispatchInfo dispatch_info,
InvokeType invoke_type,
MethodReference resolved_method_reference,
- ClinitCheckRequirement clinit_check_requirement)
+ ClinitCheckRequirement clinit_check_requirement,
+ bool enable_intrinsic_opt)
: HInvoke(kInvokeStaticOrDirect,
allocator,
number_of_arguments,
@@ -4959,7 +4966,8 @@ class HInvokeStaticOrDirect final : public HInvoke {
method_reference,
resolved_method,
resolved_method_reference,
- invoke_type),
+ invoke_type,
+ enable_intrinsic_opt),
dispatch_info_(dispatch_info) {
SetPackedField<ClinitCheckRequirementField>(clinit_check_requirement);
}
@@ -5171,7 +5179,8 @@ class HInvokeVirtual final : public HInvoke {
MethodReference method_reference,
ArtMethod* resolved_method,
MethodReference resolved_method_reference,
- uint32_t vtable_index)
+ uint32_t vtable_index,
+ bool enable_intrinsic_opt)
: HInvoke(kInvokeVirtual,
allocator,
number_of_arguments,
@@ -5181,7 +5190,8 @@ class HInvokeVirtual final : public HInvoke {
method_reference,
resolved_method,
resolved_method_reference,
- kVirtual),
+ kVirtual,
+ enable_intrinsic_opt),
vtable_index_(vtable_index) {
}
@@ -5233,7 +5243,8 @@ class HInvokeInterface final : public HInvoke {
ArtMethod* resolved_method,
MethodReference resolved_method_reference,
uint32_t imt_index,
- MethodLoadKind load_kind)
+ MethodLoadKind load_kind,
+ bool enable_intrinsic_opt)
: HInvoke(kInvokeInterface,
allocator,
number_of_arguments + (NeedsCurrentMethod(load_kind) ? 1 : 0),
@@ -5243,7 +5254,8 @@ class HInvokeInterface final : public HInvoke {
method_reference,
resolved_method,
resolved_method_reference,
- kInterface),
+ kInterface,
+ enable_intrinsic_opt),
imt_index_(imt_index),
hidden_argument_load_kind_(load_kind) {
}
diff --git a/compiler/optimizing/optimizing_unit_test.h b/compiler/optimizing/optimizing_unit_test.h
index f18ffc7f83..2e05c41f01 100644
--- a/compiler/optimizing/optimizing_unit_test.h
+++ b/compiler/optimizing/optimizing_unit_test.h
@@ -461,7 +461,8 @@ class OptimizingUnitTestHelper {
HInvokeStaticOrDirect::DispatchInfo{},
InvokeType::kStatic,
/* resolved_method_reference= */ method_reference,
- HInvokeStaticOrDirect::ClinitCheckRequirement::kNone);
+ HInvokeStaticOrDirect::ClinitCheckRequirement::kNone,
+ !graph_->IsDebuggable());
for (auto [ins, idx] : ZipCount(MakeIterationRange(args))) {
res->SetRawInputAt(idx, ins);
}