mirror of
https://github.com/zebrajr/node.git
synced 2026-01-15 12:15:26 +00:00
bootstrap: support more builtins in the embedded code cache
This patch: - Make NativeModuleLoader::LookupAndCompile() detect parameters based on module IDs. This allows us to compile more builtins when generating the embedded bootstrap, including - internal/per_context/* - internal/bootstrap/* - internal/main/* - Move pre_execution.js to lib/internal/process as it needs to be compiled as a regular built-in module, unlike other scripts in lib/internal/bootstrap - Move markBootstrapComplete() to the performance binding instead of making it a function-wrapper-based global to reduce number of special cases. PR-URL: https://github.com/nodejs/node/pull/44018 Reviewed-By: Chengzhong Wu <legendecas@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net>
This commit is contained in:
@@ -326,6 +326,8 @@ class NativeModule {
|
||||
requireWithFallbackInDeps : nativeModuleRequire;
|
||||
|
||||
const fn = compileFunction(id);
|
||||
// Arguments must match the parameters specified in
|
||||
// NativeModuleLoader::LookupAndCompile().
|
||||
fn(this.exports, requireFn, this, process, internalBinding, primordials);
|
||||
|
||||
this.loaded = true;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
//
|
||||
// This file is expected not to perform any asynchronous operations itself
|
||||
// when being executed - those should be done in either
|
||||
// `lib/internal/bootstrap/pre_execution.js` or in main scripts. The majority
|
||||
// `lib/internal/process/pre_execution.js` or in main scripts. The majority
|
||||
// of the code here focuses on setting up the global proxy and the process
|
||||
// object in a synchronous manner.
|
||||
// As special caution is given to the performance of the startup process,
|
||||
@@ -28,7 +28,7 @@
|
||||
// Then, depending on how the Node.js instance is launched, one of the main
|
||||
// scripts in `lib/internal/main` will be selected by C++ to start the actual
|
||||
// execution. They may run additional setups exported by
|
||||
// `lib/internal/bootstrap/pre_execution.js` depending on the runtime states.
|
||||
// `lib/internal/process/pre_execution.js` depending on the runtime states.
|
||||
|
||||
'use strict';
|
||||
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
globals:
|
||||
markBootstrapComplete: true
|
||||
@@ -5,8 +5,9 @@
|
||||
|
||||
const { getOptionValue } = require('internal/options');
|
||||
const {
|
||||
prepareMainThreadExecution
|
||||
} = require('internal/bootstrap/pre_execution');
|
||||
prepareMainThreadExecution,
|
||||
markBootstrapComplete
|
||||
} = require('internal/process/pre_execution');
|
||||
|
||||
const {
|
||||
readStdin
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
// that depends on run time states.
|
||||
// It is currently only intended for preparing contexts for embedders.
|
||||
|
||||
/* global markBootstrapComplete */
|
||||
const {
|
||||
prepareMainThreadExecution
|
||||
} = require('internal/bootstrap/pre_execution');
|
||||
prepareMainThreadExecution,
|
||||
markBootstrapComplete
|
||||
} = require('internal/process/pre_execution');
|
||||
|
||||
prepareMainThreadExecution();
|
||||
markBootstrapComplete();
|
||||
@@ -3,8 +3,9 @@
|
||||
// Stdin is not a TTY, we will read it and execute it.
|
||||
|
||||
const {
|
||||
prepareMainThreadExecution
|
||||
} = require('internal/bootstrap/pre_execution');
|
||||
prepareMainThreadExecution,
|
||||
markBootstrapComplete
|
||||
} = require('internal/process/pre_execution');
|
||||
|
||||
const { getOptionValue } = require('internal/options');
|
||||
|
||||
|
||||
@@ -8,8 +8,9 @@ const {
|
||||
} = primordials;
|
||||
|
||||
const {
|
||||
prepareMainThreadExecution
|
||||
} = require('internal/bootstrap/pre_execution');
|
||||
prepareMainThreadExecution,
|
||||
markBootstrapComplete
|
||||
} = require('internal/process/pre_execution');
|
||||
const { evalModule, evalScript } = require('internal/process/execution');
|
||||
const { addBuiltinLibsToObject } = require('internal/modules/cjs/helpers');
|
||||
|
||||
|
||||
@@ -3,8 +3,9 @@
|
||||
// `node inspect ...` or `node debug ...`
|
||||
|
||||
const {
|
||||
prepareMainThreadExecution
|
||||
} = require('internal/bootstrap/pre_execution');
|
||||
prepareMainThreadExecution,
|
||||
markBootstrapComplete
|
||||
} = require('internal/process/pre_execution');
|
||||
|
||||
prepareMainThreadExecution();
|
||||
|
||||
|
||||
@@ -114,7 +114,7 @@ function requireForUserSnapshot(id) {
|
||||
function main() {
|
||||
const {
|
||||
prepareMainThreadExecution
|
||||
} = require('internal/bootstrap/pre_execution');
|
||||
} = require('internal/process/pre_execution');
|
||||
|
||||
prepareMainThreadExecution(true, false);
|
||||
|
||||
|
||||
@@ -20,8 +20,9 @@ const { types } = internalBinding('options');
|
||||
const hasCrypto = Boolean(process.versions.openssl);
|
||||
|
||||
const {
|
||||
prepareMainThreadExecution
|
||||
} = require('internal/bootstrap/pre_execution');
|
||||
prepareMainThreadExecution,
|
||||
markBootstrapComplete
|
||||
} = require('internal/process/pre_execution');
|
||||
|
||||
const typeLookup = [];
|
||||
for (const key of ObjectKeys(types))
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
const {
|
||||
prepareMainThreadExecution
|
||||
} = require('internal/bootstrap/pre_execution');
|
||||
prepareMainThreadExecution,
|
||||
markBootstrapComplete
|
||||
} = require('internal/process/pre_execution');
|
||||
|
||||
prepareMainThreadExecution();
|
||||
markBootstrapComplete();
|
||||
|
||||
@@ -4,8 +4,9 @@
|
||||
// the main module is not specified and stdin is a TTY.
|
||||
|
||||
const {
|
||||
prepareMainThreadExecution
|
||||
} = require('internal/bootstrap/pre_execution');
|
||||
prepareMainThreadExecution,
|
||||
markBootstrapComplete
|
||||
} = require('internal/process/pre_execution');
|
||||
|
||||
const esmLoader = require('internal/process/esm_loader');
|
||||
const {
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
const {
|
||||
prepareMainThreadExecution
|
||||
} = require('internal/bootstrap/pre_execution');
|
||||
prepareMainThreadExecution,
|
||||
markBootstrapComplete
|
||||
} = require('internal/process/pre_execution');
|
||||
|
||||
prepareMainThreadExecution(true);
|
||||
|
||||
|
||||
@@ -12,7 +12,8 @@ const {
|
||||
} = primordials;
|
||||
const {
|
||||
prepareMainThreadExecution,
|
||||
} = require('internal/bootstrap/pre_execution');
|
||||
markBootstrapComplete
|
||||
} = require('internal/process/pre_execution');
|
||||
const { spawn } = require('child_process');
|
||||
const { readdirSync, statSync } = require('fs');
|
||||
const console = require('internal/console/global');
|
||||
|
||||
@@ -30,8 +30,9 @@ const {
|
||||
initializeReport,
|
||||
initializeSourceMapsHandlers,
|
||||
loadPreloadModules,
|
||||
setupTraceCategoryState
|
||||
} = require('internal/bootstrap/pre_execution');
|
||||
setupTraceCategoryState,
|
||||
markBootstrapComplete
|
||||
} = require('internal/process/pre_execution');
|
||||
|
||||
const {
|
||||
threadId,
|
||||
|
||||
@@ -596,6 +596,10 @@ function loadPreloadModules() {
|
||||
}
|
||||
}
|
||||
|
||||
function markBootstrapComplete() {
|
||||
internalBinding('performance').markBootstrapComplete();
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
refreshRuntimeOptions,
|
||||
patchProcessObject,
|
||||
@@ -616,5 +620,6 @@ module.exports = {
|
||||
setupInspectorHooks,
|
||||
initializeReport,
|
||||
initializeCJSLoader,
|
||||
initializeWASI
|
||||
initializeWASI,
|
||||
markBootstrapComplete
|
||||
};
|
||||
@@ -12,7 +12,6 @@ const {
|
||||
setSerializeCallback,
|
||||
setDeserializeCallback,
|
||||
setDeserializeMainFunction: _setDeserializeMainFunction,
|
||||
markBootstrapComplete
|
||||
} = internalBinding('mksnapshot');
|
||||
|
||||
function isBuildingSnapshot() {
|
||||
@@ -87,8 +86,9 @@ function setDeserializeMainFunction(callback, data) {
|
||||
|
||||
_setDeserializeMainFunction(function deserializeMain() {
|
||||
const {
|
||||
prepareMainThreadExecution
|
||||
} = require('internal/bootstrap/pre_execution');
|
||||
prepareMainThreadExecution,
|
||||
markBootstrapComplete
|
||||
} = require('internal/process/pre_execution');
|
||||
|
||||
// This should be in sync with run_main_module.js until we make that
|
||||
// a built-in main function.
|
||||
|
||||
@@ -15,7 +15,7 @@ function lazyUndici() {
|
||||
|
||||
// This is essentially an implementation of a v8::WasmStreamingCallback, except
|
||||
// that it is implemented in JavaScript because the fetch() implementation is
|
||||
// difficult to use from C++. See lib/internal/bootstrap/pre_execution.js and
|
||||
// difficult to use from C++. See lib/internal/process/pre_execution.js and
|
||||
// src/node_wasm_web_api.cc that interact with this function.
|
||||
function wasmStreamingCallback(streamState, source) {
|
||||
(async () => {
|
||||
|
||||
@@ -452,13 +452,12 @@ MaybeLocal<Value> LoadEnvironment(
|
||||
native_module::NativeModuleLoader::Add(
|
||||
name.c_str(), UnionBytes(**main_utf16, main_utf16->length()));
|
||||
env->set_main_utf16(std::move(main_utf16));
|
||||
std::vector<Local<String>> params = {
|
||||
env->process_string(),
|
||||
env->require_string()};
|
||||
// Arguments must match the parameters specified in
|
||||
// NativeModuleLoader::LookupAndCompile().
|
||||
std::vector<Local<Value>> args = {
|
||||
env->process_object(),
|
||||
env->native_module_require()};
|
||||
return ExecuteBootstrapper(env, name.c_str(), ¶ms, &args);
|
||||
return ExecuteBootstrapper(env, name.c_str(), &args);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -683,8 +682,6 @@ Maybe<bool> InitializePrimordials(Local<Context> context) {
|
||||
|
||||
Local<String> primordials_string =
|
||||
FIXED_ONE_BYTE_STRING(isolate, "primordials");
|
||||
Local<String> global_string = FIXED_ONE_BYTE_STRING(isolate, "global");
|
||||
Local<String> exports_string = FIXED_ONE_BYTE_STRING(isolate, "exports");
|
||||
|
||||
// Create primordials first and make it available to per-context scripts.
|
||||
Local<Object> primordials = Object::New(isolate);
|
||||
@@ -700,12 +697,12 @@ Maybe<bool> InitializePrimordials(Local<Context> context) {
|
||||
nullptr};
|
||||
|
||||
for (const char** module = context_files; *module != nullptr; module++) {
|
||||
std::vector<Local<String>> parameters = {
|
||||
global_string, exports_string, primordials_string};
|
||||
// Arguments must match the parameters specified in
|
||||
// NativeModuleLoader::LookupAndCompile().
|
||||
Local<Value> arguments[] = {context->Global(), exports, primordials};
|
||||
MaybeLocal<Function> maybe_fn =
|
||||
native_module::NativeModuleLoader::LookupAndCompile(
|
||||
context, *module, ¶meters, nullptr);
|
||||
context, *module, nullptr);
|
||||
Local<Function> fn;
|
||||
if (!maybe_fn.ToLocal(&fn)) {
|
||||
return Nothing<bool>();
|
||||
|
||||
68
src/node.cc
68
src/node.cc
@@ -125,7 +125,6 @@ using native_module::NativeModuleLoader;
|
||||
|
||||
using v8::EscapableHandleScope;
|
||||
using v8::Function;
|
||||
using v8::FunctionCallbackInfo;
|
||||
using v8::Isolate;
|
||||
using v8::Local;
|
||||
using v8::MaybeLocal;
|
||||
@@ -170,11 +169,10 @@ void SignalExit(int signo, siginfo_t* info, void* ucontext) {
|
||||
|
||||
MaybeLocal<Value> ExecuteBootstrapper(Environment* env,
|
||||
const char* id,
|
||||
std::vector<Local<String>>* parameters,
|
||||
std::vector<Local<Value>>* arguments) {
|
||||
EscapableHandleScope scope(env->isolate());
|
||||
MaybeLocal<Function> maybe_fn =
|
||||
NativeModuleLoader::LookupAndCompile(env->context(), id, parameters, env);
|
||||
NativeModuleLoader::LookupAndCompile(env->context(), id, env);
|
||||
|
||||
Local<Function> fn;
|
||||
if (!maybe_fn.ToLocal(&fn)) {
|
||||
@@ -293,12 +291,8 @@ void Environment::InitializeDiagnostics() {
|
||||
MaybeLocal<Value> Environment::BootstrapInternalLoaders() {
|
||||
EscapableHandleScope scope(isolate_);
|
||||
|
||||
// Create binding loaders
|
||||
std::vector<Local<String>> loaders_params = {
|
||||
process_string(),
|
||||
FIXED_ONE_BYTE_STRING(isolate_, "getLinkedBinding"),
|
||||
FIXED_ONE_BYTE_STRING(isolate_, "getInternalBinding"),
|
||||
primordials_string()};
|
||||
// Arguments must match the parameters specified in
|
||||
// NativeModuleLoader::LookupAndCompile().
|
||||
std::vector<Local<Value>> loaders_args = {
|
||||
process_object(),
|
||||
NewFunctionTemplate(isolate_, binding::GetLinkedBinding)
|
||||
@@ -311,8 +305,7 @@ MaybeLocal<Value> Environment::BootstrapInternalLoaders() {
|
||||
|
||||
// Bootstrap internal loaders
|
||||
Local<Value> loader_exports;
|
||||
if (!ExecuteBootstrapper(
|
||||
this, "internal/bootstrap/loaders", &loaders_params, &loaders_args)
|
||||
if (!ExecuteBootstrapper(this, "internal/bootstrap/loaders", &loaders_args)
|
||||
.ToLocal(&loader_exports)) {
|
||||
return MaybeLocal<Value>();
|
||||
}
|
||||
@@ -334,28 +327,25 @@ MaybeLocal<Value> Environment::BootstrapInternalLoaders() {
|
||||
MaybeLocal<Value> Environment::BootstrapNode() {
|
||||
EscapableHandleScope scope(isolate_);
|
||||
|
||||
// Arguments must match the parameters specified in
|
||||
// NativeModuleLoader::LookupAndCompile().
|
||||
// process, require, internalBinding, primordials
|
||||
std::vector<Local<String>> node_params = {
|
||||
process_string(),
|
||||
require_string(),
|
||||
internal_binding_string(),
|
||||
primordials_string()};
|
||||
std::vector<Local<Value>> node_args = {
|
||||
process_object(),
|
||||
native_module_require(),
|
||||
internal_binding_loader(),
|
||||
primordials()};
|
||||
|
||||
MaybeLocal<Value> result = ExecuteBootstrapper(
|
||||
this, "internal/bootstrap/node", &node_params, &node_args);
|
||||
MaybeLocal<Value> result =
|
||||
ExecuteBootstrapper(this, "internal/bootstrap/node", &node_args);
|
||||
|
||||
if (result.IsEmpty()) {
|
||||
return MaybeLocal<Value>();
|
||||
}
|
||||
|
||||
if (!no_browser_globals()) {
|
||||
result = ExecuteBootstrapper(
|
||||
this, "internal/bootstrap/browser", &node_params, &node_args);
|
||||
result =
|
||||
ExecuteBootstrapper(this, "internal/bootstrap/browser", &node_args);
|
||||
|
||||
if (result.IsEmpty()) {
|
||||
return MaybeLocal<Value>();
|
||||
@@ -366,8 +356,7 @@ MaybeLocal<Value> Environment::BootstrapNode() {
|
||||
auto thread_switch_id =
|
||||
is_main_thread() ? "internal/bootstrap/switches/is_main_thread"
|
||||
: "internal/bootstrap/switches/is_not_main_thread";
|
||||
result =
|
||||
ExecuteBootstrapper(this, thread_switch_id, &node_params, &node_args);
|
||||
result = ExecuteBootstrapper(this, thread_switch_id, &node_args);
|
||||
|
||||
if (result.IsEmpty()) {
|
||||
return MaybeLocal<Value>();
|
||||
@@ -377,8 +366,7 @@ MaybeLocal<Value> Environment::BootstrapNode() {
|
||||
owns_process_state()
|
||||
? "internal/bootstrap/switches/does_own_process_state"
|
||||
: "internal/bootstrap/switches/does_not_own_process_state";
|
||||
result = ExecuteBootstrapper(
|
||||
this, process_state_switch_id, &node_params, &node_args);
|
||||
result = ExecuteBootstrapper(this, process_state_switch_id, &node_args);
|
||||
|
||||
if (result.IsEmpty()) {
|
||||
return MaybeLocal<Value>();
|
||||
@@ -420,35 +408,20 @@ MaybeLocal<Value> Environment::RunBootstrapping() {
|
||||
return scope.Escape(result);
|
||||
}
|
||||
|
||||
void MarkBootstrapComplete(const FunctionCallbackInfo<Value>& args) {
|
||||
Environment* env = Environment::GetCurrent(args);
|
||||
env->performance_state()->Mark(
|
||||
performance::NODE_PERFORMANCE_MILESTONE_BOOTSTRAP_COMPLETE);
|
||||
}
|
||||
|
||||
static
|
||||
MaybeLocal<Value> StartExecution(Environment* env, const char* main_script_id) {
|
||||
EscapableHandleScope scope(env->isolate());
|
||||
CHECK_NOT_NULL(main_script_id);
|
||||
|
||||
std::vector<Local<String>> parameters = {
|
||||
env->process_string(),
|
||||
env->require_string(),
|
||||
env->internal_binding_string(),
|
||||
env->primordials_string(),
|
||||
FIXED_ONE_BYTE_STRING(env->isolate(), "markBootstrapComplete")};
|
||||
|
||||
std::vector<Local<Value>> arguments = {
|
||||
env->process_object(),
|
||||
env->native_module_require(),
|
||||
env->internal_binding_loader(),
|
||||
env->primordials(),
|
||||
NewFunctionTemplate(env->isolate(), MarkBootstrapComplete)
|
||||
->GetFunction(env->context())
|
||||
.ToLocalChecked()};
|
||||
// Arguments must match the parameters specified in
|
||||
// NativeModuleLoader::LookupAndCompile().
|
||||
std::vector<Local<Value>> arguments = {env->process_object(),
|
||||
env->native_module_require(),
|
||||
env->internal_binding_loader(),
|
||||
env->primordials()};
|
||||
|
||||
return scope.EscapeMaybe(
|
||||
ExecuteBootstrapper(env, main_script_id, ¶meters, &arguments));
|
||||
ExecuteBootstrapper(env, main_script_id, &arguments));
|
||||
}
|
||||
|
||||
MaybeLocal<Value> StartExecution(Environment* env, StartExecutionCallback cb) {
|
||||
@@ -461,8 +434,7 @@ MaybeLocal<Value> StartExecution(Environment* env, StartExecutionCallback cb) {
|
||||
if (cb != nullptr) {
|
||||
EscapableHandleScope scope(env->isolate());
|
||||
|
||||
if (StartExecution(env, "internal/bootstrap/environment").IsEmpty())
|
||||
return {};
|
||||
if (StartExecution(env, "internal/main/environment").IsEmpty()) return {};
|
||||
|
||||
StartExecutionCallbackInfo info = {
|
||||
env->process_object(),
|
||||
|
||||
@@ -308,7 +308,6 @@ v8::MaybeLocal<v8::Object> GetPerContextExports(v8::Local<v8::Context> context);
|
||||
v8::MaybeLocal<v8::Value> ExecuteBootstrapper(
|
||||
Environment* env,
|
||||
const char* id,
|
||||
std::vector<v8::Local<v8::String>>* parameters,
|
||||
std::vector<v8::Local<v8::Value>>* arguments);
|
||||
void MarkBootstrapComplete(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
|
||||
|
||||
@@ -184,21 +184,6 @@ ScriptCompiler::CachedData* NativeModuleLoader::GetCodeCache(
|
||||
return it->second.get();
|
||||
}
|
||||
|
||||
MaybeLocal<Function> NativeModuleLoader::CompileAsModule(
|
||||
Local<Context> context,
|
||||
const char* id,
|
||||
NativeModuleLoader::Result* result) {
|
||||
Isolate* isolate = context->GetIsolate();
|
||||
std::vector<Local<String>> parameters = {
|
||||
FIXED_ONE_BYTE_STRING(isolate, "exports"),
|
||||
FIXED_ONE_BYTE_STRING(isolate, "require"),
|
||||
FIXED_ONE_BYTE_STRING(isolate, "module"),
|
||||
FIXED_ONE_BYTE_STRING(isolate, "process"),
|
||||
FIXED_ONE_BYTE_STRING(isolate, "internalBinding"),
|
||||
FIXED_ONE_BYTE_STRING(isolate, "primordials")};
|
||||
return LookupAndCompileInternal(context, id, ¶meters, result);
|
||||
}
|
||||
|
||||
#ifdef NODE_BUILTIN_MODULES_PATH
|
||||
static std::string OnDiskFileName(const char* id) {
|
||||
std::string filename = NODE_BUILTIN_MODULES_PATH;
|
||||
@@ -360,29 +345,84 @@ MaybeLocal<Function> NativeModuleLoader::LookupAndCompileInternal(
|
||||
MaybeLocal<Function> NativeModuleLoader::LookupAndCompile(
|
||||
Local<Context> context,
|
||||
const char* id,
|
||||
std::vector<Local<String>>* parameters,
|
||||
Environment* optional_env) {
|
||||
Result result;
|
||||
MaybeLocal<Function> maybe =
|
||||
GetInstance()->LookupAndCompileInternal(context, id, parameters, &result);
|
||||
std::vector<Local<String>> parameters;
|
||||
Isolate* isolate = context->GetIsolate();
|
||||
// Detects parameters of the scripts based on module ids.
|
||||
// internal/bootstrap/loaders: process, getLinkedBinding,
|
||||
// getInternalBinding, primordials
|
||||
if (strcmp(id, "internal/bootstrap/loaders") == 0) {
|
||||
parameters = {
|
||||
FIXED_ONE_BYTE_STRING(isolate, "process"),
|
||||
FIXED_ONE_BYTE_STRING(isolate, "getLinkedBinding"),
|
||||
FIXED_ONE_BYTE_STRING(isolate, "getInternalBinding"),
|
||||
FIXED_ONE_BYTE_STRING(isolate, "primordials"),
|
||||
};
|
||||
} else if (strncmp(id,
|
||||
"internal/per_context/",
|
||||
strlen("internal/per_context/")) == 0) {
|
||||
// internal/per_context/*: global, exports, primordials
|
||||
parameters = {
|
||||
FIXED_ONE_BYTE_STRING(isolate, "global"),
|
||||
FIXED_ONE_BYTE_STRING(isolate, "exports"),
|
||||
FIXED_ONE_BYTE_STRING(isolate, "primordials"),
|
||||
};
|
||||
} else if (strncmp(id, "internal/main/", strlen("internal/main/")) == 0) {
|
||||
// internal/main/*: process, require, internalBinding, primordials
|
||||
parameters = {
|
||||
FIXED_ONE_BYTE_STRING(isolate, "process"),
|
||||
FIXED_ONE_BYTE_STRING(isolate, "require"),
|
||||
FIXED_ONE_BYTE_STRING(isolate, "internalBinding"),
|
||||
FIXED_ONE_BYTE_STRING(isolate, "primordials"),
|
||||
};
|
||||
} else if (strncmp(id, "embedder_main_", strlen("embedder_main_")) == 0) {
|
||||
// Synthetic embedder main scripts from LoadEnvironment(): process, require
|
||||
parameters = {
|
||||
FIXED_ONE_BYTE_STRING(isolate, "process"),
|
||||
FIXED_ONE_BYTE_STRING(isolate, "require"),
|
||||
};
|
||||
} else if (strncmp(id,
|
||||
"internal/bootstrap/",
|
||||
strlen("internal/bootstrap/")) == 0) {
|
||||
// internal/bootstrap/*: process, require, internalBinding, primordials
|
||||
parameters = {
|
||||
FIXED_ONE_BYTE_STRING(isolate, "process"),
|
||||
FIXED_ONE_BYTE_STRING(isolate, "require"),
|
||||
FIXED_ONE_BYTE_STRING(isolate, "internalBinding"),
|
||||
FIXED_ONE_BYTE_STRING(isolate, "primordials"),
|
||||
};
|
||||
} else {
|
||||
// others: exports, require, module, process, internalBinding, primordials
|
||||
parameters = {
|
||||
FIXED_ONE_BYTE_STRING(isolate, "exports"),
|
||||
FIXED_ONE_BYTE_STRING(isolate, "require"),
|
||||
FIXED_ONE_BYTE_STRING(isolate, "module"),
|
||||
FIXED_ONE_BYTE_STRING(isolate, "process"),
|
||||
FIXED_ONE_BYTE_STRING(isolate, "internalBinding"),
|
||||
FIXED_ONE_BYTE_STRING(isolate, "primordials"),
|
||||
};
|
||||
}
|
||||
|
||||
MaybeLocal<Function> maybe = GetInstance()->LookupAndCompileInternal(
|
||||
context, id, ¶meters, &result);
|
||||
if (optional_env != nullptr) {
|
||||
RecordResult(id, result, optional_env);
|
||||
}
|
||||
return maybe;
|
||||
}
|
||||
|
||||
bool NativeModuleLoader::CompileAllModules(Local<Context> context) {
|
||||
bool NativeModuleLoader::CompileAllBuiltins(Local<Context> context) {
|
||||
NativeModuleLoader* loader = GetInstance();
|
||||
std::vector<std::string> ids = loader->GetModuleIds();
|
||||
bool all_succeeded = true;
|
||||
std::string v8_tools_prefix = "internal/deps/v8/tools/";
|
||||
for (const auto& id : ids) {
|
||||
// TODO(joyeecheung): compile non-module scripts here too.
|
||||
if (!loader->CanBeRequired(id.c_str())) {
|
||||
if (id.compare(0, v8_tools_prefix.size(), v8_tools_prefix) == 0) {
|
||||
continue;
|
||||
}
|
||||
v8::TryCatch bootstrapCatch(context->GetIsolate());
|
||||
Result result;
|
||||
USE(loader->CompileAsModule(context, id.c_str(), &result));
|
||||
USE(loader->LookupAndCompile(context, id.c_str(), nullptr));
|
||||
if (bootstrapCatch.HasCaught()) {
|
||||
per_process::Debug(DebugCategory::CODE_CACHE,
|
||||
"Failed to compile code cache for %s\n",
|
||||
@@ -538,16 +578,15 @@ void NativeModuleLoader::RecordResult(const char* id,
|
||||
env->native_modules_without_cache.insert(id);
|
||||
}
|
||||
}
|
||||
|
||||
void NativeModuleLoader::CompileFunction(
|
||||
const FunctionCallbackInfo<Value>& args) {
|
||||
Environment* env = Environment::GetCurrent(args);
|
||||
CHECK(args[0]->IsString());
|
||||
node::Utf8Value id_v(env->isolate(), args[0].As<String>());
|
||||
const char* id = *id_v;
|
||||
NativeModuleLoader::Result result;
|
||||
MaybeLocal<Function> maybe =
|
||||
GetInstance()->CompileAsModule(env->context(), id, &result);
|
||||
RecordResult(id, result, env);
|
||||
GetInstance()->LookupAndCompile(env->context(), id, env);
|
||||
Local<Function> fn;
|
||||
if (maybe.ToLocal(&fn)) {
|
||||
args.GetReturnValue().Set(fn);
|
||||
|
||||
@@ -45,10 +45,11 @@ class NODE_EXTERN_PRIVATE NativeModuleLoader {
|
||||
v8::Local<v8::Context> context,
|
||||
void* priv);
|
||||
|
||||
// The parameters used to compile the scripts are detected based on
|
||||
// the pattern of the id.
|
||||
static v8::MaybeLocal<v8::Function> LookupAndCompile(
|
||||
v8::Local<v8::Context> context,
|
||||
const char* id,
|
||||
std::vector<v8::Local<v8::String>>* parameters,
|
||||
Environment* optional_env);
|
||||
|
||||
static v8::Local<v8::Object> GetSourceObject(v8::Local<v8::Context> context);
|
||||
@@ -57,7 +58,7 @@ class NODE_EXTERN_PRIVATE NativeModuleLoader {
|
||||
static bool Exists(const char* id);
|
||||
static bool Add(const char* id, const UnionBytes& source);
|
||||
|
||||
static bool CompileAllModules(v8::Local<v8::Context> context);
|
||||
static bool CompileAllBuiltins(v8::Local<v8::Context> context);
|
||||
static void RefreshCodeCache(const std::vector<CodeCacheInfo>& in);
|
||||
static void CopyCodeCache(std::vector<CodeCacheInfo>* out);
|
||||
|
||||
@@ -100,9 +101,6 @@ class NODE_EXTERN_PRIVATE NativeModuleLoader {
|
||||
const char* id,
|
||||
std::vector<v8::Local<v8::String>>* parameters,
|
||||
Result* result);
|
||||
v8::MaybeLocal<v8::Function> CompileAsModule(v8::Local<v8::Context> context,
|
||||
const char* id,
|
||||
Result* result);
|
||||
|
||||
static void RecordResult(const char* id,
|
||||
NativeModuleLoader::Result result,
|
||||
|
||||
@@ -267,6 +267,12 @@ void GetTimeOriginTimeStamp(const FunctionCallbackInfo<Value>& args) {
|
||||
args.GetIsolate(), env->time_origin_timestamp() / MICROS_PER_MILLIS));
|
||||
}
|
||||
|
||||
void MarkBootstrapComplete(const FunctionCallbackInfo<Value>& args) {
|
||||
Environment* env = Environment::GetCurrent(args);
|
||||
env->performance_state()->Mark(
|
||||
performance::NODE_PERFORMANCE_MILESTONE_BOOTSTRAP_COMPLETE);
|
||||
}
|
||||
|
||||
void Initialize(Local<Object> target,
|
||||
Local<Value> unused,
|
||||
Local<Context> context,
|
||||
@@ -306,6 +312,7 @@ void Initialize(Local<Object> target,
|
||||
SetMethod(context, target, "getTimeOrigin", GetTimeOrigin);
|
||||
SetMethod(context, target, "getTimeOriginTimestamp", GetTimeOriginTimeStamp);
|
||||
SetMethod(context, target, "createELDHistogram", CreateELDHistogram);
|
||||
SetMethod(context, target, "markBootstrapComplete", MarkBootstrapComplete);
|
||||
|
||||
Local<Object> constants = Object::New(isolate);
|
||||
|
||||
@@ -360,6 +367,7 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
|
||||
registry->Register(GetTimeOrigin);
|
||||
registry->Register(GetTimeOriginTimeStamp);
|
||||
registry->Register(CreateELDHistogram);
|
||||
registry->Register(MarkBootstrapComplete);
|
||||
HistogramBase::RegisterExternalReferences(registry);
|
||||
IntervalHistogram::RegisterExternalReferences(registry);
|
||||
}
|
||||
|
||||
@@ -986,7 +986,8 @@ int SnapshotBuilder::Generate(SnapshotData* out,
|
||||
|
||||
#ifdef NODE_USE_NODE_CODE_CACHE
|
||||
// Regenerate all the code cache.
|
||||
if (!native_module::NativeModuleLoader::CompileAllModules(main_context)) {
|
||||
if (!native_module::NativeModuleLoader::CompileAllBuiltins(
|
||||
main_context)) {
|
||||
return UNCAUGHT_EXCEPTION_ERROR;
|
||||
}
|
||||
native_module::NativeModuleLoader::CopyCodeCache(&(out->code_cache));
|
||||
@@ -1220,7 +1221,6 @@ void Initialize(Local<Object> target,
|
||||
Local<Context> context,
|
||||
void* priv) {
|
||||
SetMethod(context, target, "compileSerializeMain", CompileSerializeMain);
|
||||
SetMethod(context, target, "markBootstrapComplete", MarkBootstrapComplete);
|
||||
SetMethod(context, target, "setSerializeCallback", SetSerializeCallback);
|
||||
SetMethod(context, target, "setDeserializeCallback", SetDeserializeCallback);
|
||||
SetMethod(context,
|
||||
@@ -1231,7 +1231,6 @@ void Initialize(Local<Object> target,
|
||||
|
||||
void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
|
||||
registry->Register(CompileSerializeMain);
|
||||
registry->Register(MarkBootstrapComplete);
|
||||
registry->Register(SetSerializeCallback);
|
||||
registry->Register(SetDeserializeCallback);
|
||||
registry->Register(SetDeserializeMainFunction);
|
||||
|
||||
@@ -52,7 +52,6 @@ const expectedModules = new Set([
|
||||
'NativeModule internal/assert',
|
||||
'NativeModule internal/async_hooks',
|
||||
'NativeModule internal/blocklist',
|
||||
'NativeModule internal/bootstrap/pre_execution',
|
||||
'NativeModule internal/buffer',
|
||||
'NativeModule internal/console/constructor',
|
||||
'NativeModule internal/console/global',
|
||||
@@ -105,6 +104,7 @@ const expectedModules = new Set([
|
||||
'NativeModule internal/process/esm_loader',
|
||||
'NativeModule internal/process/execution',
|
||||
'NativeModule internal/process/per_thread',
|
||||
'NativeModule internal/process/pre_execution',
|
||||
'NativeModule internal/process/promises',
|
||||
'NativeModule internal/process/report',
|
||||
'NativeModule internal/process/signal',
|
||||
|
||||
@@ -12,7 +12,7 @@ const {
|
||||
} = require('internal/test/binding');
|
||||
const {
|
||||
getCacheUsage,
|
||||
moduleCategories: { canBeRequired, cannotBeRequired }
|
||||
moduleCategories: { canBeRequired }
|
||||
} = internalBinding('native_module');
|
||||
|
||||
for (const key of canBeRequired) {
|
||||
@@ -54,20 +54,12 @@ if (!process.features.cached_builtins) {
|
||||
} else { // Native compiled
|
||||
assert(process.config.variables.node_use_node_code_cache);
|
||||
|
||||
if (!isMainThread) {
|
||||
for (const key of [ 'internal/bootstrap/pre_execution' ]) {
|
||||
canBeRequired.add(key);
|
||||
cannotBeRequired.delete(key);
|
||||
}
|
||||
}
|
||||
|
||||
const wrong = [];
|
||||
for (const key of loadedModules) {
|
||||
if (cannotBeRequired.has(key) && !compiledWithoutCache.has(key)) {
|
||||
wrong.push(`"${key}" should've been compiled **without** code cache`);
|
||||
if (key.startsWith('internal/deps/v8/tools')) {
|
||||
continue;
|
||||
}
|
||||
if (canBeRequired.has(key) &&
|
||||
!compiledWithCache.has(key) &&
|
||||
if (!compiledWithCache.has(key) &&
|
||||
compiledInSnapshot.indexOf(key) === -1) {
|
||||
wrong.push(`"${key}" should've been compiled **with** code cache`);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user