Skip to content

Commit af6dc17

Browse files
joyeecheungUlisesGascon
authored andcommitted
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: #49108 Reviewed-By: Benjamin Gruenbaum <[email protected]> Reviewed-By: Yagiz Nizipli <[email protected]>
1 parent 11c85ff commit af6dc17

File tree

2 files changed

+34
-22
lines changed

2 files changed

+34
-22
lines changed

src/node_builtins.cc

+32-21
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

+2-1
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)