9#ifdef ENABLE_SLOW_DCHECKS
29#define TRACE(broker, x) TRACE_BROKER(broker, x)
36 bool tracing_enabled,
CodeKind code_kind)
38#if V8_COMPRESS_POINTERS
49 root_index_map_(isolate),
50 array_and_object_prototypes_(zone()),
51 tracing_enabled_(tracing_enabled),
52 code_kind_(code_kind),
54 property_access_infos_(zone()) {
55 TRACE(
this,
"Constructing heap broker");
61 std::ostringstream oss;
62 oss <<
"[" <<
this <<
"] ";
68static thread_local JSHeapBroker* current_broker =
nullptr;
71 : prev_broker_(current_broker) {
75 current_broker = prev_broker_;
79JSHeapBroker* JSHeapBroker::Current() {
81 return current_broker;
91 info->DetachPersistentHandles());
97 std::unique_ptr<PersistentHandles> ph =
100 info->set_persistent_handles(std::move(ph));
105 TRACE(
this,
"Stopping serialization");
111 TRACE(
this,
"Retiring");
127 while (!IsUndefined(maybe_context,
isolate())) {
130 context->get(Context::INITIAL_ARRAY_PROTOTYPE_INDEX);
132 context->get(Context::INITIAL_OBJECT_PROTOTYPE_INDEX);
137 maybe_context = context->next_context_link();
146#define TYPED_ARRAY_STRING_TAG(Type, type, TYPE, ctype) \
147 case ElementsKind::TYPE##_ELEMENTS: \
148 return Type##Array_string();
151#undef TYPED_ARRAY_STRING_TAG
164 *
object, Context::INITIAL_ARRAY_PROTOTYPE_INDEX) ||
165 object->map(
isolate_)->instance_type() == JS_OBJECT_PROTOTYPE_TYPE;
210#define V(Type, name, Name) \
211 void JSHeapBroker::Init##Name() { \
213 name##_ = MakeRefAssumeMemoryFence(this, isolate()->factory()->name()); \
232 if (inferred_maps.
empty()) {
253 bool always_keep_group_target)
const {
257 if (inferred_maps.
size() == 0)
return refined_feedback;
262 for (
size_t i = 1;
i < group.
size(); ++
i) {
264 if (inferred_maps.
contains(source)) {
269 MapRef target = group.front();
270 bool const keep_target = always_keep_group_target ||
272 new_group.
size() > 1;
276 std::swap(new_group[0], new_group[new_group.
size() - 1]);
279 if (!new_group.
empty()) {
284 return refined_feedback;
293 cell_or_context_(cell),
294 index_and_immutable_(0 ) {
300 index_and_immutable_(0 ) {
305 int slot_index,
bool immutable,
308 cell_or_context_(script_context),
309 index_and_immutable_(
FeedbackNexus::SlotIndexBits::encode(slot_index) |
400 : load_mode(load_mode) {}
412 : access_mode_(access_mode), load_store_mode_(store_mode) {
421 keyed_mode_(keyed_mode),
422 transition_groups_(zone) {
432 for (
MapRef map : group) {
433 if (!map.IsStringMap())
return false;
447 bool has_deprecated_map_without_migration_target)
451 has_deprecated_map_without_migration_target_(
452 has_deprecated_map_without_migration_target) {
463 CHECK(source.IsValid());
465 CHECK(insertion.second);
501 OptionalNameRef static_name) {
507 bool has_deprecated_map_without_migration_target =
false;
509 [
this, &maps, &has_deprecated_map_without_migration_target](
514 if (map.is_deprecated()) {
519 if (maybe_map.has_value()) {
524 if (!map.is_migration_target()) {
528 has_deprecated_map_without_migration_target =
true;
531 if (map.is_abandoned_prototype_map())
return;
535 OptionalNameRef name =
541 if (!maybe_handler.
is_null()) {
559 if (name.has_value()) {
564 *
name, maps,
kind, has_deprecated_map_without_migration_target);
594 if (
IsSmi(*feedback_value)) {
598 int const script_context_index =
599 FeedbackNexus::ContextIndexBits::decode(number);
600 int const context_slot_index = FeedbackNexus::SlotIndexBits::decode(number);
606 OptionalObjectRef
contents = context.get(
broker, context_slot_index);
611 FeedbackNexus::ImmutabilityBit::decode(number), nexus.
kind());
614 CHECK(IsPropertyCell(*feedback_value));
662 OptionalJSObjectRef optional_constructor;
667 if (maybe_constructor.
ToHandle(&constructor)) {
723 OptionalHeapObjectRef target_ref;
743 : feedback.AsBinaryOperation().value();
750 : feedback.AsTypeOf().value();
758 : feedback.AsCompareOperation().value();
764 : feedback.AsForIn().value();
826 OptionalNameRef static_name) {
865 possible_transition_targets.
reserve(maps.size());
866 for (
MapRef& map : maps) {
867 if (map.CanInlineElementAccess() &&
870 possible_transition_targets.
push_back(map.object());
882 if (!map.is_stable()) {
887 transition_target = map.object()->FindElementsKindTransitionedMap(
890 possible_transition_targets.
end()),
894 if (transition_target.
is_null()) {
895 TransitionGroup group(1, map,
zone());
896 transition_groups.insert({
map, group});
899 TransitionGroup new_group(1, target,
zone());
900 TransitionGroup& actual_group =
901 transition_groups.insert({
target, new_group}).first->second;
902 actual_group.push_back(map);
908 for (
auto& entry : transition_groups) {
909 result->AddGroup(std::move(entry.second));
917 CHECK(!group.empty());
920#ifdef ENABLE_SLOW_DCHECKS
923 for (
MapRef map : group) {
927 std::count_if(some_group.begin(), some_group.end(),
928 [&](
MapRef some_map) { return some_map.equals(map); });
937 if (raw_name.
is_null())
return std::nullopt;
952 TRACE(
this,
"Storing PropertyAccessInfo for "
953 << access_mode <<
" of property " << name <<
" on map "
void push_back(const_reference x)
iterator begin() noexcept
CompareOperationHint GetCompareOperationFeedback() const
FeedbackSlotKind kind() const
KeyedAccessStoreMode GetKeyedAccessStoreMode() const
IcCheckType GetKeyType() const
float ComputeCallFrequency()
ForInHint GetForInFeedback() const
bool IsUninitialized() const
Tagged< Name > GetName() const
MaybeDirectHandle< JSObject > GetConstructorFeedback() const
MaybeObjectHandle ExtractMegaDOMHandler()
Tagged< MaybeObject > GetFeedback() const
CallFeedbackContent GetCallFeedbackContent()
KeyedAccessLoadMode GetKeyedAccessLoadMode() const
TypeOfFeedback::Result GetTypeOfFeedback() const
InlineCacheState ic_state() const
SpeculationMode GetSpeculationMode()
BinaryOperationHint GetBinaryOperationFeedback() const
void IterateMapsWithUnclearedHandler(F) const
bool IsPendingAllocation(Tagged< HeapObject > object)
Tagged< Object > native_contexts_list() const
bool IsInCreationContext(Tagged< JSObject > object, uint32_t index)
ThreadId thread_id() const
std::unique_ptr< PersistentHandles > DetachPersistentHandles()
void AttachPersistentHandles(std::unique_ptr< PersistentHandles > persistent_handles)
static std::optional< Tagged< Map > > TryUpdateNoLock(Isolate *isolate, Tagged< Map > old_map, ConcurrencyMode cmode) V8_WARN_UNUSED_RESULT
V8_WARN_UNUSED_RESULT V8_INLINE bool ToHandle(DirectHandle< S > *out) const
IndirectHandle< Object > object() const
static double NumberValue(Tagged< Number > obj)
bool HasOverflowed() const
bool GetHeapObject(Tagged< HeapObject > *result) const
V8_INLINE constexpr bool is_null() const
static ThreadId Current()
bool contains(ZoneCompactSet< T > const &other) const
void push_back(const T &value)
PropertyAccessInfo ComputePropertyAccessInfo(MapRef map, NameRef name, AccessMode access_mode) const
OptionalObjectRef get(JSHeapBroker *broker, int index) const
CurrentHeapBrokerScope(JSHeapBroker *broker)
~CurrentHeapBrokerScope()
ElementAccessFeedback(Zone *zone, KeyedAccessMode const &keyed_mode, FeedbackSlotKind slot_kind)
bool HasOnlyStringMaps(JSHeapBroker *broker) const
ZoneVector< MapRef > TransitionGroup
void AddGroup(TransitionGroup &&group)
KeyedAccessMode keyed_mode() const
ZoneVector< TransitionGroup > transition_groups_
ZoneVector< TransitionGroup > const & transition_groups() const
ElementAccessFeedback const & Refine(JSHeapBroker *broker, ZoneVector< MapRef > const &inferred_maps) const
KeyedAccessMode const keyed_mode_
bool IsPropertyCell() const
ContextRef script_context() const
int const index_and_immutable_
OptionalObjectRef const cell_or_context_
PropertyCellRef property_cell() const
OptionalObjectRef GetConstantHint(JSHeapBroker *broker) const
bool IsMegamorphic() const
GlobalAccessFeedback(PropertyCellRef cell, FeedbackSlotKind slot_kind)
bool IsScriptContextSlot() const
InsufficientFeedback(FeedbackSlotKind slot_kind)
ProcessedFeedback const & ReadFeedbackForInstanceOf(FeedbackSource const &source)
Handle< T > CanonicalPersistentHandle(Tagged< T > object)
ProcessedFeedback const & ReadFeedbackForForIn(FeedbackSource const &source) const
ProcessedFeedback const & ReadFeedbackForCall(FeedbackSource const &source)
BinaryOperationHint GetFeedbackForBinaryOperation(FeedbackSource const &source)
ProcessedFeedback const & GetFeedbackForPropertyAccess(FeedbackSource const &source, AccessMode mode, OptionalNameRef static_name)
bool StackHasOverflowed() const
OptionalNameRef GetNameFeedback(FeedbackNexus const &nexus)
ProcessedFeedback const & ProcessFeedbackForBinaryOperation(FeedbackSource const &source)
JSHeapBroker(Isolate *isolate, Zone *broker_zone, bool tracing_enabled, CodeKind code_kind)
ProcessedFeedback const & GetFeedback(FeedbackSource const &source) const
ProcessedFeedback const & GetFeedbackForArrayOrObjectLiteral(FeedbackSource const &source)
bool IsMainThread() const
bool FeedbackIsInsufficient(FeedbackSource const &source) const
ProcessedFeedback const & ReadFeedbackForArrayOrObjectLiteral(FeedbackSource const &source)
void DetachLocalIsolate(OptimizedCompilationInfo *info)
ProcessedFeedback const & ProcessFeedbackForCompareOperation(FeedbackSource const &source)
std::unique_ptr< PersistentHandles > ph_
void CollectArrayAndObjectPrototypes()
ProcessedFeedback const & ReadFeedbackForCompareOperation(FeedbackSource const &source) const
TypeOfFeedback::Result GetFeedbackForTypeOf(FeedbackSource const &source)
ProcessedFeedback const & ReadFeedbackForRegExpLiteral(FeedbackSource const &source)
const ProcessedFeedback & NewInsufficientFeedback(FeedbackSlotKind kind) const
ProcessedFeedback const & ReadFeedbackForTemplateObject(FeedbackSource const &source)
ObjectData * GetOrCreateData(Handle< Object > object, GetOrCreateDataFlags flags={})
ProcessedFeedback const & ProcessFeedbackForForIn(FeedbackSource const &source)
ProcessedFeedback const & GetFeedbackForGlobalAccess(FeedbackSource const &source)
ZoneUnorderedMap< FeedbackSource, ProcessedFeedback const *, FeedbackSource::Hash, FeedbackSource::Equal > feedback_
CompilationDependencies * dependencies_
ProcessedFeedback const & GetFeedbackForInstanceOf(FeedbackSource const &source)
ProcessedFeedback const & ProcessFeedbackForTypeOf(FeedbackSource const &source)
ForInHint GetFeedbackForForIn(FeedbackSource const &source)
bool ObjectMayBeUninitialized(DirectHandle< Object > object) const
LocalIsolate * local_isolate() const
void IncrementTracingIndentation()
void SetFeedback(FeedbackSource const &source, ProcessedFeedback const *feedback)
ProcessedFeedback const & GetFeedbackForCall(FeedbackSource const &source)
ElementAccessFeedback const & ProcessFeedbackMapsForElementAccess(ZoneVector< MapRef > &maps, KeyedAccessMode const &keyed_mode, FeedbackSlotKind slot_kind)
LocalIsolate * local_isolate_
PropertyAccessInfo GetPropertyAccessInfo(MapRef map, NameRef name, AccessMode access_mode)
ZoneUnorderedMap< PropertyAccessTarget, PropertyAccessInfo, PropertyAccessTarget::Hash, PropertyAccessTarget::Equal > property_access_infos_
void SetTargetNativeContextRef(DirectHandle< NativeContext > native_context)
NativeContextRef target_native_context() const
bool IsArrayOrObjectPrototype(JSObjectRef object) const
ObjectData * TryGetOrCreateData(Handle< Object > object, GetOrCreateDataFlags flags={})
Isolate * isolate() const
ProcessedFeedback const & GetFeedbackForTemplateObject(FeedbackSource const &source)
FeedbackSlotKind GetFeedbackSlotKind(FeedbackSource const &source) const
ProcessedFeedback const & ReadFeedbackForPropertyAccess(FeedbackSource const &source, AccessMode mode, OptionalNameRef static_name)
bool HasFeedback(FeedbackSource const &source) const
OptionalNativeContextRef target_native_context_
void AttachLocalIsolate(OptimizedCompilationInfo *info, LocalIsolate *local_isolate)
ZoneUnorderedSet< IndirectHandle< JSObject >, IndirectHandle< JSObject >::hash, IndirectHandle< JSObject >::equal_to > array_and_object_prototypes_
StringRef GetTypedArrayStringTag(ElementsKind kind)
NexusConfig feedback_nexus_config() const
ProcessedFeedback const & GetFeedbackForRegExpLiteral(FeedbackSource const &source)
void DecrementTracingIndentation()
unsigned trace_indentation_
std::string Trace() const
ProcessedFeedback const & ReadFeedbackForTypeOf(FeedbackSource const &source) const
CompareOperationHint GetFeedbackForCompareOperation(FeedbackSource const &source)
ProcessedFeedback const & ReadFeedbackForBinaryOperation(FeedbackSource const &source) const
ProcessedFeedback const & ReadFeedbackForGlobalAccess(JSHeapBroker *broker, FeedbackSource const &source)
AccessMode access_mode() const
KeyedAccessMode(AccessMode access_mode, KeyedAccessLoadMode load_mode)
KeyedAccessStoreMode store_mode() const
static KeyedAccessMode FromNexus(FeedbackNexus const &nexus)
union v8::internal::compiler::KeyedAccessMode::LoadStoreMode load_store_mode_
AccessMode const access_mode_
KeyedAccessLoadMode load_mode() const
MegaDOMPropertyAccessFeedback(FunctionTemplateInfoRef info_ref, FeedbackSlotKind slot_kind)
NamedAccessFeedback(NameRef name, ZoneVector< MapRef > const &maps, FeedbackSlotKind slot_kind, bool has_deprecated_map_without_migration_target=false)
ElementAccessFeedback const & AsElementAccess() const
bool IsInsufficient() const
ForInFeedback const & AsForIn() const
GlobalAccessFeedback const & AsGlobalAccess() const
InstanceOfFeedback const & AsInstanceOf() const
TypeOfOpFeedback const & AsTypeOf() const
RegExpLiteralFeedback const & AsRegExpLiteral() const
TemplateObjectFeedback const & AsTemplateObject() const
MegaDOMPropertyAccessFeedback const & AsMegaDOMPropertyAccess() const
BinaryOperationFeedback const & AsBinaryOperation() const
NamedAccessFeedback const & AsNamedAccess() const
ProcessedFeedback(Kind kind, FeedbackSlotKind slot_kind)
FeedbackSlotKind slot_kind() const
LiteralFeedback const & AsLiteral() const
CompareOperationFeedback const & AsCompareOperation() const
CallFeedback const & AsCall() const
V8_WARN_UNUSED_RESULT bool Cache(JSHeapBroker *broker) const
ObjectRef value(JSHeapBroker *broker) const
Handle< SharedFunctionInfo > info
#define RAB_GSAB_TYPED_ARRAYS_WITH_TYPED_ARRAY_TYPE(V)
#define TYPED_ARRAY_STRING_TAG(Type, type, TYPE, ctype)
ZoneVector< RpoNumber > & result
InstructionOperand source
ref_traits< T >::ref_type MakeRefAssumeMemoryFence(JSHeapBroker *broker, Tagged< T > object)
OptionalRef< typename ref_traits< T >::ref_type > TryMakeRef(JSHeapBroker *broker, ObjectData *data)
ref_traits< T >::ref_type MakeRef(JSHeapBroker *broker, Tagged< T > object)
bool IsKeyedHasICKind(FeedbackSlotKind kind)
bool IsDefineNamedOwnICKind(FeedbackSlotKind kind)
bool IsSetNamedICKind(FeedbackSlotKind kind)
v8::MemorySpan< DirectHandle< Map > > MapHandlesSpan
V8_INLINE constexpr bool IsSmi(TaggedImpl< kRefType, StorageType > obj)
@ kLoadGlobalNotInsideTypeof
@ kLoadGlobalInsideTypeof
bool IsLoadICKind(FeedbackSlotKind kind)
too high values may cause the compiler to set high thresholds for inlining to as much as possible avoid inlined allocation of objects that cannot escape trace load stores from virtual maglev objects use TurboFan fast string builder analyze liveness of environment slots and zap dead values trace TurboFan load elimination emit data about basic block usage in builtins to this enable builtin reordering when run mksnapshot flag for emit warnings when applying builtin profile data verify register allocation in TurboFan randomly schedule instructions to stress dependency tracking enable store store elimination in TurboFan rewrite far to near simulate GC compiler thread race related to allow float parameters to be passed in simulator mode JS Wasm Run additional turbo_optimize_inlined_js_wasm_wrappers enable experimental feedback collection in generic lowering enable Turboshaft s WasmLoadElimination enable Turboshaft s low level load elimination for JS enable Turboshaft s escape analysis for string concatenation use enable Turbolev features that we want to ship in the not too far future trace individual Turboshaft reduction steps trace intermediate Turboshaft reduction steps invocation count threshold for early optimization Enables optimizations which favor memory size over execution speed Enables sampling allocation profiler with X as a sample interval min size of a semi the new space consists of two semi spaces max size of the Collect garbage after Collect garbage after keeps maps alive for< n > old space garbage collections print one detailed trace line in name
bool IsStoreInArrayLiteralICKind(FeedbackSlotKind kind)
bool IsFastElementsKind(ElementsKind kind)
V8_INLINE constexpr bool IsHeapObject(TaggedImpl< kRefType, StorageType > obj)
V8_EXPORT_PRIVATE FlagValues v8_flags
bool IsKeyedLoadICKind(FeedbackSlotKind kind)
bool IsDefineKeyedOwnICKind(FeedbackSlotKind kind)
bool IsTypedArrayOrRabGsabTypedArrayElementsKind(ElementsKind kind)
bool IsDefineKeyedOwnPropertyInLiteralKind(FeedbackSlotKind kind)
ElementsKind GetInitialFastElementsKind()
bool IsGlobalICKind(FeedbackSlotKind kind)
bool IsKeyedStoreICKind(FeedbackSlotKind kind)
!IsContextMap !IsContextMap native_context
Tagged< To > Cast(Tagged< From > value, const v8::SourceLocation &loc=INIT_SOURCE_LOCATION_IN_DEBUG)
static constexpr AcquireLoadTag kAcquireLoad
OptimizedCompilationInfo * info_
#define READ_ONLY_ROOT_LIST(V)
base::Vector< const char > contents
#define DCHECK_NOT_NULL(val)
#define DCHECK_IMPLIES(v1, v2)
#define DCHECK_NE(v1, v2)
#define CHECK_NE(lhs, rhs)
#define CHECK_EQ(lhs, rhs)
#define DCHECK(condition)
#define DCHECK_EQ(v1, v2)
KeyedAccessStoreMode store_mode
KeyedAccessLoadMode load_mode
LoadStoreMode(KeyedAccessLoadMode load_mode)