diff --git a/src/README.md b/src/README.md index 300b74c28d5..20453b405b3 100644 --- a/src/README.md +++ b/src/README.md @@ -467,10 +467,16 @@ void Initialize(Local target, NODE_BINDING_CONTEXT_AWARE_INTERNAL(cares_wrap, Initialize) ``` -If the C++ binding is loaded during bootstrap, it needs to be registered -with the utilities in `node_external_reference.h`, like this: +#### Registering binding functions used in bootstrap + +If the C++ binding is loaded during bootstrap, in addition to registering it +using `NODE_BINDING_CONTEXT_AWARE_INTERNAL` for `internalBinding()` lookup, +it also needs to be registered with `NODE_BINDING_EXTERNAL_REFERENCE` so that +the external references can be resolved from the built-in snapshot, like this: ```cpp +#include "node_external_reference.h" + namespace node { namespace util { void RegisterExternalReferences(ExternalReferenceRegistry* registry) { @@ -498,7 +504,8 @@ Unknown external reference 0x107769200. /bin/sh: line 1: 6963 Illegal instruction: 4 out/Release/node_mksnapshot out/Release/gen/node_snapshot.cc ``` -You can try using a debugger to symbolicate the external reference. For example, +You can try using a debugger to symbolicate the external reference in order to find +out the binding functions that you forget to register. For example, with lldb's `image lookup --address` command (with gdb it's `info symbol`): ```console @@ -514,7 +521,9 @@ Process 7012 stopped ``` Which explains that the unregistered external reference is -`node::util::GetHiddenValue` defined in `node_util.cc`. +`node::util::GetHiddenValue` defined in `node_util.cc`, and should be registered +using `registry->Register()` in a registration function marked by +`NODE_BINDING_EXTERNAL_REFERENCE`. diff --git a/tools/snapshot/README.md b/tools/snapshot/README.md index 3ae6547a0a2..d61c2306e35 100644 --- a/tools/snapshot/README.md +++ b/tools/snapshot/README.md @@ -8,9 +8,46 @@ instead of executing code to bootstrap, it can deserialize the context from an embedded snapshot, which readily contains the result of the bootstrap, so that Node.js can start up faster. -Currently only the main context of the main Node.js instance supports snapshot -deserialization, and the snapshot does not yet cover the entire bootstrap -process. Work is being done to expand the support. +The built-in snapshot consists of the following snapshots: + +## Isolate snapshot + +Which is used whenever a `v8::Isolate` is created using the data returned by +`node::SnapshotBuilder::GetEmbeddedSnapshotData`. + +## Context snapshots + +Which are used when a `v8::Context` is created from a `v8::Isolate` deserialized +from the snapshot. There are four context snapshots in the snapshot blob. + +1. The default context snapshot, used for contexts created by + `v8::Context::New()`, it only contains V8 built-ins, matching the + layout of the isolate snapshot. +1. The vm context snapshot, which can be deserialized using + `v8::Context::FromSnapshot(isolate, node::SnapshotData::kNodeVMContextIndex, ...)`. + It captures initializations specific to vm contexts done by + `node::contextify::ContextifyContext::CreateV8Context()`. +1. The base context snapshot, which can be deserialized using + `v8::Context::FromSnapshot(isolate, node::SnapshotData::kNodeBaseContextIndex, ...)`. + It currently captures initializations done by `node::NewContext()` + but is intended to include more as a basis for worker thread + contexts. +1. The main context snapshot, which can be deserialized using + `v8::Context::FromSnapshot(isolate, node::SnapshotData::kNodeMainContextIndex, ...)`. + This is the snapshot for the main context on the main thread, and + captures initializations done by `node::CommonEnvironmentSetup::CreateForSnapshotting()`, + most notably `node::CreateEnvironment()`, which runs the following scripts via + `node::Realm::RunBootstrapping()` for the main context as a principal realm, + so that at runtime, these scripts do not need to be run. Instead only the context + initialized by them is deserialized at runtime. + 1. `internal/bootstrap/realm` + 2. `internal/bootstrap/node` + 3. `internal/bootstrap/web/exposed-wildcard` + 4. `internal/bootstrap/web/exposed-window-or-worker` + 5. `internal/bootstrap/switches/is_main_thread` + 6. `internal/bootstrap/switches/does_own_process_state` + +For more information about these contexts, see the comment in `src/node_context_data.h`. ## How it's built and used @@ -39,3 +76,22 @@ For debugging, Node.js can be built without Node.js's own snapshot if `--without-node-snapshot` is passed to `configure`. A Node.js executable with Node.js snapshot embedded can also be launched without deserializing from it if the command line argument `--no-node-snapshot` is passed. + +### When `node_mksnapshot` crashes.. + +Due to this two-phase building process, sometimes when there is an issue +in the code, the build may crash early at executing `node_mksnapshot` instead of crashing +at executing the final executable `node`. If the crash can be reproduced when running +the `node` executable built with `--without-node-snapshot`, it means the crash likely +has nothing to do with snapshots, and only shows up in `node_mksnapshot` because it's +the first Node.js executable being run. + +If the crash comes from a `mksnapshot` executable (notice that it doesn't have the `node_` +prefix), that comes from V8's own snapshot building process, not the one in Node.js, and the +fix likely needs to be in V8 or the build configurations of V8. + +If it `node_mksnapshot` crashes with an error message containing +something like `Unknown external reference 0x107769200`, see +[Registering binding functions used in bootstrap][] on how to fix it. + +[Registering binding functions used in bootstrap]: ../../src/README.md#registering-binding-functions-used-in-bootstrap