Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion common.gypi
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@

# Reset this number to 0 on major V8 upgrades.
# Increment by one for each non-official patch applied to deps/v8.
'v8_embedder_string': '-node.53',
'v8_embedder_string': '-node.55',

##### V8 defaults for Node.js #####

Expand Down
56 changes: 36 additions & 20 deletions deps/v8/src/compiler/heap-refs.cc
Original file line number Diff line number Diff line change
Expand Up @@ -839,34 +839,33 @@ InstanceType HeapObjectData::GetMapInstanceType() const {

namespace {

bool IsReadOnlyLengthDescriptor(Isolate* isolate,
DirectHandle<Map> jsarray_map) {
DCHECK(!jsarray_map->is_dictionary_map());
Tagged<DescriptorArray> descriptors =
jsarray_map->instance_descriptors(isolate, kRelaxedLoad);
bool IsReadOnlyLengthDescriptor(JSHeapBroker* broker, MapRef jsarray_map) {
DCHECK(!jsarray_map.is_dictionary_map());
DescriptorArrayRef descriptors = jsarray_map.instance_descriptors(broker);
static_assert(
JSArray::kLengthOffset == JSObject::kHeaderSize,
"The length should be the first property on the descriptor array");
InternalIndex offset(0);
return descriptors->GetDetails(offset).IsReadOnly();
return descriptors.GetPropertyDetails(offset).IsReadOnly();
}

// Important: this predicate does not check Protectors::IsNoElementsIntact. The
// compiler checks protectors through the compilation dependency mechanism; it
// doesn't make sense to do that here as part of every MapData construction.
// Callers *must* take care to take the correct dependency themselves.
bool SupportsFastArrayIteration(JSHeapBroker* broker, DirectHandle<Map> map) {
return map->instance_type() == JS_ARRAY_TYPE &&
IsFastElementsKind(map->elements_kind()) &&
IsJSArray(map->prototype()) &&
broker->IsArrayOrObjectPrototype(broker->CanonicalPersistentHandle(
Cast<JSArray>(map->prototype())));
bool SupportsFastArrayIteration(JSHeapBroker* broker, MapRef map) {
if (map.instance_type() != JS_ARRAY_TYPE ||
!IsFastElementsKind(map.elements_kind())) {
return false;
}
HeapObjectRef prototype = map.prototype(broker);
return prototype.IsJSArray() &&
prototype.AsJSArray().IsArrayOrObjectPrototype(broker);
}

bool SupportsFastArrayResize(JSHeapBroker* broker, DirectHandle<Map> map) {
return SupportsFastArrayIteration(broker, map) && map->is_extensible() &&
!map->is_dictionary_map() &&
!IsReadOnlyLengthDescriptor(broker->isolate(), map);
bool SupportsFastArrayResize(JSHeapBroker* broker, MapRef map) {
return SupportsFastArrayIteration(broker, map) && map.is_extensible() &&
!map.is_dictionary_map() && !IsReadOnlyLengthDescriptor(broker, map);
}

} // namespace
Expand Down Expand Up @@ -1039,8 +1038,6 @@ void JSHeapBroker::InitializeAndStartSerializing(
refs_ =
zone()->New<RefsMap>(kInitialRefsBucketCount, AddressMatcher(), zone());

CollectArrayAndObjectPrototypes();

SetTargetNativeContextRef(target_native_context);
}

Expand Down Expand Up @@ -1250,11 +1247,11 @@ bool MapRef::PrototypesElementsDoNotHaveAccessorsOrThrow(
}

bool MapRef::supports_fast_array_iteration(JSHeapBroker* broker) const {
return SupportsFastArrayIteration(broker, object());
return SupportsFastArrayIteration(broker, *this);
}

bool MapRef::supports_fast_array_resize(JSHeapBroker* broker) const {
return SupportsFastArrayResize(broker, object());
return SupportsFastArrayResize(broker, *this);
}

namespace {
Expand Down Expand Up @@ -1626,6 +1623,7 @@ HEAP_ACCESSOR_B(Map, bit_field3, NumberOfOwnDescriptors,
Map::Bits3::NumberOfOwnDescriptorsBits)
HEAP_ACCESSOR_B(Map, bit_field3, is_migration_target,
Map::Bits3::IsMigrationTargetBit)
BIMODAL_ACCESSOR_B(Map, bit_field3, is_extensible, Map::Bits3::IsExtensibleBit)
BIMODAL_ACCESSOR_B(Map, bit_field3, construction_counter,
Map::Bits3::ConstructionCounterBits)
HEAP_ACCESSOR_B(Map, bit_field, has_prototype_slot,
Expand Down Expand Up @@ -1807,6 +1805,11 @@ ObjectRef MapRef::GetConstructor(JSHeapBroker* broker) const {
return MakeRefAssumeMemoryFence(broker, object()->GetConstructor());
}

NativeContextRef MapRef::native_context(JSHeapBroker* broker) const {
// Immutable after initialization.
return MakeRefAssumeMemoryFence(broker, object()->native_context());
}

HeapObjectRef MapRef::GetBackPointer(JSHeapBroker* broker) const {
// Immutable after initialization.
return MakeRefAssumeMemoryFence(broker,
Expand Down Expand Up @@ -2461,6 +2464,19 @@ OptionalMapRef JSObjectRef::GetObjectCreateMap(JSHeapBroker* broker) const {
maybe_object_create_map.GetHeapObjectAssumeWeak(), kAssumeMemoryFence));
}

bool JSObjectRef::IsArrayOrObjectPrototype(JSHeapBroker* broker) const {
MapRef map = this->map(broker);
if (map.instance_type() == JS_OBJECT_PROTOTYPE_TYPE) return true;
// Keep in sync with Isolate::IsInCreationContext:
MapRef metamap = map.map(broker);
// Filter out native-context independent objects.
if (*metamap.object() == ReadOnlyRoots(broker->isolate()).meta_map())
return false;
OptionalNativeContextRef native_context = metamap.native_context(broker);
if (!native_context.has_value()) return false;
return native_context->initial_array_prototype(broker).equals(*this);
}

bool PropertyCellRef::Cache(JSHeapBroker* broker) const {
if (data_->should_access_heap()) return true;
CHECK(broker->mode() == JSHeapBroker::kSerializing ||
Expand Down
6 changes: 6 additions & 0 deletions deps/v8/src/compiler/heap-refs.h
Original file line number Diff line number Diff line change
Expand Up @@ -623,6 +623,10 @@ class JSObjectRef : public JSReceiverRef {
bool IsElementsTenured(FixedArrayBaseRef elements);

OptionalMapRef GetObjectCreateMap(JSHeapBroker* broker) const;

// Check if this object is its creation context's %ArrayPrototype% or
// %ObjectPrototype%.
bool IsArrayOrObjectPrototype(JSHeapBroker* broker) const;
};

class JSDataViewRef : public JSObjectRef {
Expand Down Expand Up @@ -899,6 +903,7 @@ class V8_EXPORT_PRIVATE MapRef : public HeapObjectRef {
bool has_indexed_interceptor() const;
int construction_counter() const;
bool is_migration_target() const;
bool is_extensible() const;
bool supports_fast_array_iteration(JSHeapBroker* broker) const;
bool supports_fast_array_resize(JSHeapBroker* broker) const;
bool is_abandoned_prototype_map() const;
Expand Down Expand Up @@ -940,6 +945,7 @@ class V8_EXPORT_PRIVATE MapRef : public HeapObjectRef {

MapRef FindRootMap(JSHeapBroker* broker) const;
ObjectRef GetConstructor(JSHeapBroker* broker) const;
NativeContextRef native_context(JSHeapBroker* broker) const;
};

struct HolderLookupResult {
Expand Down
38 changes: 0 additions & 38 deletions deps/v8/src/compiler/js-heap-broker.cc
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ JSHeapBroker::JSHeapBroker(Isolate* isolate, Zone* broker_zone,
refs_(zone()->New<RefsMap>(kMinimalRefsBucketCount, AddressMatcher(),
zone())),
root_index_map_(isolate),
array_and_object_prototypes_(zone()),
tracing_enabled_(tracing_enabled),
code_kind_(code_kind),
feedback_(zone()),
Expand Down Expand Up @@ -118,28 +117,6 @@ void JSHeapBroker::SetTargetNativeContextRef(
target_native_context_ = MakeRef(this, *native_context);
}

void JSHeapBroker::CollectArrayAndObjectPrototypes() {
DisallowGarbageCollection no_gc;
CHECK_EQ(mode(), kSerializing);
CHECK(array_and_object_prototypes_.empty());

Tagged<Object> maybe_context = isolate()->heap()->native_contexts_list();
while (!IsUndefined(maybe_context, isolate())) {
Tagged<Context> context = Cast<Context>(maybe_context);
Tagged<Object> array_prot =
context->get(Context::INITIAL_ARRAY_PROTOTYPE_INDEX);
Tagged<Object> object_prot =
context->get(Context::INITIAL_OBJECT_PROTOTYPE_INDEX);
array_and_object_prototypes_.emplace(
CanonicalPersistentHandle(Cast<JSObject>(array_prot)));
array_and_object_prototypes_.emplace(
CanonicalPersistentHandle(Cast<JSObject>(object_prot)));
maybe_context = context->next_context_link();
}

CHECK(!array_and_object_prototypes_.empty());
}

StringRef JSHeapBroker::GetTypedArrayStringTag(ElementsKind kind) {
DCHECK(IsTypedArrayOrRabGsabTypedArrayElementsKind(kind));
switch (kind) {
Expand All @@ -154,21 +131,6 @@ StringRef JSHeapBroker::GetTypedArrayStringTag(ElementsKind kind) {
}
}

bool JSHeapBroker::IsArrayOrObjectPrototype(JSObjectRef object) const {
return IsArrayOrObjectPrototype(object.object());
}

bool JSHeapBroker::IsArrayOrObjectPrototype(Handle<JSObject> object) const {
if (mode() == kDisabled) {
return isolate()->IsInCreationContext(
*object, Context::INITIAL_ARRAY_PROTOTYPE_INDEX) ||
object->map(isolate_)->instance_type() == JS_OBJECT_PROTOTYPE_TYPE;
}
CHECK(!array_and_object_prototypes_.empty());
return array_and_object_prototypes_.find(object) !=
array_and_object_prototypes_.end();
}

ObjectData* JSHeapBroker::TryGetOrCreateData(Tagged<Object> object,
GetOrCreateDataFlags flags) {
return TryGetOrCreateData(CanonicalPersistentHandle(object), flags);
Expand Down
21 changes: 5 additions & 16 deletions deps/v8/src/compiler/js-heap-broker.h
Original file line number Diff line number Diff line change
Expand Up @@ -192,11 +192,6 @@ class V8_EXPORT_PRIVATE JSHeapBroker {
ObjectData* TryGetOrCreateData(Tagged<Object> object,
GetOrCreateDataFlags flags = {});

// Check if {object} is any native context's %ArrayPrototype% or
// %ObjectPrototype%.
bool IsArrayOrObjectPrototype(JSObjectRef object) const;
bool IsArrayOrObjectPrototype(Handle<JSObject> object) const;

bool HasFeedback(FeedbackSource const& source) const;
void SetFeedback(FeedbackSource const& source,
ProcessedFeedback const* feedback);
Expand Down Expand Up @@ -285,12 +280,11 @@ class V8_EXPORT_PRIVATE JSHeapBroker {
if (Tagged<HeapObject> heap_object;
TryCast<HeapObject>(object, &heap_object)) {
RootIndex root_index;
// CollectArrayAndObjectPrototypes calls this function often with T equal
// to JSObject. The root index map only contains immortal, immutable
// objects; it never contains any instances of type JSObject, since
// JSObjects must exist within a NativeContext, and NativeContexts can be
// created and destroyed. Thus, we can skip the lookup in the root index
// map for those values and save a little time.
// The root index map only contains immortal, immutable objects; it never
// contains any instances of type JSObject, since JSObjects must exist
// within a NativeContext, and NativeContexts can be created and
// destroyed. Thus, we can skip the lookup in the root index map for those
// values and save a little time.
if constexpr (std::is_convertible_v<T, JSObject>) {
DCHECK(!root_index_map_.Lookup(heap_object, &root_index));
} else if (root_index_map_.Lookup(heap_object, &root_index)) {
Expand Down Expand Up @@ -428,8 +422,6 @@ class V8_EXPORT_PRIVATE JSHeapBroker {
ProcessedFeedback const& ReadFeedbackForTemplateObject(
FeedbackSource const& source);

void CollectArrayAndObjectPrototypes();

void set_persistent_handles(
std::unique_ptr<PersistentHandles> persistent_handles) {
DCHECK_NULL(ph_);
Expand Down Expand Up @@ -457,9 +449,6 @@ class V8_EXPORT_PRIVATE JSHeapBroker {
OptionalNativeContextRef target_native_context_;
RefsMap* refs_;
RootIndexMap root_index_map_;
ZoneUnorderedSet<IndirectHandle<JSObject>, IndirectHandle<JSObject>::hash,
IndirectHandle<JSObject>::equal_to>
array_and_object_prototypes_;
BrokerMode mode_ = kDisabled;
bool const tracing_enabled_;
CodeKind const code_kind_;
Expand Down
2 changes: 1 addition & 1 deletion deps/v8/src/compiler/js-native-context-specialization.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4245,7 +4245,7 @@ bool JSNativeContextSpecialization::CanTreatHoleAsUndefined(
for (MapRef receiver_map : receiver_maps) {
ObjectRef receiver_prototype = receiver_map.prototype(broker());
if (!receiver_prototype.IsJSObject() ||
!broker()->IsArrayOrObjectPrototype(receiver_prototype.AsJSObject())) {
!receiver_prototype.AsJSObject().IsArrayOrObjectPrototype(broker())) {
return false;
}
}
Expand Down
2 changes: 1 addition & 1 deletion deps/v8/src/compiler/node-properties.cc
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,7 @@ NodeProperties::InferMapsResult NodeProperties::InferMapsUnsafe(
// TODO(bmeurer): This can be removed once the Array.prototype and
// Object.prototype have NO_ELEMENTS elements kind.
if (!ref.IsJSObject() ||
!broker->IsArrayOrObjectPrototype(ref.AsJSObject())) {
!ref.AsJSObject().IsArrayOrObjectPrototype(broker)) {
if (ref.map(broker).is_stable()) {
// The {receiver_map} is only reliable when we install a stability
// code dependency.
Expand Down
2 changes: 1 addition & 1 deletion deps/v8/src/maglev/maglev-graph-builder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5594,7 +5594,7 @@ bool MaglevGraphBuilder::CanTreatHoleAsUndefined(
for (compiler::MapRef receiver_map : receiver_maps) {
compiler::ObjectRef receiver_prototype = receiver_map.prototype(broker());
if (!receiver_prototype.IsJSObject() ||
!broker()->IsArrayOrObjectPrototype(receiver_prototype.AsJSObject())) {
!receiver_prototype.AsJSObject().IsArrayOrObjectPrototype(broker())) {
return false;
}
}
Expand Down
Loading