28NodeType GetNodeType(compiler::JSHeapBroker*
broker, LocalIsolate* isolate,
29 const KnownNodeAspects& aspects, ValueNode* node) {
32 NodeType type = aspects.NodeTypeFor(node);
33 if (type != NodeType::kUnknown) {
44 bool any_merged_map_is_unstable =
false;
47 lhs.MergeWith(rhs, zone, any_merged_map_is_unstable);
48 return !lhs.no_info_available();
57 DCHECK_IMPLIES(lhs.node == rhs.node,
58 lhs.effect_epoch == rhs.effect_epoch);
59 DCHECK_NE(lhs.effect_epoch, kEffectEpochOverflow);
60 DCHECK_EQ(Node::needs_epoch_check(lhs.node->opcode()),
61 lhs.effect_epoch != kEffectEpochForPureInstructions);
63 return lhs.node == rhs.node && lhs.effect_epoch >= effect_epoch_;
68 auto merge_loaded_properties =
77 other.loaded_constant_properties,
78 merge_loaded_properties);
80 merge_loaded_properties);
82 other.loaded_context_constants);
86 }
else if (other.may_have_aliasing_contexts() !=
96template <
typename Key>
97bool NextInIgnoreList(
typename ZoneSet<Key>::const_iterator& ignore,
98 typename ZoneSet<Key>::const_iterator& ignore_end,
100 while (ignore != ignore_end && *ignore < cur) {
103 return ignore != ignore_end && *ignore == cur;
109 if (
v8_flags.trace_maglev_graph_building) {
110 std::cout <<
" ! Clearing unstable node aspects" << std::endl;
128 bool optimistic_initial_state,
130 : any_map_for_any_node_is_unstable(false),
131 loaded_constant_properties(other.loaded_constant_properties),
132 loaded_properties(zone),
133 loaded_context_constants(other.loaded_context_constants),
134 loaded_context_slots(zone),
135 available_expressions(zone),
136 may_have_aliasing_contexts_(
138 effect_epoch_(other.effect_epoch_),
140 if (!other.any_map_for_any_node_is_unstable) {
141 node_infos = other.node_infos;
143 for (const auto& it : node_infos) {
144 DCHECK(!it.second.any_map_is_unstable());
147 }
else if (optimistic_initial_state &&
148 !loop_effects->unstable_aspects_cleared) {
149 node_infos = other.node_infos;
150 any_map_for_any_node_is_unstable = other.any_map_for_any_node_is_unstable;
152 for (const auto& it : other.node_infos) {
153 node_infos.emplace(it.first,
154 NodeInfo::ClearUnstableMapsOnCopy{it.second});
157 if (optimistic_initial_state && !loop_effects->unstable_aspects_cleared) {
160 if (loop_effects->objects_written.empty() &&
161 loop_effects->keys_cleared.empty()) {
162 loaded_properties = other.loaded_properties;
164 auto cleared_key = loop_effects->keys_cleared.begin();
165 auto cleared_keys_end = loop_effects->keys_cleared.end();
166 auto cleared_obj = loop_effects->objects_written.begin();
167 auto cleared_objs_end = loop_effects->objects_written.end();
168 for (auto loaded_key : other.loaded_properties) {
169 if (NextInIgnoreList(cleared_key, cleared_keys_end, loaded_key.first)) {
172 auto& props_for_key =
173 loaded_properties.try_emplace(loaded_key.first, zone).first->second;
174 for (auto loaded_obj : loaded_key.second) {
175 if (!NextInIgnoreList(cleared_obj, cleared_objs_end,
177 props_for_key.emplace(loaded_obj);
182 if (loop_effects->context_slot_written.empty()) {
183 loaded_context_slots = other.loaded_context_slots;
185 auto slot_written = loop_effects->context_slot_written.begin();
186 auto slot_written_end = loop_effects->context_slot_written.end();
187 for (auto loaded : other.loaded_context_slots) {
188 if (!NextInIgnoreList(slot_written, slot_written_end, loaded.first)) {
189 loaded_context_slots.emplace(loaded);
193 if (!loaded_context_slots.empty()) {
194 if (loop_effects->may_have_aliasing_contexts) {
195 may_have_aliasing_contexts_ = ContextSlotLoadsAlias::Yes;
197 may_have_aliasing_contexts_ = other.may_have_aliasing_contexts();
205 increment_effect_epoch();
206 for (
const auto& e : other.available_expressions) {
207 if (e.second.effect_epoch >= effect_epoch()) {
208 available_expressions.emplace(e);
218template <
typename As,
typename Bs,
typename CompareFunction,
219 typename IsEmptyFunction = std::nullptr_t>
220bool AspectIncludes(
const As& as,
const Bs& bs,
const CompareFunction&
Compare,
221 const IsEmptyFunction IsEmpty =
nullptr) {
222 typename As::const_iterator a = as.begin();
223 typename Bs::const_iterator b = bs.begin();
224 while (a != as.end()) {
225 if constexpr (!std::is_same_v<IsEmptyFunction, std::nullptr_t>) {
226 if (IsEmpty(a->second)) {
231 if (b == bs.end())
return false;
232 while (b->first < a->first) {
234 if (b == bs.end())
return false;
236 if (!(a->first == b->first))
return false;
237 if (!
Compare(a->second, b->second)) {
248template <
typename As,
typename Bs,
typename Function>
249bool MaybeEmptyAspectIncludes(
const As& as,
const Bs& bs,
251 return AspectIncludes<As, Bs, Function>(as, bs,
Compare,
252 [](
auto x) {
return x.empty(); });
255template <
typename As,
typename Bs,
typename Function>
256bool MaybeNullAspectIncludes(
const As& as,
const Bs& bs,
258 return AspectIncludes<As, Bs, Function>(as, bs,
Compare,
259 [](
auto x) {
return x ==
nullptr; });
262bool NodeInfoIncludes(
const NodeInfo& before,
const NodeInfo& after) {
263 if (!
NodeTypeIs(after.type(), before.type())) {
266 if (before.possible_maps_are_known() && before.any_map_is_unstable()) {
267 if (!after.possible_maps_are_known()) {
270 if (!before.possible_maps().contains(after.possible_maps())) {
277bool NodeInfoIsEmpty(
const NodeInfo& info) {
278 return info.type() == NodeType::kUnknown && !info.possible_maps_are_known();
281bool NodeInfoTypeIs(
const NodeInfo& before,
const NodeInfo& after) {
282 return NodeTypeIs(after.type(), before.type());
285bool SameValue(ValueNode* before, ValueNode* after) {
return before == after; }
289bool KnownNodeAspects::IsCompatibleWithLoopHeader(
297 may_have_aliasing_contexts() &&
298 may_have_aliasing_contexts() != ContextSlotLoadsAlias::None) {
300 std::cout <<
"KNA after loop has incompatible "
301 "loop_header.may_have_aliasing_contexts\n";
306 bool had_effects = effect_epoch() != loop_header.
effect_epoch();
309 if (!AspectIncludes(loop_header.
node_infos, node_infos, NodeInfoTypeIs,
312 std::cout <<
"KNA after effectless loop has incompatible node_infos\n";
323 if (!AspectIncludes(loop_header.
node_infos, node_infos, NodeInfoIncludes,
326 std::cout <<
"KNA after loop has incompatible node_infos\n";
332 if (!MaybeEmptyAspectIncludes(
334 [](
auto a,
auto b) { return AspectIncludes(a, b, SameValue); })) {
336 std::cout <<
"KNA after loop has incompatible loaded_properties\n";
343 loaded_context_slots, SameValue)) {
345 std::cout <<
"KNA after loop has incompatible loaded_context_slots\n";
357 int merge_offset,
int predecessor_count,
BasicBlock* predecessor,
361 info, merge_offset, predecessor_count, 1,
362 info.zone()->AllocateArray<BasicBlock*>(predecessor_count),
363 BasicBlockType::kDefault, liveness);
367 entry = state.get(
reg);
374 state.known_node_aspects()->TryGetInfoFor(entry)));
379 state.known_node_aspects()->
Clone(info.zone());
380 state.virtual_objects().Snapshot();
388 int merge_offset,
int predecessor_count,
393 info, merge_offset, predecessor_count, 0,
394 info.zone()->AllocateArray<BasicBlock*>(predecessor_count),
395 BasicBlockType::kLoopHeader, liveness);
397 kIsLoopWithPeeledIterationBit::update(state->bitfield_, has_been_peeled);
398 state->loop_metadata_ =
LoopMetadata{loop_info,
nullptr};
400 state->known_node_aspects_ =
402 state->bitfield_ = kIsResumableLoopBit::update(state->bitfield_,
true);
405 auto& frame_state = state->frame_state_;
407 frame_state.ForEachParameter(
410 if (assignments.ContainsParameter(
reg.ToParameterIndex())) {
411 entry = state->NewLoopPhi(info.zone(),
reg);
412 }
else if (state->is_resumable_loop()) {
414 entry = start_state.
get(
reg);
421 frame_state.
context(info) =
nullptr;
422 if (state->is_resumable_loop()) {
426 frame_state.context(info) = state->NewLoopPhi(
427 info.zone(), interpreter::Register::current_context());
429 frame_state.ForEachLocal(
432 if (assignments.ContainsLocal(
reg.index())) {
433 entry = state->NewLoopPhi(info.zone(),
reg);
436 DCHECK(!frame_state.liveness()->AccumulatorIsLive());
442MergePointInterpreterFrameState::NewForCatchBlock(
449 unit, handler_offset, 0, 0,
nullptr,
450 was_used ? BasicBlockType::kExceptionHandlerStart
451 : BasicBlockType::kUnusedExceptionHandlerStart,
458 if (frame_state.liveness()->AccumulatorIsLive()) {
460 zone, interpreter::Register::virtual_accumulator());
462 frame_state.ForEachRegister(
469MergePointInterpreterFrameState::MergePointInterpreterFrameState(
473 : merge_offset_(merge_offset),
474 predecessor_count_(predecessor_count),
475 predecessors_so_far_(predecessors_so_far),
477 predecessors_(predecessors),
478 frame_state_(info, liveness),
479 per_predecessor_alternatives_(
483 frame_state_.size(info))) {}
489 if (!
v8_flags.trace_maglev_graph_building)
return;
490 std::cout <<
" " <<
reg.ToString() <<
": "
495 std::cout << cur_info->type();
496 if (cur_info->possible_maps_are_known()) {
497 std::cout <<
" " << cur_info->possible_maps().size();
502 << PrintNodeLabel(compilation_unit.
graph_labeller(), unmerged_value)
506 std::cout << in_info->type();
507 if (in_info->possible_maps_are_known()) {
508 std::cout <<
" " << in_info->possible_maps().size();
514void PrintAfterMerge(
const MaglevCompilationUnit& compilation_unit,
515 ValueNode* merged_value, KnownNodeAspects* kna) {
516 if (!
v8_flags.trace_maglev_graph_building)
return;
518 << PrintNodeLabel(compilation_unit.graph_labeller(), merged_value)
520 << PrintNode(compilation_unit.graph_labeller(), merged_value)
524 if (
auto out_info = kna->TryGetInfoFor(merged_value)) {
525 std::cout << out_info->type();
526 if (out_info->possible_maps_are_known()) {
527 std::cout <<
" " << out_info->possible_maps().size();
532 std::cout <<
">" << std::endl;
545 bool optimistic_loop_phis) {
549 PrintBeforeMerge(compilation_unit, value, unmerged.
get(
reg),
reg,
553 optimistic_loop_phis);
563 if (merged == unmerged) {
569 if (
v8_flags.trace_maglev_graph_building) {
570 std::cout <<
" - Merging VOS: "
576 <<
"(unmerged)" << std::endl;
579 auto maybe_result = merged->
Merge(
582 return MergeVirtualObjectValue(builder, unmerged_aspects, a, b);
599 if (unmerged_vos.
is_empty())
return;
617 auto& map = unmerged_vos == vos ? unmerged_map : merged_map;
618 map.emplace(vo->allocation(), vo);
622 for (
auto [
_, merged] : merged_map) {
624 auto it = unmerged_map.
find(merged->allocation());
625 if (it != unmerged_map.
end()) {
626 unmerged = it->second;
627 unmerged_map.
erase(it);
631 if (unmerged !=
nullptr) {
640 for (
auto [
_, unmerged] : unmerged_map) {
642 auto it = merged_map.
find(unmerged->allocation());
643 if (it != merged_map.
end()) {
647 unmerged->allocation());
649 if (merged !=
nullptr) {
661 bool optimistic_initial_state,
LoopEffects* loop_effects) {
663 v8_flags.maglev_optimistic_peeled_loops);
675 if (
v8_flags.trace_maglev_graph_building) {
676 std::cout <<
"Initializing "
677 << (optimistic_initial_state ?
"optimistic " :
"")
678 <<
"loop state..." << std::endl;
681 MergePhis(builder, compilation_unit, unmerged, predecessor,
682 optimistic_initial_state);
690 phi->set_owner(block);
702 return InitializeLoop(builder, compilation_unit, unmerged, predecessor);
706 if (
v8_flags.trace_maglev_graph_building) {
707 std::cout <<
"Merging..." << std::endl;
712 MergePhis(builder, compilation_unit, unmerged, predecessor,
false);
736 if (
v8_flags.trace_maglev_graph_building) {
737 std::cout <<
"Merging loop backedge..." << std::endl;
741 PrintBeforeMerge(compilation_unit, value, loop_end_state.
get(
reg),
reg,
744 value, loop_end_state.
get(
reg));
769 const std::function<
BasicBlock*()>& FinishBlock) {
785 if (
v8_flags.trace_maglev_graph_building) {
786 std::cout <<
"Merging failed, peeling loop instead... " << std::endl;
792 bool phis_can_merge =
true;
795 if (!value->Is<
Phi>())
return;
796 Phi* phi = value->Cast<
Phi>();
797 if (!phi->is_loop_phi())
return;
798 if (phi->merge_state() !=
this)
return;
801 if (old_type != NodeType::kUnknown) {
806 if (
v8_flags.trace_maglev_loop_speeling) {
807 std::cout <<
"Cannot merge " << new_type <<
" into " << old_type
808 <<
" for r" <<
reg.index() <<
"\n";
810 phis_can_merge =
false;
814 if (!phis_can_merge) {
824 if (
v8_flags.trace_maglev_graph_building) {
825 std::cout <<
"Next peeling not needed due to compatible state" << std::endl;
830 PrintBeforeMerge(compilation_unit, value, loop_end_state.
get(
reg),
reg,
833 value, loop_end_state.
get(
reg));
869 if (
v8_flags.trace_maglev_graph_building) {
870 std::cout <<
"- Merging into exception handler @" <<
this << std::endl;
887 PrintBeforeMerge(*handler_unit, value, builder_frame.
get(
reg),
reg,
890 builder_frame.
get(
reg),
nullptr);
895 PrintBeforeMerge(*handler_unit, value, builder_frame.
get(
reg),
reg,
898 builder_frame.
get(
reg),
nullptr);
907 PrintBeforeMerge(*handler_unit, context,
923 DCHECK_EQ(value->properties().value_representation(),
925 DCHECK(!value->properties().is_conversion());
935 if (value->Is<StringLength>() ||
936 value->Is<BuiltinStringPrototypeCharCodeOrCodePointAt>()) {
938 "String length must fit into a Smi");
940 }
else if (NodeTypeIsSmi(node_type)) {
952ValueNode* FromUint32ToTagged(
const MaglevGraphBuilder* builder,
953 NodeType node_type, ValueNode* value,
954 BasicBlock* predecessor) {
955 DCHECK_EQ(value->properties().value_representation(),
957 DCHECK(!value->properties().is_conversion());
960 if (NodeTypeIsSmi(node_type)) {
966 predecessor->nodes().push_back(tagged);
967 builder->compilation_unit()->RegisterNodeInGraphLabeller(tagged);
971ValueNode* FromIntPtrToTagged(
const MaglevGraphBuilder* builder,
972 NodeType node_type, ValueNode* value,
973 BasicBlock* predecessor) {
974 DCHECK_EQ(value->properties().value_representation(),
976 DCHECK(!value->properties().is_conversion());
980 predecessor->nodes().push_back(tagged);
981 builder->compilation_unit()->RegisterNodeInGraphLabeller(tagged);
985ValueNode* FromFloat64ToTagged(
const MaglevGraphBuilder* builder,
986 NodeType node_type, ValueNode* value,
987 BasicBlock* predecessor) {
988 DCHECK_EQ(value->properties().value_representation(),
990 DCHECK(!value->properties().is_conversion());
994 builder->zone(), {value},
997 predecessor->nodes().push_back(tagged);
998 builder->compilation_unit()->RegisterNodeInGraphLabeller(tagged);
1002ValueNode* FromHoleyFloat64ToTagged(
const MaglevGraphBuilder* builder,
1003 NodeType node_type, ValueNode* value,
1004 BasicBlock* predecessor) {
1005 DCHECK_EQ(value->properties().value_representation(),
1007 DCHECK(!value->properties().is_conversion());
1011 builder->zone(), {value},
1014 predecessor->nodes().push_back(tagged);
1015 builder->compilation_unit()->RegisterNodeInGraphLabeller(tagged);
1019ValueNode* NonTaggedToTagged(
const MaglevGraphBuilder* builder,
1020 NodeType node_type, ValueNode* value,
1021 BasicBlock* predecessor) {
1022 switch (value->properties().value_representation()) {
1026 return FromInt32ToTagged(builder, node_type, value, predecessor);
1028 return FromUint32ToTagged(builder, node_type, value, predecessor);
1030 return FromIntPtrToTagged(builder, node_type, value, predecessor);
1032 return FromFloat64ToTagged(builder, node_type, value, predecessor);
1034 return FromHoleyFloat64ToTagged(builder, node_type, value, predecessor);
1037ValueNode* EnsureTagged(
const MaglevGraphBuilder* builder,
1038 const KnownNodeAspects& known_node_aspects,
1039 ValueNode* value, BasicBlock* predecessor) {
1040 if (value->properties().value_representation() ==
1045 auto info_it = known_node_aspects.FindInfo(value);
1046 const NodeInfo* info =
1047 known_node_aspects.IsValid(info_it) ? &info_it->second :
nullptr;
1049 if (
auto alt = info->alternative().tagged()) {
1053 return NonTaggedToTagged(builder, info ? info->type() : NodeType::kUnknown,
1054 value, predecessor);
1061 if (!alt)
return NodeType::kUnknown;
1069 bool optimistic_loop_phis) {
1072 if (merged ==
nullptr) {
1077 if (per_predecessor_alternatives) {
1092 result->set_post_loop_type(unmerged_type);
1093 if (optimistic_loop_phis) {
1099 NodeType initial_optimistic_type = unmerged_type;
1103 initial_optimistic_type =
1106 result->set_type(initial_optimistic_type);
1109 if (optimistic_loop_phis) {
1111 node_info->IntersectType(unmerged_type);
1113 result->merge_type(unmerged_type);
1115 result->merge_post_loop_type(unmerged_type);
1120 if (
result !=
nullptr &&
result->merge_state() ==
this) {
1137 unmerged_aspects, unmerged);
1138 if (
result->is_loop_phi()) {
1139 UpdateLoopPhiType(
result, unmerged_type);
1141 result->merge_type(unmerged_type);
1143 unmerged = EnsureTagged(builder, unmerged_aspects, unmerged,
1150 if (merged == unmerged) {
1152 if (per_predecessor_alternatives) {
1199 if (
v8_flags.trace_maglev_graph_building) {
1201 result->initialize_input_null(
i);
1210 NodeType type = merged_type != NodeType::kUnknown
1214 for (
const Alternatives* alt : *per_predecessor_alternatives) {
1215 ValueNode* tagged = is_tagged ? merged : alt->tagged_alternative();
1216 if (tagged ==
nullptr) {
1218 tagged = NonTaggedToTagged(builder, alt->node_type(), merged,
1222 type =
IntersectType(type, merged_type != NodeType::kUnknown
1232 NodeType unmerged_type = GetNodeType(
1234 unmerged = EnsureTagged(builder, unmerged_aspects, unmerged,
1238 if (
result->is_loop_phi()) {
1240 UpdateLoopPhiType(
result, type);
1249std::optional<ValueNode*>
1257 if (
result !=
nullptr &&
result->merge_state() ==
this) {
1260 unmerged_aspects, unmerged);
1261 unmerged = EnsureTagged(builder, unmerged_aspects, unmerged,
1264 result->change_input(
i, unmerged);
1267 result->merge_type(unmerged_type);
1268 result->merge_post_loop_type(unmerged_type);
1272 if (merged == unmerged) {
1283 if (merged_nested_alloc != unmerged_nested_alloc) {
1301 if (
v8_flags.trace_maglev_graph_building) {
1303 result->initialize_input_null(
i);
1315 result->set_input(
i, tagged_merged);
1318 NodeType unmerged_type = GetNodeType(
1320 unmerged = EnsureTagged(builder, unmerged_aspects, unmerged,
1323 result->set_input(
i, unmerged);
1337 if (
result ==
nullptr ||
result->merge_state() !=
this) {
1343 unmerged_aspects, unmerged);
1344 unmerged = EnsureTagged(builder, unmerged_aspects, unmerged,
1348 result->merge_post_loop_type(type);
1353 result->promote_post_loop_type();
1361 if (
result->uses_require_31_bit_value()) {
1362 unmerged_phi->SetUseRequires31BitValue();
1373 if (
v8_flags.trace_maglev_graph_building) {
1375 result->initialize_input_null(
i);
1384 phi->reduce_input_count(num);
1387 phi->promote_post_loop_type();
1419 if (
auto unconditional_control =
1421 DCHECK_EQ(unconditional_control->predecessor_id(),
i + 1);
1422 unconditional_control->set_predecessor_id(
i);
1429 for (
int i = predecessor_id;
i < phi->input_count() - 1;
i++) {
1430 phi->change_input(
i, phi->
input(
i + 1).node());
1432 phi->reduce_input_count(1);
iterator erase(const iterator &position)
iterator find(const key_type &key)
static bool constexpr IsValid(T value)
static const uint32_t kMaxLength
void push_back(const T &value)
static constexpr Register current_context()
static constexpr Register invalid_value()
void set_predecessor_id(int id)
ControlNode * control_node() const
ZoneVector< Node * > & nodes()
const VirtualObjectList & virtual_objects() const
void ForEachParameter(const MaglevCompilationUnit &info, Function &&f) const
void ForEachValue(const MaglevCompilationUnit &info, Function &&f)
void ForEachLocal(const MaglevCompilationUnit &info, Function &&f) const
ValueNode *& context(const MaglevCompilationUnit &info)
void set_virtual_objects(const VirtualObjectList &vos)
void UpdateObject(VirtualObject *object)
KnownNodeAspects * known_node_aspects()
ValueNode * get(interpreter::Register reg) const
const VirtualObjectList & virtual_objects() const
bool toplevel_is_osr() const
MaglevCompilationUnit * toplevel_compilation_unit() const
compiler::SharedFunctionInfoRef shared_function_info() const
MaglevGraphLabeller * graph_labeller() const
MaglevCompilationInfo * info() const
void RegisterNodeInGraphLabeller(const Node *node)
void RecordUseReprHint(Phi *phi, UseRepresentationSet reprs)
const InterpreterFrameState & current_interpreter_frame() const
DeoptFrame GetLatestCheckpointedFrame()
LocalIsolate * local_isolate() const
MaglevCompilationUnit * compilation_unit() const
SmiConstant * GetSmiConstant(int constant) const
compiler::JSHeapBroker * broker() const
NodeType node_type() const
BasicBlock * predecessor_at(int i) const
static MergePointInterpreterFrameState * New(const MaglevCompilationUnit &info, const InterpreterFrameState &state, int merge_offset, int predecessor_count, BasicBlock *predecessor, const compiler::BytecodeLivenessState *liveness)
void ReducePhiPredecessorCount(unsigned num)
void InitializeWithBasicBlock(BasicBlock *current_block)
ValueNode * NewLoopPhi(Zone *zone, interpreter::Register reg)
bool is_unmerged_loop() const
void PrintVirtualObjects(const MaglevCompilationUnit &info, VirtualObjectList from_ifs, const char *prelude=nullptr)
CompactInterpreterFrameState frame_state_
ValueNode * NewExceptionPhi(Zone *zone, interpreter::Register reg)
const LoopEffects * loop_effects()
interpreter::Register catch_block_context_register() const
bool is_exception_handler() const
void Merge(MaglevGraphBuilder *graph_builder, InterpreterFrameState &unmerged, BasicBlock *predecessor)
void MergeLoop(MaglevGraphBuilder *graph_builder, InterpreterFrameState &loop_end_state, BasicBlock *loop_end_block)
void MergeVirtualObject(MaglevGraphBuilder *builder, const VirtualObjectList unmerged_vos, const KnownNodeAspects &unmerged_aspects, VirtualObject *merged, VirtualObject *unmerged)
DeoptFrame * backedge_deopt_frame_
uint32_t predecessors_so_far_
NodeType AlternativeType(const Alternatives *alt)
void MergeThrow(MaglevGraphBuilder *handler_builder, const MaglevCompilationUnit *handler_unit, const KnownNodeAspects &known_node_aspects, const VirtualObjectList virtual_objects)
Alternatives::List * per_predecessor_alternatives_
void set_virtual_objects(const VirtualObjectList &vos)
BasicBlock ** predecessors_
uint32_t predecessor_count_
bool TryMergeLoop(MaglevGraphBuilder *graph_builder, InterpreterFrameState &loop_end_state, const std::function< BasicBlock *()> &FinishBlock)
ValueNode * MergeValue(const MaglevGraphBuilder *graph_builder, interpreter::Register owner, const KnownNodeAspects &unmerged_aspects, ValueNode *merged, ValueNode *unmerged, Alternatives::List *per_predecessor_alternatives, bool optimistic_loop_phis=false)
KnownNodeAspects * known_node_aspects_
std::optional< LoopMetadata > loop_metadata_
void MergeLoopValue(MaglevGraphBuilder *graph_builder, interpreter::Register owner, const KnownNodeAspects &unmerged_aspects, ValueNode *merged, ValueNode *unmerged)
void set_loop_effects(LoopEffects *loop_effects)
void RemovePredecessorAt(int predecessor_id)
std::optional< ValueNode * > MergeVirtualObjectValue(const MaglevGraphBuilder *graph_builder, const KnownNodeAspects &unmerged_aspects, ValueNode *merged, ValueNode *unmerged)
interpreter::Register catch_block_context_register_
void MergePhis(MaglevGraphBuilder *builder, MaglevCompilationUnit &compilation_unit, InterpreterFrameState &unmerged, BasicBlock *predecessor, bool optimistic_loop_phis)
bool IsUnreachableByForwardEdge() const
void MergeVirtualObjects(MaglevGraphBuilder *builder, MaglevCompilationUnit &compilation_unit, InterpreterFrameState &unmerged, BasicBlock *predecessor)
void InitializeLoop(MaglevGraphBuilder *graph_builder, MaglevCompilationUnit &compilation_unit, InterpreterFrameState &unmerged, BasicBlock *predecessor, bool optimistic_initial_state=false, LoopEffects *loop_effects=nullptr)
constexpr bool Is() const
void set_input(int index, ValueNode *node)
static Derived * New(Zone *zone, std::initializer_list< ValueNode * > inputs, Args &&... args)
constexpr OpProperties properties() const
constexpr ValueRepresentation value_representation() const
static VirtualObject * WalkUntilCommon(const VirtualObjectList &list1, const VirtualObjectList &list2, Function &&f)
VirtualObject * FindAllocatedWith(const InlinedAllocation *allocation) const
std::optional< VirtualObject * > Merge(const VirtualObject *other, uint32_t new_object_id, Zone *zone, Function MergeValue) const
void set_allocation(InlinedAllocation *allocation)
bool compatible_for_merge(const VirtualObject *other) const
InlinedAllocation * allocation() const
Handle< SharedFunctionInfo > info
std::optional< TNode< JSArray > > a
ZoneVector< RpoNumber > & result
LiftoffAssembler::CacheState state
constexpr NodeType CombineType(NodeType left, NodeType right)
constexpr bool NodeTypeIs(NodeType type, NodeType to_check)
constexpr bool IsEmptyNodeType(NodeType type)
constexpr NodeType IntersectType(NodeType left, NodeType right)
NodeType StaticTypeForNode(compiler::JSHeapBroker *broker, LocalIsolate *isolate, ValueNode *node)
void DestructivelyIntersect(ZoneMap< Key, Value > &lhs_map, const ZoneMap< Key, Value > &rhs_map, MergeFunc &&func=MergeFunc())
bool Is(IndirectHandle< U > value)
bool IsResumableFunction(FunctionKind kind)
V8_EXPORT_PRIVATE FlagValues v8_flags
int Compare(const T &a, const T &b)
#define DCHECK_LE(v1, v2)
#define DCHECK_NOT_NULL(val)
#define DCHECK_IMPLIES(v1, v2)
#define DCHECK(condition)
#define DCHECK_LT(v1, v2)
#define DCHECK_EQ(v1, v2)
#define DCHECK_GT(v1, v2)
BytecodeLoopAssignments & assignments()
ContextSlotLoadsAlias may_have_aliasing_contexts() const
ZoneMap< uint32_t, AvailableExpression > available_expressions
KnownNodeAspects(KnownNodeAspects &&other)=delete
KnownNodeAspects * Clone(Zone *zone) const
ZoneMap< std::tuple< ValueNode *, int >, ValueNode * > loaded_context_constants
bool any_map_for_any_node_is_unstable
LoadedPropertyMap loaded_properties
const NodeInfo * TryGetInfoFor(ValueNode *node) const
void ClearUnstableNodeAspects()
void Merge(const KnownNodeAspects &other, Zone *zone)
uint32_t effect_epoch() const
LoadedPropertyMap loaded_constant_properties
bool IsCompatibleWithLoopHeader(const KnownNodeAspects &other) const
KnownNodeAspects * CloneForLoopHeader(bool optimistic_initial_state, LoopEffects *loop_effects, Zone *zone) const
LoadedContextSlots loaded_context_slots
ContextSlotLoadsAlias may_have_aliasing_contexts_
#define V8_UNLIKELY(condition)