v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
heap-refs.cc
Go to the documentation of this file.
1// Copyright 2021 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
6
7#include <optional>
8
12
13#ifdef ENABLE_SLOW_DCHECKS
14#include <algorithm>
15#endif
16
17#include "src/api/api-inl.h"
29
30namespace v8 {
31namespace internal {
32namespace compiler {
33
34#define TRACE(broker, x) TRACE_BROKER(broker, x)
35#define TRACE_MISSING(broker, x) TRACE_BROKER_MISSING(broker, x)
36
37// There are several kinds of ObjectData values.
38//
39// kSmi: The underlying V8 object is a Smi and the data is an instance of the
40// base class (ObjectData), i.e. it's basically just the handle. Because the
41// object is a Smi, it's safe to access the handle in order to extract the
42// number value, and AsSmi() does exactly that.
43//
44// kBackgroundSerializedHeapObject: The underlying V8 object is a HeapObject
45// and the data is an instance of the corresponding (most-specific) subclass,
46// e.g. JSFunctionData, which provides serialized information about the
47// object. Allows serialization from the background thread.
48//
49// kUnserializedHeapObject: The underlying V8 object is a HeapObject and the
50// data is an instance of the base class (ObjectData), i.e. it basically
51// carries no information other than the handle.
52//
53// kNeverSerializedHeapObject: The underlying V8 object is a (potentially
54// mutable) HeapObject and the data is an instance of ObjectData. Its handle
55// must be persistent so that the GC can update it at a safepoint. Via this
56// handle, the object can be accessed concurrently to the main thread.
57//
58// kUnserializedReadOnlyHeapObject: The underlying V8 object is a read-only
59// HeapObject and the data is an instance of ObjectData. For
60// ReadOnlyHeapObjects, it is OK to access heap even from off-thread, so
61// these objects need not be serialized.
69
70namespace {
71
72bool Is64() { return kSystemPointerSize == 8; }
73
74} // namespace
75
76class ObjectData : public ZoneObject {
77 public:
80 : object_(object),
81 kind_(kind)
82#ifdef DEBUG
83 ,
85#endif // DEBUG
86 {
87 // This assignment ensures we don't end up inserting the same object
88 // in an endless recursion.
89 *storage = this;
90
91 TRACE(broker, "Creating data " << this << " for handle " << object.address()
92 << " (" << Brief(*object) << ")");
93
94 // It is safe to access read only heap objects and builtins from a
95 // background thread. When we read fields of these objects, we may create
96 // ObjectData on the background thread.
97 // This is safe too since we don't create handles but just get handles from
98 // read only root table or builtins table.
99 // All other objects need to be canonicalized in a persistent handle scope.
100 // See CanonicalPersistentHandle().
101 Isolate* isolate = broker->isolate();
102 USE(isolate);
106 broker->IsCanonicalHandle(object));
112 i::IsHeapObject(*object) &&
114 }
115
116#define DECLARE_IS(Name) bool Is##Name() const;
118#undef DECLARE_IS
119
120#define DECLARE_AS(Name) Name##Data* As##Name();
122#undef DECLARE_AS
123
125 ObjectDataKind kind() const { return kind_; }
126 bool is_smi() const { return kind_ == kSmi; }
132 bool IsNull() const { return i::IsNull(*object_); }
133
134#ifdef DEBUG
135 JSHeapBroker* broker() const { return broker_; }
136#endif // DEBUG
137
138 private:
141#ifdef DEBUG
142 JSHeapBroker* const broker_; // For DCHECKs.
143#endif // DEBUG
144};
145
147 public:
150
151 std::optional<bool> TryGetBooleanValue(JSHeapBroker* broker) const;
152 ObjectData* map() const { return map_; }
154
155 private:
156 std::optional<bool> TryGetBooleanValueImpl(JSHeapBroker* broker) const;
157
159};
160
162 public:
165
167
172
173 ObjectData* value() const {
175 return value_;
176 }
177
178 private:
180 ObjectData* value_ = nullptr;
181
182 bool serialized() const { return value_ != nullptr; }
183};
184
185namespace {
186
187ZoneVector<Address> GetCFunctions(Tagged<FixedArray> function_overloads,
188 Isolate* isolate, Zone* zone) {
189 const int len = function_overloads->length() /
191 ZoneVector<Address> c_functions = ZoneVector<Address>(len, zone);
192 for (int i = 0; i < len; i++) {
193 c_functions[i] = v8::ToCData<kCFunctionTag>(
194 isolate, function_overloads->get(
196 }
197 return c_functions;
198}
199
200ZoneVector<const CFunctionInfo*> GetCSignatures(
201 Tagged<FixedArray> function_overloads, Isolate* isolate, Zone* zone) {
202 const int len = function_overloads->length() /
204 ZoneVector<const CFunctionInfo*> c_signatures =
205 ZoneVector<const CFunctionInfo*>(len, zone);
206 for (int i = 0; i < len; i++) {
208 isolate, function_overloads->get(
210 }
211 return c_signatures;
212}
213
214} // namespace
215
220
222 if (serialized()) return true;
223
224 TraceScope tracer(broker, this, "PropertyCellData::Serialize");
225 auto cell = Cast<PropertyCell>(object());
226
227 // While this code runs on a background thread, the property cell might
228 // undergo state transitions via calls to PropertyCell::Transition. These
229 // transitions follow a certain protocol on which we rely here to ensure that
230 // we only report success when we can guarantee consistent data. A key
231 // property is that after transitioning from cell type A to B (A != B), there
232 // will never be a transition back to A, unless A is kConstant and the new
233 // value is the hole (i.e. the property cell was invalidated, which is a final
234 // state).
235
236 PropertyDetails property_details = cell->property_details(kAcquireLoad);
237
238 Handle<Object> value =
239 broker->CanonicalPersistentHandle(cell->value(kAcquireLoad));
240 if (broker->ObjectMayBeUninitialized(value)) {
241 DCHECK(!broker->IsMainThread());
242 return false;
243 }
244
245 {
246 PropertyDetails property_details_again =
247 cell->property_details(kAcquireLoad);
248 if (property_details != property_details_again) {
249 DCHECK(!broker->IsMainThread());
250 return false;
251 }
252 }
253
255 DCHECK(!broker->IsMainThread());
256 return false;
257 }
258
259 ObjectData* value_data = broker->TryGetOrCreateData(value);
260 if (value_data == nullptr) {
261 DCHECK(!broker->IsMainThread());
262 return false;
263 }
264
266
267 DCHECK(!serialized());
269 value_ = value_data;
271 return true;
272}
273
275 public:
279};
280
282 public:
286};
287
288namespace {
289
290// Separate function for racy HeapNumber value read, so that we can explicitly
291// suppress it in TSAN (see tools/sanitizers/tsan_suppressions.txt).
292// We prevent inlining of this function in TSAN builds, so that TSAN does indeed
293// see that this is where the race is, and does indeed ignore it.
294#ifdef V8_IS_TSAN
296#endif
297uint64_t RacyReadHeapNumberBits(Tagged<HeapNumber> value) {
298 return value->value_as_bits();
299}
300
301std::optional<Tagged<Object>> GetOwnFastConstantDataPropertyFromHeap(
302 JSHeapBroker* broker, JSObjectRef holder, Representation representation,
303 FieldIndex field_index) {
304 std::optional<Tagged<Object>> constant;
305 {
307 PtrComprCageBase cage_base = broker->cage_base();
308
309 // This check to ensure the live map is the same as the cached map to
310 // to protect us against reads outside the bounds of the heap. This could
311 // happen if the Ref was created in a prior GC epoch, and the object
312 // shrunk in size. It might end up at the edge of a heap boundary. If
313 // we see that the map is the same in this GC epoch, we are safe.
314 Tagged<Map> map = holder.object()->map(cage_base, kAcquireLoad);
315 if (*holder.map(broker).object() != map) {
316 TRACE_BROKER_MISSING(broker, "Map changed for " << holder);
317 return {};
318 }
319
320 if (field_index.is_inobject()) {
321 constant =
322 holder.object()->RawInobjectPropertyAt(cage_base, map, field_index);
323 if (!constant.has_value()) {
325 broker, "Constant field in " << holder << " is unsafe to read");
326 return {};
327 }
328 } else {
330 holder.object()->raw_properties_or_hash(cage_base, kRelaxedLoad);
331 // Ensure that the object is safe to inspect.
333 return {};
334 }
335 if (!IsPropertyArray(raw_properties_or_hash, cage_base)) {
337 broker,
338 "Expected PropertyArray for backing store in " << holder << ".");
339 return {};
340 }
341 Tagged<PropertyArray> properties =
343 const int array_index = field_index.outobject_array_index();
344 if (array_index < properties->length(kAcquireLoad)) {
345 constant = properties->get(array_index);
346 } else {
348 broker, "Backing store for " << holder << " not long enough.");
349 return {};
350 }
351 }
352 // We might read the uninitialized sentinel, if we race with the main
353 // thread adding a new property to the object (having set the map, but not
354 // yet initialised the property value). Since this is a tight race, it won't
355 // happen very often, so we can just abort the load.
356 // TODO(leszeks): We could instead sleep/yield and spin the load, since the
357 // timing on this is tight enough that we wouldn't delay the compiler thread
358 // by much.
359 if (IsUninitialized(constant.value())) {
360 TRACE_BROKER_MISSING(broker, "Read uninitialized property.");
361 return {};
362 }
363
364 // {constant} needs to pass the gc predicate before we can introspect on it.
365 if (broker->ObjectMayBeUninitialized(constant.value())) return {};
366
367 // Ensure that {constant} matches the {representation} we expect for the
368 // field.
369 if (!Object::FitsRepresentation(*constant, representation, false)) {
370 const char* repString = IsSmi(*constant) ? "Smi"
371 : IsHeapNumber(*constant) ? "HeapNumber"
372 : "HeapObject";
373 TRACE_BROKER_MISSING(broker, "Mismatched representation for "
374 << holder << ". Expected "
375 << representation << ", but object is a "
376 << repString);
377 return {};
378 }
379 }
380 return constant;
381}
382
383// Tries to get the property at {dict_index}. If we are within bounds of the
384// object, we are guaranteed to see valid heap words even if the data is wrong.
385OptionalObjectRef GetOwnDictionaryPropertyFromHeap(
386 JSHeapBroker* broker, DirectHandle<JSObject> receiver,
387 InternalIndex dict_index) {
388 Handle<Object> constant;
389 {
391 // DictionaryPropertyAt will check that we are within the bounds of the
392 // object.
393 std::optional<Tagged<Object>> maybe_constant =
395 broker->isolate()->heap());
396 DCHECK_IMPLIES(broker->IsMainThread(), maybe_constant);
397 if (!maybe_constant) return {};
398 constant = broker->CanonicalPersistentHandle(maybe_constant.value());
399 }
400 return TryMakeRef(broker, constant);
401}
402
403} // namespace
404
406 public:
410};
411
413 public:
417};
418
426
428 public:
433};
434
436 public:
442
444
445 bool has_initial_map() const {
446 DCHECK(serialized_);
447 return has_initial_map_;
448 }
450 DCHECK(serialized_);
452 }
454 DCHECK(serialized_);
456 }
457
459 DCHECK(serialized_);
460 return context_;
461 }
463 DCHECK(serialized_);
464 return initial_map_;
465 }
467 DCHECK(serialized_);
468 return instance_prototype_;
469 }
471 DCHECK(serialized_);
472 return shared_;
473 }
475 DCHECK(serialized_);
476 return feedback_cell_;
477 }
482
483 // Track serialized fields that are actually used, in order to relax
484 // ConsistentJSFunctionView dependency validation as much as possible.
497
498 bool has_any_used_field() const { return used_fields_ != 0; }
499 bool has_used_field(UsedField used_field) const {
500 return (used_fields_ & used_field) != 0;
501 }
502 void set_used_field(UsedField used_field) { used_fields_ |= used_field; }
503
504 private:
506
507#ifdef DEBUG
508 bool serialized_ = false;
509#endif // DEBUG
510
513
515 bool has_initial_map_ = false;
518
521 nullptr; // Derives from prototype_or_initial_map_.
523 nullptr; // Derives from prototype_or_initial_map_.
524 ObjectData* shared_ = nullptr;
527 // prototype_or_initial_map_.
528};
529
531 public:
534 : HeapObjectData(broker, storage, object, kind),
535 as_uint64_(object->AsUint64(nullptr)),
536 as_int64_(object->AsInt64(&lossless_)) {}
537
538 uint64_t AsUint64() const { return as_uint64_; }
539 int64_t AsInt64(bool* lossless) const {
540 *lossless = lossless_;
541 return as_int64_;
542 }
543
544 private:
545 const uint64_t as_uint64_;
546 const int64_t as_int64_;
548};
549
554
555class MapData : public HeapObjectData {
556 public:
559
561 int instance_size() const { return instance_size_; }
562 uint32_t bit_field2() const { return bit_field2_; }
563 uint32_t bit_field3() const { return bit_field3_; }
565 CHECK(InstanceTypeChecker::IsJSObject(instance_type()));
567 }
572
573 private:
574 // The following fields should be const in principle, but construction
575 // requires locking the MapUpdater lock. For this reason, it's easier to
576 // initialize these inside the constructor body, not in the initializer list.
577
580 uint32_t bit_field2_;
581 uint32_t bit_field3_;
585};
586
587namespace {
588
589int InstanceSizeWithMinSlack(JSHeapBroker* broker, MapRef map) {
590 // This operation is split into two phases (1. map collection, 2. map
591 // processing). This is to avoid having to take two locks
592 // (full_transition_array_access and map_updater_access) at once and thus
593 // having to deal with related deadlock issues.
595 maps.push_back(map.object());
596
597 {
599
600 // Has to be an initial map.
601 DCHECK(IsUndefined(map.object()->GetBackPointer(), broker->isolate()));
602
603 static constexpr bool kConcurrentAccess = true;
604 TransitionsAccessor(broker->isolate(), *map.object(), kConcurrentAccess)
606 maps.push_back(broker->CanonicalPersistentHandle(m));
607 });
608 }
609
610 // The lock is needed for UnusedPropertyFields and InstanceSizeFromSlack.
612
613 int slack = std::numeric_limits<int>::max();
614 for (DirectHandle<Map> m : maps) {
615 slack = std::min(slack, m->UnusedPropertyFields());
616 }
617
618 return map.object()->InstanceSizeFromSlack(slack);
619}
620
621} // namespace
622
623// IMPORTANT: Keep this sync'd with JSFunctionData::IsConsistentWithHeapState.
625 DCHECK(!serialized_);
626
627 TraceScope tracer(broker, this, "JSFunctionData::Cache");
628 DirectHandle<JSFunction> function = Cast<JSFunction>(object());
629
630 // This function may run on the background thread and thus must be individual
631 // fields in a thread-safe manner. Consistency between fields is *not*
632 // guaranteed here, instead we verify it in `IsConsistentWithHeapState`,
633 // called during job finalization. Relaxed loads are thus okay: we're
634 // guaranteed to see an initialized JSFunction object, and after
635 // initialization fields remain in a valid state.
636
637 ContextRef context =
638 MakeRefAssumeMemoryFence(broker, function->context(kRelaxedLoad));
639 context_ = context.data();
640
641 SharedFunctionInfoRef shared =
642 MakeRefAssumeMemoryFence(broker, function->shared(kRelaxedLoad));
643 shared_ = shared.data();
644
645 if (function->has_prototype_slot()) {
646 prototype_or_initial_map_ = broker->GetOrCreateData(
647 function->prototype_or_initial_map(kAcquireLoad), kAssumeMemoryFence);
648
650 if (has_initial_map_) {
651 // MapData is not used for initial_map_ because some
652 // AlwaysSharedSpaceJSObject subclass constructors (e.g. SharedArray) have
653 // initial maps in RO space, which can be accessed directly.
655
656 MapRef initial_map_ref = TryMakeRef<Map>(broker, initial_map_).value();
657 if (initial_map_ref.IsInobjectSlackTrackingInProgress()) {
659 InstanceSizeWithMinSlack(broker, initial_map_ref);
660 } else {
662 initial_map_ref.instance_size();
663 }
665 }
666
667 if (has_initial_map_) {
671 broker, Cast<Map>(initial_map_->object())->prototype())
672 .data();
673 } else if (prototype_or_initial_map_->IsHeapObject() &&
674 !IsTheHole(
678 }
679 }
680
681 PrototypeRequiresRuntimeLookup_ = function->PrototypeRequiresRuntimeLookup();
682
684 broker, function->raw_feedback_cell(kAcquireLoad));
685 feedback_cell_ = feedback_cell.data();
686
687#ifdef DEBUG
688 serialized_ = true;
689#endif // DEBUG
690}
691
692// IMPORTANT: Keep this sync'd with JSFunctionData::Cache.
694 DCHECK(serialized_);
695
697
698 if (*context_->object() != f->context()) {
699 TRACE_BROKER_MISSING(broker, "JSFunction::context");
700 return false;
701 }
702
703 CHECK_EQ(*shared_->object(), f->shared());
704
705 if (f->has_prototype_slot()) {
708 f->prototype_or_initial_map(kAcquireLoad)) {
709 TRACE_BROKER_MISSING(broker, "JSFunction::prototype_or_initial_map");
710 return false;
711 }
713 has_initial_map_ != f->has_initial_map()) {
714 TRACE_BROKER_MISSING(broker, "JSFunction::has_initial_map");
715 return false;
716 }
718 has_instance_prototype_ != f->has_instance_prototype()) {
719 TRACE_BROKER_MISSING(broker, "JSFunction::has_instance_prototype");
720 return false;
721 }
722 } else {
725 }
726
727 if (has_initial_map()) {
729 *initial_map_->object() != f->initial_map()) {
730 TRACE_BROKER_MISSING(broker, "JSFunction::initial_map");
731 return false;
732 }
735 f->ComputeInstanceSizeWithMinSlack(f->GetIsolate())) {
737 "JSFunction::ComputeInstanceSizeWithMinSlack");
738 return false;
739 }
740 } else {
742 }
743
746 *instance_prototype_->object() != f->instance_prototype()) {
747 TRACE_BROKER_MISSING(broker, "JSFunction::instance_prototype");
748 return false;
749 }
750 } else {
752 }
753
755 PrototypeRequiresRuntimeLookup_ != f->PrototypeRequiresRuntimeLookup()) {
756 TRACE_BROKER_MISSING(broker, "JSFunction::PrototypeRequiresRuntimeLookup");
757 return false;
758 }
759
761 *feedback_cell_->object() != f->raw_feedback_cell()) {
762 TRACE_BROKER_MISSING(broker, "JSFunction::raw_feedback_cell");
763 return false;
764 }
765
766 return true;
767}
768
770 DCHECK(broker->IsMainThread());
771 return data()->AsJSFunction()->IsConsistentWithHeapState(broker);
772}
773
777 : ObjectData(broker, storage, object, kind), map_(nullptr) {
778 // At this point, this object may already be in the RefsMap. GetOrCreateData
779 // will lookup objects in there. If (e.g. due to in-sandbox corruption) the
780 // object graph is such that we end up retrieving ourselves from the RefsMap
781 // in the recursive GetOrCreateData call, then we'll see uninitialized data
782 // for the map_ field. To avoid this, initialize it to nullptr first.
783 map_ = broker->GetOrCreateData(object->map(broker->cage_base(), kAcquireLoad),
787}
788
790 JSHeapBroker* broker) const {
791 // Keep in sync with Object::BooleanValue.
794 broker->IsMainThread() && result.has_value(),
795 result.value() == Object::BooleanValue(*object(), broker->isolate()));
796 return result;
797}
798
800 JSHeapBroker* broker) const {
802 Tagged<Object> o = *object();
803 Isolate* isolate = broker->isolate();
805 if (IsTrue(o, isolate)) {
806 return true;
807 } else if (IsFalse(o, isolate)) {
808 return false;
809 } else if (IsNullOrUndefined(o, isolate)) {
810 return false;
811 } else if (MapRef{map()}.is_undetectable()) {
812 return false; // Undetectable object is false.
813 } else if (InstanceTypeChecker::IsString(t)) {
814 // TODO(jgruber): Implement in possible cases.
815 return {};
816 } else if (InstanceTypeChecker::IsHeapNumber(t)) {
817 return {};
818 } else if (InstanceTypeChecker::IsBigInt(t)) {
819 return {};
820 }
821 return true;
822}
823
825 ObjectData* map_data = map();
826 if (map_data->should_access_heap()) {
827 // The map instance type is used to check if a static_cast to the right
828 // subclass is valid. We shouldn't read the value from the heap except if
829 // it's coming from the ReadOnly pages.
831 return Cast<Map>(map_data->object())->instance_type();
832 }
833 if (this == map_data) {
834 // Handle infinite recursion in case this object is a contextful meta map.
835 return MAP_TYPE;
836 }
837 return map_data->AsMap()->instance_type();
838}
839
840namespace {
841
842bool IsReadOnlyLengthDescriptor(Isolate* isolate,
843 DirectHandle<Map> jsarray_map) {
844 DCHECK(!jsarray_map->is_dictionary_map());
845 Tagged<DescriptorArray> descriptors =
846 jsarray_map->instance_descriptors(isolate, kRelaxedLoad);
847 static_assert(
848 JSArray::kLengthOffset == JSObject::kHeaderSize,
849 "The length should be the first property on the descriptor array");
851 return descriptors->GetDetails(offset).IsReadOnly();
852}
853
854// Important: this predicate does not check Protectors::IsNoElementsIntact. The
855// compiler checks protectors through the compilation dependency mechanism; it
856// doesn't make sense to do that here as part of every MapData construction.
857// Callers *must* take care to take the correct dependency themselves.
858bool SupportsFastArrayIteration(JSHeapBroker* broker, DirectHandle<Map> map) {
859 return map->instance_type() == JS_ARRAY_TYPE &&
860 IsFastElementsKind(map->elements_kind()) &&
861 IsJSArray(map->prototype()) &&
863 Cast<JSArray>(map->prototype())));
864}
865
866bool SupportsFastArrayResize(JSHeapBroker* broker, DirectHandle<Map> map) {
867 return SupportsFastArrayIteration(broker, map) && map->is_extensible() &&
868 !map->is_dictionary_map() &&
869 !IsReadOnlyLengthDescriptor(broker->isolate(), map);
870}
871
872} // namespace
873
876 : HeapObjectData(broker, storage, object, kind) {
877 // This lock ensure that MapData can always be background-serialized, i.e.
878 // while the lock is held the Map object may not be modified (except in
879 // benign ways).
880 // TODO(jgruber): Consider removing this lock by being smrt.
882
883 // When background serializing the map, we can perform a lite serialization
884 // since the MapRef will read some of the Map's fields can be read directly.
885
886 // Even though MapRefs can read {instance_type} directly, other classes depend
887 // on {instance_type} being serialized.
888 instance_type_ = object->instance_type();
889 instance_size_ = object->instance_size();
890
891 bit_field2_ = object->bit_field2();
892
893 // Both bit_field3 (and below bit_field) are special fields: Even though most
894 // of the individual bits inside of the bitfield could be read / written
895 // non-atomically, the bitfield itself has to use atomic relaxed accessors
896 // since some fields since can be modified in live objects.
897 // TODO(solanes, v8:7790): Assess if adding the exclusive lock in more places
898 // (e.g for set_has_non_instance_prototype) makes sense. Pros: these fields
899 // can use the non-atomic accessors. Cons: We would be acquiring an exclusive
900 // lock in more places.
901 bit_field3_ = object->relaxed_bit_field3();
902 is_abandoned_prototype_map_ = object->is_abandoned_prototype_map();
903 if (IsJSObjectMap(*object)) {
904 unused_property_fields_ = object->UnusedPropertyFields();
905 in_object_properties_ = object->GetInObjectProperties();
906 } else {
909 }
910}
911
913 public:
918
919 uint32_t length() const { return length_; }
920
921 private:
922 int const length_;
923};
924
931
932// Only used in JSNativeContextSpecialization.
940
941class JSArrayData : public JSObjectData {
942 public:
946};
947
954
956 public:
960};
961
962#define DEFINE_IS(Name) \
963 bool ObjectData::Is##Name() const { \
964 if (should_access_heap()) { \
965 return i::Is##Name(*object()); \
966 } \
967 if (is_smi()) return false; \
968 InstanceType instance_type = \
969 static_cast<const HeapObjectData*>(this)->GetMapInstanceType(); \
970 return InstanceTypeChecker::Is##Name(instance_type); \
971 }
973#undef DEFINE_IS
974
975#define DEFINE_AS(Name) \
976 Name##Data* ObjectData::As##Name() { \
977 CHECK(Is##Name()); \
978 CHECK(kind_ == kBackgroundSerializedHeapObject); \
979 return static_cast<Name##Data*>(this); \
980 }
982#undef DEFINE_AS
983
984bool ObjectRef::equals(ObjectRef other) const { return data_ == other.data_; }
985
987 DCHECK_NOT_NULL(depth);
988
989 if (*depth == 0) return *this;
990
991 Tagged<Context> current = *object();
992 while (*depth != 0 && i::IsContext(current->unchecked_previous())) {
993 current = Cast<Context>(current->unchecked_previous());
994 (*depth)--;
995 }
996 // The `previous` field is immutable after initialization and the
997 // context itself is read through an atomic load.
998 return MakeRefAssumeMemoryFence(broker, current);
999}
1000
1001OptionalObjectRef ContextRef::get(JSHeapBroker* broker, int index) const {
1002 CHECK_LE(0, index);
1003 // Length is immutable after initialization.
1004 if (index >= object()->length(kRelaxedLoad)) return {};
1005 return TryMakeRef(broker, object()->get(index));
1006}
1007
1009 int index) const {
1010 if (!object()->IsScriptContext()) {
1011 return {};
1012 }
1013
1014 // No side data for slots which are not variables in the context.
1016 return {};
1017 }
1018
1019 OptionalObjectRef maybe_side_data =
1021 if (!maybe_side_data.has_value()) return {};
1022 // The FixedArray itself will stay constant, but its contents may change while
1023 // we compile in the background.
1024 FixedArrayRef side_data_fixed_array = maybe_side_data.value().AsFixedArray();
1025 return side_data_fixed_array.TryGet(
1027}
1028
1030 DirectHandle<NativeContext> target_native_context) {
1031 TraceScope tracer(this, "JSHeapBroker::InitializeAndStartSerializing");
1032
1035
1036 // Throw away the dummy data that we created while disabled.
1037 feedback_.clear();
1038 refs_->Clear();
1039 refs_ =
1041
1043
1045}
1046
1047namespace {
1048
1049constexpr ObjectDataKind ObjectDataKindFor(RefSerializationKind kind) {
1050 switch (kind) {
1055 }
1056}
1057
1058} // namespace
1059
1061 GetOrCreateDataFlags flags) {
1062 RefsMap::Entry* entry = refs_->Lookup(object.address());
1063 if (entry != nullptr) return entry->value;
1064
1065 if (mode() == JSHeapBroker::kDisabled) {
1066 entry = refs_->LookupOrInsert(object.address());
1067 ObjectData** storage = &entry->value;
1068 if (*storage == nullptr) {
1069 entry->value = zone()->New<ObjectData>(
1070 this, storage, object,
1071 IsSmi(*object) ? kSmi : kUnserializedHeapObject);
1072 }
1073 return *storage;
1074 }
1075
1078
1079 ObjectData* object_data;
1080 if (IsSmi(*object)) {
1081 entry = refs_->LookupOrInsert(object.address());
1082 return zone()->New<ObjectData>(this, &entry->value, object, kSmi);
1083 }
1084
1085 DCHECK(!IsSmi(*object));
1086
1087 const bool crash_on_error = (flags & kCrashOnError) != 0;
1088
1089 if ((flags & kAssumeMemoryFence) == 0 &&
1091 TRACE_BROKER_MISSING(this, "Object may be uninitialized " << *object);
1092 CHECK_WITH_MSG(!crash_on_error, "Ref construction failed");
1093 return nullptr;
1094 }
1095
1097 entry = refs_->LookupOrInsert(object.address());
1098 return zone()->New<ObjectData>(this, &entry->value, object,
1100 }
1101
1102 InstanceType instance_type =
1103 Cast<HeapObject>(*object)->map()->instance_type();
1104#define CREATE_DATA(Name) \
1105 if (i::InstanceTypeChecker::Is##Name(instance_type)) { \
1106 entry = refs_->LookupOrInsert(object.address()); \
1107 object_data = zone()->New<ref_traits<Name>::data_type>( \
1108 this, &entry->value, Cast<Name>(object), \
1109 ObjectDataKindFor(ref_traits<Name>::ref_serialization_kind)); \
1110 /* NOLINTNEXTLINE(readability/braces) */ \
1111 } else
1113#undef CREATE_DATA
1114 {
1115 UNREACHABLE();
1116 }
1117
1118 // Ensure that the original instance type matches the one of the serialized
1119 // object (if the object was serialized). In particular, this is important
1120 // for Maps: in GetMapInstanceType we have special handling for maps and will
1121 // report MAP_TYPE for objects whose map pointer points back to itself. With
1122 // heap corruption, a non-map object can be made to point to itself though,
1123 // in which case we may later treat a non-MapData object as a MapData object.
1124 // See also crbug.com/326700497 for more details.
1125 if (!object_data->should_access_heap()) {
1127 instance_type,
1128 static_cast<HeapObjectData*>(object_data)->GetMapInstanceType());
1129 }
1130
1131 // At this point the entry pointer is not guaranteed to be valid as
1132 // the refs_ hash hable could be resized by one of the constructors above.
1133 DCHECK_EQ(object_data, refs_->Lookup(object.address())->value);
1134 return object_data;
1135}
1136
1137#define DEFINE_IS_AND_AS(Name) \
1138 bool ObjectRef::Is##Name() const { return data()->Is##Name(); } \
1139 Name##Ref ObjectRef::As##Name() const { \
1140 DCHECK(Is##Name()); \
1141 return Name##Ref(data()); \
1142 }
1144#undef DEFINE_IS_AND_AS
1145
1146bool ObjectRef::IsSmi() const { return data()->is_smi(); }
1147
1148int ObjectRef::AsSmi() const {
1149 DCHECK(IsSmi());
1150 // Handle-dereference is always allowed for Handle<Smi>.
1151 return Cast<Smi>(*object()).value();
1152}
1153
1154#define DEF_TESTER(Type, ...) \
1155 bool MapRef::Is##Type##Map() const { \
1156 return InstanceTypeChecker::Is##Type(instance_type()); \
1157 }
1159#undef DEF_TESTER
1160
1162 return *this == broker->boolean_map();
1163}
1164
1166 // The check below only works for string maps.
1167 DCHECK(IsStringMap());
1169}
1170
1172 return IsJSPrimitiveWrapperMap() &&
1174}
1175
1179
1181 if (!IsJSObjectMap()) return false;
1182 if (is_access_check_needed()) return false;
1183 if (has_indexed_interceptor()) return false;
1185 if (IsFastElementsKind(kind)) return true;
1187 (Is64() || (kind != BIGINT64_ELEMENTS && kind != BIGUINT64_ELEMENTS))) {
1188 return true;
1189 }
1191 kind != RAB_GSAB_BIGUINT64_ELEMENTS &&
1192 kind != RAB_GSAB_BIGINT64_ELEMENTS) {
1193 return true;
1194 }
1195 return false;
1196}
1197
1199 ElementsKind kind) const {
1200 const ElementsKind current_kind = elements_kind();
1201 if (kind == current_kind) return *this;
1202
1203#ifdef DEBUG
1204 // If starting from an initial JSArray map, TryAsElementsKind must succeed
1205 // and return the expected transitioned JSArray map.
1206 NativeContextRef native_context = broker->target_native_context();
1207 if (equals(native_context.GetInitialJSArrayMap(broker, current_kind))) {
1208 // Note that GetInitialJSArrayMap can park the current scope, which can
1209 // trigger a GC, which means that everything above this point that isn't in
1210 // a Handle could be invalidated.
1211 Tagged<Map> initial_js_array_map =
1212 *native_context.GetInitialJSArrayMap(broker, kind).object();
1213 Tagged<Map> as_elements_kind_map =
1214 Map::TryAsElementsKind(broker->isolate(), object(), kind,
1216 .value();
1217 CHECK_EQ(as_elements_kind_map, initial_js_array_map);
1218 }
1219#endif // DEBUG
1220
1221 std::optional<Tagged<Map>> maybe_result = Map::TryAsElementsKind(
1222 broker->isolate(), object(), kind, ConcurrencyMode::kConcurrent);
1223
1224 if (!maybe_result.has_value()) {
1225 TRACE_BROKER_MISSING(broker, "MapRef::AsElementsKind " << *this);
1226 return {};
1227 }
1228 return MakeRefAssumeMemoryFence(broker, maybe_result.value());
1229}
1230
1232 JSHeapBroker* broker, ZoneVector<MapRef>* prototype_maps) {
1233 DCHECK_NOT_NULL(prototype_maps);
1234 MapRef prototype_map = prototype(broker).map(broker);
1235 while (prototype_map.oddball_type(broker) != OddballType::kNull) {
1236 // For the purposes of depending on prototypes' elements behavior when
1237 // doing keyed property sets, non-extensible and sealed fast elements are
1238 // okay because they behave like fast elements for stores into holes on
1239 // the receiver. In such cases, the value is stored on the receiver's
1240 // elements and does not trigger any setters and does not throw.
1241 //
1242 // Note that frozen elements are _not_ okay because of the "override
1243 // mistake":
1244 //
1245 // Object.prototype[1] = "x";
1246 // Object.freeze(Object.prototype);
1247 // ([])[1] = "y"; <-- throws in strict mode, nop in sloppy mode
1248 if (!prototype_map.IsJSObjectMap() || !prototype_map.is_stable() ||
1250 prototype_map.elements_kind())) {
1251 return false;
1252 }
1253 prototype_maps->push_back(prototype_map);
1254 prototype_map = prototype_map.prototype(broker).map(broker);
1255 }
1256 return true;
1257}
1258
1260 return SupportsFastArrayIteration(broker, object());
1261}
1262
1264 return SupportsFastArrayResize(broker, object());
1265}
1266
1267namespace {
1268
1269void RecordConsistentJSFunctionViewDependencyIfNeeded(
1271 JSFunctionData::UsedField used_field) {
1272 if (!data->has_any_used_field()) {
1273 // Deduplicate dependencies.
1275 }
1276 data->set_used_field(used_field);
1277}
1278
1279} // namespace
1280
1281OptionalFeedbackVectorRef JSFunctionRef::feedback_vector(
1282 JSHeapBroker* broker) const {
1283 return raw_feedback_cell(broker).feedback_vector(broker);
1284}
1285
1287 JSHeapBroker* broker) const {
1288 if (data_->should_access_heap()) {
1289 return object()->ComputeInstanceSizeWithMinSlack(broker->isolate());
1290 }
1291 RecordConsistentJSFunctionViewDependencyIfNeeded(
1292 broker, *this, data()->AsJSFunction(),
1294 return data()->AsJSFunction()->initial_map_instance_size_with_min_slack();
1295}
1296
1298 if (instance_type() != ODDBALL_TYPE) {
1299 return OddballType::kNone;
1300 }
1301 if (equals(broker->undefined_map())) {
1303 }
1304 if (equals(broker->null_map())) {
1305 return OddballType::kNull;
1306 }
1307 if (equals(broker->boolean_map())) {
1308 return OddballType::kBoolean;
1309 }
1310 UNREACHABLE();
1311}
1312
1314 int index) const {
1316 object()->closure_feedback_cell(index));
1317}
1318
1320 JSHeapBroker* broker) const {
1321 return TryMakeRef(broker, object()->raw_properties_or_hash());
1322}
1323
1325 FieldIndex index) const {
1326 CHECK(index.is_inobject());
1328 {
1330 PtrComprCageBase cage_base = broker->cage_base();
1331 Tagged<Map> current_map = object()->map(cage_base, kAcquireLoad);
1332
1333 // If the map changed in some prior GC epoch, our {index} could be
1334 // outside the valid bounds of the cached map.
1335 if (*map(broker).object() != current_map) {
1336 TRACE_BROKER_MISSING(broker, "Map change detected in " << *this);
1337 return {};
1338 }
1339
1340 std::optional<Tagged<Object>> maybe_value =
1341 object()->RawInobjectPropertyAt(cage_base, current_map, index);
1342 if (!maybe_value.has_value()) {
1344 "Unable to safely read property in " << *this);
1345 return {};
1346 }
1347 value = broker->CanonicalPersistentHandle(maybe_value.value());
1348 }
1349 return TryMakeRef(broker, value);
1350}
1351
1355
1357 CHECK_LT(descriptor_index.as_int(), NumberOfOwnDescriptors());
1358 FieldIndex result = FieldIndex::ForDescriptor(*object(), descriptor_index);
1359 DCHECK(result.is_inobject());
1360 return result;
1361}
1362
1364 return object()->GetInObjectPropertyOffset(i);
1365}
1366
1368 JSHeapBroker* broker, InternalIndex descriptor_index) const {
1369 CHECK_LT(descriptor_index.as_int(), NumberOfOwnDescriptors());
1370 return instance_descriptors(broker).GetPropertyDetails(descriptor_index);
1371}
1372
1374 InternalIndex descriptor_index) const {
1375 CHECK_LT(descriptor_index.as_int(), NumberOfOwnDescriptors());
1376 return instance_descriptors(broker).GetPropertyKey(broker, descriptor_index);
1377}
1378
1380 Handle<Map> fixed_cow_array_map =
1381 broker->isolate()->factory()->fixed_cow_array_map();
1382 return equals(MakeRef(broker, fixed_cow_array_map));
1383}
1384
1386 return instance_type() <= LAST_PRIMITIVE_HEAP_OBJECT_TYPE;
1387}
1388
1390 InternalIndex descriptor_index) const {
1391 CHECK_LT(descriptor_index.as_int(), NumberOfOwnDescriptors());
1392 // TODO(solanes, v8:7790): Consider caching the result of the field owner on
1393 // the descriptor array. It would be useful for same map as well as any
1394 // other map sharing that descriptor array.
1396 broker, object()->FindFieldOwner(broker->cage_base(), descriptor_index));
1397}
1398
1400 uint32_t index) const {
1401 Tagged<String> maybe_char;
1403 &maybe_char, broker->isolate(), broker->local_isolate(), *object(),
1404 index);
1405
1407 TRACE_BROKER_MISSING(broker, "StringRef::GetCharAsStringOrUndefined on "
1408 << *this << " at index " << index);
1409 return {};
1410 }
1411
1413 return TryMakeRef(broker, maybe_char);
1414}
1415
1417 return IsInternalizedString() || IsThinString(*object());
1418}
1419
1423
1425 return object()->IsOneByteRepresentation();
1426}
1427
1428// TODO(leszeks): The broker is only needed here for tracing, maybe we could get
1429// it from a thread local instead.
1430std::optional<Handle<String>> StringRef::ObjectIfContentAccessible(
1432 if (!IsContentAccessible()) {
1434 broker,
1435 "content for kNeverSerialized unsupported string kind " << *this);
1436 return std::nullopt;
1437 } else {
1438 return object();
1439 }
1440}
1441
1442uint32_t StringRef::length() const { return object()->length(kAcquireLoad); }
1443
1444std::optional<uint16_t> StringRef::GetFirstChar(JSHeapBroker* broker) const {
1445 return GetChar(broker, 0);
1446}
1447
1448std::optional<uint16_t> StringRef::GetChar(JSHeapBroker* broker,
1449 uint32_t index) const {
1450 if (!IsContentAccessible()) {
1452 broker,
1453 "get char for kNeverSerialized unsupported string kind " << *this);
1454 return std::nullopt;
1455 }
1456
1457 if (!broker->IsMainThread()) {
1458 return object()->Get(index, broker->local_isolate());
1459 } else {
1460 // TODO(solanes, v8:7790): Remove this case once the inlining phase is
1461 // done concurrently all the time.
1462 return object()->Get(index);
1463 }
1464}
1465
1466std::optional<double> StringRef::ToNumber(JSHeapBroker* broker) {
1467 if (!IsContentAccessible()) {
1469 broker,
1470 "number for kNeverSerialized unsupported string kind " << *this);
1471 return std::nullopt;
1472 }
1473
1474 return TryStringToDouble(broker->local_isolate(), object());
1475}
1476
1477std::optional<double> StringRef::ToInt(JSHeapBroker* broker, int radix) {
1478 if (!IsContentAccessible()) {
1480 broker, "toInt for kNeverSerialized unsupported string kind " << *this);
1481 return std::nullopt;
1482 }
1483
1484 return TryStringToInt(broker->local_isolate(), object(), radix);
1485}
1486
1488 return object()->constant_elements()->length();
1489}
1490
1491OptionalObjectRef FixedArrayRef::TryGet(JSHeapBroker* broker, int i) const {
1493 {
1495 CHECK_GE(i, 0);
1496 value = broker->CanonicalPersistentHandle(object()->get(i, kAcquireLoad));
1497 if (i >= object()->length(kAcquireLoad)) {
1498 // Right-trimming happened.
1499 CHECK_LT(i, length());
1500 return {};
1501 }
1502 }
1503 return TryMakeRef(broker, value);
1504}
1505
1509 CHECK(data_->should_access_heap());
1510 return Float64::FromBits(object()->get_representation(i));
1511}
1512
1514 JSHeapBroker* broker) const {
1515 return broker->CanonicalPersistentHandle(object()->SourcePositionTable());
1516}
1517
1519 return reinterpret_cast<Address>(object()->handler_table()->begin());
1520}
1521
1523 return object()->handler_table()->length();
1524}
1525
1526#define IF_ACCESS_FROM_HEAP_C(name) \
1527 if (data_->should_access_heap()) { \
1528 return object()->name(); \
1529 }
1530
1531#define IF_ACCESS_FROM_HEAP(result, name) \
1532 if (data_->should_access_heap()) { \
1533 return MakeRef(broker, Cast<result>(object()->name())); \
1534 }
1535
1536// Macros for definining a const getter that, depending on the data kind,
1537// either looks into the heap or into the serialized data.
1538#define BIMODAL_ACCESSOR(holder, result, name) \
1539 result##Ref holder##Ref::name(JSHeapBroker* broker) const { \
1540 IF_ACCESS_FROM_HEAP(result, name); \
1541 return result##Ref(ObjectRef::data()->As##holder()->name()); \
1542 }
1543
1544// Like above except that the result type is not an XYZRef.
1545#define BIMODAL_ACCESSOR_C(holder, result, name) \
1546 result holder##Ref::name() const { \
1547 IF_ACCESS_FROM_HEAP_C(name); \
1548 return ObjectRef::data()->As##holder()->name(); \
1549 }
1550
1551// Like above but for BitFields.
1552#define BIMODAL_ACCESSOR_B(holder, field, name, BitField) \
1553 typename BitField::FieldType holder##Ref::name() const { \
1554 IF_ACCESS_FROM_HEAP_C(name); \
1555 return BitField::decode(ObjectRef::data()->As##holder()->field()); \
1556 }
1557
1558#define HEAP_ACCESSOR_C(holder, result, name) \
1559 result holder##Ref::name() const { return object()->name(); }
1560
1561#define HEAP_ACCESSOR_B(holder, field, name, BitField) \
1562 typename BitField::FieldType holder##Ref::name() const { \
1563 return object()->name(); \
1564 }
1565
1569
1570HEAP_ACCESSOR_C(AllocationSite, bool, CanInlineCall)
1571HEAP_ACCESSOR_C(AllocationSite, bool, PointsToLiteral)
1574
1575BIMODAL_ACCESSOR_C(BigInt, uint64_t, AsUint64)
1576int64_t BigIntRef::AsInt64(bool* lossless) const {
1577 if (data_->should_access_heap()) {
1578 return object()->AsInt64(lossless);
1579 }
1580 return ObjectRef::data()->AsBigInt()->AsInt64(lossless);
1581}
1582
1583int BytecodeArrayRef::length() const { return object()->length(); }
1585 return object()->register_count();
1586}
1588 return object()->parameter_count();
1589}
1591 return object()->parameter_count_without_receiver();
1592}
1594 return object()->max_arguments();
1595}
1598 return object()->incoming_new_target_or_generator_register();
1599}
1600
1602
1603HEAP_ACCESSOR_C(HeapNumber, double, value)
1604
1605uint64_t HeapNumberRef::value_as_bits() const {
1606 return object()->value_as_bits();
1607}
1608
1610 JSHeapBroker* broker) const {
1611 // Immutable after initialization.
1613}
1614
1616 // Immutable after initialization.
1617 return MakeRefAssumeMemoryFence(broker, object()->bound_this());
1618}
1619
1621 // Immutable after initialization.
1622 return MakeRefAssumeMemoryFence(broker, object()->bound_arguments());
1623}
1624
1625// Immutable after initialization.
1626HEAP_ACCESSOR_C(JSDataView, size_t, byte_length)
1627
1628BIMODAL_ACCESSOR_B(Map, bit_field2, elements_kind, Map::Bits2::ElementsKindBits)
1629HEAP_ACCESSOR_B(Map, bit_field3, is_dictionary_map,
1630 Map::Bits3::IsDictionaryMapBit)
1631HEAP_ACCESSOR_B(Map, bit_field3, is_deprecated, Map::Bits3::IsDeprecatedBit)
1633 Map::Bits3::NumberOfOwnDescriptorsBits)
1634HEAP_ACCESSOR_B(Map, bit_field3, is_migration_target,
1635 Map::Bits3::IsMigrationTargetBit)
1637 Map::Bits3::ConstructionCounterBits)
1639 Map::Bits1::HasPrototypeSlotBit)
1641 Map::Bits1::IsAccessCheckNeededBit)
1642HEAP_ACCESSOR_B(Map, bit_field, is_callable, Map::Bits1::IsCallableBit)
1643HEAP_ACCESSOR_B(Map, bit_field, has_indexed_interceptor,
1644 Map::Bits1::HasIndexedInterceptorBit)
1645HEAP_ACCESSOR_B(Map, bit_field, is_constructor, Map::Bits1::IsConstructorBit)
1646HEAP_ACCESSOR_B(Map, bit_field, is_undetectable, Map::Bits1::IsUndetectableBit)
1647BIMODAL_ACCESSOR_C(Map, int, instance_size)
1648HEAP_ACCESSOR_C(Map, int, NextFreePropertyIndex)
1649BIMODAL_ACCESSOR_C(Map, int, UnusedPropertyFields)
1650HEAP_ACCESSOR_C(Map, InstanceType, instance_type)
1651BIMODAL_ACCESSOR_C(Map, bool, is_abandoned_prototype_map)
1652
1653int ObjectBoilerplateDescriptionRef::boilerplate_properties_count() const {
1654 return object()->boilerplate_properties_count();
1655}
1656
1659
1661 JSHeapBroker* broker) const {
1662 // Immutable after initialization.
1664 broker, Cast<HeapObject>(object()->data(broker->isolate())));
1665}
1666
1667StringRef RegExpBoilerplateDescriptionRef::source(JSHeapBroker* broker) const {
1668 // Immutable after initialization.
1669 return MakeRefAssumeMemoryFence(broker, object()->source());
1670}
1671
1672int RegExpBoilerplateDescriptionRef::flags() const { return object()->flags(); }
1673
1675 return object()->callback(broker->isolate());
1676}
1677
1679 JSHeapBroker* broker) const {
1680 ObjectRef data =
1682 if (data.IsTheHole()) return {};
1683 return data;
1684}
1685
1687 JSHeapBroker* broker) const {
1688 return i::IsUndefined(object()->signature(), broker->isolate());
1689}
1690
1691HEAP_ACCESSOR_C(FunctionTemplateInfo, bool, accept_any_receiver)
1692HEAP_ACCESSOR_C(FunctionTemplateInfo, int16_t,
1693 allowed_receiver_instance_type_range_start)
1694HEAP_ACCESSOR_C(FunctionTemplateInfo, int16_t,
1696
1698 JSHeapBroker* broker, MapRef receiver_map) {
1699 const HolderLookupResult not_found;
1700 if (!receiver_map.IsJSObjectMap() || (receiver_map.is_access_check_needed() &&
1701 !object()->accept_any_receiver())) {
1702 return not_found;
1703 }
1704
1705 DirectHandle<FunctionTemplateInfo> expected_receiver_type;
1706 {
1708 Tagged<HeapObject> signature = object()->signature();
1709 if (i::IsUndefined(signature)) {
1710 return HolderLookupResult(CallOptimization::kHolderIsReceiver);
1711 }
1712 expected_receiver_type = broker->CanonicalPersistentHandle(
1713 Cast<FunctionTemplateInfo>(signature));
1714 if (expected_receiver_type->IsTemplateFor(*receiver_map.object())) {
1715 return HolderLookupResult(CallOptimization::kHolderIsReceiver);
1716 }
1717 if (!receiver_map.IsJSGlobalProxyMap()) return not_found;
1718 }
1719
1720 HeapObjectRef prototype = receiver_map.prototype(broker);
1721 if (prototype.IsNull()) return not_found;
1722 if (!expected_receiver_type->IsTemplateFor(prototype.object()->map())) {
1723 return not_found;
1724 }
1725 CHECK(prototype.IsJSObject());
1726 return HolderLookupResult(CallOptimization::kHolderFound,
1727 prototype.AsJSObject());
1728}
1729
1730HEAP_ACCESSOR_C(ScopeInfo, int, ContextLength)
1731HEAP_ACCESSOR_C(ScopeInfo, bool, HasContextExtensionSlot)
1732HEAP_ACCESSOR_C(ScopeInfo, bool, SomeContextHasExtension)
1733HEAP_ACCESSOR_C(ScopeInfo, bool, HasOuterScopeInfo)
1734HEAP_ACCESSOR_C(ScopeInfo, bool, HasContext)
1735HEAP_ACCESSOR_C(ScopeInfo, bool, ClassScopeHasPrivateBrand)
1736HEAP_ACCESSOR_C(ScopeInfo, bool, SloppyEvalCanExtendVars)
1737HEAP_ACCESSOR_C(ScopeInfo, ScopeType, scope_type)
1738
1740 return MakeRefAssumeMemoryFence(broker, object()->OuterScopeInfo());
1741}
1742
1744
1746 JSHeapBroker* broker) const {
1747 CHECK(HasBytecodeArray());
1748 Tagged<BytecodeArray> bytecode_array;
1749 if (!broker->IsMainThread()) {
1750 bytecode_array = object()->GetBytecodeArray(broker->local_isolate());
1751 } else {
1752 bytecode_array = object()->GetBytecodeArray(broker->isolate());
1753 }
1754 return MakeRefAssumeMemoryFence(broker, bytecode_array);
1755}
1756
1757#define DEF_SFI_ACCESSOR(type, name) \
1758 HEAP_ACCESSOR_C(SharedFunctionInfo, type, name)
1760#undef DEF_SFI_ACCESSOR
1761
1763 if (broker->IsMainThread()) {
1764 return object()->HasBreakInfo(broker->isolate());
1765 } else {
1766 LocalIsolate* local_isolate = broker->local_isolate();
1768 local_isolate->shared_function_info_access(), local_isolate);
1769 return object()->HasBreakInfo(local_isolate->GetMainThreadIsolateUnsafe());
1770 }
1771}
1772
1774 JSHeapBroker* broker) const {
1775 return broker->IsMainThread()
1776 ? object()->GetInlineability(broker->isolate())
1777 : object()->GetInlineability(broker->local_isolate());
1778}
1779
1781 DCHECK(data_->should_access_heap());
1783}
1784
1786 return object()->was_once_deoptimized();
1787}
1788
1790 InternalIndex descriptor_index) const {
1791 CHECK_LT(descriptor_index.as_int(), NumberOfOwnDescriptors());
1792 return instance_descriptors(broker).GetStrongValue(broker, descriptor_index);
1793}
1794
1800
1805
1807 // TODO(solanes, v8:7790): Consider caching the result of the root map.
1809 object()->FindRootMap(broker->cage_base()));
1810}
1811
1813 // Immutable after initialization.
1814 return MakeRefAssumeMemoryFence(broker, object()->GetConstructor());
1815}
1816
1818 // Immutable after initialization.
1820 Cast<HeapObject>(object()->GetBackPointer()));
1821}
1822
1824 // Underlying field written 1. during initialization or 2. with release-store.
1825 return object()->is_on_heap(kAcquireLoad);
1826}
1827
1829 CHECK(!is_on_heap());
1830 // Immutable after initialization.
1831 return object()->length();
1832}
1833
1835 // Immutable after initialization (since this is not used for RAB/GSAB).
1836 return object()->byte_length();
1837}
1838
1840 // Immutable after initialization.
1841 return map(broker).elements_kind();
1842}
1843
1845 CHECK(!is_on_heap());
1846 // Immutable after initialization.
1847 return MakeRef<HeapObject>(broker, object()->buffer());
1848}
1849
1851 CHECK(!is_on_heap());
1852 // Underlying field written 1. during initialization or 2. protected by the
1853 // is_on_heap release/acquire semantics (external_pointer store happens-before
1854 // base_pointer store, and this external_pointer load happens-after
1855 // base_pointer load).
1857 return object()->DataPtr();
1858}
1859
1861 auto elements_kind = map(broker).elements_kind();
1862 return elements_kind == FAST_STRING_WRAPPER_ELEMENTS ||
1863 elements_kind == SLOW_STRING_WRAPPER_ELEMENTS;
1864}
1865
1869
1871 return object()->GetConstructorFunctionIndex();
1872}
1873
1874bool MapRef::is_stable() const {
1876 return !Map::Bits3::IsUnstableBit::decode(data()->AsMap()->bit_field3());
1877}
1878
1879bool MapRef::CanBeDeprecated() const { return object()->CanBeDeprecated(); }
1880
1881bool MapRef::CanTransition() const { return object()->CanTransition(); }
1882
1884 return object()->GetInObjectPropertiesStartInWords();
1885}
1886
1889 return data()->AsMap()->in_object_properties();
1890}
1891
1893 return i::IsExternalString(*object());
1894}
1895
1897 JSHeapBroker* broker) const {
1898 return GetCFunctions(Cast<FixedArray>(object()->GetCFunctionOverloads()),
1899 broker->isolate(), broker->zone());
1900}
1901
1903 JSHeapBroker* broker) const {
1904 return GetCSignatures(Cast<FixedArray>(object()->GetCFunctionOverloads()),
1905 broker->isolate(), broker->zone());
1906}
1907
1908bool StringRef::IsSeqString() const { return i::IsSeqString(*object()); }
1909
1911 // The scope_info is immutable after initialization.
1912 return MakeRefAssumeMemoryFence(broker, object()->scope_info());
1913}
1914
1923
1925 ElementsKind kind) const {
1926 switch (kind) {
1928 return js_array_packed_smi_elements_map(broker);
1929 case HOLEY_SMI_ELEMENTS:
1930 return js_array_holey_smi_elements_map(broker);
1932 return js_array_packed_double_elements_map(broker);
1934 return js_array_holey_double_elements_map(broker);
1935 case PACKED_ELEMENTS:
1936 return js_array_packed_elements_map(broker);
1937 case HOLEY_ELEMENTS:
1938 return js_array_holey_elements_map(broker);
1939 default:
1940 UNREACHABLE();
1941 }
1942}
1943
1944#define DEF_NATIVE_CONTEXT_ACCESSOR(ResultType, Name) \
1945 ResultType##Ref NativeContextRef::Name(JSHeapBroker* broker) const { \
1946 return MakeRefAssumeMemoryFence( \
1947 broker, Cast<ResultType>(object()->Name(kAcquireLoad))); \
1948 }
1950#undef DEF_NATIVE_CONTEXT_ACCESSOR
1951
1953 JSHeapBroker* broker, MapRef map) const {
1954 CHECK(map.IsPrimitiveMap());
1955 switch (map.constructor_function_index()) {
1957 return std::nullopt;
1958 case Context::BIGINT_FUNCTION_INDEX:
1959 return bigint_function(broker);
1960 case Context::BOOLEAN_FUNCTION_INDEX:
1961 return boolean_function(broker);
1962 case Context::NUMBER_FUNCTION_INDEX:
1963 return number_function(broker);
1964 case Context::STRING_FUNCTION_INDEX:
1965 return string_function(broker);
1966 case Context::SYMBOL_FUNCTION_INDEX:
1967 return symbol_function(broker);
1968 default:
1969 UNREACHABLE();
1970 }
1971}
1972
1973bool ObjectRef::IsNull() const { return i::IsNull(*object()); }
1974
1975bool ObjectRef::IsUndefined() const { return i::IsUndefined(*object()); }
1976
1977bool ObjectRef::IsTheHole() const {
1978 if (i::IsTheHole(*object())) return true;
1979 DCHECK(!i::IsHole(*object()));
1980 return false;
1981}
1982
1983bool ObjectRef::IsPropertyCellHole() const {
1984 if (i::IsPropertyCellHole(*object())) return true;
1985 DCHECK(!i::IsHole(*object()));
1986 return false;
1987}
1988
1989bool ObjectRef::IsHashTableHole() const {
1990 if (i::IsHashTableHole(*object())) return true;
1991 DCHECK(!i::IsHole(*object()));
1992 return false;
1993}
1994
1995HoleType ObjectRef::HoleType() const {
1996 // Trusted objects cannot be TheHole and comparing them to TheHole is not
1997 // allowed, as they live in different cage bases.
1998 if (i::IsHeapObject(*object()) &&
1999 i::HeapLayout::InTrustedSpace(Cast<HeapObject>(*object())))
2000 return HoleType::kNone;
2001#define IF_HOLE_THEN_RETURN(Name, name, Root) \
2002 if (i::Is##Name(*object())) { \
2003 return HoleType::k##Name; \
2004 }
2005
2007#undef IF_HOLE_THEN_RETURN
2008
2009 return HoleType::kNone;
2010}
2011
2012bool ObjectRef::IsNullOrUndefined() const { return IsNull() || IsUndefined(); }
2013
2014std::optional<bool> ObjectRef::TryGetBooleanValue(JSHeapBroker* broker) const {
2015 if (data_->should_access_heap()) {
2016 return Object::BooleanValue(*object(), broker->isolate());
2017 }
2018 if (IsSmi()) return AsSmi() != 0;
2019 return data()->AsHeapObject()->TryGetBooleanValue(broker);
2020}
2021
2022Maybe<double> ObjectRef::OddballToNumber(JSHeapBroker* broker) const {
2023 OddballType type = AsHeapObject().map(broker).oddball_type(broker);
2024
2025 switch (type) {
2026 case OddballType::kBoolean: {
2027 ObjectRef true_ref = broker->true_value();
2028 return this->equals(true_ref) ? Just(1.0) : Just(0.0);
2029 }
2031 return Just(std::numeric_limits<double>::quiet_NaN());
2032 }
2033 case OddballType::kNull: {
2034 return Just(0.0);
2035 }
2036 default: {
2037 return Nothing<double>();
2038 }
2039 }
2040}
2041
2042bool ObjectRef::should_access_heap() const {
2043 return data()->should_access_heap();
2044}
2045
2047 JSHeapBroker* broker, FixedArrayBaseRef elements_ref, uint32_t index,
2048 CompilationDependencies* dependencies) const {
2049 std::optional<Tagged<Object>> maybe_element = GetOwnConstantElementFromHeap(
2050 broker, *elements_ref.object(), map(broker).elements_kind(), index);
2051 if (!maybe_element.has_value()) return {};
2052
2053 OptionalObjectRef result = TryMakeRef(broker, maybe_element.value());
2054 if (result.has_value()) {
2055 dependencies->DependOnOwnConstantElement(*this, index, *result);
2056 }
2057 return result;
2058}
2059
2062 ElementsKind elements_kind, uint32_t index) const {
2064
2065 DirectHandle<JSObject> holder = object();
2066
2067 // This block is carefully constructed to avoid Ref creation and access since
2068 // this method may be called after the broker has retired.
2069 // The relaxed `length` read is safe to use in this case since:
2070 // - TryGetOwnConstantElement (below) only detects a constant for JSArray
2071 // holders if the array is frozen.
2072 // - Frozen arrays can't change length.
2073 // - We've already seen the corresponding map (when this JSObjectRef was
2074 // created);
2075 // - The release-load of that map ensures we read the newest value
2076 // of `length` below.
2077 if (i::IsJSArray(*holder)) {
2078 Tagged<Object> array_length_obj =
2079 Cast<JSArray>(*holder)->length(broker->isolate(), kRelaxedLoad);
2080 if (!i::IsSmi(array_length_obj)) {
2081 // Can't safely read into HeapNumber objects without atomic semantics
2082 // (relaxed would be sufficient due to the guarantees above).
2083 return {};
2084 }
2085 uint32_t array_length;
2086 if (!Object::ToArrayLength(array_length_obj, &array_length)) {
2087 return {};
2088 }
2089 // See also ElementsAccessorBase::GetMaxIndex.
2090 if (index >= array_length) return {};
2091 }
2092
2093 Tagged<Object> maybe_element;
2095 &maybe_element, broker->isolate(), broker->local_isolate(), *holder,
2096 elements, elements_kind, index);
2097
2099 TRACE_BROKER_MISSING(broker, "JSObject::GetOwnConstantElement on "
2100 << *this << " at index " << index);
2101 return {};
2103 return {};
2104 }
2105
2107 return maybe_element;
2108}
2109
2111 JSHeapBroker* broker, Representation field_representation, FieldIndex index,
2112 CompilationDependencies* dependencies) const {
2113 // Use GetOwnFastConstantDoubleProperty for doubles.
2114 DCHECK(!field_representation.IsDouble());
2115
2116 std::optional<Tagged<Object>> constant =
2117 GetOwnFastConstantDataPropertyFromHeap(broker, *this,
2118 field_representation, index);
2119 if (!constant) return {};
2120
2121 OptionalObjectRef result =
2122 TryMakeRef(broker, broker->CanonicalPersistentHandle(constant.value()));
2123
2124 if (!result.has_value()) return {};
2125
2126 dependencies->DependOnOwnConstantDataProperty(*this, map(broker), index,
2127 *result);
2128 return result;
2129}
2130
2133 CompilationDependencies* dependencies) const {
2134 std::optional<Tagged<Object>> constant =
2135 GetOwnFastConstantDataPropertyFromHeap(broker, *this,
2136 Representation::Double(), index);
2137 if (!constant) return {};
2138
2139 DCHECK(i::IsHeapNumber(constant.value()));
2140
2141 Float64 unboxed_value = Float64::FromBits(
2142 RacyReadHeapNumberBits(Cast<HeapNumber>(constant.value())));
2143
2144 dependencies->DependOnOwnConstantDoubleProperty(*this, map(broker), index,
2145 unboxed_value);
2146 return unboxed_value;
2147}
2148
2151 CompilationDependencies* dependencies) const {
2152 CHECK(index.is_found());
2153 OptionalObjectRef result =
2154 GetOwnDictionaryPropertyFromHeap(broker, object(), index);
2155 if (result.has_value()) {
2156 dependencies->DependOnOwnConstantDictionaryProperty(*this, index, *result);
2157 }
2158 return result;
2159}
2160
2162 // Safe to read concurrently because:
2163 // - boilerplates are immutable after initialization.
2164 // - boilerplates are published into the feedback vector.
2165 // These facts also mean we can expect a valid value.
2166 return length_unsafe(broker).value();
2167}
2168
2170 return TryMakeRef(broker, object()->length(broker->isolate(), kRelaxedLoad));
2171}
2172
2174 FixedArrayBaseRef elements_ref,
2175 uint32_t index) const {
2176 // Note: we'd like to check `elements_ref == elements()` here, but due to
2177 // concurrency this may not hold. The code below must be able to deal with
2178 // concurrent `elements` modifications.
2179
2180 // Due to concurrency, the kind read here may not be consistent with
2181 // `elements_ref`. The caller has to guarantee consistency at runtime by
2182 // other means (e.g. through a runtime equality check or a compilation
2183 // dependency).
2184 ElementsKind elements_kind = map(broker).elements_kind();
2185
2186 // We only inspect fixed COW arrays, which may only occur for fast
2187 // smi/objects elements kinds.
2188 if (!IsSmiOrObjectElementsKind(elements_kind)) return {};
2189 DCHECK(IsFastElementsKind(elements_kind));
2190 if (!elements_ref.map(broker).IsFixedCowArrayMap(broker)) return {};
2191
2192 // As the name says, the `length` read here is unsafe and may not match
2193 // `elements`. We rely on the invariant that any `length` change will
2194 // also result in an `elements` change to make this safe. The `elements`
2195 // consistency check in the caller thus also guards the value of `length`.
2196 OptionalObjectRef length_ref = length_unsafe(broker);
2197
2198 if (!length_ref.has_value()) return {};
2199
2200 // Likewise we only deal with smi lengths.
2201 if (!length_ref->IsSmi()) return {};
2202
2203 std::optional<Tagged<Object>> result =
2205 broker->isolate(), *elements_ref.AsFixedArray().object(),
2206 elements_kind, length_ref->AsSmi(), index);
2207 if (!result.has_value()) return {};
2208
2209 return TryMakeRef(broker, result.value());
2210}
2211
2213 int cell_index) const {
2214 return TryMakeRef(broker, object()->GetCell(cell_index));
2215}
2216
2218 return TryMakeRef(broker, object()->import_meta(kAcquireLoad));
2219}
2220
2222 PtrComprCageBase cage_base = broker->cage_base();
2223 return TryMakeRef(broker, object()->map(cage_base, kAcquireLoad),
2225}
2226
2227namespace {
2228
2229OddballType GetOddballType(Isolate* isolate, Tagged<Map> map) {
2230 if (map->instance_type() != ODDBALL_TYPE) {
2231 return OddballType::kNone;
2232 }
2233 ReadOnlyRoots roots(isolate);
2234 if (map == roots.undefined_map()) {
2236 }
2237 if (map == roots.null_map()) {
2238 return OddballType::kNull;
2239 }
2240 if (map == roots.boolean_map()) {
2241 return OddballType::kBoolean;
2242 }
2243 UNREACHABLE();
2244}
2245
2246} // namespace
2247
2249 if (data_->should_access_heap()) {
2250 Tagged<Map> map = Cast<HeapObject>(object())->map(broker->cage_base());
2252 if (map->is_undetectable()) flags |= HeapObjectType::kUndetectable;
2253 if (map->is_callable()) flags |= HeapObjectType::kCallable;
2254 return HeapObjectType(map->instance_type(), map->elements_kind(), flags,
2255 GetOddballType(broker->isolate(), map), HoleType());
2256 }
2259 if (map(broker).is_callable()) flags |= HeapObjectType::kCallable;
2260 return HeapObjectType(map(broker).instance_type(),
2261 map(broker).elements_kind(), flags,
2262 map(broker).oddball_type(broker), HoleType());
2263}
2264
2266 if (!PointsToLiteral()) return {};
2267 DCHECK(data_->should_access_heap());
2268 return TryMakeRef(broker, object()->boilerplate(kAcquireLoad));
2269}
2270
2271OptionalFixedArrayBaseRef JSObjectRef::elements(JSHeapBroker* broker,
2272 RelaxedLoadTag tag) const {
2273 return TryMakeRef(broker, object()->elements(tag));
2274}
2275
2277 IF_ACCESS_FROM_HEAP_C(length);
2278 return data()->AsFixedArrayBase()->length();
2279}
2280
2282 InternalIndex descriptor_index) const {
2283 return object()->GetDetails(descriptor_index);
2284}
2285
2287 JSHeapBroker* broker, InternalIndex descriptor_index) const {
2288 // A property key that has been written to a descriptor array must be being
2289 // read because it was observed in a map, which means this write must have
2290 // been published.
2291 NameRef result =
2292 MakeRefAssumeMemoryFence(broker, object()->GetKey(descriptor_index));
2293 CHECK(result.IsUniqueName());
2294 return result;
2295}
2296
2298 JSHeapBroker* broker, InternalIndex descriptor_index) const {
2299 Tagged<HeapObject> heap_object;
2300 if (!object()
2301 ->GetValue(descriptor_index)
2302 .GetHeapObjectIfStrong(&heap_object)) {
2303 return {};
2304 }
2305 // Since the descriptors in the descriptor array can be changed in-place
2306 // via DescriptorArray::Replace, we might get a value that we haven't seen
2307 // before.
2308 return TryMakeRef(broker, heap_object);
2309}
2310
2311OptionalFeedbackVectorRef FeedbackCellRef::feedback_vector(
2312 JSHeapBroker* broker) const {
2313 ObjectRef contents = value(broker);
2314 if (!contents.IsFeedbackVector()) return {};
2315 return contents.AsFeedbackVector();
2316}
2317
2318OptionalSharedFunctionInfoRef FeedbackCellRef::shared_function_info(
2319 JSHeapBroker* broker) const {
2320 OptionalFeedbackVectorRef vector = feedback_vector(broker);
2321 if (!vector.has_value()) return {};
2322 return vector->shared_function_info(broker);
2323}
2324
2325#ifdef V8_ENABLE_LEAPTIERING
2327#endif
2328
2330 JSHeapBroker* broker) const {
2331 // Immutable after initialization.
2333}
2334
2336 // Must match Name::IsUniqueName.
2337 return IsInternalizedString() || IsSymbol();
2338}
2339
2340IndirectHandle<Object> ObjectRef::object() const { return data_->object(); }
2341
2342#define DEF_OBJECT_GETTER(T) \
2343 IndirectHandle<T> T##Ref::object() const { \
2344 return IndirectHandle<T>( \
2345 reinterpret_cast<Address*>(data_->object().address())); \
2346 }
2347
2349#undef DEF_OBJECT_GETTER
2350
2351ObjectData* ObjectRef::data() const {
2352#ifdef DEBUG
2353 switch (JSHeapBroker::Current()->mode()) {
2355 break;
2358 break;
2362 break;
2363 }
2364#endif
2365
2366 return data_;
2367}
2368
2369#define JSFUNCTION_BIMODAL_ACCESSOR_WITH_DEP(Result, Name, UsedField) \
2370 Result##Ref JSFunctionRef::Name(JSHeapBroker* broker) const { \
2371 IF_ACCESS_FROM_HEAP(Result, Name); \
2372 RecordConsistentJSFunctionViewDependencyIfNeeded( \
2373 broker, *this, data()->AsJSFunction(), UsedField); \
2374 return Result##Ref(data()->AsJSFunction()->Name()); \
2375 }
2376
2377#define JSFUNCTION_BIMODAL_ACCESSOR_WITH_DEP_C(Result, Name, UsedField) \
2378 Result JSFunctionRef::Name(JSHeapBroker* broker) const { \
2379 IF_ACCESS_FROM_HEAP_C(Name); \
2380 RecordConsistentJSFunctionViewDependencyIfNeeded( \
2381 broker, *this, data()->AsJSFunction(), UsedField); \
2382 return data()->AsJSFunction()->Name(); \
2383 }
2384
2385// Like JSFUNCTION_BIMODAL_ACCESSOR_WITH_DEP_C but only depend on the
2386// field in question if its recorded value is "relevant". This is in order to
2387// tolerate certain state changes during compilation, e.g. from "has no feedback
2388// vector" (in which case we would simply do less optimization) to "has feedback
2389// vector".
2390#define JSFUNCTION_BIMODAL_ACCESSOR_WITH_DEP_RELEVANT_C( \
2391 Result, Name, UsedField, RelevantValue) \
2392 Result JSFunctionRef::Name(JSHeapBroker* broker) const { \
2393 IF_ACCESS_FROM_HEAP_C(Name); \
2394 Result const result = data()->AsJSFunction()->Name(); \
2395 if (result == RelevantValue) { \
2396 RecordConsistentJSFunctionViewDependencyIfNeeded( \
2397 broker, *this, data()->AsJSFunction(), UsedField); \
2398 } \
2399 return result; \
2400 }
2401
2404 true)
2406 bool, has_instance_prototype, JSFunctionData::kHasInstancePrototype, true)
2408 bool, PrototypeRequiresRuntimeLookup,
2409 JSFunctionData::kPrototypeRequiresRuntimeLookup, false)
2410
2412 JSFunctionData::kInitialMap)
2414 JSFunctionData::kInstancePrototype)
2416 JSFunctionData::kFeedbackCell)
2417
2420#ifdef V8_ENABLE_LEAPTIERING
2422#endif
2423
2424#undef JSFUNCTION_BIMODAL_ACCESSOR_WITH_DEP
2425#undef JSFUNCTION_BIMODAL_ACCESSOR_WITH_DEP_C
2426
2427OptionalCodeRef JSFunctionRef::code(JSHeapBroker* broker) const {
2428 return TryMakeRef(broker, object()->code(broker->isolate()));
2429}
2430
2435
2437 JSHeapBroker* broker) const {
2438 if (!object()->IsApiFunction()) return {};
2439 return TryMakeRef(broker, object()->api_func_data());
2440}
2441
2443 return object()->scope_info()->ContextHeaderLength();
2444}
2445
2447 return object()->scope_info()->ParametersStartIndex();
2448}
2449
2453
2455 DirectHandle<Map> map_handle = Cast<Map>(map(broker).object());
2456 // Note: implemented as an acquire-load.
2457 if (!map_handle->is_prototype_map()) return {};
2458
2459 DirectHandle<Object> maybe_proto_info = broker->CanonicalPersistentHandle(
2460 map_handle->prototype_info(kAcquireLoad));
2461 if (!IsPrototypeInfo(*maybe_proto_info)) return {};
2462
2463 Tagged<MaybeObject> maybe_object_create_map =
2464 Cast<PrototypeInfo>(maybe_proto_info)->ObjectCreateMap(kAcquireLoad);
2465 if (!maybe_object_create_map.IsWeak()) return {};
2466
2467 return MapRef(broker->GetOrCreateData(
2468 maybe_object_create_map.GetHeapObjectAssumeWeak(), kAssumeMemoryFence));
2469}
2470
2472 if (data_->should_access_heap()) return true;
2475 return data()->AsPropertyCell()->Cache(broker);
2476}
2477
2479 ObjectRef proxy_proto =
2480 global_proxy_object(broker).map(broker).prototype(broker);
2481 return !proxy_proto.equals(global_object(broker));
2482}
2483
2485 NameRef name) const {
2486 std::optional<Tagged<PropertyCell>> maybe_cell =
2488 broker->isolate(), broker->local_isolate_or_isolate(),
2489 broker->target_native_context().global_object(broker).object(),
2490 name.object());
2491 if (!maybe_cell.has_value()) return {};
2492 return TryMakeRef(broker, *maybe_cell);
2493}
2494
2495std::ostream& operator<<(std::ostream& os, ObjectRef ref) {
2496 if (!v8_flags.concurrent_recompilation) {
2497 // We cannot be in a background thread so it's safe to read the heap.
2498 AllowHandleDereference allow_handle_dereference;
2499 return os << ref.data() << " {" << ref.object() << "}";
2500 } else if (ref.data_->should_access_heap()) {
2501 return os << ref.data() << " {" << ref.object() << "}";
2502 } else {
2503 return os << ref.data();
2504 }
2505}
2506
2508 Tagged<Code> code = *object();
2509 const unsigned value = code->inlined_bytecode_size();
2510 if (value != 0 && code->marked_for_deoptimization()) {
2511 // Don't report inlined bytecode size if the code object was already
2512 // deoptimized.
2513 return 0;
2514 }
2515 return value;
2516}
2517
2518#undef BIMODAL_ACCESSOR
2519#undef BIMODAL_ACCESSOR_B
2520#undef BIMODAL_ACCESSOR_C
2521#undef HEAP_ACCESSOR_B
2522#undef HEAP_ACCESSOR_C
2523#undef IF_ACCESS_FROM_HEAP
2524#undef IF_ACCESS_FROM_HEAP_C
2525#undef TRACE
2526#undef TRACE_MISSING
2527
2528} // namespace compiler
2529} // namespace internal
2530} // namespace v8
friend Zone
Definition asm-types.cc:195
uint8_t data_[MAX_STACK_LENGTH]
union v8::internal::@341::BuiltinMetadata::KindSpecificData data
Builtins::Kind kind
Definition builtins.cc:40
#define SBXCHECK_EQ(lhs, rhs)
Definition check.h:62
static V8_EXPORT_PRIVATE std::optional< Tagged< Object > > TryGetOwnCowElement(Isolate *isolate, Tagged< FixedArray > array_elements, ElementsKind elements_kind, int array_length, size_t index)
Definition lookup.cc:1492
static V8_EXPORT_PRIVATE Result TryGetOwnChar(Tagged< String > *result_out, Isolate *isolate, LocalIsolate *local_isolate, Tagged< String > string, size_t index)
Definition lookup.cc:1601
static V8_EXPORT_PRIVATE Result TryGetOwnConstantElement(Tagged< Object > *result_out, Isolate *isolate, LocalIsolate *local_isolate, Tagged< JSObject > holder, Tagged< FixedArrayBase > elements, ElementsKind elements_kind, size_t index)
Definition lookup.cc:1537
static V8_EXPORT_PRIVATE std::optional< Tagged< PropertyCell > > TryGetPropertyCell(Isolate *isolate, LocalIsolate *local_isolate, DirectHandle< JSGlobalObject > holder, DirectHandle< Name > name)
Definition lookup.cc:1638
static const int FIRST_FUNCTION_MAP_INDEX
Definition contexts.h:570
static const int LAST_FUNCTION_MAP_INDEX
Definition contexts.h:571
Isolate * isolate() const
Definition factory.h:1281
static FieldIndex ForDescriptor(Tagged< Map > map, InternalIndex descriptor_index)
static const int kFunctionOverloadEntrySize
Definition templates.h:255
static V8_INLINE bool InYoungGeneration(Tagged< Object > object)
constexpr int as_int() const
static Handle< Object > DictionaryPropertyAt(Isolate *isolate, DirectHandle< JSObject > object, InternalIndex dict_index)
static constexpr uint32_t kMaxElementIndex
Definition js-objects.h:924
static constexpr bool kOffHeapDataPtrEqualsExternalPointer
Isolate * GetMainThreadIsolateUnsafe() const
base::Mutex * shared_function_info_access()
static const int kNoSlackTracking
Definition map.h:349
static std::optional< Tagged< Map > > TryAsElementsKind(Isolate *isolate, DirectHandle< Map > map, ElementsKind kind, ConcurrencyMode cmode)
Definition map.cc:1152
static const int kNoConstructorFunctionIndex
Definition map.h:257
static bool ToArrayLength(Tagged< Object > obj, uint32_t *index)
static V8_EXPORT_PRIVATE bool BooleanValue(Tagged< Object > obj, IsolateT *isolate)
static bool FitsRepresentation(Tagged< Object > obj, Representation representation, bool allow_coercion=true)
static V8_EXPORT_PRIVATE bool IsActive(Isolate *isolate)
static bool CheckDataIsCompatible(PropertyDetails details, Tagged< Object > value)
Definition objects.cc:6525
PropertyCellType cell_type() const
static constexpr PropertyDetails Empty(PropertyCellType cell_type=PropertyCellType::kNoCell)
static V8_EXPORT_PRIVATE bool Contains(Address address)
static V8_EXPORT_PRIVATE bool SandboxSafeContains(Tagged< HeapObject > object)
static constexpr Representation Double()
constexpr bool IsDouble() const
constexpr bool IsWeak() const
Tagged< HeapObject > GetHeapObjectAssumeWeak() const
void TraverseTransitionTree(const TraverseCallback &callback)
void push_back(const T &value)
T * New(Args &&... args)
Definition zone.h:114
OptionalJSObjectRef boilerplate(JSHeapBroker *broker) const
ObjectRef nested_site(JSHeapBroker *broker) const
IndirectHandle< ArrayBoilerplateDescription > object() const
BigIntData(JSHeapBroker *broker, ObjectData **storage, IndirectHandle< BigInt > object, ObjectDataKind kind)
Definition heap-refs.cc:532
int64_t AsInt64(bool *lossless) const
Definition heap-refs.cc:539
int64_t AsInt64(bool *lossless) const
interpreter::Register incoming_new_target_or_generator_register() const
IndirectHandle< BytecodeArray > object() const
IndirectHandle< TrustedByteArray > SourcePositionTable(JSHeapBroker *broker) const
unsigned GetInlinedBytecodeSize() const
IndirectHandle< Code > object() const
void DependOnOwnConstantDataProperty(JSObjectRef holder, MapRef map, FieldIndex index, ObjectRef value)
void DependOnOwnConstantDictionaryProperty(JSObjectRef holder, InternalIndex index, ObjectRef value)
void DependOnOwnConstantDoubleProperty(JSObjectRef holder, MapRef map, FieldIndex index, Float64 value)
void DependOnOwnConstantElement(JSObjectRef holder, uint32_t index, ObjectRef element)
ContextRef previous(JSHeapBroker *broker, size_t *depth) const
Definition heap-refs.cc:986
OptionalObjectRef get(JSHeapBroker *broker, int index) const
IndirectHandle< Context > object() const
OptionalObjectRef TryGetSideData(JSHeapBroker *broker, int index) const
ScopeInfoRef scope_info(JSHeapBroker *broker) const
PropertyDetails GetPropertyDetails(InternalIndex descriptor_index) const
IndirectHandle< DescriptorArray > object() const
NameRef GetPropertyKey(JSHeapBroker *broker, InternalIndex descriptor_index) const
OptionalObjectRef GetStrongValue(JSHeapBroker *broker, InternalIndex descriptor_index) const
OptionalSharedFunctionInfoRef shared_function_info(JSHeapBroker *broker) const
OptionalFeedbackVectorRef feedback_vector(JSHeapBroker *broker) const
ObjectRef value(JSHeapBroker *broker) const
SharedFunctionInfoRef shared_function_info(JSHeapBroker *broker) const
FeedbackCellRef GetClosureFeedbackCell(JSHeapBroker *broker, int index) const
IndirectHandle< FeedbackVector > object() const
FixedArrayBaseData(JSHeapBroker *broker, ObjectData **storage, IndirectHandle< FixedArrayBase > object, ObjectDataKind kind)
Definition heap-refs.cc:914
IndirectHandle< FixedArrayBase > object() const
FixedArrayData(JSHeapBroker *broker, ObjectData **storage, IndirectHandle< FixedArray > object, ObjectDataKind kind)
Definition heap-refs.cc:927
OptionalObjectRef TryGet(JSHeapBroker *broker, int i) const
Float64 GetFromImmutableFixedDoubleArray(int i) const
ZoneVector< const CFunctionInfo * > c_signatures(JSHeapBroker *broker) const
HolderLookupResult LookupHolderOfExpectedType(JSHeapBroker *broker, MapRef receiver_map)
ZoneVector< Address > c_functions(JSHeapBroker *broker) const
IndirectHandle< FunctionTemplateInfo > object() const
Address callback(JSHeapBroker *broker) const
bool is_signature_undefined(JSHeapBroker *broker) const
OptionalObjectRef callback_data(JSHeapBroker *broker) const
std::optional< bool > TryGetBooleanValue(JSHeapBroker *broker) const
Definition heap-refs.cc:789
std::optional< bool > TryGetBooleanValueImpl(JSHeapBroker *broker) const
Definition heap-refs.cc:799
InstanceType GetMapInstanceType() const
Definition heap-refs.cc:824
HeapObjectData(JSHeapBroker *broker, ObjectData **storage, IndirectHandle< HeapObject > object, ObjectDataKind kind)
Definition heap-refs.cc:774
OptionalMapRef map_direct_read(JSHeapBroker *broker) const
HeapObjectType GetHeapObjectType(JSHeapBroker *broker) const
V8_EXPORT_PRIVATE MapRef map(JSHeapBroker *broker) const
JSArrayData(JSHeapBroker *broker, ObjectData **storage, IndirectHandle< JSArray > object, ObjectDataKind kind)
Definition heap-refs.cc:943
ObjectRef GetBoilerplateLength(JSHeapBroker *broker) const
OptionalObjectRef length_unsafe(JSHeapBroker *broker) const
OptionalObjectRef GetOwnCowElement(JSHeapBroker *broker, FixedArrayBaseRef elements_ref, uint32_t index) const
JSBoundFunctionData(JSHeapBroker *broker, ObjectData **storage, IndirectHandle< JSBoundFunction > object, ObjectDataKind kind)
Definition heap-refs.cc:429
ObjectRef bound_this(JSHeapBroker *broker) const
JSReceiverRef bound_target_function(JSHeapBroker *broker) const
FixedArrayRef bound_arguments(JSHeapBroker *broker) const
JSDataViewData(JSHeapBroker *broker, ObjectData **storage, IndirectHandle< JSDataView > object, ObjectDataKind kind)
Definition heap-refs.cc:414
bool has_used_field(UsedField used_field) const
Definition heap-refs.cc:499
void Cache(JSHeapBroker *broker)
Definition heap-refs.cc:624
void set_used_field(UsedField used_field)
Definition heap-refs.cc:502
bool IsConsistentWithHeapState(JSHeapBroker *broker) const
Definition heap-refs.cc:693
JSFunctionData(JSHeapBroker *broker, ObjectData **storage, IndirectHandle< JSFunction > object, ObjectDataKind kind)
Definition heap-refs.cc:437
ObjectData * instance_prototype() const
Definition heap-refs.cc:466
ObjectData * raw_feedback_cell() const
Definition heap-refs.cc:474
OptionalFeedbackVectorRef feedback_vector(JSHeapBroker *broker) const
OptionalCodeRef code(JSHeapBroker *broker) const
NativeContextRef native_context(JSHeapBroker *broker) const
int InitialMapInstanceSizeWithMinSlack(JSHeapBroker *broker) const
bool IsConsistentWithHeapState(JSHeapBroker *broker) const
Definition heap-refs.cc:769
IndirectHandle< JSFunction > object() const
JSGlobalObjectData(JSHeapBroker *broker, ObjectData **storage, IndirectHandle< JSGlobalObject > object, ObjectDataKind kind)
Definition heap-refs.cc:950
OptionalPropertyCellRef GetPropertyCell(JSHeapBroker *broker, NameRef name) const
JSGlobalProxyData(JSHeapBroker *broker, ObjectData **storage, IndirectHandle< JSGlobalProxy > object, ObjectDataKind kind)
Definition heap-refs.cc:957
static constexpr uint32_t kInitialRefsBucketCount
PtrComprCageBase cage_base() const
Handle< T > CanonicalPersistentHandle(Tagged< T > object)
CompilationDependencies * dependencies() const
ZoneUnorderedMap< FeedbackSource, ProcessedFeedback const *, FeedbackSource::Hash, FeedbackSource::Equal > feedback_
void InitializeAndStartSerializing(DirectHandle< NativeContext > native_context)
bool ObjectMayBeUninitialized(DirectHandle< Object > object) const
void SetTargetNativeContextRef(DirectHandle< NativeContext > native_context)
NativeContextRef target_native_context() const
bool IsArrayOrObjectPrototype(JSObjectRef object) const
ObjectData * TryGetOrCreateData(Handle< Object > object, GetOrCreateDataFlags flags={})
JSObjectData(JSHeapBroker *broker, ObjectData **storage, IndirectHandle< JSObject > object, ObjectDataKind kind)
Definition heap-refs.cc:283
OptionalObjectRef GetOwnFastConstantDataProperty(JSHeapBroker *broker, Representation field_representation, FieldIndex index, CompilationDependencies *dependencies) const
IndirectHandle< JSObject > object() const
OptionalMapRef GetObjectCreateMap(JSHeapBroker *broker) const
OptionalObjectRef GetOwnConstantElement(JSHeapBroker *broker, FixedArrayBaseRef elements_ref, uint32_t index, CompilationDependencies *dependencies) const
OptionalFixedArrayBaseRef elements(JSHeapBroker *broker, RelaxedLoadTag) const
OptionalObjectRef GetOwnDictionaryProperty(JSHeapBroker *broker, InternalIndex index, CompilationDependencies *dependencies) const
OptionalObjectRef RawInobjectPropertyAt(JSHeapBroker *broker, FieldIndex index) const
std::optional< Float64 > GetOwnFastConstantDoubleProperty(JSHeapBroker *broker, FieldIndex index, CompilationDependencies *dependencies) const
OptionalObjectRef raw_properties_or_hash(JSHeapBroker *broker) const
std::optional< Tagged< Object > > GetOwnConstantElementFromHeap(JSHeapBroker *broker, Tagged< FixedArrayBase > elements, ElementsKind elements_kind, uint32_t index) const
bool IsElementsTenured(FixedArrayBaseRef elements)
JSPrimitiveWrapperData(JSHeapBroker *broker, ObjectData **storage, IndirectHandle< JSPrimitiveWrapper > object, ObjectDataKind kind)
Definition heap-refs.cc:421
bool IsStringWrapper(JSHeapBroker *broker) const
JSReceiverData(JSHeapBroker *broker, ObjectData **storage, IndirectHandle< JSReceiver > object, ObjectDataKind kind)
Definition heap-refs.cc:276
JSTypedArrayData(JSHeapBroker *broker, ObjectData **storage, IndirectHandle< JSTypedArray > object, ObjectDataKind kind)
Definition heap-refs.cc:407
IndirectHandle< JSTypedArray > object() const
ElementsKind elements_kind(JSHeapBroker *broker) const
HeapObjectRef buffer(JSHeapBroker *broker) const
InstanceType instance_type() const
Definition heap-refs.cc:560
bool is_abandoned_prototype_map() const
Definition heap-refs.cc:569
MapData(JSHeapBroker *broker, ObjectData **storage, IndirectHandle< Map > object, ObjectDataKind kind)
Definition heap-refs.cc:874
bool supports_fast_array_resize(JSHeapBroker *broker) const
NameRef GetPropertyKey(JSHeapBroker *broker, InternalIndex descriptor_index) const
ObjectRef GetConstructor(JSHeapBroker *broker) const
PropertyDetails GetPropertyDetails(JSHeapBroker *broker, InternalIndex descriptor_index) const
DescriptorArrayRef instance_descriptors(JSHeapBroker *broker) const
IndirectHandle< Map > object() const
MapRef FindRootMap(JSHeapBroker *broker) const
int GetInObjectPropertiesStartInWords() const
int GetInObjectPropertyOffset(int index) const
bool IsFixedCowArrayMap(JSHeapBroker *broker) const
bool PrototypesElementsDoNotHaveAccessorsOrThrow(JSHeapBroker *broker, ZoneVector< MapRef > *prototype_maps)
HeapObjectRef prototype(JSHeapBroker *broker) const
InstanceType instance_type() const
HeapObjectRef GetBackPointer(JSHeapBroker *broker) const
OptionalObjectRef GetStrongValue(JSHeapBroker *broker, InternalIndex descriptor_number) const
OddballType oddball_type(JSHeapBroker *broker) const
ElementsKind elements_kind() const
MapRef FindFieldOwner(JSHeapBroker *broker, InternalIndex descriptor_index) const
FieldIndex GetFieldIndexFor(InternalIndex descriptor_index) const
bool supports_fast_array_iteration(JSHeapBroker *broker) const
bool IsInobjectSlackTrackingInProgress() const
bool IsBooleanMap(JSHeapBroker *broker) const
OptionalMapRef AsElementsKind(JSHeapBroker *broker, ElementsKind kind) const
OptionalJSFunctionRef GetConstructorFunction(JSHeapBroker *broker, MapRef map) const
MapRef GetFunctionMapFromIndex(JSHeapBroker *broker, int index) const
MapRef GetInitialJSArrayMap(JSHeapBroker *broker, ElementsKind kind) const
bool GlobalIsDetached(JSHeapBroker *broker) const
IndirectHandle< Object > object() const
Definition heap-refs.cc:124
IndirectHandle< Object > const object_
Definition heap-refs.cc:139
ObjectData(JSHeapBroker *broker, ObjectData **storage, IndirectHandle< Object > object, ObjectDataKind kind)
Definition heap-refs.cc:78
ObjectDataKind kind() const
Definition heap-refs.cc:125
PropertyDetails property_details() const
Definition heap-refs.cc:168
PropertyCellData(JSHeapBroker *broker, ObjectData **storage, IndirectHandle< PropertyCell > object, ObjectDataKind kind)
Definition heap-refs.cc:216
bool Cache(JSHeapBroker *broker)
Definition heap-refs.cc:221
V8_WARN_UNUSED_RESULT bool Cache(JSHeapBroker *broker) const
Entry * Lookup(const Address &key) const
Definition refs-map.cc:21
Entry * LookupOrInsert(const Address &key)
Definition refs-map.cc:25
StringRef source(JSHeapBroker *broker) const
HeapObjectRef data(JSHeapBroker *broker) const
IndirectHandle< RegExpBoilerplateDescription > object() const
ScriptContextTableData(JSHeapBroker *broker, ObjectData **storage, IndirectHandle< ScriptContextTable > object, ObjectDataKind kind)
Definition heap-refs.cc:935
bool HasBreakInfo(JSHeapBroker *broker) const
OptionalFunctionTemplateInfoRef function_template_info(JSHeapBroker *broker) const
SharedFunctionInfo::Inlineability GetInlineability(JSHeapBroker *broker) const
IndirectHandle< SharedFunctionInfo > object() const
ScopeInfoRef scope_info(JSHeapBroker *broker) const
OptionalObjectRef import_meta(JSHeapBroker *broker) const
OptionalCellRef GetCell(JSHeapBroker *broker, int cell_index) const
OptionalObjectRef GetCharAsStringOrUndefined(JSHeapBroker *broker, uint32_t index) const
std::optional< double > ToInt(JSHeapBroker *broker, int radix)
std::optional< uint16_t > GetFirstChar(JSHeapBroker *broker) const
std::optional< uint16_t > GetChar(JSHeapBroker *broker, uint32_t index) const
std::optional< Handle< String > > ObjectIfContentAccessible(JSHeapBroker *broker)
IndirectHandle< String > object() const
std::optional< double > ToNumber(JSHeapBroker *broker)
Handle< Code > code
const MapRef map_
JSHeapBroker *const broker_
JSHeapBroker * broker
#define CREATE_DATA(Name)
#define DEF_NATIVE_CONTEXT_ACCESSOR(ResultType, Name)
#define HEAP_ACCESSOR_C(holder, result, name)
#define DECLARE_AS(Name)
Definition heap-refs.cc:120
#define JSFUNCTION_BIMODAL_ACCESSOR_WITH_DEP_RELEVANT_C( Result, Name, UsedField, RelevantValue)
#define JSFUNCTION_BIMODAL_ACCESSOR_WITH_DEP(Result, Name, UsedField)
#define IF_ACCESS_FROM_HEAP_C(name)
#define BIMODAL_ACCESSOR(holder, result, name)
#define HEAP_ACCESSOR_B(holder, field, name, BitField)
#define DEF_SFI_ACCESSOR(type, name)
#define DEFINE_IS_AND_AS(Name)
#define BIMODAL_ACCESSOR_C(holder, result, name)
#define DEF_OBJECT_GETTER(T)
#define DEFINE_IS(Name)
Definition heap-refs.cc:962
#define BIMODAL_ACCESSOR_B(holder, field, name, BitField)
#define DEFINE_AS(Name)
Definition heap-refs.cc:975
#define DEF_TESTER(Type,...)
#define IF_HOLE_THEN_RETURN(Name, name, Root)
#define DECLARE_IS(Name)
Definition heap-refs.cc:116
#define HEAP_BROKER_OBJECT_LIST(V)
Definition heap-refs.h:152
#define HEAP_BROKER_BACKGROUND_SERIALIZED_OBJECT_LIST(V)
Definition heap-refs.h:154
#define BROKER_SFI_FIELDS(V)
Definition heap-refs.h:1101
#define BROKER_NATIVE_CONTEXT_FIELDS(V)
Definition heap-refs.h:723
#define INSTANCE_TYPE_CHECKERS(V)
int32_t offset
TNode< Context > context
TNode< Object > receiver
std::map< const std::string, const std::string > map
#define TRACE_BROKER_MISSING(broker, x)
ZoneVector< RpoNumber > & result
#define TRACE(...)
InstructionOperand source
int m
Definition mul-fft.cc:294
V8_INLINE constexpr bool IsThinString(InstanceType instance_type)
V8_INLINE constexpr bool IsTwoByteString(InstanceType instance_type)
true JSFunctionData::kInitialMap raw_feedback_cell
Map::Bits3::NumberOfOwnDescriptorsBits Map::Bits3::ConstructionCounterBits is_access_check_needed
base::Flags< GetOrCreateDataFlag > GetOrCreateDataFlags
Map::Bits3::NumberOfOwnDescriptorsBits Map::Bits3::ConstructionCounterBits bit_field
ref_traits< T >::ref_type MakeRefAssumeMemoryFence(JSHeapBroker *broker, Tagged< T > object)
OptionalRef< typename ref_traits< T >::ref_type > TryMakeRef(JSHeapBroker *broker, ObjectData *data)
std::ostream & operator<<(std::ostream &os, AccessMode access_mode)
Map::Bits3::NumberOfOwnDescriptorsBits construction_counter
ref_traits< T >::ref_type MakeRef(JSHeapBroker *broker, Tagged< T > object)
std::optional< double > TryStringToDouble(LocalIsolate *isolate, DirectHandle< String > object, uint32_t max_length_for_conversion)
PerThreadAssertScopeDebugOnly< false, SAFEPOINTS_ASSERT, HEAP_ALLOCATION_ASSERT > DisallowGarbageCollection
Map::Bits1::HasPrototypeSlotBit Map::Bits1::HasNamedInterceptorBit Map::Bits1::IsUndetectableBit Map::Bits1::IsConstructorBit bit_field2
Definition map-inl.h:123
bool IsFastOrNonextensibleOrSealedElementsKind(ElementsKind kind)
bool IsTypedArrayElementsKind(ElementsKind kind)
bool IsRabGsabTypedArrayElementsKind(ElementsKind kind)
Tagged(T object) -> Tagged< T >
V8_INLINE constexpr bool IsSmi(TaggedImpl< kRefType, StorageType > obj)
Definition objects.h:665
kInterpreterTrampolineOffset Tagged< HeapObject >
kStaticElementsTemplateOffset kInstancePropertiesTemplateOffset Tagged< FixedArray >
@ SLOW_STRING_WRAPPER_ELEMENTS
@ FAST_STRING_WRAPPER_ELEMENTS
Flag flags[]
Definition flags.cc:3797
Map::Bits1::HasPrototypeSlotBit Map::Bits1::HasNamedInterceptorBit is_undetectable
Definition map-inl.h:113
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 allocation gc speed threshold for starting incremental marking via a task in percent of available threshold for starting incremental marking immediately in percent of available Use a single schedule for determining a marking schedule between JS and C objects schedules the minor GC task with kUserVisible priority max worker number of concurrent for NumberOfWorkerThreads start background threads that allocate memory concurrent_array_buffer_sweeping use parallel threads to clear weak refs in the atomic pause trace progress of the incremental marking trace object counts and memory usage report a tick only when allocated zone memory changes by this amount TracingFlags::gc_stats TracingFlags::gc_stats track native contexts that are expected to be garbage collected verify heap pointers before and after GC memory reducer runs GC with ReduceMemoryFootprint flag Maximum number of memory reducer GCs scheduled Old gen GC speed is computed directly from gc tracer counters Perform compaction on full GCs based on V8 s default heuristics Perform compaction on every full GC Perform code space compaction when finalizing a full GC with stack Stress GC compaction to flush out bugs with moving objects flush of baseline code when it has not been executed recently Use time base code flushing instead of age Use a progress bar to scan large objects in increments when incremental marking is active force incremental marking for small heaps and run it more often force marking at random points between and force scavenge at random points between and reclaim otherwise unreachable unmodified wrapper objects when possible less compaction in non memory reducing mode use high priority threads for concurrent Marking Test mode only flag It allows an unit test to select evacuation candidates use incremental marking for CppHeap cppheap_concurrent_marking c value for membalancer A special constant to balance between memory and space tradeoff The smaller the more memory it uses enable use of SSE4 instructions if available enable use of AVX VNNI instructions if available enable use of POPCNT instruction if available force all emitted branches to be in long mode(MIPS/PPC only)") DEFINE_BOOL(partial_constant_pool
bool IsNullOrUndefined(Tagged< Object > obj, Isolate *isolate)
bool IsSmiOrObjectElementsKind(ElementsKind kind)
constexpr int kSystemPointerSize
Definition globals.h:410
Handle< T > IndirectHandle
Definition globals.h:1086
instance_descriptors
Definition map-inl.h:52
DONT_OVERRIDE DISABLE_ALLOCATION_SITES HOLEY_ELEMENTS
Map::Bits1::HasPrototypeSlotBit Map::Bits1::HasNamedInterceptorBit Map::Bits1::IsUndetectableBit Map::Bits1::IsConstructorBit Map::Bits2::IsImmutablePrototypeBit is_deprecated
Definition map-inl.h:129
bool IsFastElementsKind(ElementsKind kind)
DONT_OVERRIDE DISABLE_ALLOCATION_SITES DISABLE_ALLOCATION_SITES HOLEY_DOUBLE_ELEMENTS
V8_INLINE constexpr bool IsHeapObject(TaggedImpl< kRefType, StorageType > obj)
Definition objects.h:669
V8_EXPORT_PRIVATE FlagValues v8_flags
return value
Definition map-inl.h:893
constexpr bool Is64()
std::optional< double > TryStringToInt(LocalIsolate *isolate, DirectHandle< String > object, int radix)
bool IsStringWrapperElementsKind(ElementsKind kind)
kInstanceDescriptorsOffset kTransitionsOrPrototypeInfoOffset IsNull(value)||IsJSProxy(value)||IsWasmObject(value)||(IsJSObject(value) &&(HeapLayout
Definition map-inl.h:70
kInstanceDescriptorsOffset kTransitionsOrPrototypeInfoOffset prototype
Definition map-inl.h:69
allowed_receiver_instance_type_range_end
!IsContextMap !IsContextMap native_context
Definition map-inl.h:877
Tagged< To > Cast(Tagged< From > value, const v8::SourceLocation &loc=INIT_SOURCE_LOCATION_IN_DEBUG)
Definition casting.h:150
Maybe< T > Nothing()
Definition v8-maybe.h:112
static constexpr RelaxedLoadTag kRelaxedLoad
Definition globals.h:2909
T ToCData(i::Isolate *isolate, v8::internal::Tagged< v8::internal::Object > obj)
Definition api-inl.h:23
static constexpr AcquireLoadTag kAcquireLoad
Definition globals.h:2908
Maybe< T > Just(const T &t)
Definition v8-maybe.h:117
#define HOLE_LIST(V)
uint32_t equals
base::Vector< const char > contents
#define DCHECK_LE(v1, v2)
Definition logging.h:490
#define CHECK_GE(lhs, rhs)
#define DCHECK_NULL(val)
Definition logging.h:491
#define CHECK_IMPLIES(lhs, rhs)
#define CHECK(condition)
Definition logging.h:124
#define CHECK_GT(lhs, rhs)
#define CHECK_LT(lhs, rhs)
#define CHECK_LE(lhs, rhs)
#define CHECK_WITH_MSG(condition, message)
Definition logging.h:118
#define DCHECK_NOT_NULL(val)
Definition logging.h:492
#define DCHECK_IMPLIES(v1, v2)
Definition logging.h:493
#define CHECK_NE(lhs, rhs)
#define DCHECK_GE(v1, v2)
Definition logging.h:488
#define CHECK_EQ(lhs, rhs)
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_EQ(v1, v2)
Definition logging.h:485
#define USE(...)
Definition macros.h:293
#define V8_NOINLINE
Definition v8config.h:586