mirror of
https://github.com/nodejs/node.git
synced 2024-11-21 10:59:27 +00:00
bootstrap: do not generate code cache in an unfinalized isolate
V8 now no longer supports serializing code cache in an isolate with unfinalized read-only space. So guard the code cache regeneration with the `is_building_snapshot()` flag. When the isolate is created for snapshot generation, the code cache is going to be serialized separately anyway, so there is no need to do it in the builtin loader. PR-URL: https://github.com/nodejs/node/pull/49108 Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
This commit is contained in:
parent
4c3db74a39
commit
fe219e0438
@ -254,7 +254,7 @@ MaybeLocal<Function> BuiltinLoader::LookupAndCompileInternal(
|
||||
Local<Context> context,
|
||||
const char* id,
|
||||
std::vector<Local<String>>* parameters,
|
||||
BuiltinLoader::Result* result) {
|
||||
Realm* optional_realm) {
|
||||
Isolate* isolate = context->GetIsolate();
|
||||
EscapableHandleScope scope(isolate);
|
||||
|
||||
@ -320,9 +320,13 @@ MaybeLocal<Function> BuiltinLoader::LookupAndCompileInternal(
|
||||
// will never be in any of these two sets, but the two sets are only for
|
||||
// testing anyway.
|
||||
|
||||
*result = (has_cache && !script_source.GetCachedData()->rejected)
|
||||
? Result::kWithCache
|
||||
: Result::kWithoutCache;
|
||||
Result result = (has_cache && !script_source.GetCachedData()->rejected)
|
||||
? Result::kWithCache
|
||||
: Result::kWithoutCache;
|
||||
if (optional_realm != nullptr) {
|
||||
DCHECK_EQ(this, optional_realm->env()->builtin_loader());
|
||||
RecordResult(id, result, optional_realm);
|
||||
}
|
||||
|
||||
if (has_cache) {
|
||||
per_process::Debug(DebugCategory::CODE_CACHE,
|
||||
@ -336,28 +340,35 @@ MaybeLocal<Function> BuiltinLoader::LookupAndCompileInternal(
|
||||
: "is accepted");
|
||||
}
|
||||
|
||||
if (*result == Result::kWithoutCache) {
|
||||
if (result == Result::kWithoutCache && optional_realm != nullptr &&
|
||||
!optional_realm->env()->isolate_data()->is_building_snapshot()) {
|
||||
// We failed to accept this cache, maybe because it was rejected, maybe
|
||||
// because it wasn't present. Either way, we'll attempt to replace this
|
||||
// code cache info with a new one.
|
||||
std::shared_ptr<ScriptCompiler::CachedData> new_cached_data(
|
||||
ScriptCompiler::CreateCodeCacheForFunction(fun));
|
||||
CHECK_NOT_NULL(new_cached_data);
|
||||
|
||||
{
|
||||
RwLock::ScopedLock lock(code_cache_->mutex);
|
||||
code_cache_->map.insert_or_assign(
|
||||
id, BuiltinCodeCacheData(std::move(new_cached_data)));
|
||||
}
|
||||
// This is only done when the isolate is not being serialized because
|
||||
// V8 does not support serializing code cache with an unfinalized read-only
|
||||
// space (which is what isolates pending to be serialized have).
|
||||
SaveCodeCache(id, fun);
|
||||
}
|
||||
|
||||
return scope.Escape(fun);
|
||||
}
|
||||
|
||||
void BuiltinLoader::SaveCodeCache(const char* id, Local<Function> fun) {
|
||||
std::shared_ptr<ScriptCompiler::CachedData> new_cached_data(
|
||||
ScriptCompiler::CreateCodeCacheForFunction(fun));
|
||||
CHECK_NOT_NULL(new_cached_data);
|
||||
|
||||
{
|
||||
RwLock::ScopedLock lock(code_cache_->mutex);
|
||||
code_cache_->map.insert_or_assign(
|
||||
id, BuiltinCodeCacheData(std::move(new_cached_data)));
|
||||
}
|
||||
}
|
||||
|
||||
MaybeLocal<Function> BuiltinLoader::LookupAndCompile(Local<Context> context,
|
||||
const char* id,
|
||||
Realm* optional_realm) {
|
||||
Result result;
|
||||
std::vector<Local<String>> parameters;
|
||||
Isolate* isolate = context->GetIsolate();
|
||||
// Detects parameters of the scripts based on module ids.
|
||||
@ -403,11 +414,7 @@ MaybeLocal<Function> BuiltinLoader::LookupAndCompile(Local<Context> context,
|
||||
}
|
||||
|
||||
MaybeLocal<Function> maybe =
|
||||
LookupAndCompileInternal(context, id, ¶meters, &result);
|
||||
if (optional_realm != nullptr) {
|
||||
DCHECK_EQ(this, optional_realm->env()->builtin_loader());
|
||||
RecordResult(id, result, optional_realm);
|
||||
}
|
||||
LookupAndCompileInternal(context, id, ¶meters, optional_realm);
|
||||
return maybe;
|
||||
}
|
||||
|
||||
@ -483,13 +490,17 @@ bool BuiltinLoader::CompileAllBuiltins(Local<Context> context) {
|
||||
continue;
|
||||
}
|
||||
v8::TryCatch bootstrapCatch(context->GetIsolate());
|
||||
USE(LookupAndCompile(context, id.data(), nullptr));
|
||||
auto fn = LookupAndCompile(context, id.data(), nullptr);
|
||||
if (bootstrapCatch.HasCaught()) {
|
||||
per_process::Debug(DebugCategory::CODE_CACHE,
|
||||
"Failed to compile code cache for %s\n",
|
||||
id.data());
|
||||
all_succeeded = false;
|
||||
PrintCaughtException(context->GetIsolate(), context, bootstrapCatch);
|
||||
} else {
|
||||
// This is used by the snapshot builder, so save the code cache
|
||||
// unconditionally.
|
||||
SaveCodeCache(id.data(), fn.ToLocalChecked());
|
||||
}
|
||||
}
|
||||
return all_succeeded;
|
||||
|
@ -147,7 +147,8 @@ class NODE_EXTERN_PRIVATE BuiltinLoader {
|
||||
v8::Local<v8::Context> context,
|
||||
const char* id,
|
||||
std::vector<v8::Local<v8::String>>* parameters,
|
||||
Result* result);
|
||||
Realm* optional_realm);
|
||||
void SaveCodeCache(const char* id, v8::Local<v8::Function> fn);
|
||||
|
||||
static void RecordResult(const char* id,
|
||||
BuiltinLoader::Result result,
|
||||
|
Loading…
Reference in New Issue
Block a user