| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 660da78 commit bc009d0
15 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -10,6 +10,9 @@ changes: | |||
| 10 | 10 | - version: REPLACEME | |
| 11 | 11 | pr-url: https://github.com/nodejs/node/pull/46824 | |
| 12 | 12 | description: Added support for "useSnapshot". | |
| 13 | + - version: REPLACEME | ||
| 14 | + pr-url: https://github.com/nodejs/node/pull/48191 | ||
| 15 | + description: Added support for "useCodeCache". | ||
| 13 | 16 | --> | |
| 14 | 17 | ||
| 15 | 18 | > Stability: 1 - Experimental: This feature is being designed and will change. | |
@@ -174,7 +177,8 @@ The configuration currently reads the following top-level fields: | |||
| 174 | 177 | "main": "/path/to/bundled/script.js", | |
| 175 | 178 | "output": "/path/to/write/the/generated/blob.blob", | |
| 176 | 179 | "disableExperimentalSEAWarning": true, // Default: false | |
| 177 | - "useSnapshot": false // Default: false | ||
| 180 | + "useSnapshot": false, // Default: false | ||
| 181 | + "useCodeCache": true // Default: false | ||
| 178 | 182 | } | |
| 179 | 183 | ``` | |
| 180 | 184 | ||
@@ -213,6 +217,18 @@ and the main script can use the [`v8.startupSnapshot` API][] to adapt to | |||
| 213 | 217 | these constraints. See | |
| 214 | 218 | [documentation about startup snapshot support in Node.js][]. | |
| 215 | 219 | ||
| 220 | + ### V8 code cache support | ||
| 221 | + | ||
| 222 | + When `useCodeCache` is set to `true` in the configuration, during the generation | ||
| 223 | + of the single executable preparation blob, Node.js will compile the `main` | ||
| 224 | + script to generate the V8 code cache. The generated code cache would be part of | ||
| 225 | + the preparation blob and get injected into the final executable. When the single | ||
| 226 | + executable application is launched, instead of compiling the `main` script from | ||
| 227 | + scratch, Node.js would use the code cache to speed up the compilation, then | ||
| 228 | + execute the script, which would improve the startup performance. | ||
| 229 | + | ||
| 230 | + **Note:** `import()` does not work when `useCodeCache` is `true`. | ||
| 231 | + | ||
| 216 | 232 | ## Notes | |
| 217 | 233 | ||
| 218 | 234 | ### `require(id)` in the injected module is not file based | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1123,7 +1123,7 @@ Module.prototype.require = function(id) { | |||
| 1123 | 1123 | let resolvedArgv; | |
| 1124 | 1124 | let hasPausedEntry = false; | |
| 1125 | 1125 | let Script; | |
| 1126 | - function wrapSafe(filename, content, cjsModuleInstance) { | ||
| 1126 | + function wrapSafe(filename, content, cjsModuleInstance, codeCache) { | ||
| 1127 | 1127 | if (patched) { | |
| 1128 | 1128 | const wrapper = Module.wrap(content); | |
| 1129 | 1129 | if (Script === undefined) { | |
@@ -1158,13 +1158,21 @@ function wrapSafe(filename, content, cjsModuleInstance) { | |||
| 1158 | 1158 | '__dirname', | |
| 1159 | 1159 | ], { | |
| 1160 | 1160 | filename, | |
| 1161 | + cachedData: codeCache, | ||
| 1161 | 1162 | importModuleDynamically(specifier, _, importAssertions) { | |
| 1162 | 1163 | const cascadedLoader = getCascadedLoader(); | |
| 1163 | 1164 | return cascadedLoader.import(specifier, normalizeReferrerURL(filename), | |
| 1164 | 1165 | importAssertions); | |
| 1165 | 1166 | }, | |
| 1166 | 1167 | }); | |
| 1167 | 1168 | ||
| 1169 | + // The code cache is used for SEAs only. | ||
| 1170 | + if (codeCache && | ||
| 1171 | + result.cachedDataRejected !== false && | ||
| 1172 | + internalBinding('sea').isSea()) { | ||
| 1173 | + process.emitWarning('Code cache data rejected.'); | ||
| 1174 | + } | ||
| 1175 | + | ||
| 1168 | 1176 | // Cache the source map for the module if present. | |
| 1169 | 1177 | if (result.sourceMapURL) { | |
| 1170 | 1178 | maybeCacheSourceMap(filename, content, this, false, undefined, result.sourceMapURL); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,7 +1,8 @@ | |||
| 1 | 1 | 'use strict'; | |
| 2 | - const { codes: { ERR_UNKNOWN_BUILTIN_MODULE } } = require('internal/errors'); | ||
| 3 | 2 | const { BuiltinModule: { normalizeRequirableId } } = require('internal/bootstrap/realm'); | |
| 4 | 3 | const { Module, wrapSafe } = require('internal/modules/cjs/loader'); | |
| 4 | + const { codes: { ERR_UNKNOWN_BUILTIN_MODULE } } = require('internal/errors'); | ||
| 5 | + const { getCodeCache, getCodePath, isSea } = internalBinding('sea'); | ||
| 5 | 6 | ||
| 6 | 7 | // This is roughly the same as: | |
| 7 | 8 | // | |
@@ -15,7 +16,11 @@ const { Module, wrapSafe } = require('internal/modules/cjs/loader'); | |||
| 15 | 16 | ||
| 16 | 17 | function embedderRunCjs(contents) { | |
| 17 | 18 | const filename = process.execPath; | |
| 18 | - const compiledWrapper = wrapSafe(filename, contents); | ||
| 19 | + const compiledWrapper = wrapSafe( | ||
| 20 | + isSea() ? getCodePath() : filename, | ||
| 21 | + contents, | ||
| 22 | + undefined, | ||
| 23 | + getCodeCache()); | ||
| 19 | 24 | ||
| 20 | 25 | const customModule = new Module(filename, null); | |
| 21 | 26 | customModule.filename = filename; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -4,34 +4,15 @@ | |||
| 4 | 4 | #include "util-inl.h" | |
| 5 | 5 | ||
| 6 | 6 | namespace node { | |
| 7 | - using v8::ArrayBuffer; | ||
| 8 | 7 | using v8::Context; | |
| 9 | 8 | using v8::Isolate; | |
| 10 | 9 | using v8::Local; | |
| 11 | 10 | using v8::Object; | |
| 12 | 11 | using v8::String; | |
| 13 | 12 | using v8::Value; | |
| 14 | 13 | ||
| 15 | - static Isolate* NewIsolate(v8::ArrayBuffer::Allocator* allocator) { | ||
| 16 | - Isolate* isolate = Isolate::Allocate(); | ||
| 17 | - CHECK_NOT_NULL(isolate); | ||
| 18 | - per_process::v8_platform.Platform()->RegisterIsolate(isolate, | ||
| 19 | - uv_default_loop()); | ||
| 20 | - Isolate::CreateParams params; | ||
| 21 | - params.array_buffer_allocator = allocator; | ||
| 22 | - Isolate::Initialize(isolate, params); | ||
| 23 | - return isolate; | ||
| 24 | - } | ||
| 25 | - | ||
| 26 | - void JSONParser::FreeIsolate(Isolate* isolate) { | ||
| 27 | - per_process::v8_platform.Platform()->UnregisterIsolate(isolate); | ||
| 28 | - isolate->Dispose(); | ||
| 29 | - } | ||
| 30 | - | ||
| 31 | 14 | JSONParser::JSONParser() | |
| 32 | - : allocator_(ArrayBuffer::Allocator::NewDefaultAllocator()), | ||
| 33 | - isolate_(NewIsolate(allocator_.get())), | ||
| 34 | - handle_scope_(isolate_.get()), | ||
| 15 | + : handle_scope_(isolate_.get()), | ||
| 35 | 16 | context_(isolate_.get(), Context::New(isolate_.get())), | |
| 36 | 17 | context_scope_(context_.Get(isolate_.get())) {} | |
| 37 | 18 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -24,9 +24,7 @@ class JSONParser { | |||
| 24 | 24 | private: | |
| 25 | 25 | // We might want a lighter-weight JSON parser for this use case. But for now | |
| 26 | 26 | // using V8 is good enough. | |
| 27 | - static void FreeIsolate(v8::Isolate* isolate); | ||
| 28 | - std::unique_ptr<v8::ArrayBuffer::Allocator> allocator_; | ||
| 29 | - DeleteFnPtr<v8::Isolate, FreeIsolate> isolate_; | ||
| 27 | + RAIIIsolate isolate_; | ||
| 30 | 28 | v8::HandleScope handle_scope_; | |
| 31 | 29 | v8::Global<v8::Context> context_; | |
| 32 | 30 | v8::Context::Scope context_scope_; | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -935,6 +935,22 @@ Maybe<bool> StoreCodeCacheResult( | |||
| 935 | 935 | return Just(true); | |
| 936 | 936 | } | |
| 937 | 937 | ||
| 938 | + // TODO(RaisinTen): Reuse in ContextifyContext::CompileFunction(). | ||
| 939 | + MaybeLocal<Function> CompileFunction(Local<Context> context, | ||
| 940 | + Local<String> filename, | ||
| 941 | + Local<String> content, | ||
| 942 | + std::vector<Local<String>>* parameters) { | ||
| 943 | + ScriptOrigin script_origin(context->GetIsolate(), filename, 0, 0, true); | ||
| 944 | + ScriptCompiler::Source script_source(content, script_origin); | ||
| 945 | + | ||
| 946 | + return ScriptCompiler::CompileFunction(context, | ||
| 947 | + &script_source, | ||
| 948 | + parameters->size(), | ||
| 949 | + parameters->data(), | ||
| 950 | + 0, | ||
| 951 | + nullptr); | ||
| 952 | + } | ||
| 953 | + | ||
| 938 | 954 | bool ContextifyScript::InstanceOf(Environment* env, | |
| 939 | 955 | const Local<Value>& value) { | |
| 940 | 956 | return !value.IsEmpty() && | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -210,6 +210,12 @@ v8::Maybe<bool> StoreCodeCacheResult( | |||
| 210 | 210 | bool produce_cached_data, | |
| 211 | 211 | std::unique_ptr<v8::ScriptCompiler::CachedData> new_cached_data); | |
| 212 | 212 | ||
| 213 | + v8::MaybeLocal<v8::Function> CompileFunction( | ||
| 214 | + v8::Local<v8::Context> context, | ||
| 215 | + v8::Local<v8::String> filename, | ||
| 216 | + v8::Local<v8::String> content, | ||
| 217 | + std::vector<v8::Local<v8::String>>* parameters); | ||
| 218 | + | ||
| 213 | 219 | } // namespace contextify | |
| 214 | 220 | } // namespace node | |
| 215 | 221 | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments