diff --git a/patches/v8/.patches b/patches/v8/.patches index 727f76be41..dc98544242 100644 --- a/patches/v8/.patches +++ b/patches/v8/.patches @@ -1,2 +1 @@ chore_allow_customizing_microtask_policy_per_context.patch -preserve_field_repr_in_property_array_extension.patch diff --git a/patches/v8/preserve_field_repr_in_property_array_extension.patch b/patches/v8/preserve_field_repr_in_property_array_extension.patch deleted file mode 100644 index 139f080baa..0000000000 --- a/patches/v8/preserve_field_repr_in_property_array_extension.patch +++ /dev/null @@ -1,302 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Leszek Swirski -Date: Wed, 12 Nov 2025 16:46:01 +0100 -Subject: Preserve field repr in property array extension - -Walk the descriptor array in lockstep with the property array when -extending the latter. - -Fixed: 460017370 -Change-Id: If0b4fc3c5f62fc0cc373588cbddc3c0a95c7225c -Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/7146166 -Commit-Queue: Leszek Swirski -Reviewed-by: Nico Hartmann -Reviewed-by: Igor Sheludko -Cr-Commit-Position: refs/heads/main@{#103674} - -diff --git a/src/compiler/access-builder.cc b/src/compiler/access-builder.cc -index d8f618f2bbec1c854956225dd568c235dea780cb..ad6172b555f86cb7d9f5fdf8912f407cd69139d4 100644 ---- a/src/compiler/access-builder.cc -+++ b/src/compiler/access-builder.cc -@@ -4,6 +4,8 @@ - - #include "src/compiler/access-builder.h" - -+#include "src/codegen/machine-type.h" -+#include "src/compiler/property-access-builder.h" - #include "src/compiler/type-cache.h" - #include "src/handles/handles-inl.h" - #include "src/objects/arguments.h" -@@ -1070,12 +1072,16 @@ FieldAccess AccessBuilder::ForFeedbackVectorSlot(int index) { - } - - // static --FieldAccess AccessBuilder::ForPropertyArraySlot(int index) { -+FieldAccess AccessBuilder::ForPropertyArraySlot(int index, -+ Representation representation) { - int offset = PropertyArray::OffsetOfElementAt(index); -- FieldAccess access = {kTaggedBase, offset, -- Handle(), OptionalMapRef(), -- Type::Any(), MachineType::AnyTagged(), -- kFullWriteBarrier, "PropertyArraySlot"}; -+ MachineType machine_type = -+ representation.IsHeapObject() || representation.IsDouble() -+ ? MachineType::TaggedPointer() -+ : MachineType::AnyTagged(); -+ FieldAccess access = { -+ kTaggedBase, offset, Handle(), OptionalMapRef(), -+ Type::Any(), machine_type, kFullWriteBarrier, "PropertyArraySlot"}; - return access; - } - -diff --git a/src/compiler/access-builder.h b/src/compiler/access-builder.h -index 8e7d9cdf979f5daebd4daf605293320b1b105c77..4feaefc0a6cf401cd528b162f212d931c4d71cbf 100644 ---- a/src/compiler/access-builder.h -+++ b/src/compiler/access-builder.h -@@ -11,6 +11,7 @@ - #include "src/compiler/write-barrier-kind.h" - #include "src/objects/elements-kind.h" - #include "src/objects/js-objects.h" -+#include "src/objects/property-details.h" - - namespace v8 { - namespace internal { -@@ -318,7 +319,8 @@ class V8_EXPORT_PRIVATE AccessBuilder final - static FieldAccess ForFeedbackVectorSlot(int index); - - // Provides access to PropertyArray slots. -- static FieldAccess ForPropertyArraySlot(int index); -+ static FieldAccess ForPropertyArraySlot(int index, -+ Representation representation); - - // Provides access to ScopeInfo flags. - static FieldAccess ForScopeInfoFlags(); -diff --git a/src/compiler/js-native-context-specialization.cc b/src/compiler/js-native-context-specialization.cc -index faeda3e2623afbd453acc61ea05ec534b060a31e..dc8fcd4c65658c6dd32606a3ce3ff4952b4d9364 100644 ---- a/src/compiler/js-native-context-specialization.cc -+++ b/src/compiler/js-native-context-specialization.cc -@@ -38,6 +38,7 @@ - #include "src/objects/elements-kind.h" - #include "src/objects/feedback-vector.h" - #include "src/objects/heap-number.h" -+#include "src/objects/property-details.h" - #include "src/objects/string.h" - - namespace v8 { -@@ -4235,25 +4236,59 @@ Node* JSNativeContextSpecialization::BuildExtendPropertiesBackingStore( - // for intermediate states of chains of property additions. That makes - // it unclear what the best approach is here. - DCHECK_EQ(map.UnusedPropertyFields(), 0); -- int length = map.NextFreePropertyIndex() - map.GetInObjectProperties(); -+ int in_object_length = map.GetInObjectProperties(); -+ int length = map.NextFreePropertyIndex() - in_object_length; - // Under normal circumstances, NextFreePropertyIndex() will always be larger - // than GetInObjectProperties(). However, an attacker able to corrupt heap - // memory can break this invariant, in which case we'll get confused here, - // potentially causing a sandbox violation. This CHECK defends against that. - SBXCHECK_GE(length, 0); - int new_length = length + JSObject::kFieldsAdded; -+ -+ // Find the descriptor index corresponding to the first out-of-object -+ // property. -+ DescriptorArrayRef descs = map.instance_descriptors(broker()); -+ InternalIndex first_out_of_object_descriptor(in_object_length); -+ InternalIndex number_of_descriptors(descs.object()->number_of_descriptors()); -+ for (InternalIndex i(in_object_length); i < number_of_descriptors; ++i) { -+ PropertyDetails details = descs.GetPropertyDetails(i); -+ // Skip over non-field properties. -+ if (details.location() != PropertyLocation::kField) { -+ continue; -+ } -+ // Skip over in-object fields. -+ // TODO(leszeks): We could make this smarter, like a binary search. -+ if (details.field_index() < in_object_length) { -+ continue; -+ } -+ first_out_of_object_descriptor = i; -+ break; -+ } -+ - // Collect the field values from the {properties}. -- ZoneVector values(zone()); -+ ZoneVector> values(zone()); - values.reserve(new_length); -- for (int i = 0; i < length; ++i) { -+ -+ // Walk the property descriptors alongside the property values, to make -+ // sure to get and store them with the right machine type. -+ InternalIndex descriptor = first_out_of_object_descriptor; -+ for (int i = 0; i < length; ++i, ++descriptor) { -+ PropertyDetails details = descs.GetPropertyDetails(descriptor); -+ while (details.location() != PropertyLocation::kField) { -+ ++descriptor; -+ details = descs.GetPropertyDetails(descriptor); -+ } -+ DCHECK_EQ(i, details.field_index() - in_object_length); - Node* value = effect = graph()->NewNode( -- simplified()->LoadField(AccessBuilder::ForFixedArraySlot(i)), -+ simplified()->LoadField( -+ AccessBuilder::ForPropertyArraySlot(i, details.representation())), - properties, effect, control); -- values.push_back(value); -+ values.push_back({value, details.representation()}); - } - // Initialize the new fields to undefined. - for (int i = 0; i < JSObject::kFieldsAdded; ++i) { -- values.push_back(jsgraph()->UndefinedConstant()); -+ values.push_back( -+ {jsgraph()->UndefinedConstant(), Representation::Tagged()}); - } - - // Compute new length and hash. -@@ -4291,7 +4326,8 @@ Node* JSNativeContextSpecialization::BuildExtendPropertiesBackingStore( - a.Store(AccessBuilder::ForMap(), jsgraph()->PropertyArrayMapConstant()); - a.Store(AccessBuilder::ForPropertyArrayLengthAndHash(), new_length_and_hash); - for (int i = 0; i < new_length; ++i) { -- a.Store(AccessBuilder::ForFixedArraySlot(i), values[i]); -+ a.Store(AccessBuilder::ForPropertyArraySlot(i, values[i].second), -+ values[i].first); - } - return a.Finish(); - } -diff --git a/src/compiler/turboshaft/turbolev-early-lowering-reducer-inl.h b/src/compiler/turboshaft/turbolev-early-lowering-reducer-inl.h -index 0c63f5ca2083976cd8cf3c1df003562acdadca76..d8b5571b3ca5b5d4e10ca87985b8bdb814ab46f2 100644 ---- a/src/compiler/turboshaft/turbolev-early-lowering-reducer-inl.h -+++ b/src/compiler/turboshaft/turbolev-early-lowering-reducer-inl.h -@@ -14,6 +14,7 @@ - #include "src/compiler/turboshaft/representations.h" - #include "src/deoptimizer/deoptimize-reason.h" - #include "src/objects/contexts.h" -+#include "src/objects/descriptor-array-inl.h" - #include "src/objects/instance-type-inl.h" - - namespace v8::internal::compiler::turboshaft { -@@ -318,8 +319,32 @@ class TurbolevEarlyLoweringReducer : public Next { - } - - V ExtendPropertiesBackingStore( -- V old_property_array, V object, int old_length, -+ V old_property_array, V object, -+ const compiler::MapRef& old_map, int old_length, - V frame_state, const FeedbackSource& feedback) { -+ int in_object_length = old_map.GetInObjectProperties(); -+ -+ // Find the descriptor index corresponding to the first out-of-object -+ // property. -+ DescriptorArrayRef descs = old_map.instance_descriptors(broker_); -+ InternalIndex first_out_of_object_descriptor(in_object_length); -+ InternalIndex number_of_descriptors( -+ descs.object()->number_of_descriptors()); -+ for (InternalIndex i(in_object_length); i < number_of_descriptors; ++i) { -+ PropertyDetails details = descs.GetPropertyDetails(i); -+ // Skip over non-field properties. -+ if (details.location() != PropertyLocation::kField) { -+ continue; -+ } -+ // Skip over in-object fields. -+ // TODO(leszeks): We could make this smarter, like a binary search. -+ if (details.field_index() < in_object_length) { -+ continue; -+ } -+ first_out_of_object_descriptor = i; -+ break; -+ } -+ - // Allocate new PropertyArray. - int new_length = old_length + JSObject::kFieldsAdded; - Uninitialized new_property_array = -@@ -330,18 +355,28 @@ class TurbolevEarlyLoweringReducer : public Next { - __ HeapConstant(factory_->property_array_map())); - - // Copy existing properties over. -- for (int i = 0; i < old_length; i++) { -+ InternalIndex descriptor = first_out_of_object_descriptor; -+ for (int i = 0; i < old_length; ++i, ++descriptor) { -+ PropertyDetails details = descs.GetPropertyDetails(descriptor); -+ while (details.location() != PropertyLocation::kField) { -+ ++descriptor; -+ details = descs.GetPropertyDetails(descriptor); -+ } -+ DCHECK_EQ(i, details.field_index() - in_object_length); -+ Representation r = details.representation(); -+ - V old_value = __ template LoadField( -- old_property_array, AccessBuilder::ForPropertyArraySlot(i)); -+ old_property_array, AccessBuilder::ForPropertyArraySlot(i, r)); - __ InitializeField(new_property_array, -- AccessBuilder::ForPropertyArraySlot(i), old_value); -+ AccessBuilder::ForPropertyArraySlot(i, r), old_value); - } - - // Initialize new properties to undefined. - V undefined = __ HeapConstant(factory_->undefined_value()); - for (int i = 0; i < JSObject::kFieldsAdded; ++i) { - __ InitializeField(new_property_array, -- AccessBuilder::ForPropertyArraySlot(old_length + i), -+ AccessBuilder::ForPropertyArraySlot( -+ old_length + i, Representation::Tagged()), - undefined); - } - -diff --git a/src/compiler/turboshaft/turbolev-graph-builder.cc b/src/compiler/turboshaft/turbolev-graph-builder.cc -index 34b06d2ba836f60bf940612564c92b52dceaf5b3..819ac484904cd72aad64a4193f82db47a02dabd8 100644 ---- a/src/compiler/turboshaft/turbolev-graph-builder.cc -+++ b/src/compiler/turboshaft/turbolev-graph-builder.cc -@@ -2789,10 +2789,11 @@ class GraphBuildingNodeProcessor { - maglev::ProcessResult Process(maglev::ExtendPropertiesBackingStore* node, - const maglev::ProcessingState& state) { - GET_FRAME_STATE_MAYBE_ABORT(frame_state, node->eager_deopt_info()); -- SetMap(node, __ ExtendPropertiesBackingStore( -- Map(node->property_array_input()), -- Map(node->object_input()), node->old_length(), frame_state, -- node->eager_deopt_info()->feedback_to_update())); -+ SetMap(node, -+ __ ExtendPropertiesBackingStore( -+ Map(node->property_array_input()), Map(node->object_input()), -+ node->old_map(), node->old_length(), frame_state, -+ node->eager_deopt_info()->feedback_to_update())); - return maglev::ProcessResult::kContinue; - } - -diff --git a/src/maglev/maglev-graph-builder.cc b/src/maglev/maglev-graph-builder.cc -index 6cfe938ae94d86e023be208f3ec09822ec569fb3..ba28636e41a4a46e08c957b2640c9f20c911b9ce 100644 ---- a/src/maglev/maglev-graph-builder.cc -+++ b/src/maglev/maglev-graph-builder.cc -@@ -5189,7 +5189,7 @@ ReduceResult MaglevGraphBuilder::BuildExtendPropertiesBackingStore( - // potentially causing a sandbox violation. This CHECK defends against that. - SBXCHECK_GE(length, 0); - return AddNewNode({property_array, receiver}, -- length); -+ map, length); - } - - MaybeReduceResult MaglevGraphBuilder::TryBuildStoreField( -diff --git a/src/maglev/maglev-ir.h b/src/maglev/maglev-ir.h -index 4792ca5387c9f4229179a66ff6c15346e222342b..233eed0baf18aa814caae4b3241130ff289157ca 100644 ---- a/src/maglev/maglev-ir.h -+++ b/src/maglev/maglev-ir.h -@@ -9165,8 +9165,10 @@ class ExtendPropertiesBackingStore - using Base = FixedInputValueNodeT<2, ExtendPropertiesBackingStore>; - - public: -- explicit ExtendPropertiesBackingStore(uint64_t bitfield, int old_length) -- : Base(bitfield), old_length_(old_length) {} -+ explicit ExtendPropertiesBackingStore(uint64_t bitfield, -+ const compiler::MapRef& old_map, -+ int old_length) -+ : Base(bitfield), old_map_(old_map), old_length_(old_length) {} - - static constexpr OpProperties kProperties = - OpProperties::CanAllocate() | OpProperties::CanRead() | -@@ -9186,9 +9188,11 @@ class ExtendPropertiesBackingStore - void GenerateCode(MaglevAssembler*, const ProcessingState&); - void PrintParams(std::ostream&) const; - -+ const compiler::MapRef& old_map() const { return old_map_; } - int old_length() const { return old_length_; } - - private: -+ const compiler::MapRef old_map_; - const int old_length_; - }; -