Is it safe to reuse code cache generated before a context snapshot is serialized?

147 views
Skip to first unread message

jo...@igalia.com

unread,
Feb 21, 2022, 2:39:48 PM2/21/22
to v8-users

Hi,

I am running into a bug and I am not sure if it's caused by inappropriate usage of the SnapshotCreator API or a bug in V8. This was an issue discovered when working on the user land snapshot prototype in Node.js (https://github.com/nodejs/node/pull/38905), the upstream issue is https://github.com/nodejs/node/issues/40832. This prototype does a few things:

1. It generates code cache for a list of scripts.
2. It then run a subset of scripts mentioned in 1 to initialize a context and uses the code cache generated in 1 to compile them during the process. Then it snapshots the context with the v8::SnapshotCreator (this is the bootstrap snapshot that Node.js releases currently ship with).
3. A Node.js binary is built with the code cache and the initial snapshot mentioned in 1 & 2. It uses the snapshot built in step 2 to bootstrap itself, then executes a script specified by the user, and generates another context snapshot, then serializes it into another blob.
4. It initializes the context again with the snapshot blob generated in step 3 (which replaces the snapshot blob generated in 2), but when it needs to load any scripts not executed in 2 or 3, it still uses the code cache generated in step 1.

My understanding is that the serialized code and SFI and whatnot is part of the context snapshot, and as long as the sanity check passes, the code cache generated before the snapshot should be the same as the one in the snapshot if FunctionCodeHandling::kKeep is used. However the prototype runs into several memory bugs during deserialization of the user land snapshot - in release mode a script not included in the snapshot but compiled with the old code cache (that is, it is not executed after the final snapshot is loaded) throws an NonCallable error with a value strangely turning into undefined. In debug mode a relaxed load from a map crashes with EXC_BAD_ACCESS during compilation. So I suspect that this bug has something to do with GC or the concurrent compiler, but it is difficult to reproduce with only V8 - perhaps it needs a particular graph to trigger this bug and the prototype happens to generate such graphs more reliably.

Steps to reproduce:

1. Check out https://github.com/joyeecheung/node/tree/snapshot-mem-bug, build it with the instructions in https://github.com/nodejs/node/blob/rundefined/BUILDING.md (I do `cd /path/to/node && ./configure --ninja && ninja -C out/Release`). This is a prototype that allows user to specify a user script to snapshot with --snapshot-main, and generates a context snapshot containing a Node.js application using v8::SnapshotCreator. It can load the snapshot with another flag --snapshot-blob.
2. Run `out/Release/node --snapshot-main test/fixtures/snapshot/mem-bug.js && out/Release/node --snapshot-blob snapshot.blob test/fixtures/empty.js`, which throws the following error (some logging shows that the PromiseResolve function turned into undefined):

```
node:internal/modules/esm/module_job:32
const resolvedPromise = PromiseResolve();
                        ^

TypeError: PromiseResolve is not a function
    at node:internal/modules/esm/module_job:32:25
    at NativeModule.compileForInternalLoader (node:internal/bootstrap/loaders:312:7)
    at nativeModuleRequire (node:internal/bootstrap/loaders:341:14)
    at node:internal/modules/esm/module_map:3:19
    at NativeModule.compileForInternalLoader (node:internal/bootstrap/loaders:312:7)
    at nativeModuleRequire (node:internal/bootstrap/loaders:341:14)
    at node:internal/modules/esm/loader:36:19
    at NativeModule.compileForInternalLoader (node:internal/bootstrap/loaders:312:7)
    at nativeModuleRequire (node:internal/bootstrap/loaders:341:14)
    at node:internal/process/esm_loader:10:23
```

Some observations:

