From 23069c34b26133642953072d596b86cf8484215c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Zasso?= Date: Wed, 8 Nov 2023 08:10:46 +0000 Subject: [PATCH] deps: V8: cherry-pick d69c7937c99d MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Original commit message: [snapshot] Dont defer ByteArray when serializing JSTypedArray needs the base_pointer ByteArray immediately if it's on heap. JSTypedArray's base_pointer was initialized to Smi::uninitialized_deserialization_value at first when deserializing, and if base_pointer was deferred, we will mistakenly check JSTypedArray not on heap. Bug: v8:13149 Change-Id: I104c83ff9a2017de1c8071a9e116baa602f6977d Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3813068 Reviewed-by: Jakob Linke Commit-Queue: 王澳 Cr-Commit-Position: refs/heads/main@{#82254} Refs: https://github.com/v8/v8/commit/d69c7937c99da7f67c3877cd63ae81d2c55978f3 PR-URL: https://github.com/nodejs/node/pull/46425 Reviewed-By: Joyee Cheung --- deps/v8/src/snapshot/deserializer.cc | 7 +++- .../src/snapshot/serializer-deserializer.cc | 5 ++- deps/v8/test/cctest/test-serialize.cc | 40 +++++++++++++++++++ 3 files changed, 50 insertions(+), 2 deletions(-) diff --git a/deps/v8/src/snapshot/deserializer.cc b/deps/v8/src/snapshot/deserializer.cc index e1383ca2b7fe0d..96e8427efa69da 100644 --- a/deps/v8/src/snapshot/deserializer.cc +++ b/deps/v8/src/snapshot/deserializer.cc @@ -427,6 +427,8 @@ void Deserializer::PostProcessNewJSReceiver( reinterpret_cast(backing_store) + data_view.byte_offset()); } else if (InstanceTypeChecker::IsJSTypedArray(instance_type)) { auto typed_array = JSTypedArray::cast(raw_obj); + // Note: ByteArray objects must not be deferred s.t. they are + // available here for is_on_heap(). See also: CanBeDeferred. // Fixup typed array pointers. if (typed_array.is_on_heap()) { typed_array.AddExternalPointerCompensationForDeserialization( @@ -517,7 +519,10 @@ void Deserializer::PostProcessNewObject(Handle map, // to |ObjectDeserializer::CommitPostProcessedObjects()|. new_allocation_sites_.push_back(Handle::cast(obj)); } else { - DCHECK(CanBeDeferred(*obj)); + // We dont defer ByteArray because JSTypedArray needs the base_pointer + // ByteArray immediately if it's on heap. + DCHECK(CanBeDeferred(*obj) || + InstanceTypeChecker::IsByteArray(instance_type)); } } } diff --git a/deps/v8/src/snapshot/serializer-deserializer.cc b/deps/v8/src/snapshot/serializer-deserializer.cc index d32de12ec05932..5d758cd8253498 100644 --- a/deps/v8/src/snapshot/serializer-deserializer.cc +++ b/deps/v8/src/snapshot/serializer-deserializer.cc @@ -51,10 +51,13 @@ bool SerializerDeserializer::CanBeDeferred(HeapObject o) { // 3. JS objects with embedder fields cannot be deferred because the // serialize/deserialize callbacks need the back reference immediately to // identify the object. + // 4. ByteArray cannot be deferred as JSTypedArray needs the base_pointer + // ByteArray immediately if it's on heap. // TODO(leszeks): Could we defer string serialization if forward references // were resolved after object post processing? return !o.IsMap() && !o.IsInternalizedString() && - !(o.IsJSObject() && JSObject::cast(o).GetEmbedderFieldCount() > 0); + !(o.IsJSObject() && JSObject::cast(o).GetEmbedderFieldCount() > 0) && + !o.IsByteArray(); } void SerializerDeserializer::RestoreExternalReferenceRedirector( diff --git a/deps/v8/test/cctest/test-serialize.cc b/deps/v8/test/cctest/test-serialize.cc index 4252d4bd652034..e7f1dd4760c861 100644 --- a/deps/v8/test/cctest/test-serialize.cc +++ b/deps/v8/test/cctest/test-serialize.cc @@ -4990,6 +4990,46 @@ UNINITIALIZED_TEST(SnapshotCreatorAnonClassWithKeep) { delete[] blob.data; } +UNINITIALIZED_TEST(SnapshotCreatorDontDeferByteArrayForTypedArray) { + DisableAlwaysOpt(); + v8::StartupData blob; + { + v8::SnapshotCreator creator; + v8::Isolate* isolate = creator.GetIsolate(); + { + v8::HandleScope handle_scope(isolate); + + v8::Local context = v8::Context::New(isolate); + v8::Context::Scope context_scope(context); + CompileRun( + "const z = new Uint8Array(1);\n" + "class A { \n" + " static x() { \n" + " } \n" + "} \n" + "class B extends A {} \n" + "B.foo = ''; \n" + "class C extends B {} \n" + "class D extends C {} \n" + "class E extends B {} \n" + "function F() {} \n" + "Object.setPrototypeOf(F, D); \n"); + creator.SetDefaultContext(context); + } + + blob = + creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear); + CHECK(blob.raw_size > 0 && blob.data != nullptr); + } + { + SnapshotCreator creator(nullptr, &blob); + v8::Isolate* isolate = creator.GetIsolate(); + v8::HandleScope scope(isolate); + USE(v8::Context::New(isolate)); + } + delete[] blob.data; +} + class V8_NODISCARD DisableLazySourcePositionScope { public: DisableLazySourcePositionScope()