[maglev] Add deopt reasons to eager deopts.
Bug: v8:7700 Change-Id: Iba160350ad2062abf7da6b97d04d255e0f780f4d Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3757893 Commit-Queue: Leszek Swirski <leszeks@chromium.org> Reviewed-by: Victor Gomes <victorgomes@chromium.org> Cr-Commit-Position: refs/heads/main@{#81725}
This commit is contained in:
parent
8cd5d85d63
commit
e7e29e4a12
@ -9,7 +9,9 @@
|
||||
#include "src/codegen/register.h"
|
||||
#include "src/codegen/reglist.h"
|
||||
#include "src/codegen/safepoint-table.h"
|
||||
#include "src/codegen/source-position.h"
|
||||
#include "src/codegen/x64/register-x64.h"
|
||||
#include "src/common/globals.h"
|
||||
#include "src/deoptimizer/translation-array.h"
|
||||
#include "src/execution/frame-constants.h"
|
||||
#include "src/interpreter/bytecode-register.h"
|
||||
@ -407,8 +409,11 @@ class MaglevCodeGeneratorImpl final {
|
||||
for (EagerDeoptInfo* deopt_info : code_gen_state_.eager_deopts()) {
|
||||
EmitEagerDeopt(deopt_info);
|
||||
|
||||
// TODO(leszeks): Record source positions.
|
||||
__ RecordDeoptReason(deopt_info->reason, 0, SourcePosition::Unknown(),
|
||||
deopt_index);
|
||||
__ bind(&deopt_info->deopt_entry_label);
|
||||
__ CallForDeoptimization(Builtin::kDeoptimizationEntry_Eager, 0,
|
||||
__ CallForDeoptimization(Builtin::kDeoptimizationEntry_Eager, deopt_index,
|
||||
&deopt_info->deopt_entry_label,
|
||||
DeoptimizeKind::kEager, nullptr, nullptr);
|
||||
deopt_index++;
|
||||
@ -420,7 +425,7 @@ class MaglevCodeGeneratorImpl final {
|
||||
EmitLazyDeopt(deopt_info);
|
||||
|
||||
__ bind(&deopt_info->deopt_entry_label);
|
||||
__ CallForDeoptimization(Builtin::kDeoptimizationEntry_Lazy, 0,
|
||||
__ CallForDeoptimization(Builtin::kDeoptimizationEntry_Lazy, deopt_index,
|
||||
&deopt_info->deopt_entry_label,
|
||||
DeoptimizeKind::kLazy, nullptr, nullptr);
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "src/compiler/feedback-source.h"
|
||||
#include "src/compiler/heap-refs.h"
|
||||
#include "src/compiler/processed-feedback.h"
|
||||
#include "src/deoptimizer/deoptimize-reason.h"
|
||||
#include "src/handles/maybe-handles-inl.h"
|
||||
#include "src/ic/handler-configuration-inl.h"
|
||||
#include "src/interpreter/bytecode-flags.h"
|
||||
@ -691,7 +692,8 @@ bool MaglevGraphBuilder::TryBuildPropertyCellAccess(
|
||||
compiler::ObjectRef property_cell_value = property_cell.value();
|
||||
if (property_cell_value.IsTheHole()) {
|
||||
// The property cell is no longer valid.
|
||||
EmitUnconditionalDeopt();
|
||||
EmitUnconditionalDeopt(
|
||||
DeoptimizeReason::kInsufficientTypeFeedbackForGenericNamedAccess);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -739,7 +741,8 @@ void MaglevGraphBuilder::VisitLdaGlobal() {
|
||||
broker()->GetFeedbackForGlobalAccess(feedback_source);
|
||||
|
||||
if (access_feedback.IsInsufficient()) {
|
||||
EmitUnconditionalDeopt();
|
||||
EmitUnconditionalDeopt(
|
||||
DeoptimizeReason::kInsufficientTypeFeedbackForGenericNamedAccess);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -875,7 +878,8 @@ void MaglevGraphBuilder::VisitGetNamedProperty() {
|
||||
|
||||
switch (processed_feedback.kind()) {
|
||||
case compiler::ProcessedFeedback::kInsufficient:
|
||||
EmitUnconditionalDeopt();
|
||||
EmitUnconditionalDeopt(
|
||||
DeoptimizeReason::kInsufficientTypeFeedbackForGenericNamedAccess);
|
||||
return;
|
||||
|
||||
case compiler::ProcessedFeedback::kNamedAccess: {
|
||||
@ -917,7 +921,8 @@ void MaglevGraphBuilder::VisitGetKeyedProperty() {
|
||||
|
||||
switch (processed_feedback.kind()) {
|
||||
case compiler::ProcessedFeedback::kInsufficient:
|
||||
EmitUnconditionalDeopt();
|
||||
EmitUnconditionalDeopt(
|
||||
DeoptimizeReason::kInsufficientTypeFeedbackForGenericKeyedAccess);
|
||||
return;
|
||||
|
||||
default:
|
||||
@ -1026,7 +1031,8 @@ void MaglevGraphBuilder::VisitSetNamedProperty() {
|
||||
|
||||
switch (processed_feedback.kind()) {
|
||||
case compiler::ProcessedFeedback::kInsufficient:
|
||||
EmitUnconditionalDeopt();
|
||||
EmitUnconditionalDeopt(
|
||||
DeoptimizeReason::kInsufficientTypeFeedbackForGenericNamedAccess);
|
||||
return;
|
||||
|
||||
case compiler::ProcessedFeedback::kNamedAccess: {
|
||||
@ -1067,7 +1073,8 @@ void MaglevGraphBuilder::VisitDefineNamedOwnProperty() {
|
||||
|
||||
switch (processed_feedback.kind()) {
|
||||
case compiler::ProcessedFeedback::kInsufficient:
|
||||
EmitUnconditionalDeopt();
|
||||
EmitUnconditionalDeopt(
|
||||
DeoptimizeReason::kInsufficientTypeFeedbackForGenericNamedAccess);
|
||||
return;
|
||||
|
||||
case compiler::ProcessedFeedback::kNamedAccess: {
|
||||
@ -1141,7 +1148,8 @@ void MaglevGraphBuilder::VisitStaInArrayLiteral() {
|
||||
|
||||
switch (processed_feedback.kind()) {
|
||||
case compiler::ProcessedFeedback::kInsufficient:
|
||||
EmitUnconditionalDeopt();
|
||||
EmitUnconditionalDeopt(
|
||||
DeoptimizeReason::kInsufficientTypeFeedbackForGenericKeyedAccess);
|
||||
return;
|
||||
|
||||
default:
|
||||
@ -1390,7 +1398,8 @@ void MaglevGraphBuilder::BuildCallFromRegisters(
|
||||
broker()->GetFeedbackForCall(compiler::FeedbackSource(feedback(), slot));
|
||||
switch (processed_feedback.kind()) {
|
||||
case compiler::ProcessedFeedback::kInsufficient:
|
||||
EmitUnconditionalDeopt();
|
||||
EmitUnconditionalDeopt(
|
||||
DeoptimizeReason::kInsufficientTypeFeedbackForCall);
|
||||
return;
|
||||
|
||||
case compiler::ProcessedFeedback::kCall: {
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "src/compiler/bytecode-liveness-map.h"
|
||||
#include "src/compiler/heap-refs.h"
|
||||
#include "src/compiler/js-heap-broker.h"
|
||||
#include "src/deoptimizer/deoptimize-reason.h"
|
||||
#include "src/interpreter/bytecode-array-iterator.h"
|
||||
#include "src/interpreter/bytecode-register.h"
|
||||
#include "src/maglev/maglev-graph-labeller.h"
|
||||
@ -127,10 +128,10 @@ class MaglevGraphBuilder {
|
||||
}
|
||||
|
||||
// Called when a block is killed by an unconditional eager deopt.
|
||||
void EmitUnconditionalDeopt() {
|
||||
void EmitUnconditionalDeopt(DeoptimizeReason reason) {
|
||||
// Create a block rather than calling finish, since we don't yet know the
|
||||
// next block's offset before the loop skipping the rest of the bytecodes.
|
||||
BasicBlock* block = CreateBlock<Deopt>({});
|
||||
BasicBlock* block = CreateBlock<Deopt>({}, reason);
|
||||
ResolveJumpsToBlockAtOffset(block, block_offset_);
|
||||
|
||||
MarkBytecodeDead();
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "src/codegen/x64/assembler-x64.h"
|
||||
#include "src/common/globals.h"
|
||||
#include "src/compiler/backend/instruction.h"
|
||||
#include "src/deoptimizer/deoptimize-reason.h"
|
||||
#include "src/ic/handler-configuration.h"
|
||||
#include "src/interpreter/bytecode-flags.h"
|
||||
#include "src/maglev/maglev-code-gen-state.h"
|
||||
@ -292,37 +293,42 @@ void JumpToDeferredIf(Condition cond, MaglevCodeGenState* code_gen_state,
|
||||
// ---
|
||||
|
||||
void RegisterEagerDeopt(MaglevCodeGenState* code_gen_state,
|
||||
EagerDeoptInfo* deopt_info) {
|
||||
EagerDeoptInfo* deopt_info, DeoptimizeReason reason) {
|
||||
if (deopt_info->reason != DeoptimizeReason::kUnknown) {
|
||||
DCHECK_EQ(deopt_info->reason, reason);
|
||||
}
|
||||
if (deopt_info->deopt_entry_label.is_unused()) {
|
||||
code_gen_state->PushEagerDeopt(deopt_info);
|
||||
deopt_info->reason = reason;
|
||||
}
|
||||
}
|
||||
|
||||
void EmitEagerDeopt(MaglevCodeGenState* code_gen_state,
|
||||
EagerDeoptInfo* deopt_info) {
|
||||
RegisterEagerDeopt(code_gen_state, deopt_info);
|
||||
EagerDeoptInfo* deopt_info, DeoptimizeReason reason) {
|
||||
RegisterEagerDeopt(code_gen_state, deopt_info, reason);
|
||||
__ RecordComment("-- Jump to eager deopt");
|
||||
__ jmp(&deopt_info->deopt_entry_label);
|
||||
}
|
||||
|
||||
template <typename NodeT>
|
||||
void EmitEagerDeopt(MaglevCodeGenState* code_gen_state, NodeT* node) {
|
||||
void EmitEagerDeopt(MaglevCodeGenState* code_gen_state, NodeT* node,
|
||||
DeoptimizeReason reason) {
|
||||
static_assert(NodeT::kProperties.can_eager_deopt());
|
||||
EmitEagerDeopt(code_gen_state, node->eager_deopt_info());
|
||||
EmitEagerDeopt(code_gen_state, node->eager_deopt_info(), reason);
|
||||
}
|
||||
|
||||
void EmitEagerDeoptIf(Condition cond, MaglevCodeGenState* code_gen_state,
|
||||
EagerDeoptInfo* deopt_info) {
|
||||
RegisterEagerDeopt(code_gen_state, deopt_info);
|
||||
DeoptimizeReason reason, EagerDeoptInfo* deopt_info) {
|
||||
RegisterEagerDeopt(code_gen_state, deopt_info, reason);
|
||||
__ RecordComment("-- Jump to eager deopt");
|
||||
__ j(cond, &deopt_info->deopt_entry_label);
|
||||
}
|
||||
|
||||
template <typename NodeT>
|
||||
void EmitEagerDeoptIf(Condition cond, MaglevCodeGenState* code_gen_state,
|
||||
NodeT* node) {
|
||||
DeoptimizeReason reason, NodeT* node) {
|
||||
static_assert(NodeT::kProperties.can_eager_deopt());
|
||||
EmitEagerDeoptIf(cond, code_gen_state, node->eager_deopt_info());
|
||||
EmitEagerDeoptIf(cond, code_gen_state, reason, node->eager_deopt_info());
|
||||
}
|
||||
|
||||
// ---
|
||||
@ -743,7 +749,8 @@ void CheckMaps::GenerateCode(MaglevCodeGenState* code_gen_state,
|
||||
Register object = ToRegister(receiver_input());
|
||||
|
||||
__ Cmp(FieldOperand(object, HeapObject::kMapOffset), map().object());
|
||||
EmitEagerDeoptIf(not_equal, code_gen_state, this);
|
||||
EmitEagerDeoptIf(not_equal, code_gen_state, DeoptimizeReason::kWrongMap,
|
||||
this);
|
||||
}
|
||||
void CheckMaps::PrintParams(std::ostream& os,
|
||||
MaglevGraphLabeller* graph_labeller) const {
|
||||
@ -756,7 +763,8 @@ void CheckSmi::GenerateCode(MaglevCodeGenState* code_gen_state,
|
||||
const ProcessingState& state) {
|
||||
Register object = ToRegister(receiver_input());
|
||||
Condition is_smi = __ CheckSmi(object);
|
||||
EmitEagerDeoptIf(NegateCondition(is_smi), code_gen_state, this);
|
||||
EmitEagerDeoptIf(NegateCondition(is_smi), code_gen_state,
|
||||
DeoptimizeReason::kNotASmi, this);
|
||||
}
|
||||
void CheckSmi::PrintParams(std::ostream& os,
|
||||
MaglevGraphLabeller* graph_labeller) const {}
|
||||
@ -768,7 +776,7 @@ void CheckHeapObject::GenerateCode(MaglevCodeGenState* code_gen_state,
|
||||
const ProcessingState& state) {
|
||||
Register object = ToRegister(receiver_input());
|
||||
Condition is_smi = __ CheckSmi(object);
|
||||
EmitEagerDeoptIf(is_smi, code_gen_state, this);
|
||||
EmitEagerDeoptIf(is_smi, code_gen_state, DeoptimizeReason::kSmi, this);
|
||||
}
|
||||
void CheckHeapObject::PrintParams(std::ostream& os,
|
||||
MaglevGraphLabeller* graph_labeller) const {}
|
||||
@ -788,7 +796,8 @@ void CheckMapsWithMigration::GenerateCode(MaglevCodeGenState* code_gen_state,
|
||||
[](MaglevCodeGenState* code_gen_state, Label* return_label,
|
||||
Register object, CheckMapsWithMigration* node,
|
||||
EagerDeoptInfo* deopt_info) {
|
||||
RegisterEagerDeopt(code_gen_state, deopt_info);
|
||||
RegisterEagerDeopt(code_gen_state, deopt_info,
|
||||
DeoptimizeReason::kWrongMap);
|
||||
|
||||
// Reload the map to avoid needing to save it on a temporary in the fast
|
||||
// path.
|
||||
@ -856,7 +865,7 @@ void CheckedInternalizedString::GenerateCode(MaglevCodeGenState* code_gen_state,
|
||||
Register map_tmp = temps.PopFirst();
|
||||
|
||||
Condition is_smi = __ CheckSmi(object);
|
||||
EmitEagerDeoptIf(is_smi, code_gen_state, this);
|
||||
EmitEagerDeoptIf(is_smi, code_gen_state, DeoptimizeReason::kWrongMap, this);
|
||||
|
||||
__ LoadMap(map_tmp, object);
|
||||
__ RecordComment("Test IsInternalizedString");
|
||||
@ -1296,7 +1305,7 @@ void Int32AddWithOverflow::GenerateCode(MaglevCodeGenState* code_gen_state,
|
||||
Register left = ToRegister(left_input());
|
||||
Register right = ToRegister(right_input());
|
||||
__ addl(left, right);
|
||||
EmitEagerDeoptIf(overflow, code_gen_state, this);
|
||||
EmitEagerDeoptIf(overflow, code_gen_state, DeoptimizeReason::kOverflow, this);
|
||||
}
|
||||
|
||||
void Int32SubtractWithOverflow::AllocateVreg(
|
||||
@ -1311,7 +1320,7 @@ void Int32SubtractWithOverflow::GenerateCode(MaglevCodeGenState* code_gen_state,
|
||||
Register left = ToRegister(left_input());
|
||||
Register right = ToRegister(right_input());
|
||||
__ subl(left, right);
|
||||
EmitEagerDeoptIf(overflow, code_gen_state, this);
|
||||
EmitEagerDeoptIf(overflow, code_gen_state, DeoptimizeReason::kOverflow, this);
|
||||
}
|
||||
|
||||
void Int32MultiplyWithOverflow::AllocateVreg(
|
||||
@ -1332,7 +1341,7 @@ void Int32MultiplyWithOverflow::GenerateCode(MaglevCodeGenState* code_gen_state,
|
||||
__ movl(saved_left, result);
|
||||
// TODO(leszeks): peephole optimise multiplication by a constant.
|
||||
__ imull(result, right);
|
||||
EmitEagerDeoptIf(overflow, code_gen_state, this);
|
||||
EmitEagerDeoptIf(overflow, code_gen_state, DeoptimizeReason::kOverflow, this);
|
||||
|
||||
// If the result is zero, check if either lhs or rhs is negative.
|
||||
Label end;
|
||||
@ -1343,8 +1352,9 @@ void Int32MultiplyWithOverflow::GenerateCode(MaglevCodeGenState* code_gen_state,
|
||||
__ cmpl(saved_left, Immediate(0));
|
||||
// If one of them is negative, we must have a -0 result, which is non-int32,
|
||||
// so deopt.
|
||||
// TODO(leszeks): Consider merging these deopts.
|
||||
EmitEagerDeoptIf(less, code_gen_state, this);
|
||||
// TODO(leszeks): Consider splitting these deopts to have distinct deopt
|
||||
// reasons. Otherwise, the reason has to match the above.
|
||||
EmitEagerDeoptIf(less, code_gen_state, DeoptimizeReason::kOverflow, this);
|
||||
}
|
||||
__ bind(&end);
|
||||
}
|
||||
@ -1368,7 +1378,7 @@ void Int32DivideWithOverflow::GenerateCode(MaglevCodeGenState* code_gen_state,
|
||||
// TODO(leszeks): peephole optimise division by a constant.
|
||||
__ idivl(right);
|
||||
__ cmpl(rdx, Immediate(0));
|
||||
EmitEagerDeoptIf(equal, code_gen_state, this);
|
||||
EmitEagerDeoptIf(equal, code_gen_state, DeoptimizeReason::kNotInt32, this);
|
||||
}
|
||||
|
||||
void Int32BitwiseAnd::AllocateVreg(MaglevVregAllocationState* vreg_state) {
|
||||
@ -1632,7 +1642,8 @@ void CheckedSmiUntag::GenerateCode(MaglevCodeGenState* code_gen_state,
|
||||
// of the `sarl` for cases where the deopt uses the value from a different
|
||||
// register.
|
||||
Condition is_smi = __ CheckSmi(value);
|
||||
EmitEagerDeoptIf(NegateCondition(is_smi), code_gen_state, this);
|
||||
EmitEagerDeoptIf(NegateCondition(is_smi), code_gen_state,
|
||||
DeoptimizeReason::kNotASmi, this);
|
||||
__ SmiToInt32(value);
|
||||
}
|
||||
|
||||
@ -1645,7 +1656,7 @@ void CheckedSmiTag::GenerateCode(MaglevCodeGenState* code_gen_state,
|
||||
const ProcessingState& state) {
|
||||
Register reg = ToRegister(input());
|
||||
__ addl(reg, reg);
|
||||
EmitEagerDeoptIf(overflow, code_gen_state, this);
|
||||
EmitEagerDeoptIf(overflow, code_gen_state, DeoptimizeReason::kOverflow, this);
|
||||
}
|
||||
|
||||
void Int32Constant::AllocateVreg(MaglevVregAllocationState* vreg_state) {
|
||||
@ -1700,7 +1711,8 @@ void CheckedFloat64Unbox::GenerateCode(MaglevCodeGenState* code_gen_state,
|
||||
// Check if HeapNumber, deopt otherwise.
|
||||
__ CompareRoot(FieldOperand(value, HeapObject::kMapOffset),
|
||||
RootIndex::kHeapNumberMap);
|
||||
EmitEagerDeoptIf(not_equal, code_gen_state, this);
|
||||
EmitEagerDeoptIf(not_equal, code_gen_state, DeoptimizeReason::kNotANumber,
|
||||
this);
|
||||
__ Movsd(ToDoubleRegister(result()),
|
||||
FieldOperand(value, HeapNumber::kValueOffset));
|
||||
__ bind(&done);
|
||||
@ -1960,7 +1972,11 @@ void Return::GenerateCode(MaglevCodeGenState* code_gen_state,
|
||||
void Deopt::AllocateVreg(MaglevVregAllocationState* vreg_state) {}
|
||||
void Deopt::GenerateCode(MaglevCodeGenState* code_gen_state,
|
||||
const ProcessingState& state) {
|
||||
EmitEagerDeopt(code_gen_state, this);
|
||||
EmitEagerDeopt(code_gen_state, this, reason());
|
||||
}
|
||||
void Deopt::PrintParams(std::ostream& os,
|
||||
MaglevGraphLabeller* graph_labeller) const {
|
||||
os << "(" << DeoptimizeReasonToString(reason()) << ")";
|
||||
}
|
||||
|
||||
void Jump::AllocateVreg(MaglevVregAllocationState* vreg_state) {}
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "src/common/operation.h"
|
||||
#include "src/compiler/backend/instruction.h"
|
||||
#include "src/compiler/heap-refs.h"
|
||||
#include "src/deoptimizer/deoptimize-reason.h"
|
||||
#include "src/interpreter/bytecode-register.h"
|
||||
#include "src/maglev/maglev-compilation-unit.h"
|
||||
#include "src/objects/smi.h"
|
||||
@ -488,6 +489,7 @@ class EagerDeoptInfo : public DeoptInfo {
|
||||
EagerDeoptInfo(Zone* zone, const MaglevCompilationUnit& compilation_unit,
|
||||
CheckpointedInterpreterState checkpoint)
|
||||
: DeoptInfo(zone, compilation_unit, checkpoint) {}
|
||||
DeoptimizeReason reason = DeoptimizeReason::kUnknown;
|
||||
};
|
||||
|
||||
class LazyDeoptInfo : public DeoptInfo {
|
||||
@ -2828,15 +2830,21 @@ class Return : public ControlNode {
|
||||
|
||||
class Deopt : public ControlNode {
|
||||
public:
|
||||
explicit Deopt(uint64_t bitfield) : ControlNode(bitfield) {
|
||||
explicit Deopt(uint64_t bitfield, DeoptimizeReason reason)
|
||||
: ControlNode(bitfield), reason_(reason) {
|
||||
DCHECK_EQ(NodeBase::opcode(), opcode_of<Deopt>);
|
||||
}
|
||||
|
||||
static constexpr OpProperties kProperties = OpProperties::EagerDeopt();
|
||||
|
||||
DeoptimizeReason reason() const { return reason_; }
|
||||
|
||||
void AllocateVreg(MaglevVregAllocationState*);
|
||||
void GenerateCode(MaglevCodeGenState*, const ProcessingState&);
|
||||
void PrintParams(std::ostream&, MaglevGraphLabeller*) const {}
|
||||
void PrintParams(std::ostream&, MaglevGraphLabeller*) const;
|
||||
|
||||
private:
|
||||
DeoptimizeReason reason_;
|
||||
};
|
||||
|
||||
class BranchIfTrue : public ConditionalControlNodeT<1, BranchIfTrue> {
|
||||
|
Loading…
Reference in New Issue
Block a user