1. If the prototype is built in debug mode (with ./configure --ninja --v8-non-optimized-debug --debug and the out dir is changed to out/Debug), it crashes instead with this stack trace, I guess this indicates either the memory is corrupted, or some data race happened:
    ```
    * thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x746c6975622f637d)
      * frame #0: 0x0000000100746318 node`short std::__1::__cxx_atomic_load<short>(__a=0x746c6975622f637d, __order=memory_order_relaxed) at atomic:997:12
        frame #1: 0x00000001007462c8 node`std::__1::__atomic_base<short, false>::load(this=0x746c6975622f637d, __m=memory_order_relaxed) const volatile at atomic:1603:17
        frame #2: 0x0000000100746284 node`short std::__1::atomic_load_explicit<short>(__o=0x746c6975622f637d, __m=memory_order_relaxed) at atomic:1959:17
        frame #3: 0x0000000100746254 node`v8::base::Relaxed_Load(ptr=0x746c6975622f637d) at atomicops.h:225:10
        frame #4: 0x0000000100745ea4 node`v8::internal::Map::instance_type(this=0x000000016fdf65a8) const at map-inl.h:344:7
        frame #5: 0x000000010074d504 node`v8::internal::HeapObject::IsString(this=0x000000016fdf6718, cage_base=PtrComprCageBase @ 0x000000016fdf65bf) const at instance-type-inl.h:125:1
        frame #6: 0x00000001007c2b3c node`v8::internal::HeapObject::IsThinString(this=0x000000016fdf6718, cage_base=PtrComprCageBase @ 0x000000016fdf661e) const at objects-inl.h:229:8
        frame #7: 0x00000001019a4794 node`v8::internal::Serializer::SerializeObject(this=0x000000016fdfc4e0, obj=Handle<v8::internal::HeapObject> @ 0x000000016fdf6728) at serializer.cc:131:12
        frame #8: 0x00000001019a9a94 node`v8::internal::Serializer::ObjectSerializer::VisitPointers(this=0x000000016fdf78a0, host=HeapObject @ 0x000000016fdf68d8, start=v8::internal::MaybeObjectSlot @ 0x000000016fdf68d0, end=v8::internal::MaybeObjectSlot @ 0x000000016fdf68c8) at serializer.cc:894:20
        frame #9: 0x00000001019a95d0 node`v8::internal::Serializer::ObjectSerializer::VisitPointers(this=0x000000016fdf78a0, host=HeapObject @ 0x000000016fdf6948, start=v8::internal::ObjectSlot @ 0x000000016fdf6940, end=v8::internal::ObjectSlot @ 0x000000016fdf6938) at serializer.cc:829:3
        frame #10: 0x0000000100f23a74 node`void v8::internal::BodyDescriptorBase::IteratePointers<v8::internal::ObjectVisitor>(obj=HeapObject @ 0x000000016fdf69a8, start_offset=8, end_offset=200, v=0x000000016fdf78a0) at objects-body-descriptors-inl.h:120:6
        frame #11: 0x0000000101586344 node`void v8::internal::SuffixRangeBodyDescriptor<8>::IterateBody<v8::internal::ObjectVisitor>(map=Map @ 0x000000016fdf69e8, obj=HeapObject @ 0x000000016fdf69e0, object_size=200, v=0x000000016fdf78a0) at objects-body-descriptors.h:135:5
        frame #12: 0x00000001015858f0 node`void v8::internal::CallIterateBody::apply<v8::internal::ScopeInfo::BodyDescriptor, v8::internal::ObjectVisitor>(map=Map @ 0x000000016fdf6a28, obj=HeapObject @ 0x000000016fdf6a20, object_size=200, v=0x000000016fdf78a0) at objects-body-descriptors-inl.h:1277:5
        frame #13: 0x0000000101581ebc node`auto v8::internal::BodyDescriptorApply<v8::internal::CallIterateBody, v8::internal::Map&, v8::internal::HeapObject&, int&, v8::internal::ObjectVisitor*&>(type=SCOPE_INFO_TYPE, args=0x000000016fdf7518, args=0x000000016fdf7598, args=0x000000016fdf750c, args=0x000000016fdf7500) at objects-body-descriptors-inl.h:1243:7
        frame #14: 0x0000000101558530 node`void v8::internal::HeapObject::IterateBodyFast<v8::internal::ObjectVisitor>(this=0x000000016fdf7598, map=Map @ 0x000000016fdf7518, object_size=200, v=0x000000016fdf78a0) at objects-body-descriptors-inl.h:1283:3
        frame #15: 0x000000010155939c node`v8::internal::HeapObject::IterateBody(this=0x000000016fdf7598, map=Map @ 0x000000016fdf7558, object_size=200, v=0x000000016fdf78a0) at objects.cc:2170:3
        frame #16: 0x00000001019a8cd4 node`v8::internal::Serializer::ObjectSerializer::SerializeContent(this=0x000000016fdf78a0, map=Map @ 0x000000016fdf75e8, size=200) at serializer.cc:820:14
        frame #17: 0x00000001019a78f8 node`v8::internal::Serializer::ObjectSerializer::SerializeObject(this=0x000000016fdf78a0) at serializer.cc:791:3
        frame #18: 0x00000001019a887c node`v8::internal::Serializer::ObjectSerializer::Serialize(this=0x000000016fdf78a0) at serializer.cc:723:3
        frame #19: 0x0000000101948a40 node`v8::internal::CodeSerializer::SerializeGeneric(this=0x000000016fdfc4e0, heap_object=Handle<v8::internal::HeapObject> @ 0x000000016fdf78d8) at code-serializer.cc:251:14
        frame #20: 0x0000000101948938 node`v8::internal::CodeSerializer::SerializeObjectImpl(this=0x000000016fdfc4e0, obj=Handle<v8::internal::HeapObject> @ 0x000000016fdf7c98) at code-serializer.cc:245:3
        frame #21: 0x00000001019a492c node`v8::internal::Serializer::SerializeObject(this=0x000000016fdfc4e0, obj=Handle<v8::internal::HeapObject> @ 0x000000016fdf7db8) at serializer.cc:142:3
        frame #22: 0x00000001019a9a94 node`v8::internal::Serializer::ObjectSerializer::VisitPointers(this=0x000000016fdf8f30, host=HeapObject @ 0x000000016fdf7f68, start=v8::internal::MaybeObjectSlot @ 0x000000016fdf7f60, end=v8::internal::MaybeObjectSlot @ 0x000000016fdf7f58) at serializer.cc:894:20
        frame #23: 0x00000001019a95d0 node`v8::internal::Serializer::ObjectSerializer::VisitPointers(this=0x000000016fdf8f30, host=HeapObject @ 0x000000016fdf7fd8, start=v8::internal::ObjectSlot @ 0x000000016fdf7fd0, end=v8::internal::ObjectSlot @ 0x000000016fdf7fc8) at serializer.cc:829:3
        frame #24: 0x0000000100f23a74 node`void v8::internal::BodyDescriptorBase::IteratePointers<v8::internal::ObjectVisitor>(obj=HeapObject @ 0x000000016fdf8038, start_offset=8, end_offset=152, v=0x000000016fdf8f30) at objects-body-descriptors-inl.h:120:6
        frame #25: 0x0000000101586344 node`void v8::internal::SuffixRangeBodyDescriptor<8>::IterateBody<v8::internal::ObjectVisitor>(map=Map @ 0x000000016fdf8078, obj=HeapObject @ 0x000000016fdf8070, object_size=152, v=0x000000016fdf8f30) at objects-body-descriptors.h:135:5
        frame #26: 0x0000000101584ab0 node`void v8::internal::CallIterateBody::apply<v8::internal::FixedArray::BodyDescriptor, v8::internal::ObjectVisitor>(map=Map @ 0x000000016fdf80b8, obj=HeapObject @ 0x000000016fdf80b0, object_size=152, v=0x000000016fdf8f30) at objects-body-descriptors-inl.h:1277:5
        frame #27: 0x0000000101581dcc node`auto v8::internal::BodyDescriptorApply<v8::internal::CallIterateBody, v8::internal::Map&, v8::internal::HeapObject&, int&, v8::internal::ObjectVisitor*&>(type=FIRST_FIXED_ARRAY_BASE_TYPE, args=0x000000016fdf8ba8, args=0x000000016fdf8c28, args=0x000000016fdf8b9c, args=0x000000016fdf8b90) at objects-body-descriptors-inl.h:1243:7
        frame #28: 0x0000000101558530 node`void v8::internal::HeapObject::IterateBodyFast<v8::internal::ObjectVisitor>(this=0x000000016fdf8c28, map=Map @ 0x000000016fdf8ba8, object_size=152, v=0x000000016fdf8f30) at objects-body-descriptors-inl.h:1283:3
        frame #29: 0x000000010155939c node`v8::internal::HeapObject::IterateBody(this=0x000000016fdf8c28, map=Map @ 0x000000016fdf8be8, object_size=152, v=0x000000016fdf8f30) at objects.cc:2170:3
        frame #30: 0x00000001019a8cd4 node`v8::internal::Serializer::ObjectSerializer::SerializeContent(this=0x000000016fdf8f30, map=Map @ 0x000000016fdf8c78, size=152) at serializer.cc:820:14
        frame #31: 0x00000001019a78f8 node`v8::internal::Serializer::ObjectSerializer::SerializeObject(this=0x000000016fdf8f30) at serializer.cc:791:3
        frame #32: 0x00000001019a887c node`v8::internal::Serializer::ObjectSerializer::Serialize(this=0x000000016fdf8f30) at serializer.cc:723:3
        frame #33: 0x0000000101948a40 node`v8::internal::CodeSerializer::SerializeGeneric(this=0x000000016fdfc4e0, heap_object=Handle<v8::internal::HeapObject> @ 0x000000016fdf8f68) at code-serializer.cc:251:14
        frame #34: 0x0000000101948938 node`v8::internal::CodeSerializer::SerializeObjectImpl(this=0x000000016fdfc4e0, obj=Handle<v8::internal::HeapObject> @ 0x000000016fdf9328) at code-serializer.cc:245:3
        frame #35: 0x00000001019a492c node`v8::internal::Serializer::SerializeObject(this=0x000000016fdfc4e0, obj=Handle<v8::internal::HeapObject> @ 0x000000016fdf9448) at serializer.cc:142:3
        frame #36: 0x00000001019a9a94 node`v8::internal::Serializer::ObjectSerializer::VisitPointers(this=0x000000016fdfa620, host=HeapObject @ 0x000000016fdf95f8, start=v8::internal::MaybeObjectSlot @ 0x000000016fdf95f0, end=v8::internal::MaybeObjectSlot @ 0x000000016fdf95e8) at serializer.cc:894:20
        frame #37: 0x00000001019a95d0 node`v8::internal::Serializer::ObjectSerializer::VisitPointers(this=0x000000016fdfa620, host=HeapObject @ 0x000000016fdf9668, start=v8::internal::ObjectSlot @ 0x000000016fdf9660, end=v8::internal::ObjectSlot @ 0x000000016fdf9658) at serializer.cc:829:3
        frame #38: 0x0000000100d52854 node`v8::internal::ObjectVisitor::VisitPointer(this=0x000000016fdfa620, host=HeapObject @ 0x000000016fdf96b8, p=v8::internal::ObjectSlot @ 0x000000016fdf96b0) at visitors.h:139:5
        frame #39: 0x0000000101586ba0 node`void v8::internal::BodyDescriptorBase::IteratePointer<v8::internal::ObjectVisitor>(obj=HeapObject @ 0x000000016fdf9718, offset=16, v=0x000000016fdfa620) at objects-body-descriptors-inl.h:127:6
        frame #40: 0x00000001015872fc node`void v8::internal::BytecodeArray::BodyDescriptor::IterateBody<v8::internal::ObjectVisitor>(map=Map @ 0x000000016fdf9768, obj=HeapObject @ 0x000000016fdf9760, object_size=192, v=0x000000016fdfa620) at objects-body-descriptors-inl.h:517:5
        frame #41: 0x0000000101585398 node`void v8::internal::CallIterateBody::apply<v8::internal::BytecodeArray::BodyDescriptor, v8::internal::ObjectVisitor>(map=Map @ 0x000000016fdf97a8, obj=HeapObject @ 0x000000016fdf97a0, object_size=192, v=0x000000016fdfa620) at objects-body-descriptors-inl.h:1277:5
        frame #42: 0x0000000101580c4c node`auto v8::internal::BodyDescriptorApply<v8::internal::CallIterateBody, v8::internal::Map&, v8::internal::HeapObject&, int&, v8::internal::ObjectVisitor*&>(type=BYTECODE_ARRAY_TYPE, args=0x000000016fdfa298, args=0x000000016fdfa318, args=0x000000016fdfa28c, args=0x000000016fdfa280) at objects-body-descriptors-inl.h:1201:14
        frame #43: 0x0000000101558530 node`void v8::internal::HeapObject::IterateBodyFast<v8::internal::ObjectVisitor>(this=0x000000016fdfa318, map=Map @ 0x000000016fdfa298, object_size=192, v=0x000000016fdfa620) at objects-body-descriptors-inl.h:1283:3
        frame #44: 0x000000010155939c node`v8::internal::HeapObject::IterateBody(this=0x000000016fdfa318, map=Map @ 0x000000016fdfa2d8, object_size=192, v=0x000000016fdfa620) at objects.cc:2170:3
        frame #45: 0x00000001019a8cd4 node`v8::internal::Serializer::ObjectSerializer::SerializeContent(this=0x000000016fdfa620, map=Map @ 0x000000016fdfa368, size=192) at serializer.cc:820:14
        frame #46: 0x00000001019a78f8 node`v8::internal::Serializer::ObjectSerializer::SerializeObject(this=0x000000016fdfa620) at serializer.cc:791:3
        frame #47: 0x00000001019a887c node`v8::internal::Serializer::ObjectSerializer::Serialize(this=0x000000016fdfa620) at serializer.cc:723:3
        frame #48: 0x0000000101948a40 node`v8::internal::CodeSerializer::SerializeGeneric(this=0x000000016fdfc4e0, heap_object=Handle<v8::internal::HeapObject> @ 0x000000016fdfa658) at code-serializer.cc:251:14
        frame #49: 0x0000000101948938 node`v8::internal::CodeSerializer::SerializeObjectImpl(this=0x000000016fdfc4e0, obj=Handle<v8::internal::HeapObject> @ 0x000000016fdfaa18) at code-serializer.cc:245:3
        frame #50: 0x00000001019a492c node`v8::internal::Serializer::SerializeObject(this=0x000000016fdfc4e0, obj=Handle<v8::internal::HeapObject> @ 0x000000016fdfab38) at serializer.cc:142:3
        frame #51: 0x00000001019a9a94 node`v8::internal::Serializer::ObjectSerializer::VisitPointers(this=0x000000016fdfbd30, host=HeapObject @ 0x000000016fdface8, start=v8::internal::MaybeObjectSlot @ 0x000000016fdface0, end=v8::internal::MaybeObjectSlot @ 0x000000016fdfacd8) at serializer.cc:894:20
        frame #52: 0x00000001019a95d0 node`v8::internal::Serializer::ObjectSerializer::VisitPointers(this=0x000000016fdfbd30, host=HeapObject @ 0x000000016fdfad58, start=v8::internal::ObjectSlot @ 0x000000016fdfad50, end=v8::internal::ObjectSlot @ 0x000000016fdfad48) at serializer.cc:829:3
        frame #53: 0x0000000100d527e4 node`v8::internal::ObjectVisitor::VisitCustomWeakPointers(this=0x000000016fdfbd30, host=HeapObject @ 0x000000016fdfada8, start=v8::internal::ObjectSlot @ 0x000000016fdfada0, end=v8::internal::ObjectSlot @ 0x000000016fdfad98) at visitors.h:134:5
        frame #54: 0x0000000100d523c4 node`v8::internal::ObjectVisitor::VisitCustomWeakPointer(this=0x000000016fdfbd30, host=HeapObject @ 0x000000016fdfadf8, p=v8::internal::ObjectSlot @ 0x000000016fdfadf0) at visitors.h:145:5
        frame #55: 0x0000000101586f24 node`void v8::internal::BodyDescriptorBase::IterateCustomWeakPointer<v8::internal::ObjectVisitor>(obj=HeapObject @ 0x000000016fdfae38, offset=8, v=0x000000016fdfbd30) at objects-body-descriptors-inl.h:164:6
        frame #56: 0x0000000101587ae4 node`void v8::internal::SharedFunctionInfo::BodyDescriptor::IterateBody<v8::internal::ObjectVisitor>(map=Map @ 0x000000016fdfae78, obj=HeapObject @ 0x000000016fdfae70, object_size=64, v=0x000000016fdfbd30) at objects-body-descriptors-inl.inc:87:5
        frame #57: 0x0000000101585ab8 node`void v8::internal::CallIterateBody::apply<v8::internal::SharedFunctionInfo::BodyDescriptor, v8::internal::ObjectVisitor>(map=Map @ 0x000000016fdfaeb8, obj=HeapObject @ 0x000000016fdfaeb0, object_size=64, v=0x000000016fdfbd30) at objects-body-descriptors-inl.h:1277:5
        frame #58: 0x000000010158209c node`auto v8::internal::BodyDescriptorApply<v8::internal::CallIterateBody, v8::internal::Map&, v8::internal::HeapObject&, int&, v8::internal::ObjectVisitor*&>(type=SHARED_FUNCTION_INFO_TYPE, args=0x000000016fdfb9a8, args=0x000000016fdfba28, args=0x000000016fdfb99c, args=0x000000016fdfb990) at objects-body-descriptors-inl.h:1243:7
        frame #59: 0x0000000101558530 node`void v8::internal::HeapObject::IterateBodyFast<v8::internal::ObjectVisitor>(this=0x000000016fdfba28, map=Map @ 0x000000016fdfb9a8, object_size=64, v=0x000000016fdfbd30) at objects-body-descriptors-inl.h:1283:3
        frame #60: 0x000000010155939c node`v8::internal::HeapObject::IterateBody(this=0x000000016fdfba28, map=Map @ 0x000000016fdfb9e8, object_size=64, v=0x000000016fdfbd30) at objects.cc:2170:3
        frame #61: 0x00000001019a8cd4 node`v8::internal::Serializer::ObjectSerializer::SerializeContent(this=0x000000016fdfbd30, map=Map @ 0x000000016fdfba78, size=64) at serializer.cc:820:14
        frame #62: 0x00000001019a78f8 node`v8::internal::Serializer::ObjectSerializer::SerializeObject(this=0x000000016fdfbd30) at serializer.cc:791:3
        frame #63: 0x00000001019a887c node`v8::internal::Serializer::ObjectSerializer::Serialize(this=0x000000016fdfbd30) at serializer.cc:723:3
        frame #64: 0x0000000101948a40 node`v8::internal::CodeSerializer::SerializeGeneric(this=0x000000016fdfc4e0, heap_object=Handle<v8::internal::HeapObject> @ 0x000000016fdfbd68) at code-serializer.cc:251:14
        frame #65: 0x000000010194842c node`v8::internal::CodeSerializer::SerializeObjectImpl(this=0x000000016fdfc4e0, obj=Handle<v8::internal::HeapObject> @ 0x000000016fdfc128) at code-serializer.cc:192:5
        frame #66: 0x00000001019a492c node`v8::internal::Serializer::SerializeObject(this=0x000000016fdfc4e0, obj=Handle<v8::internal::HeapObject> @ 0x000000016fdfc248) at serializer.cc:142:3
        frame #67: 0x00000001019a4a4c node`v8::internal::Serializer::SerializeRootObject(this=0x000000016fdfc4e0, slot=FullObjectSlot @ 0x000000016fdfc2a8) at serializer.cc:159:5
        frame #68: 0x00000001019a49b0 node`v8::internal::Serializer::VisitRootPointers(this=0x000000016fdfc4e0, root=kHandleScope, description=0x0000000000000000, start=FullObjectSlot @ 0x000000016fdfc2f8, end=FullObjectSlot @ 0x000000016fdfc2f0) at serializer.cc:150:5
        frame #69: 0x0000000100ca3bc8 node`v8::internal::RootVisitor::VisitRootPointer(this=0x000000016fdfc4e0, root=kHandleScope, description=0x0000000000000000, p=FullObjectSlot @ 0x000000016fdfc358) at visitors.h:75:5
        frame #70: 0x00000001019478a4 node`v8::internal::CodeSerializer::SerializeSharedFunctionInfo(this=0x000000016fdfc4e0, info=Handle<v8::internal::SharedFunctionInfo> @ 0x000000016fdfc3e8) at code-serializer.cc:102:3
        frame #71: 0x00000001019474d4 node`v8::internal::CodeSerializer::Serialize(info=Handle<v8::internal::SharedFunctionInfo> @ 0x000000016fdfc870) at code-serializer.cc:81:39
        frame #72: 0x000000010076ef94 node`v8::ScriptCompiler::CreateCodeCacheForFunction(function=(val_ = 0x0000000110064cc0)) at api.cc:2894:10
        frame #73: 0x0000000100324eec node`node::native_module::NativeModuleLoader::LookupAndCompile(this=0x0000000105ad0fd0, context=(val_ = 0x000000011081c280), id="internal/modules/esm/initialize_import_meta", parameters=0x000000016fdfcc80 size=6, result=0x000000016fdfcd64) at node_native_module.cc:309:7
        frame #74: 0x0000000100324aa8 node`node::native_module::NativeModuleLoader::CompileAsModule(this=0x0000000105ad0fd0, context=(val_ = 0x000000011081c280), id="internal/modules/esm/initialize_import_meta", result=0x000000016fdfcd64) at node_native_module.cc:187:10
        frame #75: 0x0000000100330818 node`node::native_module::NativeModuleEnv::CompileFunction(args=0x000000016fdfd210) at node_native_module_env.cc:161:42
        frame #76: 0x00000001008dcfec node`v8::internal::FunctionCallbackArguments::Call(this=0x000000016fdfd390, handler=CallHandlerInfo @ 0x000000016fdfd2b0) at api-arguments-inl.h:152:3
        frame #77: 0x00000001008da114 node`v8::internal::MaybeHandle<v8::internal::Object> v8::internal::(anonymous namespace)::HandleApiCallHelper<false>(isolate=0x00000001180b8000, function=Handle<v8::internal::HeapObject> @ 0x000000016fdfd520, new_target=Handle<v8::internal::HeapObject> @ 0x000000016fdfd518, fun_data=Handle<v8::internal::FunctionTemplateInfo> @ 0x000000016fdfd510, receiver=Handle<v8::internal::Object> @ 0x000000016fdfd508, args=BuiltinArguments @ 0x000000016fdfd4f8) at builtins-api.cc:112:36
        frame #78: 0x00000001008d8e68 node`v8::internal::Builtin_Impl_HandleApiCall(args=BuiltinArguments @ 0x000000016fdfd6d8, isolate=0x00000001180b8000) at builtins-api.cc:142:5
        frame #79: 0x00000001008d8b4c node`v8::internal::Builtin_HandleApiCall(args_length=6, args_object=0x000000016fdfd7e8, isolate=0x00000001180b8000) at builtins-api.cc:130:1
        frame #80: 0x000000010232864c node`Builtins_CEntry_Return1_DontSaveFPRegs_ArgvOnStack_BuiltinExit + 108
        frame #81: 0x00000001022a2cd8 node`Builtins_InterpreterEntryTrampoline + 248
        frame #82: 0x00000001280482ec
        frame #83: 0x00000001022a2cd8 node`Builtins_InterpreterEntryTrampoline + 248
        frame #84: 0x00000001022a2cd8 node`Builtins_InterpreterEntryTrampoline + 248
        frame #85: 0x00000001280482ec
        frame #86: 0x00000001022a2cd8 node`Builtins_InterpreterEntryTrampoline + 248
        frame #87: 0x00000001022a2cd8 node`Builtins_InterpreterEntryTrampoline + 248
        frame #88: 0x00000001280482ec
        frame #89: 0x00000001022a2cd8 node`Builtins_InterpreterEntryTrampoline + 248
        frame #90: 0x00000001022a2cd8 node`Builtins_InterpreterEntryTrampoline + 248
        frame #91: 0x00000001280482ec
        frame #92: 0x00000001022a2cd8 node`Builtins_InterpreterEntryTrampoline + 248
        frame #93: 0x00000001022a2cd8 node`Builtins_InterpreterEntryTrampoline + 248
        frame #94: 0x00000001022a2cd8 node`Builtins_InterpreterEntryTrampoline + 248
        frame #95: 0x00000001022a04b0 node`Builtins_JSEntryTrampoline + 176
        frame #96: 0x00000001022a0144 node`Builtins_JSEntry + 164
        frame #97: 0x0000000100c2937c node`v8::internal::GeneratedCode<unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, long, unsigned long**>::Call(this=0x000000016fdfe3b0, args=4698374400, args=14066118301089, args=48012300152665, args=14066118301089, args=6, args=0x000000011100a990) at simulator.h:156:12
        frame #98: 0x0000000100c254ac node`v8::internal::(anonymous namespace)::Invoke(isolate=0x00000001180b8000, params=0x000000016fdfe630)::InvokeParams const&) at execution.cc:419:33
        frame #99: 0x0000000100c249d8 node`v8::internal::Execution::Call(isolate=0x00000001180b8000, callable=Handle<v8::internal::Object> @ 0x000000016fdfe6c0, receiver=Handle<v8::internal::Object> @ 0x000000016fdfe6b8, argc=5, argv=0x000000011100a990) at execution.cc:517:10
        frame #100: 0x0000000100785f60 node`v8::Function::Call(this=0x0000000110064c40, context=(val_ = 0x000000011081c280), recv=(val_ = 0x00000001180b8170), argc=5, argv=0x000000011100a990) at api.cc:5304:7
        frame #101: 0x00000001001b9b4c node`node::ExecuteBootstrapper(env=0x0000000110808200, id="internal/main/run_main_module", parameters=0x000000016fdfea38 size=5, arguments=0x000000016fdfea10 size=5) at node.cc:185:34
        frame #102: 0x00000001001bb900 node`node::StartExecution(env=0x0000000110808200, main_script_id="internal/main/run_main_module") at node.cc:461:7
        frame #103: 0x00000001001bb590 node`node::StartExecution(env=0x0000000110808200, cb=node::StartExecutionCallback @ 0x000000016fdfecd8)>) at node.cc:521:12
        frame #104: 0x0000000100084e78 node`node::LoadEnvironment(env=0x0000000110808200, cb=node::StartExecutionCallback @ 0x000000016fdfed68)>) at environment.cc:409:10
        frame #105: 0x00000001002f3ac8 node`node::NodeMainInstance::Run(this=0x000000016fdfeed8, exit_code=0x000000016fdfedec, env=0x0000000110808200) at node_main_instance.cc:144:5
        frame #106: 0x00000001002f348c node`node::NodeMainInstance::Run(this=0x000000016fdfeed8, env_info=0x000000016fdff028) at node_main_instance.cc:138:3
        frame #107: 0x00000001001be3fc node`node::Start(argc=4, argv=0x000000016fdff358) at node.cc:1221:38
        frame #108: 0x000000010279b288 node`main(argc=4, argv=0x000000016fdff358) at node_main.cc:127:10
        frame #109: 0x000000018b3dd430 libdyld.dylib`start + 4
    ```
2. If I add any V8 flag during the snapshot building process to invalidate the code cache sanity check (e.g. `out/Release/node --snapshot-main test/fixtures/snapshot/mem-bug.js && out/Release/node --trace_gc --snapshot-blob snapshot.blob test/fixtures/empty.js`), thus preventing the code cache from being deserialized, the prototype works as expected, so I think the bug has something to do with the code (de)serializer, and therefore I had the question in the title as I am not sure if it is even safe to reuse the old code cache this way.

Would appreciate any help investigating the bug :).

jo...@igalia.com

unread,
Feb 21, 2022, 2:48:05 PM2/21/22
to v8-users
I'd like to add that so far we've found two scripts that can trigger this with the Node.js user land snapshot prototype (the prototype works otherwise fine with applications as complicated as the TypeScript compiler), which are placed in https://github.com/joyeecheung/node/tree/snapshot-mem-bug as test/fixtures/snapshot/mem-bug.js and test/fixtures/snapshot/mem-bug2.js. They both seem pretty random to me. I'll paste them below for the record:

```
'use strict';

