diff --git a/Makefile b/Makefile index 346f355ea7a298..d4e805c1d54428 100644 --- a/Makefile +++ b/Makefile @@ -103,25 +103,17 @@ $(NODE_G_EXE): config.gypi out/Makefile $(MAKE) -C out BUILDTYPE=Debug V=$(V) if [ ! -r $@ -o ! -L $@ ]; then ln -fs out/Debug/$(NODE_EXE) $@; fi -CODE_CACHE_DIR ?= out/$(BUILDTYPE)/obj/gen -CODE_CACHE_FILE ?= $(CODE_CACHE_DIR)/node_code_cache.cc - ifeq ($(BUILDTYPE),Debug) CONFIG_FLAGS += --debug endif + .PHONY: with-code-cache with-code-cache: - @echo $(CONFIG_FLAGS) - $(PYTHON) ./configure $(CONFIG_FLAGS) - $(MAKE) - mkdir -p $(CODE_CACHE_DIR) - out/$(BUILDTYPE)/$(NODE_EXE) --expose-internals tools/generate_code_cache.js $(CODE_CACHE_FILE) - $(PYTHON) ./configure --code-cache-path $(CODE_CACHE_FILE) $(CONFIG_FLAGS) - $(MAKE) + echo "'with-code-cache' target is a noop" .PHONY: test-code-cache test-code-cache: with-code-cache - $(PYTHON) tools/test.py $(PARALLEL_ARGS) --mode=$(BUILDTYPE_LOWER) code-cache + echo "'test-code-cache' target is a noop" out/Makefile: config.gypi common.gypi node.gyp \ deps/uv/uv.gyp deps/http_parser/http_parser.gyp deps/zlib/zlib.gyp \ @@ -1232,6 +1224,8 @@ LINT_CPP_FILES = $(filter-out $(LINT_CPP_EXCLUDE), $(wildcard \ test/node-api/*/*.h \ tools/icu/*.cc \ tools/icu/*.h \ + tools/code_cache/*.cc \ + tools/code_cache/*.h \ )) # Code blocks don't have newline at the end, diff --git a/configure.py b/configure.py index f32e82e6f201c3..a3a412e3a7d542 100755 --- a/configure.py +++ b/configure.py @@ -485,8 +485,9 @@ parser.add_option('--code-cache-path', action='store', dest='code_cache_path', - help='Use a file generated by tools/generate_code_cache.js to compile the' - ' code cache for builtin modules into the binary') + help='optparse.SUPPRESS_HELP') + +# End dummy list. parser.add_option('--without-ssl', action='store_true', @@ -1050,8 +1051,7 @@ def configure_node(o): o['variables']['debug_nghttp2'] = 'false' o['variables']['node_no_browser_globals'] = b(options.no_browser_globals) - if options.code_cache_path: - o['variables']['node_code_cache_path'] = options.code_cache_path + o['variables']['node_code_cache_path'] = 'yes' o['variables']['node_shared'] = b(options.shared) node_module_version = getmoduleversion.get_version() diff --git a/node.gyp b/node.gyp index ead1d67ff2fb46..8809c5204a587e 100644 --- a/node.gyp +++ b/node.gyp @@ -6,7 +6,6 @@ 'node_use_dtrace%': 'false', 'node_use_etw%': 'false', 'node_no_browser_globals%': 'false', - 'node_code_cache_path%': '', 'node_use_v8_platform%': 'true', 'node_use_bundled_v8%': 'true', 'node_shared%': 'false', @@ -224,6 +223,7 @@ 'deps/acorn/acorn/dist/acorn.js', 'deps/acorn/acorn-walk/dist/walk.js', ], + 'mkcodecache_exec': '<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)mkcodecache<(EXECUTABLE_SUFFIX)', 'conditions': [ [ 'node_shared=="true"', { 'node_target_type%': 'shared_library', @@ -280,16 +280,24 @@ { 'target_name': '<(node_core_target_name)', 'type': 'executable', - 'sources': [ - 'src/node_main.cc' + + 'defines': [ + 'NODE_WANT_INTERNALS=1', ], + 'includes': [ 'node.gypi' ], + 'include_dirs': [ 'src', 'deps/v8/include' ], + + 'sources': [ + 'src/node_main.cc' + ], + 'dependencies': [ 'deps/histogram/histogram.gyp:histogram' ], 'msvs_settings': { @@ -402,7 +410,32 @@ 'LinkIncremental': 2 # enable incremental linking }, }, - }] + }], + ['want_separate_host_toolset==0', { + 'dependencies': [ + 'mkcodecache', + ], + 'actions': [ + { + 'action_name': 'run_mkcodecache', + 'process_outputs_as_sources': 1, + 'inputs': [ + '<(mkcodecache_exec)', + ], + 'outputs': [ + '<(SHARED_INTERMEDIATE_DIR)/node_code_cache.cc', + ], + 'action': [ + '<@(_inputs)', + '<@(_outputs)', + ], + }, + ], + }, { + 'sources': [ + 'src/node_code_cache_stub.cc' + ], + }], ], }, # node_core_target_name { @@ -615,11 +648,6 @@ 'msvs_disabled_warnings!': [4244], 'conditions': [ - [ 'node_code_cache_path!=""', { - 'sources': [ '<(node_code_cache_path)' ] - }, { - 'sources': [ 'src/node_code_cache_stub.cc' ] - }], [ 'node_shared=="true" and node_module_version!="" and OS!="win"', { 'product_extension': '<(shlib_suffix)', 'xcode_settings': { @@ -1047,6 +1075,7 @@ 'defines': [ 'NODE_WANT_INTERNALS=1' ], 'sources': [ + 'src/node_code_cache_stub.cc', 'test/cctest/node_test_fixture.cc', 'test/cctest/test_aliased_buffer.cc', 'test/cctest/test_base64.cc', @@ -1075,7 +1104,9 @@ 'HAVE_INSPECTOR=1', ], }, { - 'defines': [ 'HAVE_INSPECTOR=0' ] + 'defines': [ + 'HAVE_INSPECTOR=0', + ] }], ['OS=="solaris"', { 'ldflags': [ '-I<(SHARED_INTERMEDIATE_DIR)' ] @@ -1103,21 +1134,77 @@ }], ], }, # cctest - ], # end targets + # TODO(joyeecheung): do not depend on node_lib, + # instead create a smaller static library node_lib_base that does + # just enough for node_native_module.cc and the cache builder to + # compile without compiling the generated code cache C++ file. + # So generate_code_cache -> mkcodecache -> node_lib_base, + # node_lib -> node_lib_base & generate_code_cache + { + 'target_name': 'mkcodecache', + 'type': 'executable', + + 'dependencies': [ + '<(node_lib_target_name)', + 'deps/histogram/histogram.gyp:histogram', + ], + + 'includes': [ + 'node.gypi' + ], + + 'include_dirs': [ + 'src', + 'tools/msvs/genfiles', + 'deps/v8/include', + 'deps/cares/include', + 'deps/uv/include', + ], + + 'defines': [ + 'NODE_WANT_INTERNALS=1' + ], + 'sources': [ + 'src/node_code_cache_stub.cc', + 'tools/code_cache/mkcodecache.cc', + 'tools/code_cache/cache_builder.cc', + 'tools/code_cache/cache_builder.h', + ], + + 'conditions': [ + [ 'node_report=="true"', { + 'conditions': [ + ['OS=="win"', { + 'libraries': [ + 'dbghelp.lib', + 'PsApi.lib', + 'Ws2_32.lib', + ], + 'dll_files': [ + 'dbghelp.dll', + 'PsApi.dll', + 'Ws2_32.dll', + ], + }], + ], + }], + ], + }, # mkcodecache + ], # end targets 'conditions': [ - [ 'OS=="aix" and node_shared=="true"', { + ['OS=="aix" and node_shared=="true"', { 'targets': [ { 'target_name': 'node_aix_shared', 'type': 'shared_library', 'product_name': '<(node_core_target_name)', - 'ldflags': [ '--shared' ], + 'ldflags': ['--shared'], 'product_extension': '<(shlib_suffix)', 'includes': [ 'node.gypi' ], - 'dependencies': [ '<(node_lib_target_name)' ], + 'dependencies': ['<(node_lib_target_name)'], 'include_dirs': [ 'src', 'deps/v8/include', diff --git a/node.gypi b/node.gypi index d6c4c2669834bf..10c09a68829562 100644 --- a/node.gypi +++ b/node.gypi @@ -143,8 +143,8 @@ 'conditions': [ ['OS!="aix" and node_shared=="false"', { 'ldflags': [ - '-Wl,--whole-archive,<(obj_dir)/deps/zlib/<(STATIC_LIB_PREFIX)' - 'zlib<(STATIC_LIB_SUFFIX)', + '-Wl,--whole-archive,' + '<(obj_dir)/deps/zlib/<(STATIC_LIB_PREFIX)zlib<(STATIC_LIB_SUFFIX)', '-Wl,--no-whole-archive', ], }], @@ -184,8 +184,8 @@ 'conditions': [ ['OS!="aix" and node_shared=="false"', { 'ldflags': [ - '-Wl,--whole-archive,<(obj_dir)/deps/uv/<(STATIC_LIB_PREFIX)' - 'uv<(STATIC_LIB_SUFFIX)', + '-Wl,--whole-archive,' + '<(obj_dir)/deps/uv/<(STATIC_LIB_PREFIX)uv<(STATIC_LIB_SUFFIX)', '-Wl,--no-whole-archive', ], }], @@ -223,27 +223,33 @@ [ 'OS=="aix"', { 'defines': [ '_LINUX_SOURCE_COMPAT', - '__STDC_FORMAT_MACROS' + '__STDC_FORMAT_MACROS', ], 'conditions': [ [ 'force_load=="true"', { - + 'variables': { + 'exp_filename': '<(PRODUCT_DIR)/<(_target_name).exp', + }, 'actions': [ { 'action_name': 'expfile', 'inputs': [ - '<(obj_dir)' + '<(obj_dir)', ], 'outputs': [ - '<(PRODUCT_DIR)/node.exp' + '<(exp_filename)', ], 'action': [ 'sh', 'tools/create_expfile.sh', - '<@(_inputs)', '<@(_outputs)' + '<@(_inputs)', + '<@(_outputs)', ], } ], - 'ldflags': ['-Wl,-bE:<(PRODUCT_DIR)/node.exp', '-Wl,-brtl'], + 'ldflags': [ + '-Wl,-bE:<(exp_filename)', + '-Wl,-brtl', + ], }], ], }], diff --git a/src/node_native_module_env.cc b/src/node_native_module_env.cc index fc48436dc14d44..171c649a19dd65 100644 --- a/src/node_native_module_env.cc +++ b/src/node_native_module_env.cc @@ -4,7 +4,6 @@ namespace node { namespace native_module { -using v8::ArrayBuffer; using v8::Context; using v8::DEFAULT; using v8::Function; @@ -18,11 +17,9 @@ using v8::Name; using v8::None; using v8::Object; using v8::PropertyCallbackInfo; -using v8::ScriptCompiler; using v8::Set; using v8::SideEffectType; using v8::String; -using v8::Uint8Array; using v8::Value; // TODO(joyeecheung): make these more general and put them into util.h @@ -154,26 +151,6 @@ MaybeLocal NativeModuleEnv::LookupAndCompile( return maybe; } -// This is supposed to be run only by the main thread in -// tools/generate_code_cache.js -void NativeModuleEnv::GetCodeCache(const FunctionCallbackInfo& args) { - Environment* env = Environment::GetCurrent(args); - Isolate* isolate = env->isolate(); - CHECK(env->is_main_thread()); - - CHECK(args[0]->IsString()); - node::Utf8Value id_v(isolate, args[0].As()); - const char* id = *id_v; - - ScriptCompiler::CachedData* cached_data = - NativeModuleLoader::GetInstance()->GetCodeCache(id); - if (cached_data != nullptr) { - Local buf = ArrayBuffer::New(isolate, cached_data->length); - memcpy(buf->GetContents().Data(), cached_data->data, cached_data->length); - args.GetReturnValue().Set(Uint8Array::New(buf, 0, cached_data->length)); - } -} - // TODO(joyeecheung): It is somewhat confusing that Class::Initialize // is used to initilaize to the binding, but it is the current convention. // Rename this across the code base to something that makes more sense. @@ -216,7 +193,6 @@ void NativeModuleEnv::Initialize(Local target, .Check(); env->SetMethod(target, "getCacheUsage", NativeModuleEnv::GetCacheUsage); - env->SetMethod(target, "getCodeCache", NativeModuleEnv::GetCodeCache); env->SetMethod(target, "compileFunction", NativeModuleEnv::CompileFunction); // internalBinding('native_module') should be frozen target->SetIntegrityLevel(context, IntegrityLevel::kFrozen).FromJust(); diff --git a/src/node_native_module_env.h b/src/node_native_module_env.h index 2b1fabf89b9776..1852d9b139d7b0 100644 --- a/src/node_native_module_env.h +++ b/src/node_native_module_env.h @@ -52,7 +52,6 @@ class NativeModuleEnv { const v8::PropertyCallbackInfo& info); // Compile a specific native module as a function static void CompileFunction(const v8::FunctionCallbackInfo& args); - static void GetCodeCache(const v8::FunctionCallbackInfo& args); }; } // namespace native_module diff --git a/test/code-cache/code-cache.status b/test/code-cache/code-cache.status deleted file mode 100644 index 26eb66ea2d1d2c..00000000000000 --- a/test/code-cache/code-cache.status +++ /dev/null @@ -1,21 +0,0 @@ -prefix code-cache - -# To mark a test as flaky, list the test name in the appropriate section -# below, without ".js", followed by ": PASS,FLAKY". Example: -# sample-test : PASS,FLAKY - -[true] # This section applies to all platforms - -[$system==win32] - -[$system==linux] - -[$system==macos] - -[$arch==arm || $arch==arm64] - -[$system==solaris] # Also applies to SmartOS - -[$system==freebsd] - -[$system==aix] diff --git a/test/code-cache/test-code-cache-generator.js b/test/code-cache/test-code-cache-generator.js deleted file mode 100644 index a117a2e6a6ea94..00000000000000 --- a/test/code-cache/test-code-cache-generator.js +++ /dev/null @@ -1,52 +0,0 @@ -'use strict'; - -// This test verifies that the binary is compiled with code cache and the -// cache is used when built in modules are compiled. - -const common = require('../common'); - -const tmpdir = require('../common/tmpdir'); -const { spawnSync } = require('child_process'); -const assert = require('assert'); -const path = require('path'); -const fs = require('fs'); -const readline = require('readline'); - -const generator = path.join( - __dirname, '..', '..', 'tools', 'generate_code_cache.js' -); -tmpdir.refresh(); -const dest = path.join(tmpdir.path, 'cache.cc'); - -// Run tools/generate_code_cache.js -const child = spawnSync( - process.execPath, - ['--expose-internals', generator, dest] -); -assert.ifError(child.error); -if (child.status !== 0) { - console.log(child.stderr.toString()); - assert.strictEqual(child.status, 0); -} - -// Verifies that: -// - NativeModuleEnv::InitializeCodeCache() -// are defined in the generated code. -// See src/node_native_module_env.h for explanations. - -const rl = readline.createInterface({ - input: fs.createReadStream(dest), - crlfDelay: Infinity -}); - -let hasCacheDef = false; - -rl.on('line', common.mustCallAtLeast((line) => { - if (line.includes('InitializeCodeCache(')) { - hasCacheDef = true; - } -}, 2)); - -rl.on('close', common.mustCall(() => { - assert.ok(hasCacheDef); -})); diff --git a/test/code-cache/testcfg.py b/test/code-cache/testcfg.py deleted file mode 100644 index 0e0035dfed477b..00000000000000 --- a/test/code-cache/testcfg.py +++ /dev/null @@ -1,6 +0,0 @@ -import sys, os -sys.path.append(os.path.join(os.path.dirname(__file__), '..')) -import testpy - -def GetConfiguration(context, root): - return testpy.ParallelTestConfiguration(context, root, 'code-cache') diff --git a/test/code-cache/test-code-cache.js b/test/parallel/test-code-cache.js similarity index 66% rename from test/code-cache/test-code-cache.js rename to test/parallel/test-code-cache.js index e179be7aee37b7..f120b76af27b68 100644 --- a/test/code-cache/test-code-cache.js +++ b/test/parallel/test-code-cache.js @@ -1,6 +1,6 @@ +// Flags: --expose-internals 'use strict'; -// Flags: --expose-internals // This test verifies that if the binary is compiled with code cache, // and the cache is used when built in modules are compiled. // Otherwise, verifies that no cache is used when compiling builtins. @@ -29,9 +29,9 @@ const loadedModules = process.moduleLoadList .filter((m) => m.startsWith('NativeModule')) .map((m) => m.replace('NativeModule ', '')); -// The binary is not configured with code cache, verifies that the builtins +// Cross-compiled binaries do not have code cache, verifies that the builtins // are all compiled without cache and we are doing the bookkeeping right. -if (process.config.variables.node_code_cache_path === undefined) { +if (process.config.variables.want_separate_host_toolset === 1) { console.log('The binary is not configured with code cache'); if (isMainThread) { assert.deepStrictEqual(compiledWithCache, new Set()); @@ -45,20 +45,27 @@ if (process.config.variables.node_code_cache_path === undefined) { // cache are hit assert.notDeepStrictEqual(compiledWithCache, new Set()); } -} else { - console.log('The binary is configured with code cache'); +} else { // Native compiled assert.strictEqual( - typeof process.config.variables.node_code_cache_path, - 'string' + process.config.variables.node_code_cache_path, + 'yes' ); + 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)) { - assert(compiledWithoutCache.has(key), - `"${key}" should've been compiled without code cache`); - } else { - assert(compiledWithCache.has(key), - `"${key}" should've been compiled with code cache`); + if (cannotBeRequired.has(key) && !compiledWithoutCache.has(key)) { + wrong.push(`"${key}" should've been compiled **without** code cache`); + } + if (canBeRequired.has(key) && !compiledWithCache.has(key)) { + wrong.push(`"${key}" should've been compiled **with** code cache`); } } + assert.strictEqual(wrong.length, 0, wrong.join('\n')); } diff --git a/tools/code_cache/cache_builder.cc b/tools/code_cache/cache_builder.cc new file mode 100644 index 00000000000000..8d0fb26d7e7cb0 --- /dev/null +++ b/tools/code_cache/cache_builder.cc @@ -0,0 +1,154 @@ +#include "cache_builder.h" +#include "node_native_module.h" +#include "util.h" + +#include +#include +#include +#include +#include + +namespace node { +namespace native_module { + +using v8::Context; +using v8::Function; +using v8::Isolate; +using v8::Local; +using v8::MaybeLocal; +using v8::ScriptCompiler; + +static std::string GetDefName(const std::string& id) { + char buf[64] = {0}; + size_t size = id.size(); + CHECK_LT(size, sizeof(buf)); + for (size_t i = 0; i < size; ++i) { + char ch = id[i]; + buf[i] = (ch == '-' || ch == '/') ? '_' : ch; + } + return buf; +} + +static std::string FormatSize(size_t size) { + char buf[64] = {0}; + if (size < 1024) { + snprintf(buf, sizeof(buf), "%.2fB", static_cast(size)); + } else if (size < 1024 * 1024) { + snprintf(buf, sizeof(buf), "%.2fKB", static_cast(size / 1024)); + } else { + snprintf( + buf, sizeof(buf), "%.2fMB", static_cast(size / 1024 / 1024)); + } + return buf; +} + +static std::string GetDefinition(const std::string& id, + size_t size, + const uint8_t* data) { + std::stringstream ss; + ss << "static const uint8_t " << GetDefName(id) << "[] = {\n"; + for (size_t i = 0; i < size; ++i) { + uint8_t ch = data[i]; + ss << std::to_string(ch) << (i == size - 1 ? '\n' : ','); + } + ss << "};"; + return ss.str(); +} + +static void GetInitializer(const std::string& id, std::stringstream& ss) { + std::string def_name = GetDefName(id); + ss << " code_cache.emplace(\n"; + ss << " \"" << id << "\",\n"; + ss << " std::make_unique(\n"; + ss << " " << def_name << ",\n"; + ss << " static_cast(arraysize(" << def_name << ")), policy\n"; + ss << " )\n"; + ss << " );"; +} + +static std::string GenerateCodeCache( + const std::map& data, + bool log_progress) { + std::stringstream ss; + ss << R"(#include +#include "node_native_module_env.h" + +// This file is generated by tools/mkcodecache +// and is used when configure is run with \`--code-cache-path\` + +namespace node { +namespace native_module { +)"; + + size_t total = 0; + for (const auto& x : data) { + const std::string& id = x.first; + ScriptCompiler::CachedData* cached_data = x.second; + total += cached_data->length; + std::string def = GetDefinition(id, cached_data->length, cached_data->data); + ss << def << "\n\n"; + if (log_progress) { + std::cout << "Generated cache for " << id + << ", size = " << FormatSize(cached_data->length) + << ", total = " << FormatSize(total) << "\n"; + } + } + + ss << R"(void NativeModuleEnv::InitializeCodeCache() { + NativeModuleCacheMap& code_cache = + *NativeModuleLoader::GetInstance()->code_cache(); + CHECK(code_cache.empty()); + auto policy = v8::ScriptCompiler::CachedData::BufferPolicy::BufferNotOwned; +)"; + + for (const auto& x : data) { + GetInitializer(x.first, ss); + ss << "\n\n"; + } + + ss << R"( +} + +} // namespace native_module +} // namespace node +)"; + return ss.str(); +} + +std::string CodeCacheBuilder::Generate(Local context) { + NativeModuleLoader* loader = NativeModuleLoader::GetInstance(); + std::vector ids = loader->GetModuleIds(); + + std::map data; + + for (const auto& id : ids) { + // TODO(joyeecheung): we can only compile the modules that can be + // required here because the parameters for other types of builtins + // are still very flexible. We should look into auto-generating + // the paramters from the source somehow. + if (loader->CanBeRequired(id.c_str())) { + NativeModuleLoader::Result result; + USE(loader->CompileAsModule(context, id.c_str(), &result)); + ScriptCompiler::CachedData* cached_data = + loader->GetCodeCache(id.c_str()); + if (cached_data == nullptr) { + // TODO(joyeecheung): display syntax errors + std::cerr << "Failed to complile " << id << "\n"; + } else { + data.emplace(id, cached_data); + } + } + } + + char env_buf[32]; + size_t env_size = sizeof(env_buf); + int ret = uv_os_getenv("NODE_DEBUG", env_buf, &env_size); + bool log_progress = false; + if (ret == 0 && strcmp(env_buf, "mkcodecache") == 0) { + log_progress = true; + } + return GenerateCodeCache(data, log_progress); +} + +} // namespace native_module +} // namespace node diff --git a/tools/code_cache/cache_builder.h b/tools/code_cache/cache_builder.h new file mode 100644 index 00000000000000..d5a6cd4241dfb0 --- /dev/null +++ b/tools/code_cache/cache_builder.h @@ -0,0 +1,16 @@ +#ifndef TOOLS_CODE_CACHE_CACHE_BUILDER_H_ +#define TOOLS_CODE_CACHE_CACHE_BUILDER_H_ + +#include +#include "v8.h" + +namespace node { +namespace native_module { +class CodeCacheBuilder { + public: + static std::string Generate(v8::Local context); +}; +} // namespace native_module +} // namespace node + +#endif // TOOLS_CODE_CACHE_CACHE_BUILDER_H_ diff --git a/tools/code_cache/mkcodecache.cc b/tools/code_cache/mkcodecache.cc new file mode 100644 index 00000000000000..24f7e05e1f19f7 --- /dev/null +++ b/tools/code_cache/mkcodecache.cc @@ -0,0 +1,62 @@ +#include +#include +#include +#include +#include +#include + +#include "cache_builder.h" +#include "libplatform/libplatform.h" +#include "v8.h" + +using node::native_module::CodeCacheBuilder; +using v8::ArrayBuffer; +using v8::Context; +using v8::HandleScope; +using v8::Isolate; +using v8::Local; + +#ifdef _WIN32 +#include +#include +#include + +int wmain(int argc, wchar_t* argv[]) { +#else // UNIX +int main(int argc, char* argv[]) { +#endif // _WIN32 + + if (argc < 2) { + std::cerr << "Usage: " << argv[0] << " \n"; + return 1; + } + + std::ofstream out; + out.open(argv[1], std::ios::out | std::ios::binary); + if (!out.is_open()) { + std::cerr << "Cannot open " << argv[1] << "\n"; + return 1; + } + + std::unique_ptr platform = v8::platform::NewDefaultPlatform(); + v8::V8::InitializePlatform(platform.get()); + v8::V8::Initialize(); + + // Create a new Isolate and make it the current one. + Isolate::CreateParams create_params; + create_params.array_buffer_allocator = + ArrayBuffer::Allocator::NewDefaultAllocator(); + Isolate* isolate = Isolate::New(create_params); + { + Isolate::Scope isolate_scope(isolate); + v8::HandleScope handle_scope(isolate); + v8::Local context = v8::Context::New(isolate); + v8::Context::Scope context_scope(context); + + std::string cache = CodeCacheBuilder::Generate(context); + out << cache; + out.close(); + } + + return 0; +} diff --git a/tools/generate_code_cache.js b/tools/generate_code_cache.js deleted file mode 100644 index 8afbc14a9bce4d..00000000000000 --- a/tools/generate_code_cache.js +++ /dev/null @@ -1,135 +0,0 @@ -'use strict'; - -// Flags: --expose-internals - -// This file generates the code cache for builtin modules and -// writes them into static char arrays of a C++ file that can be -// compiled into the binary using the `--code-cache-path` option -// of `configure`. - -const { internalBinding } = require('internal/test/binding'); -const { - moduleCategories: { canBeRequired }, - getCodeCache, - compileFunction, -} = internalBinding('native_module'); - -const { - types: { - isUint8Array - } -} = require('util'); - -const fs = require('fs'); - -const resultPath = process.argv[2]; -if (!resultPath) { - console.error(`Usage: ${process.argv[0]} ${process.argv[1]}` + - 'path/to/node_code_cache.cc'); - process.exit(1); -} - -/** - * Format a number of a size in bytes into human-readable strings - * @param {number} num - * @return {string} - */ -function formatSize(num) { - if (num < 1024) { - return `${(num).toFixed(2)}B`; - } else if (num < 1024 ** 2) { - return `${(num / 1024).toFixed(2)}KB`; - } else if (num < 1024 ** 3) { - return `${(num / (1024 ** 2)).toFixed(2)}MB`; - } else { - return `${(num / (1024 ** 3)).toFixed(2)}GB`; - } -} - -/** - * Generates the source code of definitions of the char arrays - * that contains the code cache and the source code of the - * initializers of the code cache. - * - * @param {string} key ID of the builtin module - * @param {Uint8Array} cache Code cache of the builtin module - * @return { definition: string, initializer: string } - */ -function getInitalizer(key, cache) { - const defName = `${key.replace(/\//g, '_').replace(/-/g, '_')}_raw`; - const definition = `static const uint8_t ${defName}[] = {\n` + - `${cache.join(',')}\n};`; - const dataDef = 'std::make_unique(' + - `${defName}, static_cast(arraysize(${defName})), ` + - 'policy)'; - const initializer = - 'code_cache->emplace(\n' + - ` "${key}",\n` + - ` ${dataDef}\n` + - ');'; - return { - definition, initializer - }; -} - -const cacheDefinitions = []; -const cacheInitializers = []; -let totalCacheSize = 0; - -function lexical(a, b) { - if (a < b) { - return -1; - } - if (a > b) { - return 1; - } - return 0; -} - -// TODO(joyeecheung): support non-modules that require different -// parameters in the wrapper. -for (const key of [...canBeRequired].sort(lexical)) { - compileFunction(key); // compile it - const cachedData = getCodeCache(key); - if (!isUint8Array(cachedData)) { - console.error(`Failed to generate code cache for '${key}'`); - process.exit(1); - } - - const size = cachedData.byteLength; - totalCacheSize += size; - const { - definition, initializer, - } = getInitalizer(key, cachedData); - cacheDefinitions.push(definition); - cacheInitializers.push(initializer); - console.log(`Generated cache for '${key}', size = ${formatSize(size)}` + - `, total = ${formatSize(totalCacheSize)}`); -} - -const result = `#include "node_native_module_env.h" - -// This file is generated by tools/generate_code_cache.js -// and is used when configure is run with \`--code-cache-path\` - -namespace node { -namespace native_module { -${cacheDefinitions.join('\n\n')} - -void NativeModuleEnv::InitializeCodeCache() { - NativeModuleCacheMap* code_cache = - NativeModuleLoader::GetInstance()->code_cache(); - if (!code_cache->empty()) { - return; - } - - auto policy = v8::ScriptCompiler::CachedData::BufferPolicy::BufferNotOwned; - ${cacheInitializers.join('\n ')} -} - -} // namespace native_module -} // namespace node -`; - -fs.writeFileSync(resultPath, result); -console.log(`Generated code cache C++ file to ${resultPath}`); diff --git a/vcbuild.bat b/vcbuild.bat index 73405b46ed6516..acbf42e538350e 100644 --- a/vcbuild.bat +++ b/vcbuild.bat @@ -190,6 +190,7 @@ if defined config_flags set configure_flags=%configure_flags% %config_flags% if defined target_arch set configure_flags=%configure_flags% --dest-cpu=%target_arch% if defined openssl_no_asm set configure_flags=%configure_flags% --openssl-no-asm if defined DEBUG_HELPER set configure_flags=%configure_flags% --verbose +if "%target_arch%"=="x86" if "%PROCESSOR_ARCHITECTURE%"=="AMD64" set configure_flags=%configure_flags% --no-cross-compiling if not exist "%~dp0deps\icu" goto no-depsicu if "%target%"=="Clean" echo deleting %~dp0deps\icu