diff --git a/lib/internal/bootstrap/cache.js b/lib/internal/bootstrap/cache.js index 17c14e816ff668..e7e46bdf5174d5 100644 --- a/lib/internal/bootstrap/cache.js +++ b/lib/internal/bootstrap/cache.js @@ -9,23 +9,50 @@ const { NativeModule, internalBinding } = require('internal/bootstrap/loaders'); +function getCodeCache(id) { + const cached = NativeModule.getCached(id); + if (cached && (cached.loaded || cached.loading)) { + return cached.script.createCachedData(); + } + + // The script has not been compiled and run + NativeModule.require(id); + return getCodeCache(id); +} + +const depsModule = Object.keys(NativeModule._source).filter( + (key) => NativeModule.isDepsModule(key) || key.startsWith('internal/deps') +); + +// Modules with source code compiled in js2c that +// cannot be compiled with the code cache +const cannotUseCache = [ + 'config', + 'sys', // deprecated + 'internal/v8_prof_polyfill', + 'internal/v8_prof_processor', + + 'internal/per_context', + + 'internal/test/binding', + // TODO(joyeecheung): update the C++ side so that + // the code cache is also used when compiling these + // two files. + 'internal/bootstrap/loaders', + 'internal/bootstrap/node' +].concat(depsModule); + module.exports = { + cachableBuiltins: Object.keys(NativeModule._source).filter( + (key) => !cannotUseCache.includes(key) + ), builtinSource: Object.assign({}, NativeModule._source), + getCodeCache, codeCache: internalBinding('code_cache'), compiledWithoutCache: NativeModule.compiledWithoutCache, compiledWithCache: NativeModule.compiledWithCache, nativeModuleWrap(script) { return NativeModule.wrap(script); }, - // Modules with source code compiled in js2c that - // cannot be compiled with the code cache - cannotUseCache: [ - 'config', - // TODO(joyeecheung): update the C++ side so that - // the code cache is also used when compiling these - // two files. - 'internal/bootstrap/loaders', - 'internal/bootstrap/node', - 'internal/per_context', - ] + cannotUseCache }; diff --git a/lib/internal/bootstrap/loaders.js b/lib/internal/bootstrap/loaders.js index c141c9adcff9b2..e85d5de9b79a49 100644 --- a/lib/internal/bootstrap/loaders.js +++ b/lib/internal/bootstrap/loaders.js @@ -118,6 +118,7 @@ this.exportKeys = undefined; this.loaded = false; this.loading = false; + this.script = null; // The ContextifyScript of the module } NativeModule._source = getBinding('natives'); @@ -165,11 +166,14 @@ return nativeModule.exports; }; + NativeModule.isDepsModule = function(id) { + return id.startsWith('node-inspect/') || id.startsWith('v8/'); + }; + NativeModule.requireForDeps = function(id) { if (!NativeModule.exists(id) || // TODO(TimothyGu): remove when DEP0084 reaches end of life. - id.startsWith('node-inspect/') || - id.startsWith('v8/')) { + NativeModule.isDepsModule(id)) { id = `internal/deps/${id}`; } return NativeModule.require(id); @@ -241,6 +245,8 @@ codeCache[this.id], false, undefined ); + this.script = script; + // One of these conditions may be false when any of the inputs // of the `node_js2c` target in node.gyp is modified. // FIXME(joyeecheung): diff --git a/test/code-cache/test-code-cache.js b/test/code-cache/test-code-cache.js index a4378343010ee6..b05e764e8ad290 100644 --- a/test/code-cache/test-code-cache.js +++ b/test/code-cache/test-code-cache.js @@ -12,9 +12,8 @@ const { } } = require('util'); const { - builtinSource, + cachableBuiltins, codeCache, - cannotUseCache, compiledWithCache, compiledWithoutCache } = require('internal/bootstrap/cache'); @@ -35,8 +34,7 @@ for (const key of loadedModules) { `"${key}" should've been compiled with code cache`); } -for (const key of Object.keys(builtinSource)) { - if (cannotUseCache.includes(key)) continue; +for (const key of cachableBuiltins) { assert(isUint8Array(codeCache[key]) && codeCache[key].length > 0, `Code cache for "${key}" should've been generated`); } diff --git a/tools/generate_code_cache.js b/tools/generate_code_cache.js index 8aab6bc286d288..740cbd718aa11e 100644 --- a/tools/generate_code_cache.js +++ b/tools/generate_code_cache.js @@ -8,12 +8,10 @@ // of `configure`. const { - nativeModuleWrap, - builtinSource, - cannotUseCache + getCodeCache, + cachableBuiltins } = require('internal/bootstrap/cache'); -const vm = require('vm'); const fs = require('fs'); const resultPath = process.argv[2]; @@ -72,25 +70,16 @@ const cacheInitializers = []; let totalCacheSize = 0; -for (const key of Object.keys(builtinSource)) { - if (cannotUseCache.includes(key)) continue; - const code = nativeModuleWrap(builtinSource[key]); - - // Note that this must corresponds to the code in - // NativeModule.prototype.compile - const script = new vm.Script(code, { - filename: `${key}.js`, - produceCachedData: true - }); - - if (!script.cachedData) { +for (const key of cachableBuiltins) { + const cachedData = getCodeCache(key); + if (!cachedData.length) { console.error(`Failed to generate code cache for '${key}'`); process.exit(1); } - const length = script.cachedData.length; + const length = cachedData.length; totalCacheSize += length; - const { definition, initializer } = getInitalizer(key, script.cachedData); + const { definition, initializer } = getInitalizer(key, cachedData); cacheDefinitions.push(definition); cacheInitializers.push(initializer); console.log(`Generated cache for '${key}', size = ${formatSize(length)}` +