|
12 | 12 | #include "v8-value.h" |
13 | 13 |
|
14 | 14 | namespace node { |
15 | | -namespace builtins { |
16 | 15 |
|
17 | 16 | using loader::HostDefinedOptions; |
18 | 17 | using v8::Boolean; |
@@ -44,9 +43,41 @@ using v8::TryCatch; |
44 | 43 | using v8::Undefined; |
45 | 44 | using v8::Value; |
46 | 45 |
|
| 46 | +namespace builtins { |
| 47 | + |
| 48 | +namespace { |
| 49 | +struct ProcessCodeCache { |
| 50 | + Mutex mutex; |
| 51 | + std::vector<CodeCacheInfo> entries; |
| 52 | + bool harvest = true; |
| 53 | +}; |
| 54 | +ProcessCodeCache& GetProcessCodeCache() { |
| 55 | + static ProcessCodeCache process_code_cache; |
| 56 | + return process_code_cache; |
| 57 | +} |
| 58 | +} // namespace |
| 59 | + |
| 60 | +void BuiltinLoader::SetProcessCodeCache(std::vector<CodeCacheInfo> entries) { |
| 61 | + ProcessCodeCache& pcc = GetProcessCodeCache(); |
| 62 | + Mutex::ScopedLock lock(pcc.mutex); |
| 63 | + pcc.entries = std::move(entries); |
| 64 | +} |
| 65 | + |
| 66 | +void BuiltinLoader::SetHarvestCodeCache(bool on) { |
| 67 | + ProcessCodeCache& pcc = GetProcessCodeCache(); |
| 68 | + Mutex::ScopedLock lock(pcc.mutex); |
| 69 | + pcc.harvest = on; |
| 70 | +} |
| 71 | + |
47 | 72 | BuiltinLoader::BuiltinLoader() |
48 | 73 | : config_(GetConfig()), code_cache_(std::make_shared<BuiltinCodeCache>()) { |
49 | 74 | LoadJavaScriptSource(); |
| 75 | + { |
| 76 | + ProcessCodeCache& pcc = GetProcessCodeCache(); |
| 77 | + Mutex::ScopedLock lock(pcc.mutex); |
| 78 | + harvest_code_cache_ = pcc.harvest; |
| 79 | + if (!pcc.entries.empty()) RefreshCodeCache(pcc.entries); |
| 80 | + } |
50 | 81 | #ifdef NODE_SHARED_BUILTIN_UNDICI_UNDICI_PATH |
51 | 82 | AddExternalizedBuiltin("internal/deps/undici/undici", |
52 | 83 | STRINGIFY(NODE_SHARED_BUILTIN_UNDICI_UNDICI_PATH)); |
@@ -422,6 +453,7 @@ MaybeLocal<Data> BuiltinLoader::LookupAndCompile( |
422 | 453 | } |
423 | 454 |
|
424 | 455 | if (result == Result::kWithoutCache && optional_realm != nullptr && |
| 456 | + harvest_code_cache_ && |
425 | 457 | !optional_realm->env()->isolate_data()->is_building_snapshot()) { |
426 | 458 | // We failed to accept this cache, maybe because it was rejected, maybe |
427 | 459 | // because it wasn't present. Either way, we'll attempt to replace this |
@@ -593,12 +625,13 @@ bool BuiltinLoader::CompileAllBuiltinsAndCopyCodeCache( |
593 | 625 |
|
594 | 626 | void BuiltinLoader::RefreshCodeCache(const std::vector<CodeCacheInfo>& in) { |
595 | 627 | RwLock::ScopedLock lock(code_cache_->mutex); |
596 | | - code_cache_->map.reserve(in.size()); |
597 | | - DCHECK(code_cache_->map.empty()); |
| 628 | + // May be called more than once, e.g. first with the code cache carried by |
| 629 | + // the snapshot and then by an embedder with caches it built for additional |
| 630 | + // (or the same) builtin ids against this isolate: merge, and let the entry |
| 631 | + // supplied last win for an id present in both. |
| 632 | + code_cache_->map.reserve(code_cache_->map.size() + in.size()); |
598 | 633 | for (auto const& [id, data] : in) { |
599 | | - auto result = code_cache_->map.emplace(id, data); |
600 | | - USE(result.second); |
601 | | - DCHECK(result.second); |
| 634 | + code_cache_->map.insert_or_assign(id, data); |
602 | 635 | } |
603 | 636 | code_cache_->has_code_cache = true; |
604 | 637 | } |
@@ -918,6 +951,38 @@ void BuiltinLoader::RegisterExternalReferences( |
918 | 951 | } |
919 | 952 |
|
920 | 953 | } // namespace builtins |
| 954 | + |
| 955 | +void SetBuiltinCodeCache(const std::vector<BuiltinCodeCacheEntry>& entries) { |
| 956 | + std::vector<builtins::CodeCacheInfo> infos; |
| 957 | + infos.reserve(entries.size()); |
| 958 | + for (const BuiltinCodeCacheEntry& e : entries) { |
| 959 | + auto cached_data = std::make_shared<ScriptCompiler::CachedData>( |
| 960 | + e.data, |
| 961 | + static_cast<int>(e.length), |
| 962 | + ScriptCompiler::CachedData::BufferNotOwned); |
| 963 | + infos.push_back({e.id, builtins::BuiltinCodeCacheData(cached_data)}); |
| 964 | + } |
| 965 | + builtins::BuiltinLoader::SetProcessCodeCache(std::move(infos)); |
| 966 | +} |
| 967 | + |
| 968 | +std::vector<OwnedBuiltinCodeCacheEntry> GenerateBuiltinCodeCache( |
| 969 | + Local<Context> context) { |
| 970 | + std::vector<OwnedBuiltinCodeCacheEntry> out; |
| 971 | + builtins::BuiltinLoader loader; |
| 972 | + loader.SetEagerCompile(); |
| 973 | + std::vector<builtins::CodeCacheInfo> infos; |
| 974 | + if (!loader.CompileAllBuiltinsAndCopyCodeCache(context, {}, &infos)) { |
| 975 | + return out; |
| 976 | + } |
| 977 | + out.reserve(infos.size()); |
| 978 | + for (const builtins::CodeCacheInfo& info : infos) { |
| 979 | + out.push_back({info.id, |
| 980 | + std::vector<uint8_t>(info.data.data, |
| 981 | + info.data.data + info.data.length)}); |
| 982 | + } |
| 983 | + return out; |
| 984 | +} |
| 985 | + |
921 | 986 | } // namespace node |
922 | 987 |
|
923 | 988 | NODE_BINDING_PER_ISOLATE_INIT( |
|
0 commit comments