diff --git a/deps/v8/include/v8-version.h b/deps/v8/include/v8-version.h index d3a60cfe29e1..9af8a12370f8 100644 --- a/deps/v8/include/v8-version.h +++ b/deps/v8/include/v8-version.h @@ -11,7 +11,7 @@ #define V8_MAJOR_VERSION 15 #define V8_MINOR_VERSION 5 #define V8_BUILD_NUMBER 35 -#define V8_PATCH_LEVEL 20 +#define V8_PATCH_LEVEL 22 // Use 1 for candidates and 0 otherwise. // (Boolean macro values are not supported by all preprocessors.) diff --git a/deps/v8/src/maglev/maglev-code-gen-state.h b/deps/v8/src/maglev/maglev-code-gen-state.h index fe88347fecab..2d1b06299921 100644 --- a/deps/v8/src/maglev/maglev-code-gen-state.h +++ b/deps/v8/src/maglev/maglev-code-gen-state.h @@ -5,6 +5,8 @@ #ifndef V8_MAGLEV_MAGLEV_CODE_GEN_STATE_H_ #define V8_MAGLEV_MAGLEV_CODE_GEN_STATE_H_ +#include + #include "src/codegen/assembler.h" #include "src/codegen/label.h" #include "src/codegen/machine-type.h" @@ -132,6 +134,15 @@ class MaglevCodeGenState { inline BasicBlock* RealJumpTarget(BasicBlock* block); + using RetainedObjects = + std::unordered_set, Handle::hash, + Handle::equal_to>; + void Retain(Handle heap_object) { + retained_objects_.insert(heap_object); + } + + const RetainedObjects& retained_objects() const { return retained_objects_; } + private: MaglevCompilationInfo* const compilation_info_; MaglevSafepointTableBuilder* const safepoint_table_builder_; @@ -143,6 +154,8 @@ class MaglevCodeGenState { std::vector lazy_deopts_; std::vector handlers_; + RetainedObjects retained_objects_; + int untagged_slots_ = 0; int tagged_slots_ = 0; uint32_t max_deopted_stack_size_ = kMaxUInt32; diff --git a/deps/v8/src/maglev/maglev-code-generator.cc b/deps/v8/src/maglev/maglev-code-generator.cc index aabf1a89ca35..db078876f73f 100644 --- a/deps/v8/src/maglev/maglev-code-generator.cc +++ b/deps/v8/src/maglev/maglev-code-generator.cc @@ -1882,6 +1882,7 @@ bool MaglevCodeGenerator::EmitCode() { EmitDeferredCode(); if (!EmitDeopts()) return false; EmitExceptionHandlerTrampolines(); + EmitRetainedObjects(); __ FinishCode(); code_gen_succeeded_ = true; @@ -2031,6 +2032,21 @@ void MaglevCodeGenerator::EmitExceptionHandlerTrampolines() { #endif } +void MaglevCodeGenerator::EmitRetainedObjects() { + if (code_gen_state_.retained_objects().empty()) return; + + // This code is never executed; it's just for inserting weak embedded objects + // into the code. + __ RecordComment("-- Retained objects"); + __ Trap(); + + MaglevAssembler::TemporaryRegisterScope temps(masm()); + Register scratch = temps.AcquireScratch(); + for (Handle heap_object : code_gen_state_.retained_objects()) { + __ Move(scratch, heap_object); + } +} + void MaglevCodeGenerator::EmitMetadata() { // Final alignment before starting on the metadata section. masm()->Align(InstructionStream::kMetadataAlignment); diff --git a/deps/v8/src/maglev/maglev-code-generator.h b/deps/v8/src/maglev/maglev-code-generator.h index e7c2967bc4dd..b38547c244a2 100644 --- a/deps/v8/src/maglev/maglev-code-generator.h +++ b/deps/v8/src/maglev/maglev-code-generator.h @@ -41,6 +41,7 @@ class MaglevCodeGenerator final { void EmitDeferredCode(); V8_NODISCARD bool EmitDeopts(); void EmitExceptionHandlerTrampolines(); + void EmitRetainedObjects(); void EmitMetadata(); void RecordInlinedFunctions(); diff --git a/deps/v8/src/maglev/maglev-ir.cc b/deps/v8/src/maglev/maglev-ir.cc index e8d91edd72a2..c25f1165cb35 100644 --- a/deps/v8/src/maglev/maglev-ir.cc +++ b/deps/v8/src/maglev/maglev-ir.cc @@ -8162,6 +8162,18 @@ void GenerateTypedArrayLoadFromDataPointer(MaglevAssembler* masm, } } +void RetainConstantTypedArrayBuffer(MaglevAssembler* masm, + compiler::JSTypedArrayRef typed_array) { + // The constant typed array comes from a constant-folded source (property + // cell, const field, ...) which holds it strongly, and the code depends on + // that source not changing. So the buffer behind the embedded data pointer + // cannot die while this code is valid. Embed the buffer anyway as defense in + // depth: with this weak reference, the code is deoptimized when the buffer + // dies. + masm->code_gen_state()->Retain( + typed_array.buffer(masm->compilation_info()->broker()).object()); +} + template void GenerateTypedArrayLoad(MaglevAssembler* masm, Register object, Register index, ResultReg result_reg, @@ -8189,6 +8201,8 @@ void GenerateConstantTypedArrayLoad(MaglevAssembler* masm, compiler::JSTypedArrayRef typed_array, Register index, ResultReg result_reg, ElementsKind kind) { + RetainConstantTypedArrayBuffer(masm, typed_array); + MaglevAssembler::TemporaryRegisterScope temps(masm); Register data_pointer = temps.Acquire(); __ Move(data_pointer, reinterpret_cast(typed_array.data_ptr())); @@ -8250,6 +8264,8 @@ void GenerateConstantTypedArrayStore(MaglevAssembler* masm, compiler::JSTypedArrayRef typed_array, Register index, ValueReg value, ElementsKind elements_kind) { + RetainConstantTypedArrayBuffer(masm, typed_array); + MaglevAssembler::TemporaryRegisterScope temps(masm); Register data_pointer = temps.Acquire(); diff --git a/deps/v8/src/objects/js-objects.cc b/deps/v8/src/objects/js-objects.cc index 47da2576efe4..8b04c8ab5b74 100644 --- a/deps/v8/src/objects/js-objects.cc +++ b/deps/v8/src/objects/js-objects.cc @@ -478,6 +478,9 @@ Maybe JSReceiver::SetOrCopyDataProperties( InstanceType target_instance_type = target->map()->instance_type(); if (InstanceTypeChecker::IsJSObject(target_instance_type) && !InstanceTypeChecker::IsJSGlobalProxy(target_instance_type) && + // Exclude remote objects (they don't have local properties anyway). + !(InstanceTypeChecker::IsJSSpecialApiObject(target_instance_type) && + !target->GetCreationContext().has_value()) && !InstanceTypeChecker::IsAlwaysSharedSpaceJSObject( target_instance_type)) { // Convert to slow properties if we're guaranteed to overflow the number diff --git a/deps/v8/src/objects/map.cc b/deps/v8/src/objects/map.cc index 3745751b01a9..dbd60ea0ff93 100644 --- a/deps/v8/src/objects/map.cc +++ b/deps/v8/src/objects/map.cc @@ -1378,8 +1378,10 @@ Handle Map::Normalize(Isolate* isolate, DirectHandle fast_map, } DirectHandle cache; if (use_cache) { + Tagged maybe_native_context = meta_map->native_context_or_null(); + DCHECK(!IsNull(maybe_native_context)); Tagged normalized_map_cache = - meta_map->native_context()->normalized_map_cache(); + Cast(maybe_native_context)->normalized_map_cache(); use_cache = !IsUndefined(normalized_map_cache); if (use_cache) { cache = Cast( diff --git a/deps/v8/test/unittests/api/remote-object-unittest.cc b/deps/v8/test/unittests/api/remote-object-unittest.cc index 753627441a0d..7a54c9805cf1 100644 --- a/deps/v8/test/unittests/api/remote-object-unittest.cc +++ b/deps/v8/test/unittests/api/remote-object-unittest.cc @@ -101,5 +101,29 @@ TEST_F(RemoteObjectTest, TypeOfRemoteObject) { EXPECT_STREQ("object", *result); } +TEST_F(RemoteObjectTest, NormalizeRemoteObject) { + Local constructor_template = + FunctionTemplate::New(isolate(), Constructor); + constructor_template->InstanceTemplate()->SetAccessCheckCallbackAndHandler( + AccessCheck, NamedPropertyHandlerConfiguration(NamedGetter), + IndexedPropertyHandlerConfiguration()); + + Local remote_object = + constructor_template->NewRemoteInstance().ToLocalChecked(); + + Local context = Context::New(isolate()); + Context::Scope context_scope(context); + + context->Global() + ->Set(context, String::NewFromUtf8Literal(isolate(), "remoteObj"), + remote_object) + .Check(); + + TryRunJS( + "const src = {};" + "for (let i = 0; i < 1200; i++) src['p' + i] = 1;" + "try { Object.assign(remoteObj, src); } catch (e) {}"); +} + } // namespace remote_object_unittest } // namespace v8