var re = /./;
re.exec = function () {
var result = [];
result.groups = { a: '7' };
return result;
};
''.replace(re, '$<a>') !== '7';
```

```
'use strict';

var chars = ('a'+'#').split('');
var entity = {};
for (var c of chars) {
entity[c] = true;
}
```


Jakob Gruber

unread,
Feb 22, 2022, 3:13:12 AM2/22/22
to v8-u...@googlegroups.com
> My understanding is that the serialized code and SFI and whatnot is part of the context snapshot

To clarify, the code cache is separate from the isolate/context snapshot; and neither contain serialized Code (Bytecode is possible though).

It does sound like snapshots are getting confused somewhere, resulting in broken object graphs. Not sure what exactly is going wrong though. Have you tried recreating the code cache as well in step 3?

--
--
v8-users mailing list
v8-u...@googlegroups.com
http://groups.google.com/group/v8-users
---
You received this message because you are subscribed to the Google Groups "v8-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to v8-users+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/v8-users/0967828b-5bf5-4d91-8d6d-aefbda398420n%40googlegroups.com.

jo...@igalia.com

unread,
Mar 15, 2022, 4:10:33 PM3/15/22
to v8-users

> Have you tried recreating the code cache as well in step 3?

I gave it a try and the crash in debug build/error in release build persist - I noticed that some code cache regenerated in step 3 have payloads different from the one generated in step 1 (though both are accepted when compilation is requested from the deserialized context).

Another observation is that the crash happens in step 4, after compiling the function with the code cache (no matter it's the regenerated  one or not) and when I try to serialize a new code cache from the function:

// It does not matter if GetCachedData() returns something created before or after the snapshot is generated
ScriptCompiler::CachedData* cached_data = GetCachedData();
ScriptCompiler::Source script_source(source, origin, cached_data);
Local<Function> fun = ScriptCompiler::CompileFunctionInContext(context, &script_source, ...).ToLocalChecked();
// This crashes with the stack trace below
ScriptCompiler::CreateCodeCacheForFunction(fun);

If I do not try to refresh the code cache with a new one created from the compiled function, and just continue execution as usual, it still crashes at the same place during lazy compilation, but with the same memory address as the one above (0x746c6975622f637d) being read as a instance type - so I am wondering what's special about this value?


* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x746c6975622f637d)
  * frame #0: 0x0000000100753390 node`short std::__1::__cxx_atomic_load<short>(__a=0x746c6975622f637d, __order=memory_order_relaxed) at atomic:997:12
    frame #1: 0x0000000100753340 node`std::__1::__atomic_base<short, false>::load(this=0x746c6975622f637d, __m=memory_order_relaxed) const volatile at atomic:1603:17
    frame #2: 0x00000001007532fc node`short std::__1::atomic_load_explicit<short>(__o=0x746c6975622f637d, __m=memory_order_relaxed) at atomic:1959:17
    frame #3: 0x00000001007532cc node`v8::base::Relaxed_Load(ptr=0x746c6975622f637d) at atomicops.h:225:10
    frame #4: 0x0000000100752f1c node`v8::internal::Map::instance_type(this=0x000000016fdfb058) const at map-inl.h:344:7
    frame #5: 0x00000001007bd888 node`v8::internal::HeapObject::IsPrimitiveHeapObject(this=0x000000016fdfb0c8, cage_base=PtrComprCageBase @ 0x000000016fdfb06f) const at instance-type-inl.h:125:1
    frame #6: 0x000000010076a1fc node`v8::internal::HeapObject::IsPrimitiveHeapObject(this=0x000000016fdfb0c8) const at instance-type-inl.h:125:1
    frame #7: 0x000000010216d870 node`v8::internal::IsPrimitiveHeapObject_NonInline(o=HeapObject @ 0x000000016fdfb0c8) at primitive-heap-object-tq.cc:11:12
    frame #8: 0x0000000100759654 node`v8::internal::TorqueGeneratedPrimitiveHeapObject<v8::internal::PrimitiveHeapObject, v8::internal::HeapObject>::TorqueGeneratedPrimitiveHeapObject(this=0x000000016fdfb2e8, ptr=58798249336529) at primitive-heap-object-tq-inl.inc:10:3
    frame #9: 0x00000001007595e4 node`v8::internal::PrimitiveHeapObject::PrimitiveHeapObject(this=0x000000016fdfb2e8, ptr=58798249336529) at primitive-heap-object-inl.h:20:1
    frame #10: 0x0000000100759534 node`v8::internal::TorqueGeneratedName<v8::internal::Name, v8::internal::PrimitiveHeapObject>::TorqueGeneratedName(this=0x000000016fdfb2e8, ptr=58798249336529) at name-tq-inl.inc:23:7
    frame #11: 0x00000001007594f4 node`v8::internal::Name::Name(this=0x000000016fdfb2e8, ptr=58798249336529) at name-inl.h:23:1
    frame #12: 0x000000010075a254 node`v8::internal::TorqueGeneratedString<v8::internal::String, v8::internal::Name>::TorqueGeneratedString(this=0x000000016fdfb2e8, ptr=58798249336529) at string-tq-inl.inc:183:7
    frame #13: 0x000000010075a214 node`v8::internal::String::String(this=0x000000016fdfb2e8, ptr=58798249336529) at string-inl.h:104:1
    frame #14: 0x000000010075a1d8 node`v8::internal::String::String(this=0x000000016fdfb2e8, ptr=58798249336529) at string-inl.h:104:1
    frame #15: 0x00000001007c90e4 node`v8::internal::TaggedField<v8::internal::String, 0>::load(cage_base=PtrComprCageBase @ 0x000000016fdfb2e7, host=HeapObject @ 0x000000016fdfb2d8, offset=104) at tagged-field-inl.h:69:10
    frame #16: 0x0000000100c14f5c node`v8::internal::TorqueGeneratedSymbol<v8::internal::Symbol, v8::internal::Name>::SymbolPrint(this=0x0000000000000000, os=0x000000016fdfb390) at objects-printer.cc:16
    frame #17: 0x0000000100c14e14 node`v8::internal::TorqueGeneratedHeapNumber<v8::internal::HeapNumber, v8::internal::PrimitiveHeapObject>::HeapNumberPrint(this=0x000018bb42ccd639, os=0x000034c086e27161) at objects-printer.cc:0
    frame #18: 0x00000001015c0140 node`v8::internal::ScopeInfo::ContextSlotIndex(scope_info=ScopeInfo @ 0x000000016fdfb440, name=String @ 0x000000016fdfb438, lookup_result=0x000000016fdfb510) at scope-info.cc:904:28
    frame #19: 0x000000010083b284 node`v8::internal::Scope::LookupInScopeInfo(this=0x0000000119062438, name=0x0000000119062b80, cache=0x0000000119062438) at scopes.cc:943:9
    frame #20: 0x000000010083e5a8 node`v8::internal::Variable* v8::internal::Scope::Lookup<(v8::internal::Scope::ScopeLookupMode)1>(proxy=0x0000000119062ba0, scope=0x0000000119062438, outer_scope_end=0x0000000000000000, cache_scope=0x0000000119062438, force_context_allocation=false) at scopes.cc:2058:20
    frame #21: 0x000000010083dc48 node`v8::internal::Variable* v8::internal::Scope::Lookup<(v8::internal::Scope::ScopeLookupMode)0>(proxy=0x0000000119062ba0, scope=0x0000000119062438, outer_scope_end=0x0000000000000000, cache_scope=0x0000000119062438, force_context_allocation=true) at scopes.cc:2105:14
    frame #22: 0x00000001008498f4 node`v8::internal::Scope::ResolveVariable(this=0x00000001190628e8, proxy=0x0000000119062ba0) at scopes.cc:2225:19
    frame #23: 0x0000000100847c18 node`v8::internal::Scope::ResolveVariablesRecursively(this=0x00000001190628e8, end=0x0000000119062608) at scopes.cc:2327:7
    frame #24: 0x0000000100847c44 node`v8::internal::Scope::ResolveVariablesRecursively(this=0x0000000119062608, end=0x0000000119062608) at scopes.cc:2333:19
    frame #25: 0x0000000100843498 node`v8::internal::DeclarationScope::AllocateVariables(this=0x0000000119062608, info=0x000000016fdfc558) at scopes.cc:1331:8
    frame #26: 0x00000001008431f8 node`v8::internal::DeclarationScope::Analyze(info=0x000000016fdfc558) at scopes.cc:692:15
    frame #27: 0x000000010164e524 node`void v8::internal::Parser::PostProcessParseResult<v8::internal::Isolate>(this=0x000000016fdfbd60, isolate=0x00000001200c0000, info=0x000000016fdfc558, literal=0x0000000119062e08) at parser.cc:703:38
    frame #28: 0x000000010165587c node`v8::internal::Parser::ParseFunction(this=0x000000016fdfbd60, isolate=0x00000001200c0000, info=0x000000016fdfc558, shared_info=Handle<v8::internal::SharedFunctionInfo> @ 0x000000016fdfbca8) at parser.cc:881:3
    frame #29: 0x00000001016a5494 node`v8::internal::parsing::ParseFunction(info=0x000000016fdfc558, shared_info=Handle<v8::internal::SharedFunctionInfo> @ 0x000000016fdfc338, isolate=0x00000001200c0000, mode=kYes) at parsing.cc:90:10
    frame #30: 0x00000001016a567c node`v8::internal::parsing::ParseAny(info=0x000000016fdfc558, shared_info=Handle<v8::internal::SharedFunctionInfo> @ 0x000000016fdfc3f0, isolate=0x00000001200c0000, mode=kYes) at parsing.cc:108:10
    frame #31: 0x00000001009cbf14 node`v8::internal::Compiler::Compile(isolate=0x00000001200c0000, shared_info=Handle<v8::internal::SharedFunctionInfo> @ 0x000000016fdfc790, flag=KEEP_EXCEPTION, is_compiled_scope=0x000000016fdfca28, create_source_positions_flag=kNo) at compiler.cc:1893:8
    frame #32: 0x00000001009ccae0 node`v8::internal::Compiler::Compile(isolate=0x00000001200c0000, function=Handle<v8::internal::JSFunction> @ 0x000000016fdfc950, flag=KEEP_EXCEPTION, is_compiled_scope=0x000000016fdfca28) at compiler.cc:1940:8
    frame #33: 0x0000000101895478 node`v8::internal::__RT_impl_Runtime_CompileLazy(args=v8::internal::RuntimeArguments @ 0x000000016fdfcaa8, isolate=0x00000001200c0000)0>, v8::internal::Isolate*) at runtime-compiler.cc:74:8
    frame #34: 0x0000000101895214 node`v8::internal::Runtime_CompileLazy(args_length=1, args_object=0x000000016fdfcb90, isolate=0x00000001200c0000) at runtime-compiler.cc:54:1
    frame #35: 0x00000001023352ac node`Builtins_CEntry_Return1_DontSaveFPRegs_ArgvOnStack_NoBuiltinExit + 108
    frame #36: 0x00000001022b0e90 node`Builtins_CompileLazy + 976
    frame #37: 0x00000001022afa78 node`Builtins_InterpreterEntryTrampoline + 248
    frame #38: 0x00000001022afa78 node`Builtins_InterpreterEntryTrampoline + 248
    frame #39: 0x00000001300482ec
    frame #40: 0x00000001022afa78 node`Builtins_InterpreterEntryTrampoline + 248
    frame #41: 0x00000001022afa78 node`Builtins_InterpreterEntryTrampoline + 248
    frame #42: 0x00000001300482ec
    frame #43: 0x00000001022afa78 node`Builtins_InterpreterEntryTrampoline + 248
    frame #44: 0x00000001022afa78 node`Builtins_InterpreterEntryTrampoline + 248
    frame #45: 0x00000001300482ec
    frame #46: 0x00000001022afa78 node`Builtins_InterpreterEntryTrampoline + 248
    frame #47: 0x00000001022afa78 node`Builtins_InterpreterEntryTrampoline + 248
    frame #48: 0x00000001300482ec
    frame #49: 0x00000001022afa78 node`Builtins_InterpreterEntryTrampoline + 248
    frame #50: 0x00000001022afa78 node`Builtins_InterpreterEntryTrampoline + 248
    frame #51: 0x00000001300482ec
    frame #52: 0x00000001022afa78 node`Builtins_InterpreterEntryTrampoline + 248
    frame #53: 0x00000001022afa78 node`Builtins_InterpreterEntryTrampoline + 248
    frame #54: 0x00000001300482ec
    frame #55: 0x00000001022afa78 node`Builtins_InterpreterEntryTrampoline + 248
    frame #56: 0x00000001022afa78 node`Builtins_InterpreterEntryTrampoline + 248
    frame #57: 0x00000001300482ec
    frame #58: 0x00000001022afa78 node`Builtins_InterpreterEntryTrampoline + 248
    frame #59: 0x00000001022afa78 node`Builtins_InterpreterEntryTrampoline + 248
    frame #60: 0x00000001300482ec
    frame #61: 0x00000001022afa78 node`Builtins_InterpreterEntryTrampoline + 248
    frame #62: 0x00000001022afa78 node`Builtins_InterpreterEntryTrampoline + 248
    frame #63: 0x00000001300482ec
    frame #64: 0x00000001022afa78 node`Builtins_InterpreterEntryTrampoline + 248
    frame #65: 0x00000001022afa78 node`Builtins_InterpreterEntryTrampoline + 248
    frame #66: 0x00000001022afa78 node`Builtins_InterpreterEntryTrampoline + 248
    frame #67: 0x00000001022ad250 node`Builtins_JSEntryTrampoline + 176
    frame #68: 0x00000001022acee4 node`Builtins_JSEntry + 164
    frame #69: 0x0000000100c363c0 node`v8::internal::GeneratedCode<unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, long, unsigned long**>::Call(this=0x000000016fdfe520, args=4832624896, args=58798249088417, args=6269625200505, args=58798249088417, args=6, args=0x000000010ef30f70) at simulator.h:156:12
    frame #70: 0x0000000100c324f0 node`v8::internal::(anonymous namespace)::Invoke(isolate=0x00000001200c0000, params=0x000000016fdfe7a0)::InvokeParams const&) at execution.cc:419:33
    frame #71: 0x0000000100c31a1c node`v8::internal::Execution::Call(isolate=0x00000001200c0000, callable=Handle<v8::internal::Object> @ 0x000000016fdfe830, receiver=Handle<v8::internal::Object> @ 0x000000016fdfe828, argc=5, argv=0x000000010ef30f70) at execution.cc:517:10
    frame #72: 0x0000000100792fd8 node`v8::Function::Call(this=0x000000010f08f040, context=(val_ = 0x0000000118846a80), recv=(val_ = 0x00000001200c0170), argc=5, argv=0x000000010ef30f70) at api.cc:5304:7
    frame #73: 0x00000001001b9c88 node`node::ExecuteBootstrapper(env=0x000000010f844e00, id="internal/main/run_main_module", parameters=0x000000016fdfeba8 size=5, arguments=0x000000016fdfeb80 size=5) at node.cc:185:34
    frame #74: 0x00000001001bba3c node`node::StartExecution(env=0x000000010f844e00, main_script_id="internal/main/run_main_module") at node.cc:461:7
    frame #75: 0x00000001001bb6cc node`node::StartExecution(env=0x000000010f844e00, cb=node::StartExecutionCallback @ 0x000000016fdfee48)>) at node.cc:521:12
    frame #76: 0x0000000100084eac node`node::LoadEnvironment(env=0x000000010f844e00, cb=node::StartExecutionCallback @ 0x000000016fdfeed8)>) at environment.cc:411:10
    frame #77: 0x00000001002f56a4 node`node::NodeMainInstance::Run(this=0x000000016fdff050, exit_code=0x000000016fdfef54, env=0x000000010f844e00) at node_main_instance.cc:151:5
    frame #78: 0x00000001002f5094 node`node::NodeMainInstance::Run(this=0x000000016fdff050) at node_main_instance.cc:145:3
    frame #79: 0x00000001001be578 node`node::Start(argc=5, argv=0x000000016fdff350) at node.cc:1213:38
    frame #80: 0x00000001027ad0bc node`main(argc=5, argv=0x000000016fdff350) at node_main.cc:127:10
    frame #81: 0x000000018b3dd430 libdyld.dylib`start + 4

jo...@igalia.com

unread,
Mar 15, 2022, 4:12:08 PM3/15/22
to v8-users
Correction: in the snippet in the last reply, the comment `// This crashes with the stack trace below` should be `// This crashes with the stack trace above`.

Jakob Gruber

unread,
Mar 16, 2022, 2:15:36 AM3/16/22
to v8-u...@googlegroups.com
I don't have any ideas right now; could you please file a bug with details on how to compile and run the repro?

jo...@igalia.com

unread,
Mar 18, 2022, 5:51:46 AM3/18/22
to v8-users
Alright, I opened https://bugs.chromium.org/p/v8/issues/detail?id=12718 with the information I've got so far about this bug.
Reply all
Reply to author
Forward
0 new messages