[maglev] Use accessors for DeoptInfo fields

... so that we can add logic to them later for builtin continuation
deopts.

Bug: v8:7700
Change-Id: I03a616243efecb5d637d6ab7d078392a0c51abf4
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3985907
Reviewed-by: Victor Gomes <victorgomes@chromium.org>
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Auto-Submit: Leszek Swirski <leszeks@chromium.org>
Commit-Queue: Victor Gomes <victorgomes@chromium.org>
Cr-Commit-Position: refs/heads/main@{#83953}
This commit is contained in:
Leszek Swirski 2022-10-27 12:49:56 +02:00 committed by V8 LUCI CQ
parent 8852999115
commit 4d8055d41e
8 changed files with 134 additions and 105 deletions

View File

@ -72,7 +72,7 @@ Register MaglevAssembler::FromAnyToRegister(const Input& input,
}
inline void MaglevAssembler::DefineLazyDeoptPoint(LazyDeoptInfo* info) {
info->deopting_call_return_pc = pc_offset_for_safepoint();
info->set_deopting_call_return_pc(pc_offset_for_safepoint());
code_gen_state()->PushLazyDeopt(info);
safepoint_table_builder()->DefineSafepoint(this);
}
@ -274,12 +274,12 @@ inline void MaglevAssembler::JumpToDeferredIf(Condition cond,
inline void MaglevAssembler::RegisterEagerDeopt(EagerDeoptInfo* deopt_info,
DeoptimizeReason reason) {
if (deopt_info->reason != DeoptimizeReason::kUnknown) {
DCHECK_EQ(deopt_info->reason, reason);
if (deopt_info->reason() != DeoptimizeReason::kUnknown) {
DCHECK_EQ(deopt_info->reason(), reason);
}
if (deopt_info->deopt_entry_label.is_unused()) {
if (deopt_info->deopt_entry_label()->is_unused()) {
code_gen_state()->PushEagerDeopt(deopt_info);
deopt_info->reason = reason;
deopt_info->set_reason(reason);
}
}
@ -289,7 +289,7 @@ inline void MaglevAssembler::EmitEagerDeopt(NodeT* node,
static_assert(NodeT::kProperties.can_eager_deopt());
RegisterEagerDeopt(node->eager_deopt_info(), reason);
RecordComment("-- Jump to eager deopt");
jmp(&node->eager_deopt_info()->deopt_entry_label);
jmp(node->eager_deopt_info()->deopt_entry_label());
}
template <typename NodeT>
@ -299,7 +299,7 @@ inline void MaglevAssembler::EmitEagerDeoptIf(Condition cond,
static_assert(NodeT::kProperties.can_eager_deopt());
RegisterEagerDeopt(node->eager_deopt_info(), reason);
RecordComment("-- Jump to eager deopt");
j(cond, &node->eager_deopt_info()->deopt_entry_label);
j(cond, node->eager_deopt_info()->deopt_entry_label());
}
} // namespace maglev

View File

@ -484,8 +484,9 @@ class ExceptionHandlerTrampolineBuilder {
ParallelMoveResolver<Register> direct_moves(masm_);
MoveVector materialising_moves;
bool save_accumulator = false;
RecordMoves(deopt_info->unit, catch_block, deopt_info->state.register_frame,
&direct_moves, &materialising_moves, &save_accumulator);
RecordMoves(deopt_info->unit(), catch_block,
deopt_info->state().register_frame, &direct_moves,
&materialising_moves, &save_accumulator);
__ bind(&handler_info->trampoline_entry);
__ RecordComment("-- Exception handler trampoline START");
@ -990,33 +991,33 @@ class MaglevTranslationArrayBuilder {
deopt_literals_(deopt_literals) {}
void BuildEagerDeopt(EagerDeoptInfo* deopt_info) {
int frame_count = 1 + deopt_info->unit.inlining_depth();
int frame_count = 1 + deopt_info->unit().inlining_depth();
int jsframe_count = frame_count;
int update_feedback_count = 0;
deopt_info->translation_index =
deopt_info->set_translation_index(
translation_array_builder_->BeginTranslation(frame_count, jsframe_count,
update_feedback_count);
update_feedback_count));
const InputLocation* current_input_location = deopt_info->input_locations;
BuildDeoptFrame(deopt_info->unit, deopt_info->state,
const InputLocation* current_input_location = deopt_info->input_locations();
BuildDeoptFrame(deopt_info->unit(), deopt_info->state(),
current_input_location);
}
void BuildLazyDeopt(LazyDeoptInfo* deopt_info) {
int frame_count = 1 + deopt_info->unit.inlining_depth();
int frame_count = 1 + deopt_info->unit().inlining_depth();
int jsframe_count = frame_count;
int update_feedback_count = 0;
deopt_info->translation_index =
deopt_info->set_translation_index(
translation_array_builder_->BeginTranslation(frame_count, jsframe_count,
update_feedback_count);
update_feedback_count));
const MaglevCompilationUnit& unit = deopt_info->unit;
const InputLocation* current_input_location = deopt_info->input_locations;
const MaglevCompilationUnit& unit = deopt_info->unit();
const InputLocation* current_input_location = deopt_info->input_locations();
if (deopt_info->state.parent) {
if (deopt_info->state().parent) {
// Deopt input locations are in the order of deopt frame emission, so
// update the pointer after emitting the parent frame.
BuildDeoptFrame(*unit.caller(), *deopt_info->state.parent,
BuildDeoptFrame(*unit.caller(), *deopt_info->state().parent,
current_input_location);
}
@ -1024,10 +1025,10 @@ class MaglevTranslationArrayBuilder {
// is the array [parameters..., locals..., accumulator]. Since it's the end,
// we don't need to worry about earlier frames.
int return_offset;
if (deopt_info->result_location ==
if (deopt_info->result_location() ==
interpreter::Register::virtual_accumulator()) {
return_offset = 0;
} else if (deopt_info->result_location.is_parameter()) {
} else if (deopt_info->result_location().is_parameter()) {
// This is slightly tricky to reason about because of zero indexing and
// fence post errors. As an example, consider a frame with 2 locals and
// 2 parameters, where we want argument index 1 -- looking at the array
@ -1037,19 +1038,19 @@ class MaglevTranslationArrayBuilder {
// and this calculation gives, correctly:
// 2 + 2 - 1 = 3
return_offset = unit.register_count() + unit.parameter_count() -
deopt_info->result_location.ToParameterIndex();
deopt_info->result_location().ToParameterIndex();
} else {
return_offset =
unit.register_count() - deopt_info->result_location.index();
unit.register_count() - deopt_info->result_location().index();
}
translation_array_builder_->BeginInterpretedFrame(
deopt_info->state.bytecode_position,
deopt_info->state().bytecode_position,
GetDeoptLiteral(*unit.shared_function_info().object()),
unit.register_count(), return_offset, deopt_info->result_size);
unit.register_count(), return_offset, deopt_info->result_size());
BuildDeoptFrameValues(unit, deopt_info->state.register_frame,
current_input_location, deopt_info->result_location,
deopt_info->result_size);
BuildDeoptFrameValues(unit, deopt_info->state().register_frame,
current_input_location, deopt_info->result_location(),
deopt_info->result_size());
}
private:
@ -1295,12 +1296,12 @@ void MaglevCodeGenerator::EmitDeopts() {
translation_builder.BuildEagerDeopt(deopt_info);
if (masm_.compilation_info()->collect_source_positions()) {
__ RecordDeoptReason(deopt_info->reason, 0, deopt_info->source_position,
deopt_index);
__ RecordDeoptReason(deopt_info->reason(), 0,
deopt_info->source_position(), deopt_index);
}
__ bind(&deopt_info->deopt_entry_label);
__ bind(deopt_info->deopt_entry_label());
__ CallForDeoptimization(Builtin::kDeoptimizationEntry_Eager, deopt_index,
&deopt_info->deopt_entry_label,
deopt_info->deopt_entry_label(),
DeoptimizeKind::kEager, nullptr, nullptr);
deopt_index++;
}
@ -1313,16 +1314,16 @@ void MaglevCodeGenerator::EmitDeopts() {
if (masm_.compilation_info()->collect_source_positions()) {
__ RecordDeoptReason(DeoptimizeReason::kUnknown, 0,
deopt_info->source_position, deopt_index);
deopt_info->source_position(), deopt_index);
}
__ bind(&deopt_info->deopt_entry_label);
__ bind(deopt_info->deopt_entry_label());
__ CallForDeoptimization(Builtin::kDeoptimizationEntry_Lazy, deopt_index,
&deopt_info->deopt_entry_label,
deopt_info->deopt_entry_label(),
DeoptimizeKind::kLazy, nullptr, nullptr);
last_updated_safepoint = safepoint_table_builder_.UpdateDeoptimizationInfo(
deopt_info->deopting_call_return_pc,
deopt_info->deopt_entry_label.pos(), last_updated_safepoint,
deopt_info->deopting_call_return_pc(),
deopt_info->deopt_entry_label()->pos(), last_updated_safepoint,
deopt_index);
deopt_index++;
}
@ -1430,22 +1431,22 @@ Handle<DeoptimizationData> MaglevCodeGenerator::GenerateDeoptimizationData(
// Populate deoptimization entries.
int i = 0;
for (EagerDeoptInfo* deopt_info : code_gen_state_.eager_deopts()) {
DCHECK_NE(deopt_info->translation_index, -1);
raw_data.SetBytecodeOffset(i, deopt_info->state.bytecode_position);
DCHECK_NE(deopt_info->translation_index(), -1);
raw_data.SetBytecodeOffset(i, deopt_info->state().bytecode_position);
raw_data.SetTranslationIndex(i,
Smi::FromInt(deopt_info->translation_index));
raw_data.SetPc(i, Smi::FromInt(deopt_info->deopt_entry_label.pos()));
Smi::FromInt(deopt_info->translation_index()));
raw_data.SetPc(i, Smi::FromInt(deopt_info->deopt_entry_label()->pos()));
#ifdef DEBUG
raw_data.SetNodeId(i, Smi::FromInt(i));
#endif // DEBUG
i++;
}
for (LazyDeoptInfo* deopt_info : code_gen_state_.lazy_deopts()) {
DCHECK_NE(deopt_info->translation_index, -1);
raw_data.SetBytecodeOffset(i, deopt_info->state.bytecode_position);
DCHECK_NE(deopt_info->translation_index(), -1);
raw_data.SetBytecodeOffset(i, deopt_info->state().bytecode_position);
raw_data.SetTranslationIndex(i,
Smi::FromInt(deopt_info->translation_index));
raw_data.SetPc(i, Smi::FromInt(deopt_info->deopt_entry_label.pos()));
Smi::FromInt(deopt_info->translation_index()));
raw_data.SetPc(i, Smi::FromInt(deopt_info->deopt_entry_label()->pos()));
#ifdef DEBUG
raw_data.SetNodeId(i, Smi::FromInt(i));
#endif // DEBUG

View File

@ -859,10 +859,7 @@ class MaglevGraphBuilder {
DCHECK_EQ(NodeT::kProperties.can_lazy_deopt(),
value->properties().can_lazy_deopt());
if constexpr (NodeT::kProperties.can_lazy_deopt()) {
DCHECK(result_location.is_valid());
DCHECK(!value->lazy_deopt_info()->result_location.is_valid());
value->lazy_deopt_info()->result_location = result_location;
value->lazy_deopt_info()->result_size = result_size;
value->lazy_deopt_info()->SetResultLocation(result_location, result_size);
}
}

View File

@ -405,8 +405,8 @@ void PrintEagerDeopt(std::ostream& os, std::vector<BasicBlock*> targets,
NodeBase* node, MaglevGraphLabeller* graph_labeller,
int max_node_id) {
EagerDeoptInfo* deopt_info = node->eager_deopt_info();
InputLocation* current_input_location = deopt_info->input_locations;
RecursivePrintEagerDeopt(os, targets, deopt_info->state, deopt_info->unit,
InputLocation* current_input_location = deopt_info->input_locations();
RecursivePrintEagerDeopt(os, targets, deopt_info->state(), deopt_info->unit(),
graph_labeller, max_node_id, current_input_location);
}
@ -454,20 +454,20 @@ void PrintLazyDeopt(std::ostream& os, std::vector<BasicBlock*> targets,
NodeT* node, MaglevGraphLabeller* graph_labeller,
int max_node_id) {
LazyDeoptInfo* deopt_info = node->lazy_deopt_info();
InputLocation* current_input_location = deopt_info->input_locations;
if (deopt_info->state.parent) {
RecursivePrintLazyDeopt(os, targets, *deopt_info->state.parent,
*deopt_info->unit.caller(), graph_labeller,
InputLocation* current_input_location = deopt_info->input_locations();
if (deopt_info->state().parent) {
RecursivePrintLazyDeopt(os, targets, *deopt_info->state().parent,
*deopt_info->unit().caller(), graph_labeller,
max_node_id, current_input_location);
}
PrintVerticalArrows(os, targets);
PrintPadding(os, graph_labeller, max_node_id, 0);
os << " ↳ lazy @" << deopt_info->state.bytecode_position << " : {";
os << " ↳ lazy @" << deopt_info->state().bytecode_position << " : {";
bool first = true;
deopt_info->state.register_frame->ForEachValue(
deopt_info->unit, [&](ValueNode* node, interpreter::Register reg) {
deopt_info->state().register_frame->ForEachValue(
deopt_info->unit(), [&](ValueNode* node, interpreter::Register reg) {
if (first) {
first = false;
} else {
@ -513,8 +513,8 @@ void PrintExceptionHandlerPoint(std::ostream& os,
os << " ↳ throw @" << handler_offset << " : {";
bool first = true;
deopt_info->state.register_frame->ForEachValue(
deopt_info->unit, [&](ValueNode* node, interpreter::Register reg) {
deopt_info->state().register_frame->ForEachValue(
deopt_info->unit(), [&](ValueNode* node, interpreter::Register reg) {
if (!reg.is_parameter() && !liveness->RegisterIsLive(reg.index())) {
// Skip, since not live at the handler offset.
return;

View File

@ -721,8 +721,8 @@ class MergePointInterpreterFrameState {
} else {
tagged = Node::New<CheckedSmiTag, std::initializer_list<ValueNode*>>(
compilation_unit.zone(), compilation_unit,
value->eager_deopt_info()->state,
value->eager_deopt_info()->source_position, {value});
value->eager_deopt_info()->state(),
value->eager_deopt_info()->source_position(), {value});
}
Node::List::AddAfter(value, tagged);

View File

@ -16,14 +16,14 @@ namespace detail {
template <typename Function>
void DeepForEachInputImpl(const MaglevCompilationUnit& unit,
const CheckpointedInterpreterState* state,
const CheckpointedInterpreterState& state,
InputLocation* input_locations, int& index,
Function&& f) {
if (state->parent) {
DeepForEachInputImpl(*unit.caller(), state->parent, input_locations, index,
if (state.parent) {
DeepForEachInputImpl(*unit.caller(), *state.parent, input_locations, index,
f);
}
state->register_frame->ForEachValue(
state.register_frame->ForEachValue(
unit, [&](ValueNode* node, interpreter::Register reg) {
f(node, reg, &input_locations[index++]);
});
@ -32,25 +32,26 @@ void DeepForEachInputImpl(const MaglevCompilationUnit& unit,
template <typename Function>
void DeepForEachInput(const EagerDeoptInfo* deopt_info, Function&& f) {
int index = 0;
DeepForEachInputImpl(deopt_info->unit, &deopt_info->state,
deopt_info->input_locations, index, f);
DeepForEachInputImpl(deopt_info->unit(), deopt_info->state(),
deopt_info->input_locations(), index, f);
}
template <typename Function>
void DeepForEachInput(const LazyDeoptInfo* deopt_info, Function&& f) {
int index = 0;
if (deopt_info->state.parent) {
DeepForEachInputImpl(*deopt_info->unit.caller(), deopt_info->state.parent,
deopt_info->input_locations, index, f);
if (deopt_info->state().parent) {
DeepForEachInputImpl(*deopt_info->unit().caller(),
*deopt_info->state().parent,
deopt_info->input_locations(), index, f);
}
// Handle the top-of-frame info separately, since we have to skip the result
// location.
deopt_info->state.register_frame->ForEachValue(
deopt_info->unit, [&](ValueNode* node, interpreter::Register reg) {
deopt_info->state().register_frame->ForEachValue(
deopt_info->unit(), [&](ValueNode* node, interpreter::Register reg) {
// Skip over the result location since it is irrelevant for lazy deopts
// (unoptimized code will recreate the result).
if (deopt_info->IsResultRegister(reg)) return;
f(node, reg, &deopt_info->input_locations[index++]);
f(node, reg, &deopt_info->input_locations()[index++]);
});
}

View File

@ -129,7 +129,8 @@ class SaveRegisterStateForCall {
MaglevSafepointTableBuilder::Safepoint DefineSafepointWithLazyDeopt(
LazyDeoptInfo* lazy_deopt_info) {
lazy_deopt_info->deopting_call_return_pc = masm->pc_offset_for_safepoint();
lazy_deopt_info->set_deopting_call_return_pc(
masm->pc_offset_for_safepoint());
masm->code_gen_state()->PushLazyDeopt(lazy_deopt_info);
return DefineSafepoint();
}
@ -389,25 +390,25 @@ size_t GetInputLocationsArraySize(const MaglevCompilationUnit& compilation_unit,
DeoptInfo::DeoptInfo(Zone* zone, const MaglevCompilationUnit& compilation_unit,
CheckpointedInterpreterState state,
SourcePosition source_position)
: unit(compilation_unit),
state(state),
input_locations(zone->NewArray<InputLocation>(
: unit_(compilation_unit),
state_(state),
input_locations_(zone->NewArray<InputLocation>(
GetInputLocationsArraySize(compilation_unit, state))),
source_position(source_position) {
source_position_(source_position) {
// Initialise InputLocations so that they correctly don't have a next use id.
for (size_t i = 0; i < GetInputLocationsArraySize(compilation_unit, state);
++i) {
new (&input_locations[i]) InputLocation();
new (&input_locations_[i]) InputLocation();
}
}
bool LazyDeoptInfo::IsResultRegister(interpreter::Register reg) const {
if (V8_LIKELY(result_size == 1)) {
return reg == result_location;
if (V8_LIKELY(result_size_ == 1)) {
return reg == result_location_;
}
DCHECK_EQ(result_size, 2);
return reg == result_location ||
reg == interpreter::Register(result_location.index() + 1);
DCHECK_EQ(result_size_, 2);
return reg == result_location_ ||
reg == interpreter::Register(result_location_.index() + 1);
}
// ---
@ -1231,7 +1232,7 @@ void CheckMaps::GenerateCode(MaglevAssembler* masm,
// deopt when we intersect the map sets.
if (maps().is_empty()) {
__ RegisterEagerDeopt(eager_deopt_info(), DeoptimizeReason::kWrongMap);
__ jmp(&eager_deopt_info()->deopt_entry_label);
__ jmp(eager_deopt_info()->deopt_entry_label());
return;
}
@ -1377,7 +1378,7 @@ void CheckMapsWithMigration::GenerateCode(MaglevAssembler* masm,
// TODO(victorgomes): This can happen, because we do not emit an unconditional
// deopt when we intersect the map sets.
if (maps().is_empty()) {
__ jmp(&eager_deopt_info()->deopt_entry_label);
__ jmp(eager_deopt_info()->deopt_entry_label());
return;
}
@ -1387,7 +1388,7 @@ void CheckMapsWithMigration::GenerateCode(MaglevAssembler* masm,
__ AssertNotSmi(object);
} else {
Condition is_smi = __ CheckSmi(object);
__ j(is_smi, &eager_deopt_info()->deopt_entry_label);
__ j(is_smi, eager_deopt_info()->deopt_entry_label());
}
ZoneLabelRef done(masm);
@ -1453,13 +1454,13 @@ void CheckMapsWithMigration::GenerateCode(MaglevAssembler* masm,
// If this is the last map to check, we should deopt if we fail.
// This is safe to do, since {eager_deopt_info} is ZoneAllocated.
(last_map ? ZoneLabelRef::UnsafeFromLabelPointer(
&eager_deopt_info()->deopt_entry_label)
eager_deopt_info()->deopt_entry_label())
: continue_label),
done, object, i, this);
} else if (last_map) {
// If it is the last map and it is not a migration target, we should deopt
// if the check fails.
__ j(not_equal, &eager_deopt_info()->deopt_entry_label);
__ j(not_equal, eager_deopt_info()->deopt_entry_label());
}
if (!last_map) {
@ -1586,10 +1587,10 @@ void CheckedInternalizedString::GenerateCode(MaglevAssembler* masm,
static_assert(kThinStringTagBit > 0);
// Deopt if this isn't a string.
__ testw(map_tmp, Immediate(kIsNotStringMask));
__ j(not_zero, &deopt_info->deopt_entry_label);
__ j(not_zero, deopt_info->deopt_entry_label());
// Deopt if this isn't a thin string.
__ testb(map_tmp, Immediate(kThinStringTagBit));
__ j(zero, &deopt_info->deopt_entry_label);
__ j(zero, deopt_info->deopt_entry_label());
__ LoadTaggedPointerField(
object, FieldOperand(object, ThinString::kActualOffset));
if (v8_flags.debug_code) {

View File

@ -682,12 +682,22 @@ class DeoptInfo {
SourcePosition source_position);
public:
const MaglevCompilationUnit& unit;
CheckpointedInterpreterState state;
InputLocation* input_locations = nullptr;
Label deopt_entry_label;
SourcePosition source_position;
int translation_index = -1;
const MaglevCompilationUnit& unit() const { return unit_; }
CheckpointedInterpreterState state() const { return state_; }
InputLocation* input_locations() const { return input_locations_; }
Label* deopt_entry_label() { return &deopt_entry_label_; }
SourcePosition source_position() const { return source_position_; }
int translation_index() const { return translation_index_; }
void set_translation_index(int index) { translation_index_ = index; }
private:
const MaglevCompilationUnit& unit_;
const CheckpointedInterpreterState state_;
InputLocation* const input_locations_;
Label deopt_entry_label_;
const SourcePosition source_position_;
int translation_index_ = -1;
};
struct RegisterSnapshot {
@ -702,7 +712,12 @@ class EagerDeoptInfo : public DeoptInfo {
CheckpointedInterpreterState checkpoint,
SourcePosition source_position)
: DeoptInfo(zone, compilation_unit, checkpoint, source_position) {}
DeoptimizeReason reason = DeoptimizeReason::kUnknown;
DeoptimizeReason reason() const { return reason_; }
void set_reason(DeoptimizeReason reason) { reason_ = reason; }
private:
DeoptimizeReason reason_ = DeoptimizeReason::kUnknown;
};
class LazyDeoptInfo : public DeoptInfo {
@ -712,12 +727,26 @@ class LazyDeoptInfo : public DeoptInfo {
SourcePosition source_position)
: DeoptInfo(zone, compilation_unit, checkpoint, source_position) {}
bool IsResultRegister(interpreter::Register reg) const;
interpreter::Register result_location() const { return result_location_; }
int result_size() const { return result_size_; }
int deopting_call_return_pc = -1;
interpreter::Register result_location =
bool IsResultRegister(interpreter::Register reg) const;
void SetResultLocation(interpreter::Register result_location,
int result_size) {
DCHECK(result_location.is_valid());
DCHECK(!result_location_.is_valid());
result_location_ = result_location;
result_size_ = result_size;
}
int deopting_call_return_pc() const { return deopting_call_return_pc_; }
void set_deopting_call_return_pc(int pc) { deopting_call_return_pc_ = pc; }
private:
int deopting_call_return_pc_ = -1;
interpreter::Register result_location_ =
interpreter::Register::invalid_value();
int result_size = 1;
int result_size_ = 1;
};
class ExceptionHandlerInfo {