Skip to content

Commit 7ecb285

Browse files
committed
src: make code cache test work with snapshots
Keep track of snapshotted modules in JS land, and move bootstrap switches into StartExecution() so that they are not included into part of the environment-independent bootstrap process. PR-URL: #32984 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Daniel Bevenius <daniel.bevenius@gmail.com>
1 parent 1faf6f4 commit 7ecb285

File tree

7 files changed

+69
-20
lines changed

7 files changed

+69
-20
lines changed

lib/internal/bootstrap/node.js

+20-12
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,8 @@ process.domain = null;
5757
process._exiting = false;
5858

5959
// process.config is serialized config.gypi
60-
process.config = JSONParse(internalBinding('native_module').config);
60+
const nativeModule = internalBinding('native_module');
61+
process.config = JSONParse(nativeModule.config);
6162
require('internal/worker/js_transferable').setup();
6263

6364
// Bootstrappers for all threads, including worker threads and main thread
@@ -192,21 +193,28 @@ process.assert = deprecate(
192193
// TODO(joyeecheung): this property has not been well-maintained, should we
193194
// deprecate it in favor of a better API?
194195
const { isDebugBuild, hasOpenSSL, hasInspector } = config;
196+
const features = {
197+
inspector: hasInspector,
198+
debug: isDebugBuild,
199+
uv: true,
200+
ipv6: true, // TODO(bnoordhuis) ping libuv
201+
tls_alpn: hasOpenSSL,
202+
tls_sni: hasOpenSSL,
203+
tls_ocsp: hasOpenSSL,
204+
tls: hasOpenSSL,
205+
// This needs to be dynamic because snapshot is built without code cache.
206+
// TODO(joyeecheung): https://github.com/nodejs/node/issues/31074
207+
// Make it possible to build snapshot with code cache
208+
get cached_builtins() {
209+
return nativeModule.hasCachedBuiltins();
210+
}
211+
};
212+
195213
ObjectDefineProperty(process, 'features', {
196214
enumerable: true,
197215
writable: false,
198216
configurable: false,
199-
value: {
200-
inspector: hasInspector,
201-
debug: isDebugBuild,
202-
uv: true,
203-
ipv6: true, // TODO(bnoordhuis) ping libuv
204-
tls_alpn: hasOpenSSL,
205-
tls_sni: hasOpenSSL,
206-
tls_ocsp: hasOpenSSL,
207-
tls: hasOpenSSL,
208-
cached_builtins: config.hasCachedBuiltins,
209-
}
217+
value: features
210218
});
211219

212220
{

src/env.cc

+20-1
Original file line numberDiff line numberDiff line change
@@ -1208,6 +1208,11 @@ EnvSerializeInfo Environment::Serialize(SnapshotCreator* creator) {
12081208
EnvSerializeInfo info;
12091209
Local<Context> ctx = context();
12101210

1211+
// Currently all modules are compiled without cache in builtin snapshot
1212+
// builder.
1213+
info.native_modules = std::vector<std::string>(
1214+
native_modules_without_cache.begin(), native_modules_without_cache.end());
1215+
12111216
info.async_hooks = async_hooks_.Serialize(ctx, creator);
12121217
info.immediate_info = immediate_info_.Serialize(ctx, creator);
12131218
info.tick_info = tick_info_.Serialize(ctx, creator);
@@ -1257,11 +1262,24 @@ std::ostream& operator<<(std::ostream& output,
12571262
return output;
12581263
}
12591264

1265+
std::ostream& operator<<(std::ostream& output,
1266+
const std::vector<std::string>& vec) {
1267+
output << "{\n";
1268+
for (const auto& info : vec) {
1269+
output << " \"" << info << "\",\n";
1270+
}
1271+
output << "}";
1272+
return output;
1273+
}
1274+
12601275
std::ostream& operator<<(std::ostream& output, const EnvSerializeInfo& i) {
12611276
output << "{\n"
1277+
<< "// -- native_modules begins --\n"
1278+
<< i.native_modules << ",\n"
1279+
<< "// -- native_modules ends --\n"
12621280
<< "// -- async_hooks begins --\n"
12631281
<< i.async_hooks << ",\n"
1264-
<< "// -- async_hooks begins --\n"
1282+
<< "// -- async_hooks ends --\n"
12651283
<< i.tick_info << ", // tick_info\n"
12661284
<< i.immediate_info << ", // immediate_info\n"
12671285
<< "// -- performance_state begins --\n"
@@ -1284,6 +1302,7 @@ std::ostream& operator<<(std::ostream& output, const EnvSerializeInfo& i) {
12841302
void Environment::DeserializeProperties(const EnvSerializeInfo* info) {
12851303
Local<Context> ctx = context();
12861304

1305+
native_modules_in_snapshot = info->native_modules;
12871306
async_hooks_.Deserialize(ctx);
12881307
immediate_info_.Deserialize(ctx);
12891308
tick_info_.Deserialize(ctx);

src/env.h

+4
Original file line numberDiff line numberDiff line change
@@ -899,6 +899,7 @@ struct PropInfo {
899899
};
900900

901901
struct EnvSerializeInfo {
902+
std::vector<std::string> native_modules;
902903
AsyncHooks::SerializeInfo async_hooks;
903904
TickInfo::SerializeInfo tick_info;
904905
ImmediateInfo::SerializeInfo immediate_info;
@@ -1086,6 +1087,9 @@ class Environment : public MemoryRetainer {
10861087

10871088
std::set<std::string> native_modules_with_cache;
10881089
std::set<std::string> native_modules_without_cache;
1090+
// This is only filled during deserialization. We use a vector since
1091+
// it's only used for tests.
1092+
std::vector<std::string> native_modules_in_snapshot;
10891093

10901094
std::unordered_multimap<int, loader::ModuleWrap*> hash_to_module_map;
10911095
std::unordered_map<uint32_t, loader::ModuleWrap*> id_to_module_map;

src/node.cc

+1
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,7 @@ MaybeLocal<Value> Environment::BootstrapNode() {
350350
return scope.EscapeMaybe(result);
351351
}
352352

353+
// TODO(joyeecheung): skip these in the snapshot building for workers.
353354
auto thread_switch_id =
354355
is_main_thread() ? "internal/bootstrap/switches/is_main_thread"
355356
: "internal/bootstrap/switches/is_not_main_thread";

src/node_config.cc

-3
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,6 @@ static void Initialize(Local<Object> target,
8484
#if defined HAVE_DTRACE || defined HAVE_ETW
8585
READONLY_TRUE_PROPERTY(target, "hasDtrace");
8686
#endif
87-
88-
READONLY_PROPERTY(target, "hasCachedBuiltins",
89-
v8::Boolean::New(isolate, native_module::has_code_cache));
9087
} // InitConfig
9188

9289
} // namespace node

src/node_native_module_env.cc

+14
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,14 @@ void NativeModuleEnv::GetCacheUsage(const FunctionCallbackInfo<Value>& args) {
9494
OneByteString(isolate, "compiledWithoutCache"),
9595
ToJsSet(context, env->native_modules_without_cache))
9696
.FromJust();
97+
98+
result
99+
->Set(env->context(),
100+
OneByteString(isolate, "compiledInSnapshot"),
101+
ToV8Value(env->context(), env->native_modules_in_snapshot)
102+
.ToLocalChecked())
103+
.FromJust();
104+
97105
args.GetReturnValue().Set(result);
98106
}
99107

@@ -155,6 +163,11 @@ MaybeLocal<Function> NativeModuleEnv::LookupAndCompile(
155163
return maybe;
156164
}
157165

166+
void HasCachedBuiltins(const FunctionCallbackInfo<Value>& args) {
167+
args.GetReturnValue().Set(
168+
v8::Boolean::New(args.GetIsolate(), has_code_cache));
169+
}
170+
158171
// TODO(joyeecheung): It is somewhat confusing that Class::Initialize
159172
// is used to initialize to the binding, but it is the current convention.
160173
// Rename this across the code base to something that makes more sense.
@@ -198,6 +211,7 @@ void NativeModuleEnv::Initialize(Local<Object> target,
198211

199212
env->SetMethod(target, "getCacheUsage", NativeModuleEnv::GetCacheUsage);
200213
env->SetMethod(target, "compileFunction", NativeModuleEnv::CompileFunction);
214+
env->SetMethod(target, "hasCachedBuiltins", HasCachedBuiltins);
201215
// internalBinding('native_module') should be frozen
202216
target->SetIntegrityLevel(context, IntegrityLevel::kFrozen).FromJust();
203217
}

test/parallel/test-code-cache.js

+10-4
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,16 @@ for (const key of canBeRequired) {
2222
// The computation has to be delayed until we have done loading modules
2323
const {
2424
compiledWithoutCache,
25-
compiledWithCache
25+
compiledWithCache,
26+
compiledInSnapshot
2627
} = getCacheUsage();
2728

28-
const loadedModules = process.moduleLoadList
29-
.filter((m) => m.startsWith('NativeModule'))
29+
function extractModules(list) {
30+
return list.filter((m) => m.startsWith('NativeModule'))
3031
.map((m) => m.replace('NativeModule ', ''));
32+
}
33+
34+
const loadedModules = extractModules(process.moduleLoadList);
3135

3236
// Cross-compiled binaries do not have code cache, verifies that the builtins
3337
// are all compiled without cache and we are doing the bookkeeping right.
@@ -62,7 +66,9 @@ if (!process.features.cached_builtins) {
6266
if (cannotBeRequired.has(key) && !compiledWithoutCache.has(key)) {
6367
wrong.push(`"${key}" should've been compiled **without** code cache`);
6468
}
65-
if (canBeRequired.has(key) && !compiledWithCache.has(key)) {
69+
if (canBeRequired.has(key) &&
70+
!compiledWithCache.has(key) &&
71+
compiledInSnapshot.indexOf(key) === -1) {
6672
wrong.push(`"${key}" should've been compiled **with** code cache`);
6773
}
6874
}

0 commit comments

Comments
 (0)