Skip to content

Commit

Permalink
refactor(runtime): manual serialization of bootstrap data (denoland#1…
Browse files Browse the repository at this point in the history
…8448)

This commit changes how data required to bootstrap main and worker
runtime is serialized. 

Instead of relying on serde_v8 and using JSON object,
we're doing manual serialization to a "v8::Array". This limits number 
of V8 strings that need to be serialized by 16. 

It also made it clear that some data could be obtained during
snapshotting instead of during bootstrap.
  • Loading branch information
bartlomieju committed Mar 28, 2023
1 parent 86c3c4f commit 795ecfa
Show file tree
Hide file tree
Showing 4 changed files with 230 additions and 62 deletions.
126 changes: 95 additions & 31 deletions runtime/js/99_main.js
Original file line number Diff line number Diff line change
Expand Up @@ -292,20 +292,29 @@ core.registerErrorBuilder(
},
);

function runtimeStart(runtimeOptions, source) {
function runtimeStart(
denoVersion,
v8Version,
tsVersion,
target,
debugFlag,
noColor,
isTty,
source,
) {
core.setMacrotaskCallback(timers.handleTimerMacrotask);
core.setMacrotaskCallback(promiseRejectMacrotaskCallback);
core.setWasmStreamingCallback(fetch.handleWasmStreaming);
core.setReportExceptionCallback(event.reportException);
ops.op_set_format_exception_callback(formatException);
version.setVersions(
runtimeOptions.denoVersion,
runtimeOptions.v8Version,
runtimeOptions.tsVersion,
denoVersion,
v8Version,
tsVersion,
);
core.setBuildInfo(runtimeOptions.target);
util.setLogDebug(runtimeOptions.debugFlag, source);
colors.setNoColor(runtimeOptions.noColor || !runtimeOptions.isTty);
core.setBuildInfo(target);
util.setLogDebug(debugFlag, source);
colors.setNoColor(noColor || !isTty);
// deno-lint-ignore prefer-primordials
Error.prepareStackTrace = core.prepareStackTrace;
}
Expand Down Expand Up @@ -403,6 +412,27 @@ function bootstrapMainRuntime(runtimeOptions) {
if (hasBootstrapped) {
throw new Error("Worker runtime already bootstrapped");
}

const [
args,
cpuCount,
debugFlag,
denoVersion,
locale,
location_,
noColor,
isTty,
tsVersion,
unstableFlag,
pid,
ppid,
target,
v8Version,
userAgent,
inspectFlag,
_,
] = runtimeOptions;

performance.setTimeOrigin(DateNow());
globalThis_ = globalThis;

Expand All @@ -414,15 +444,15 @@ function bootstrapMainRuntime(runtimeOptions) {
// If the `--location` flag isn't set, make `globalThis.location` `undefined` and
// writable, so that they can mock it themselves if they like. If the flag was
// set, define `globalThis.location`, using the provided value.
if (runtimeOptions.location == null) {
if (location_ === undefined) {
mainRuntimeGlobalProperties.location = {
writable: true,
};
} else {
location.setLocationHref(runtimeOptions.location);
location.setLocationHref(location_);
}

if (runtimeOptions.unstableFlag) {
if (unstableFlag) {
ObjectDefineProperties(globalThis, unstableWindowOrWorkerGlobalScope);
}
ObjectDefineProperties(globalThis, mainRuntimeGlobalProperties);
Expand All @@ -432,7 +462,7 @@ function bootstrapMainRuntime(runtimeOptions) {
});
ObjectSetPrototypeOf(globalThis, Window.prototype);

if (runtimeOptions.inspectFlag) {
if (inspectFlag) {
const consoleFromV8 = core.console;
const consoleFromDeno = globalThis.console;
wrapConsole(consoleFromDeno, consoleFromV8);
Expand All @@ -449,11 +479,19 @@ function bootstrapMainRuntime(runtimeOptions) {

core.setPromiseRejectCallback(promiseRejectCallback);

runtimeStart(runtimeOptions);
runtimeStart(
denoVersion,
v8Version,
tsVersion,
target,
debugFlag,
noColor,
isTty,
);

setNumCpus(runtimeOptions.cpuCount);
setUserAgent(runtimeOptions.userAgent);
setLanguage(runtimeOptions.locale);
setNumCpus(cpuCount);
setUserAgent(userAgent);
setLanguage(locale);

// These have to initialized here and not in `90_deno_ns.js` because
// the op function that needs to be passed will be invalidated by creating
Expand All @@ -477,14 +515,14 @@ function bootstrapMainRuntime(runtimeOptions) {
});

ObjectDefineProperties(finalDenoNs, {
pid: util.readOnly(runtimeOptions.pid),
ppid: util.readOnly(runtimeOptions.ppid),
noColor: util.readOnly(runtimeOptions.noColor),
args: util.readOnly(ObjectFreeze(runtimeOptions.args)),
pid: util.readOnly(pid),
ppid: util.readOnly(ppid),
noColor: util.readOnly(noColor),
args: util.readOnly(ObjectFreeze(args)),
mainModule: util.getterOnly(opMainModule),
});

if (runtimeOptions.unstableFlag) {
if (unstableFlag) {
ObjectAssign(finalDenoNs, denoNsUnstable);
// These have to initialized here and not in `90_deno_ns.js` because
// the op function that needs to be passed will be invalidated by creating
Expand All @@ -502,7 +540,7 @@ function bootstrapMainRuntime(runtimeOptions) {
// `Deno` with `Deno` namespace from "./deno.ts".
ObjectDefineProperty(globalThis, "Deno", util.readOnly(finalDenoNs));

util.log("args", runtimeOptions.args);
util.log("args", args);
}

function bootstrapWorkerRuntime(
Expand All @@ -514,6 +552,26 @@ function bootstrapWorkerRuntime(
throw new Error("Worker runtime already bootstrapped");
}

const [
args,
cpuCount,
debugFlag,
denoVersion,
locale,
location_,
noColor,
isTty,
tsVersion,
unstableFlag,
pid,
_ppid,
target,
v8Version,
_userAgent,
_inspectFlag,
enableTestingFeaturesFlag,
] = runtimeOptions;

performance.setTimeOrigin(DateNow());
globalThis_ = globalThis;

Expand All @@ -524,7 +582,7 @@ function bootstrapWorkerRuntime(
delete globalThis.bootstrap;
hasBootstrapped = true;

if (runtimeOptions.unstableFlag) {
if (unstableFlag) {
ObjectDefineProperties(globalThis, unstableWindowOrWorkerGlobalScope);
}
ObjectDefineProperties(globalThis, workerRuntimeGlobalProperties);
Expand All @@ -534,7 +592,7 @@ function bootstrapWorkerRuntime(
close: util.nonEnumerable(workerClose),
postMessage: util.writable(postMessage),
});
if (runtimeOptions.enableTestingFeaturesFlag) {
if (enableTestingFeaturesFlag) {
ObjectDefineProperty(
globalThis,
"importScripts",
Expand Down Expand Up @@ -562,14 +620,20 @@ function bootstrapWorkerRuntime(
});

runtimeStart(
runtimeOptions,
denoVersion,
v8Version,
tsVersion,
target,
debugFlag,
noColor,
isTty,
internalName ?? name,
);

location.setLocationHref(runtimeOptions.location);
location.setLocationHref(location_);

setNumCpus(runtimeOptions.cpuCount);
setLanguage(runtimeOptions.locale);
setNumCpus(cpuCount);
setLanguage(locale);

globalThis.pollForMessages = pollForMessages;

Expand All @@ -594,7 +658,7 @@ function bootstrapWorkerRuntime(
core,
});

if (runtimeOptions.unstableFlag) {
if (unstableFlag) {
ObjectAssign(finalDenoNs, denoNsUnstable);
// These have to initialized here and not in `90_deno_ns.js` because
// the op function that needs to be passed will be invalidated by creating
Expand All @@ -608,9 +672,9 @@ function bootstrapWorkerRuntime(
});
}
ObjectDefineProperties(finalDenoNs, {
pid: util.readOnly(runtimeOptions.pid),
noColor: util.readOnly(runtimeOptions.noColor),
args: util.readOnly(ObjectFreeze(runtimeOptions.args)),
pid: util.readOnly(pid),
noColor: util.readOnly(noColor),
args: util.readOnly(ObjectFreeze(args)),
});
// Setup `Deno` global - we're actually overriding already
// existing global `Deno` with `Deno` namespace from "./deno.ts".
Expand Down
5 changes: 2 additions & 3 deletions runtime/web_worker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -556,8 +556,7 @@ impl WebWorker {
// WebWorkers can have empty string as name.
{
let scope = &mut self.js_runtime.handle_scope();
let options_v8 =
deno_core::serde_v8::to_v8(scope, options.as_json()).unwrap();
let args = options.as_v8(scope);
let bootstrap_fn = self.bootstrap_fn_global.take().unwrap();
let bootstrap_fn = v8::Local::new(scope, bootstrap_fn);
let undefined = v8::undefined(scope);
Expand All @@ -568,7 +567,7 @@ impl WebWorker {
.unwrap()
.into();
bootstrap_fn
.call(scope, undefined.into(), &[options_v8, name_str, id_str])
.call(scope, undefined.into(), &[args.into(), name_str, id_str])
.unwrap();
}
// TODO(bartlomieju): this could be done using V8 API, without calling `execute_script`.
Expand Down
5 changes: 2 additions & 3 deletions runtime/worker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -361,13 +361,12 @@ impl MainWorker {

pub fn bootstrap(&mut self, options: &BootstrapOptions) {
let scope = &mut self.js_runtime.handle_scope();
let options_v8 =
deno_core::serde_v8::to_v8(scope, options.as_json()).unwrap();
let args = options.as_v8(scope);
let bootstrap_fn = self.bootstrap_fn_global.take().unwrap();
let bootstrap_fn = v8::Local::new(scope, bootstrap_fn);
let undefined = v8::undefined(scope);
bootstrap_fn
.call(scope, undefined.into(), &[options_v8])
.call(scope, undefined.into(), &[args.into()])
.unwrap();
}

Expand Down
Loading

0 comments on commit 795ecfa

Please sign in to comment.