5#ifndef V8_MAGLEV_MAGLEV_INTERPRETER_FRAME_STATE_H_
6#define V8_MAGLEV_MAGLEV_INTERPRETER_FRAME_STATE_H_
16#ifdef V8_ENABLE_MAGLEV
28class MaglevGraphBuilder;
29class MergePointInterpreterFrameState;
35template <
typename Key,
typename Value,
36 typename MergeFunc = std::equal_to<Value>>
39 MergeFunc&& func = MergeFunc()) {
42 typename ZoneMap<Key, Value>::iterator lhs_it = lhs_map.begin();
43 typename ZoneMap<Key, Value>::const_iterator rhs_it = rhs_map.begin();
44 while (lhs_it != lhs_map.end() && rhs_it != rhs_map.end()) {
45 if (lhs_it->first < rhs_it->first) {
47 lhs_it = lhs_map.erase(lhs_it);
48 }
else if (rhs_it->first < lhs_it->first) {
54 bool keep_value = func(lhs_it->second, rhs_it->second);
58 lhs_it = lhs_map.erase(lhs_it);
65 if (lhs_it != lhs_map.end()) {
66 lhs_map.erase(lhs_it, lhs_map.end());
80 type_ = other.val.type_;
82 if (other.val.possible_maps_are_known_ && !other.val.any_map_is_unstable_) {
102#define ALTERNATIVES(V) \
105 V(truncated_int32_to_number, TruncatedInt32ToNumber) \
106 V(float64, Float64) \
107 V(checked_value, CheckedValue)
110#define KIND(name, Name) k##Name,
116#define API(name, Name) \
117 ValueNode* name() const { return store_[Kind::k##Name]; } \
118 ValueNode* set_##name(ValueNode* val) { \
119 return store_[Kind::k##Name] = val; \
121 template <typename Function> \
122 ValueNode* get_or_set_##name(Function create) { \
123 if (store_[Kind::k##Name]) return store_[Kind::k##Name]; \
124 return store_[Kind::k##Name] = create(); \
143 std::array<ValueNode*, Kind::kNumberOfAlternatives>
store_;
164 return NodeTypeIsInternalizedString(
type_);
171 bool& any_merged_map_is_unstable) {
175 if (other.possible_maps_are_known_) {
188 any_merged_map_is_unstable =
201 template <
typename Function>
238 DCHECK_EQ(possible_type, NodeType::kUnknown);
296 it.second.ClearUnstableMaps();
301 template <
typename Function>
305 it.second.ClearUnstableMapsIfAny(
condition);
318 bool IsValid(NodeInfos::const_iterator& it)
const {
327 if (!
IsValid(info_it))
return nullptr;
328 return &info_it->second;
333 if (
IsValid(info_it))
return &info_it->second;
343 return NodeType::kUnknown;
374 static_assert((
kName & ~kTypeMask) == 0);
375 static_assert((
kElements & ~kTypeMask) == 0);
400 return data_ == other.data_;
403 return data_ < other.data_;
453 }
else if (context->Is<
Constant>()) {
477 std::numeric_limits<uint32_t>::max();
531 bool preserve_known_node_aspects,
Zone* zone);
535 DCHECK(!value->properties().is_conversion());
549 DCHECK(!value->properties().is_conversion());
602 entry = state.get(
reg);
613 template <
typename Function>
615 for (
int i = 0;
i < info.parameter_count();
i++) {
621 template <
typename Function>
623 for (
int i = 0;
i < info.parameter_count();
i++) {
629 template <
typename Function>
640 template <
typename Function>
651 template <
typename Function>
658 template <
typename Function>
665 template <
typename Function>
673 template <
typename Function>
708 if (
reg.is_parameter()) {
709 DCHECK_LT(
reg.ToParameterIndex(), info.parameter_count());
752#ifdef V8_ENABLE_MAGLEV
755 bool is_initialized()
const {
return values_[0].GetPayload().is_initialized; }
757 template <
typename Function>
758 void ForEachGeneralRegister(
Function&& f) {
761 f(
reg, *current_value);
766 template <
typename Function>
767 void ForEachDoubleRegister(
Function&& f) {
771 f(
reg, *current_value);
817 bool optimistic_initial_state =
false,
836 const std::function<
BasicBlock*()>& FinishBlock);
924 const char* prelude =
nullptr) {
925 if (!
v8_flags.trace_maglev_graph_building)
return;
927 std::cout << prelude << std::endl;
929 from_ifs.
Print(std::cout,
930 "* VOs (Interpreter Frame State): ", info.graph_labeller());
932 std::cout,
"* VOs (Merge Frame State): ", info.graph_labeller());
1026 template <
typename T,
typename... Args>
1037 bool optimistic_loop_phis);
1048 bool optimistic_loop_phis =
false);
1123 loop_header(loop_header),
1147 other->context_slot_written.end());
1149 other->objects_written.end());
1150 keys_cleared.insert(other->keys_cleared.begin(), other->keys_cleared.end());
1151 allocations.insert(other->allocations.begin(), other->allocations.end());
1157 bool preserve_known_node_aspects =
false,
1158 Zone* zone =
nullptr) {
1160 if (
v8_flags.trace_maglev_graph_building) {
1161 std::cout <<
"- Copying frame state from merge @" << &state << std::endl;
1165 state.frame_state().ForEachValue(
1169 if (preserve_known_node_aspects) {
static constexpr T decode(U value)
static V8_NODISCARD constexpr U update(U previous, T value)
void Union(ZoneCompactSet< T > const &other, Zone *zone)
static constexpr Register virtual_accumulator()
static constexpr Register FromParameterIndex(int index)
constexpr int ToParameterIndex() const
static constexpr Register current_context()
static constexpr Register function_closure()
const compiler::BytecodeLivenessState *const liveness_
void ForEachRegister(const MaglevCompilationUnit &info, Function &&f)
void ForEachLocal(const MaglevCompilationUnit &info, Function &&f)
const VirtualObjectList & virtual_objects() const
CompactInterpreterFrameState(const MaglevCompilationUnit &info, const compiler::BytecodeLivenessState *liveness, const InterpreterFrameState &state)
void ForEachValue(const MaglevCompilationUnit &info, Function &&f) const
void ForEachParameter(const MaglevCompilationUnit &info, Function &&f)
ValueNode *& context(const MaglevCompilationUnit &info) const
const compiler::BytecodeLivenessState * liveness() const
ValueNode *& accumulator(const MaglevCompilationUnit &info)
void ForEachParameter(const MaglevCompilationUnit &info, Function &&f) const
CompactInterpreterFrameState(CompactInterpreterFrameState &&)=delete
CompactInterpreterFrameState & operator=(CompactInterpreterFrameState &&)=delete
VirtualObjectList & virtual_objects()
void ForEachValue(const MaglevCompilationUnit &info, Function &&f)
void ForEachLocal(const MaglevCompilationUnit &info, Function &&f) const
ValueNode *& context(const MaglevCompilationUnit &info)
ValueNode **const live_registers_and_accumulator_
void ForEachRegister(const MaglevCompilationUnit &info, Function &&f) const
static size_t SizeFor(const MaglevCompilationUnit &info, const compiler::BytecodeLivenessState *liveness)
CompactInterpreterFrameState & operator=(const CompactInterpreterFrameState &)=delete
ValueNode * GetValueOf(interpreter::Register reg, const MaglevCompilationUnit &info) const
CompactInterpreterFrameState(const MaglevCompilationUnit &info, const compiler::BytecodeLivenessState *liveness)
ValueNode *& accumulator(const MaglevCompilationUnit &info) const
VirtualObjectList virtual_objects_
size_t size(const MaglevCompilationUnit &info) const
CompactInterpreterFrameState(const CompactInterpreterFrameState &)=delete
void set_virtual_objects(const VirtualObjectList &vos)
static const int context_register_count_
VirtualObjectList GetVirtualObjects() const
const InterpretedDeoptFrame & as_interpreted() const
void clear_known_node_aspects()
VirtualObjectList virtual_objects_
void CopyFrom(const MaglevCompilationUnit &info, MergePointInterpreterFrameState &state, bool preserve_known_node_aspects, Zone *zone)
void set(interpreter::Register reg, ValueNode *value)
void set_accumulator(ValueNode *value)
void add_object(VirtualObject *vobject)
InterpreterFrameState(const MaglevCompilationUnit &info)
KnownNodeAspects * known_node_aspects()
void set_known_node_aspects(KnownNodeAspects *known_node_aspects)
InterpreterFrameState(const MaglevCompilationUnit &info, KnownNodeAspects *known_node_aspects, VirtualObjectList virtual_objects)
void set_virtual_objects(const VirtualObjectList &virtual_objects)
KnownNodeAspects * known_node_aspects_
ValueNode * get(interpreter::Register reg) const
const RegisterFrameArray< ValueNode * > & frame() const
const VirtualObjectList & virtual_objects() const
RegisterFrameArray< ValueNode * > frame_
const KnownNodeAspects * known_node_aspects() const
ValueNode * accumulator() const
LoadedPropertyMapKey(compiler::NameRef ref)
static LoadedPropertyMapKey Elements()
static LoadedPropertyMapKey TypedArrayLength()
LoadedPropertyMapKey(Type type)
static constexpr int kTypeMask
bool operator==(const LoadedPropertyMapKey &other) const
static LoadedPropertyMapKey StringLength()
bool operator<(const LoadedPropertyMapKey &other) const
static constexpr DoubleRegList GetAllocatableDoubleRegisters()
static constexpr RegList GetAllocatableRegisters()
NodeType node_type() const
ValueNode * tagged_alternative() const
Alternatives(const NodeInfo *node_info)
ValueNode * tagged_alternative_
BasicBlock * predecessor_at(int i) const
void MergeDead(const MaglevCompilationUnit &compilation_unit, unsigned num=1)
void ReducePhiPredecessorCount(unsigned num)
MergePointRegisterState register_state_
friend T * Zone::New(Args &&... args)
void InitializeWithBasicBlock(BasicBlock *current_block)
uint32_t predecessors_so_far() const
ValueNode * NewLoopPhi(Zone *zone, interpreter::Register reg)
bool is_unmerged_loop() const
KnownNodeAspects * TakeKnownNodeAspects()
void PrintVirtualObjects(const MaglevCompilationUnit &info, VirtualObjectList from_ifs, const char *prelude=nullptr)
bool is_loop_with_peeled_iteration() const
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)
KnownNodeAspects * CloneKnownNodeAspects(Zone *zone)
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_
MergePointRegisterState & register_state()
const compiler::LoopInfo * loop_info() const
BasicBlockType basic_block_type() const
bool is_unmerged_unreachable_loop() const
const CompactInterpreterFrameState & frame_state() const
static MergePointInterpreterFrameState * NewForLoop(const InterpreterFrameState &start_state, const MaglevCompilationUnit &info, int merge_offset, int predecessor_count, const compiler::BytecodeLivenessState *liveness, const compiler::LoopInfo *loop_info, bool has_been_peeled=false)
bool is_resumable_loop() const
MergePointInterpreterFrameState(const MaglevCompilationUnit &info, int merge_offset, int predecessor_count, int predecessors_so_far, BasicBlock **predecessors, BasicBlockType type, const compiler::BytecodeLivenessState *liveness)
NodeType AlternativeType(const Alternatives *alt)
void MergeDeadLoop(const MaglevCompilationUnit &compilation_unit)
void MergeThrow(MaglevGraphBuilder *handler_builder, const MaglevCompilationUnit *handler_unit, const KnownNodeAspects &known_node_aspects, const VirtualObjectList virtual_objects)
void set_predecessor_at(int i, BasicBlock *val)
void TurnLoopIntoRegularBlock()
Alternatives::List * per_predecessor_alternatives_
void set_virtual_objects(const VirtualObjectList &vos)
BasicBlock ** predecessors_
uint32_t predecessor_count_
bool exception_handler_was_used() const
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_
static MergePointInterpreterFrameState * NewForCatchBlock(const MaglevCompilationUnit &unit, const compiler::BytecodeLivenessState *liveness, int handler_offset, bool was_used, interpreter::Register context_register, Graph *graph)
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)
uint32_t predecessor_count() const
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)
@ kUnusedExceptionHandlerStart
void InitializeLoop(MaglevGraphBuilder *graph_builder, MaglevCompilationUnit &compilation_unit, InterpreterFrameState &unmerged, BasicBlock *predecessor, bool optimistic_initial_state=false, LoopEffects *loop_effects=nullptr)
DeoptFrame * backedge_deopt_frame() const
static Derived * New(Zone *zone, std::initializer_list< ValueNode * > inputs, Args &&... args)
std::array< ValueNode *, Kind::kNumberOfAlternatives > store_
AlternativeNodes & operator=(const AlternativeNodes &) V8_NOEXCEPT=default
void MergeWith(const AlternativeNodes &other)
AlternativeNodes(const AlternativeNodes &) V8_NOEXCEPT=default
bool any_map_is_unstable_
void SetPossibleMaps(const PossibleMaps &possible_maps, bool any_map_is_unstable, NodeType possible_type, compiler::JSHeapBroker *broker)
AlternativeNodes & alternative()
const PossibleMaps & possible_maps() const
NodeType IntersectType(NodeType other)
bool possible_maps_are_unstable() const
AlternativeNodes alternative_
PossibleMaps possible_maps_
bool is_internalized_string() const
bool no_info_available() const
bool any_map_is_unstable() const
void ClearUnstableMapsIfAny(const Function &condition)
bool possible_maps_are_known() const
bool is_any_heap_object() const
void MergeWith(const NodeInfo &other, Zone *zone, bool &any_merged_map_is_unstable)
const AlternativeNodes & alternative() const
NodeInfo(ClearUnstableMapsOnCopy other) V8_NOEXCEPT
NodeType CombineType(NodeType other)
bool possible_maps_are_known_
void Add(VirtualObject *object)
void Print(std::ostream &os, const char *prefix, MaglevGraphLabeller *labeller) const
base::Vector< const DirectHandle< Object > > args
ZoneVector< RpoNumber > & result
static constexpr int kAllocatableDoubleRegisterCount
constexpr NodeType CombineType(NodeType left, NodeType right)
constexpr bool NodeTypeIs(NodeType type, NodeType to_check)
constexpr NodeType IntersectType(NodeType left, NodeType right)
NodeType StaticTypeForNode(compiler::JSHeapBroker *broker, LocalIsolate *isolate, ValueNode *node)
static constexpr int kAllocatableGeneralRegisterCount
NodeType StaticTypeForMap(compiler::MapRef map, compiler::JSHeapBroker *broker)
void DestructivelyIntersect(ZoneMap< Key, Value > &lhs_map, const ZoneMap< Key, Value > &rhs_map, MergeFunc &&func=MergeFunc())
V8_EXPORT_PRIVATE FlagValues v8_flags
#define DCHECK_LE(v1, v2)
#define DCHECK_NOT_NULL(val)
#define DCHECK_IMPLIES(v1, v2)
#define DCHECK_NE(v1, v2)
#define DCHECK_GE(v1, v2)
#define DCHECK(condition)
#define DCHECK_LT(v1, v2)
#define DCHECK_EQ(v1, v2)
void ClearUnstableMapsIfAny(const Function &condition)
std::tuple< ValueNode *, int > LoadedContextSlotsKey
NodeInfos::const_iterator FindInfo(ValueNode *node) const
ContextSlotLoadsAlias may_have_aliasing_contexts() const
ZoneMap< uint32_t, AvailableExpression > available_expressions
KnownNodeAspects & operator=(const KnownNodeAspects &other)=delete
bool IsValid(NodeInfos::const_iterator &it) const
NodeInfo * TryGetInfoFor(ValueNode *node)
KnownNodeAspects(KnownNodeAspects &&other)=delete
bool IsValid(NodeInfos::iterator &it)
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 ClearAvailableExpressions()
void UpdateMayHaveAliasingContexts(ValueNode *context)
void Merge(const KnownNodeAspects &other, Zone *zone)
NodeInfo * GetOrCreateInfoFor(ValueNode *node, compiler::JSHeapBroker *broker, LocalIsolate *isolate)
NodeInfos::iterator FindInfo(ValueNode *node)
NodeType NodeTypeFor(ValueNode *node) const
uint32_t effect_epoch() const
LoadedPropertyMap loaded_constant_properties
static constexpr uint32_t kEffectEpochForPureInstructions
KnownNodeAspects(const KnownNodeAspects &other) V8_NOEXCEPT=default
void increment_effect_epoch()
KnownNodeAspects(Zone *zone)
@ OnlyLoadsRelativeToConstant
@ OnlyLoadsRelativeToCurrentContext
bool IsCompatibleWithLoopHeader(const KnownNodeAspects &other) const
static constexpr uint32_t kEffectEpochOverflow
KnownNodeAspects * CloneForLoopHeader(bool optimistic_initial_state, LoopEffects *loop_effects, Zone *zone) const
KnownNodeAspects & operator=(KnownNodeAspects &&other)=delete
LoadedContextSlots loaded_context_slots
ContextSlotLoadsAlias may_have_aliasing_contexts_
bool unstable_aspects_cleared
LoopEffects(int loop_header, Zone *zone)
ZoneSet< InlinedAllocation * > allocations
void Merge(const LoopEffects *other)
ZoneSet< ValueNode * > objects_written
ZoneSet< KnownNodeAspects::LoadedContextSlotsKey > context_slot_written
ZoneSet< KnownNodeAspects::LoadedPropertyMapKey > keys_cleared
bool may_have_aliasing_contexts