Skip to content

Commit 2537a87

Browse files
committed
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.
1 parent 7ffa5d7 commit 2537a87

File tree

2 files changed

+34
-22
lines changed

2 files changed

+34
-22
lines changed

src/node_builtins.cc

Lines changed: 32 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ MaybeLocal<Function> BuiltinLoader::LookupAndCompileInternal(
254254
Local<Context> context,
255255
const char* id,
256256
std::vector<Local<String>>* parameters,
257-
BuiltinLoader::Result* result) {
257+
Realm* optional_realm) {
258258
Isolate* isolate = context->GetIsolate();
259259
EscapableHandleScope scope(isolate);
260260

@@ -320,9 +320,13 @@ MaybeLocal<Function> BuiltinLoader::LookupAndCompileInternal(
320320
// will never be in any of these two sets, but the two sets are only for
321321
// testing anyway.
322322

323-
*result = (has_cache && !script_source.GetCachedData()->rejected)
324-
? Result::kWithCache
325-
: Result::kWithoutCache;
323+
Result result = (has_cache && !script_source.GetCachedData()->rejected)
324+
? Result::kWithCache
325+
: Result::kWithoutCache;
326+
if (optional_realm != nullptr) {
327+
DCHECK_EQ(this, optional_realm->env()->builtin_loader());
328+
RecordResult(id, result, optional_realm);
329+
}
326330

327331
if (has_cache) {
328332
per_process::Debug(DebugCategory::CODE_CACHE,
@@ -336,28 +340,35 @@ MaybeLocal<Function> BuiltinLoader::LookupAndCompileInternal(
336340
: "is accepted");
337341
}
338342

339-
if (*result == Result::kWithoutCache) {
343+
if (result == Result::kWithoutCache && optional_realm != nullptr &&
344+
!optional_realm->env()->isolate_data()->is_building_snapshot()) {
340345
// We failed to accept this cache, maybe because it was rejected, maybe
341346
// because it wasn't present. Either way, we'll attempt to replace this
342347
// code cache info with a new one.
343-
std::shared_ptr<ScriptCompiler::CachedData> new_cached_data(
344-
ScriptCompiler::CreateCodeCacheForFunction(fun));
345-
CHECK_NOT_NULL(new_cached_data);
346-
347-
{
348-
RwLock::ScopedLock lock(code_cache_->mutex);
349-
code_cache_->map.insert_or_assign(
350-
id, BuiltinCodeCacheData(std::move(new_cached_data)));
351-
}
348+
// This is only done when the isolate is not being serialized because
349+
// V8 does not support serializing code cache with an unfinalized read-only
350+
// space (which is what isolates pending to be serialized have).
351+
SaveCodeCache(id, fun);
352352
}
353353

354354
return scope.Escape(fun);
355355
}
356356

357+
void BuiltinLoader::SaveCodeCache(const char* id, Local<Function> fun) {
358+
std::shared_ptr<ScriptCompiler::CachedData> new_cached_data(
359+
ScriptCompiler::CreateCodeCacheForFunction(fun));
360+
CHECK_NOT_NULL(new_cached_data);
361+
362+
{
363+
RwLock::ScopedLock lock(code_cache_->mutex);
364+
code_cache_->map.insert_or_assign(
365+
id, BuiltinCodeCacheData(std::move(new_cached_data)));
366+
}
367+
}
368+
357369
MaybeLocal<Function> BuiltinLoader::LookupAndCompile(Local<Context> context,
358370
const char* id,
359371
Realm* optional_realm) {
360-
Result result;
361372
std::vector<Local<String>> parameters;
362373
Isolate* isolate = context->GetIsolate();
363374
// Detects parameters of the scripts based on module ids.
@@ -403,11 +414,7 @@ MaybeLocal<Function> BuiltinLoader::LookupAndCompile(Local<Context> context,
403414
}
404415

405416
MaybeLocal<Function> maybe =
406-
LookupAndCompileInternal(context, id, &parameters, &result);
407-
if (optional_realm != nullptr) {
408-
DCHECK_EQ(this, optional_realm->env()->builtin_loader());
409-
RecordResult(id, result, optional_realm);
410-
}
417+
LookupAndCompileInternal(context, id, &parameters, optional_realm);
411418
return maybe;
412419
}
413420

@@ -483,13 +490,17 @@ bool BuiltinLoader::CompileAllBuiltins(Local<Context> context) {
483490
continue;
484491
}
485492
v8::TryCatch bootstrapCatch(context->GetIsolate());
486-
USE(LookupAndCompile(context, id.data(), nullptr));
493+
auto fn = LookupAndCompile(context, id.data(), nullptr);
487494
if (bootstrapCatch.HasCaught()) {
488495
per_process::Debug(DebugCategory::CODE_CACHE,
489496
"Failed to compile code cache for %s\n",
490497
id.data());
491498
all_succeeded = false;
492499
PrintCaughtException(context->GetIsolate(), context, bootstrapCatch);
500+
} else {
501+
// This is used by the snapshot builder, so save the code cache
502+
// unconditionally.
503+
SaveCodeCache(id.data(), fn.ToLocalChecked());
493504
}
494505
}
495506
return all_succeeded;

src/node_builtins.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,8 @@ class NODE_EXTERN_PRIVATE BuiltinLoader {
147147
v8::Local<v8::Context> context,
148148
const char* id,
149149
std::vector<v8::Local<v8::String>>* parameters,
150-
Result* result);
150+
Realm* optional_realm);
151+
void SaveCodeCache(const char* id, v8::Local<v8::Function> fn);
151152

152153
static void RecordResult(const char* id,
153154
BuiltinLoader::Result result,

0 commit comments

Comments
 (0)