From c37daa736b07a7eff85fc9ff0f1ca7495cf97d97 Mon Sep 17 00:00:00 2001 From: Keeley Hammond Date: Thu, 22 Jan 2026 15:04:41 -0800 Subject: [PATCH] chore: cherry-pick dba49550b12d from v8 (#49487) * chore: cherry-pick dba49550b12d from v8 * chore: update patch --- patches/v8/.patches | 1 + patches/v8/cherry-pick-dba49550b12d.patch | 270 ++++++++++++++++++++++ 2 files changed, 271 insertions(+) create mode 100644 patches/v8/cherry-pick-dba49550b12d.patch diff --git a/patches/v8/.patches b/patches/v8/.patches index dc98544242..a49be882f5 100644 --- a/patches/v8/.patches +++ b/patches/v8/.patches @@ -1 +1,2 @@ chore_allow_customizing_microtask_policy_per_context.patch +cherry-pick-dba49550b12d.patch diff --git a/patches/v8/cherry-pick-dba49550b12d.patch b/patches/v8/cherry-pick-dba49550b12d.patch new file mode 100644 index 0000000000..9b2a5695eb --- /dev/null +++ b/patches/v8/cherry-pick-dba49550b12d.patch @@ -0,0 +1,270 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Olivier=20Fl=C3=BCckiger?= +Date: Mon, 12 Jan 2026 15:41:30 +0100 +Subject: Merged: [map] Fix publishing of integrity-level transitions +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Integrity level transition target maps should not be published to the +map tree before they are fully initialized. Otherwise concurrent access +might pick up not fully updated target maps. + +Drive-By: Fix a dcheck in the map-updater to not fire when an indirectly +reachable non-deprecatable map is deprecated due to the whole subtree +being deprecated. + +Fixed: 473851441 +(cherry picked from commit e7f117bdb2fb4acbe619cf26aae2e011bf7f0e25) + +Change-Id: I8530281a55bbeed1dd158a126bad807029bf47ae +Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/7485546 +Bot-Commit: Rubber Stamper +Commit-Queue: Rubber Stamper +Auto-Submit: Olivier Flückiger +Cr-Commit-Position: refs/branch-heads/14.4@{#40} +Cr-Branched-From: 80acc26727d5a34e77dabeebe7c9213ec1bd4768-refs/heads/14.4.258@{#1} +Cr-Branched-From: ce7e597e90f6df3fa4b6df224bc613b80c635450-refs/heads/main@{#104020} + +diff --git a/src/objects/map.cc b/src/objects/map.cc +index 1428c1c5cc3a6809c99400b5eb1e800087d721b8..c316181c7e3ad8ad21177f1e1b7e2420d4a5f7f3 100644 +--- a/src/objects/map.cc ++++ b/src/objects/map.cc +@@ -646,20 +646,25 @@ Map::FieldCounts Map::GetFieldCounts() const { + } + + void Map::DeprecateTransitionTree(Isolate* isolate) { ++ DCHECK(CanBeDeprecated()); ++ return DeprecateTransitionTreeImpl(isolate); ++} ++ ++void Map::DeprecateTransitionTreeImpl(Isolate* isolate) { + if (is_deprecated()) return; + DisallowGarbageCollection no_gc; + ReadOnlyRoots roots(isolate); + TransitionsAccessor transitions(isolate, *this); + transitions.ForEachTransition( +- &no_gc, [&](Tagged map) { map->DeprecateTransitionTree(isolate); }, ++ &no_gc, ++ [&](Tagged map) { map->DeprecateTransitionTreeImpl(isolate); }, + [&](Tagged map) { + if (v8_flags.move_prototype_transitions_first) { +- map->DeprecateTransitionTree(isolate); ++ map->DeprecateTransitionTreeImpl(isolate); + } + }, + nullptr); + DCHECK(!IsFunctionTemplateInfo(constructor_or_back_pointer())); +- DCHECK(CanBeDeprecated()); + set_is_deprecated(true); + if (v8_flags.log_maps) { + LOG(isolate, MapEvent("Deprecate", direct_handle(*this, isolate), {})); +@@ -1574,6 +1579,22 @@ Handle Map::CopyReplaceDescriptors( + DirectHandle descriptors, TransitionFlag flag, + MaybeDirectHandle maybe_name, const char* reason, + TransitionKindFlag transition_kind) { ++ // Special transitions need to pass an InitMap function to initialize the map ++ // before inserting it into the transition tree. ++ CHECK_IMPLIES(flag == INSERT_TRANSITION, ++ transition_kind == PROPERTY_TRANSITION || ++ transition_kind == SIMPLE_PROPERTY_TRANSITION); ++ return CopyReplaceDescriptors( ++ isolate, map, descriptors, flag, [&](Handle) {}, maybe_name, reason, ++ transition_kind); ++} ++ ++template ++Handle Map::CopyReplaceDescriptors( ++ Isolate* isolate, DirectHandle map, ++ DirectHandle descriptors, TransitionFlag flag, ++ const InitMapCb& InitMap, MaybeDirectHandle maybe_name, ++ const char* reason, TransitionKindFlag transition_kind) { + DCHECK(descriptors->IsSortedNoDuplicates()); + + Handle result = CopyDropDescriptors(isolate, map); +@@ -1585,15 +1606,16 @@ Handle Map::CopyReplaceDescriptors( + result->set_may_have_interesting_properties(true); + } + ++ bool insert_transition = false; + if (map->is_prototype_map()) { + result->InitializeDescriptors(isolate, *descriptors); + } else { + if (flag == INSERT_TRANSITION && + TransitionsAccessor::CanHaveMoreTransitions(isolate, map)) { ++ insert_transition = true; + result->InitializeDescriptors(isolate, *descriptors); + + DCHECK(!maybe_name.is_null()); +- ConnectTransition(isolate, map, result, name, transition_kind); + is_connected = true; + } else if ((transition_kind == PROTOTYPE_TRANSITION && + v8_flags.move_prototype_transitions_first) || +@@ -1611,6 +1633,10 @@ Handle Map::CopyReplaceDescriptors( + result->InitializeDescriptors(isolate, *descriptors); + } + } ++ InitMap(result); ++ if (insert_transition) { ++ ConnectTransition(isolate, map, result, name, transition_kind); ++ } + if (v8_flags.log_maps && !is_connected) { + LOG(isolate, + MapEvent("ReplaceDescriptors", map, result, reason, +@@ -1866,68 +1892,70 @@ Handle Map::CopyForPreventExtensions( + DescriptorArray::CopyUpToAddAttributes( + isolate, direct_handle(map->instance_descriptors(isolate), isolate), + num_descriptors, attrs_to_add); ++ ++ auto InitMap = [&](Handle new_map) { ++ new_map->set_is_extensible(false); ++ if (!IsTypedArrayOrRabGsabTypedArrayElementsKind(map->elements_kind())) { ++ ElementsKind new_kind = IsStringWrapperElementsKind(map->elements_kind()) ++ ? SLOW_STRING_WRAPPER_ELEMENTS ++ : DICTIONARY_ELEMENTS; ++ if (!old_map_is_dictionary_elements_kind) { ++ switch (map->elements_kind()) { ++ case PACKED_ELEMENTS: ++ if (attrs_to_add == SEALED) { ++ new_kind = PACKED_SEALED_ELEMENTS; ++ } else if (attrs_to_add == FROZEN) { ++ new_kind = PACKED_FROZEN_ELEMENTS; ++ } else { ++ new_kind = PACKED_NONEXTENSIBLE_ELEMENTS; ++ } ++ break; ++ case PACKED_NONEXTENSIBLE_ELEMENTS: ++ if (attrs_to_add == SEALED) { ++ new_kind = PACKED_SEALED_ELEMENTS; ++ } else if (attrs_to_add == FROZEN) { ++ new_kind = PACKED_FROZEN_ELEMENTS; ++ } ++ break; ++ case PACKED_SEALED_ELEMENTS: ++ if (attrs_to_add == FROZEN) { ++ new_kind = PACKED_FROZEN_ELEMENTS; ++ } ++ break; ++ case HOLEY_ELEMENTS: ++ if (attrs_to_add == SEALED) { ++ new_kind = HOLEY_SEALED_ELEMENTS; ++ } else if (attrs_to_add == FROZEN) { ++ new_kind = HOLEY_FROZEN_ELEMENTS; ++ } else { ++ new_kind = HOLEY_NONEXTENSIBLE_ELEMENTS; ++ } ++ break; ++ case HOLEY_NONEXTENSIBLE_ELEMENTS: ++ if (attrs_to_add == SEALED) { ++ new_kind = HOLEY_SEALED_ELEMENTS; ++ } else if (attrs_to_add == FROZEN) { ++ new_kind = HOLEY_FROZEN_ELEMENTS; ++ } ++ break; ++ case HOLEY_SEALED_ELEMENTS: ++ if (attrs_to_add == FROZEN) { ++ new_kind = HOLEY_FROZEN_ELEMENTS; ++ } ++ break; ++ default: ++ break; ++ } ++ } ++ new_map->set_elements_kind(new_kind); ++ } ++ }; ++ + // Do not track transitions during bootstrapping. + TransitionFlag flag = + isolate->bootstrapper()->IsActive() ? OMIT_TRANSITION : INSERT_TRANSITION; +- Handle new_map = +- CopyReplaceDescriptors(isolate, map, new_desc, flag, transition_marker, +- reason, SPECIAL_TRANSITION); +- new_map->set_is_extensible(false); +- if (!IsTypedArrayOrRabGsabTypedArrayElementsKind(map->elements_kind())) { +- ElementsKind new_kind = IsStringWrapperElementsKind(map->elements_kind()) +- ? SLOW_STRING_WRAPPER_ELEMENTS +- : DICTIONARY_ELEMENTS; +- if (!old_map_is_dictionary_elements_kind) { +- switch (map->elements_kind()) { +- case PACKED_ELEMENTS: +- if (attrs_to_add == SEALED) { +- new_kind = PACKED_SEALED_ELEMENTS; +- } else if (attrs_to_add == FROZEN) { +- new_kind = PACKED_FROZEN_ELEMENTS; +- } else { +- new_kind = PACKED_NONEXTENSIBLE_ELEMENTS; +- } +- break; +- case PACKED_NONEXTENSIBLE_ELEMENTS: +- if (attrs_to_add == SEALED) { +- new_kind = PACKED_SEALED_ELEMENTS; +- } else if (attrs_to_add == FROZEN) { +- new_kind = PACKED_FROZEN_ELEMENTS; +- } +- break; +- case PACKED_SEALED_ELEMENTS: +- if (attrs_to_add == FROZEN) { +- new_kind = PACKED_FROZEN_ELEMENTS; +- } +- break; +- case HOLEY_ELEMENTS: +- if (attrs_to_add == SEALED) { +- new_kind = HOLEY_SEALED_ELEMENTS; +- } else if (attrs_to_add == FROZEN) { +- new_kind = HOLEY_FROZEN_ELEMENTS; +- } else { +- new_kind = HOLEY_NONEXTENSIBLE_ELEMENTS; +- } +- break; +- case HOLEY_NONEXTENSIBLE_ELEMENTS: +- if (attrs_to_add == SEALED) { +- new_kind = HOLEY_SEALED_ELEMENTS; +- } else if (attrs_to_add == FROZEN) { +- new_kind = HOLEY_FROZEN_ELEMENTS; +- } +- break; +- case HOLEY_SEALED_ELEMENTS: +- if (attrs_to_add == FROZEN) { +- new_kind = HOLEY_FROZEN_ELEMENTS; +- } +- break; +- default: +- break; +- } +- } +- new_map->set_elements_kind(new_kind); +- } +- return new_map; ++ return CopyReplaceDescriptors(isolate, map, new_desc, flag, InitMap, ++ transition_marker, reason, SPECIAL_TRANSITION); + } + + namespace { +diff --git a/src/objects/map.h b/src/objects/map.h +index 37ce48e7f4340687e19c895888da41b71409e12b..3b50cc46d10f5b8052f5659abca8baf17b77febe 100644 +--- a/src/objects/map.h ++++ b/src/objects/map.h +@@ -1070,6 +1070,14 @@ class Map : public TorqueGeneratedMap { + static Handle CopyAddDescriptor(Isolate* isolate, DirectHandle map, + Descriptor* descriptor, + TransitionFlag flag); ++ ++ template ++ static Handle CopyReplaceDescriptors( ++ Isolate* isolate, DirectHandle map, ++ DirectHandle descriptors, TransitionFlag flag, ++ const InitMapCb& InitMap, MaybeDirectHandle maybe_name, ++ const char* reason, TransitionKindFlag transition_kind); ++ + static Handle CopyReplaceDescriptors( + Isolate* isolate, DirectHandle map, + DirectHandle descriptors, TransitionFlag flag, +@@ -1084,6 +1092,7 @@ class Map : public TorqueGeneratedMap { + PropertyNormalizationMode mode); + + void DeprecateTransitionTree(Isolate* isolate); ++ void DeprecateTransitionTreeImpl(Isolate* isolate); + + void ReplaceDescriptors(Isolate* isolate, + Tagged new_descriptors);