Skip to content

Commit

Permalink
fix: add vatDecRef to kernel, offer to liveslots
Browse files Browse the repository at this point in the history
In the future, when liveslots implements GC and discovers that a Presence has
ceased to be referenced by the user-level vat code, it will call this
function to decrement the kernel's reference count for the imported object's
c-list entry.

`vatDecRef` might be called at any time (although always in its own turn).
The kernel will eventually add the decref information to a queue, to be
processed between cranks. For now, the kernel only records the information if
an option was set to enable it (for future unit tests).

Most of this patch is the kernel-worker protocol wiring to allow
child-process vat workers to deliver the decref back up to the kernel
process.

Liveslots does not use this yet. A future patch will switch it on.

refs #1872
  • Loading branch information
warner committed Oct 27, 2020
1 parent 3949dfb commit f0721d9
Show file tree
Hide file tree
Showing 7 changed files with 50 additions and 10 deletions.
12 changes: 9 additions & 3 deletions packages/SwingSet/src/controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,12 @@ export async function makeSwingsetController(
insistStorageAPI(hostStorage);

// build console early so we can add console.log to diagnose early problems
const { verbose, debugPrefix = '', slogFile } = runtimeOptions;
const {
verbose,
debugPrefix = '',
slogFile,
testTrackDecref,
} = runtimeOptions;
if (typeof Compartment === 'undefined') {
throw Error('SES must be installed before calling makeSwingsetController');
}
Expand Down Expand Up @@ -188,7 +193,7 @@ export async function makeSwingsetController(
FinalizationRegistry,
};

const kernelOptions = { verbose };
const kernelOptions = { verbose, testTrackDecref };
const kernel = buildKernel(kernelEndowments, deviceEndowments, kernelOptions);

if (runtimeOptions.verbose) {
Expand Down Expand Up @@ -280,8 +285,9 @@ export async function buildVatController(
verbose,
kernelBundles,
debugPrefix,
testTrackDecref,
} = runtimeOptions;
const actualRuntimeOptions = { verbose, debugPrefix };
const actualRuntimeOptions = { verbose, debugPrefix, testTrackDecref };
const initializationOptions = { verbose, kernelBundles };
let bootstrapResult;
if (!swingsetIsInitialized(hostStorage)) {
Expand Down
17 changes: 14 additions & 3 deletions packages/SwingSet/src/kernel/kernel.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ export default function buildKernel(
FinalizationRegistry,
} = kernelEndowments;
deviceEndowments = { ...deviceEndowments }; // copy so we can modify
const { verbose } = kernelOptions;
const { verbose, testTrackDecref = false } = kernelOptions;
const logStartup = verbose ? console.debug : () => 0;

insistStorageAPI(hostStorage);
Expand Down Expand Up @@ -144,6 +144,17 @@ export default function buildKernel(
return kernelSlog.vatConsole(vatID, origConsole);
}

const pendingDecrefs = [];
function decref(vatID, vref, count) {
assert(ephemeral.vats.has(vatID), `unknown vatID ${vatID}`);
assert(count > 0, `bad count ${count}`);
// TODO: decrement the clist import counter by 'count', then GC if zero
if (testTrackDecref) {
console.log(`kernel decref [${vatID}].${vref} -= ${count}`);
pendingDecrefs.push({ vatID, vref, count });
}
}

// runQueue entries are {type, vatID, more..}. 'more' depends on type:
// * deliver: target, msg
// * notifyFulfillToData/notifyFulfillToPresence/notifyReject:
Expand Down Expand Up @@ -531,7 +542,7 @@ export default function buildKernel(
}
}

const gcTools = harden({ WeakRef, FinalizationRegistry });
const gcTools = harden({ WeakRef, FinalizationRegistry, decref });
const vatManagerFactory = makeVatManagerFactory({
allVatPowers,
kernelKeeper,
Expand Down Expand Up @@ -955,7 +966,7 @@ export default function buildKernel(
// a time, so any log() calls that were interleaved during their
// original execution will be sorted by vat in the replace). Logs are
// not kept in the persistent state, only in ephemeral state.
return { log: ephemeral.log, ...kernelKeeper.dump() };
return { log: ephemeral.log, pendingDecrefs, ...kernelKeeper.dump() };
},
kdebugEnable,

Expand Down
3 changes: 3 additions & 0 deletions packages/SwingSet/src/kernel/vatManager/factory.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,18 +30,21 @@ export function makeVatManagerFactory({
makeNodeWorker,
kernelKeeper,
testLog: allVatPowers.testLog,
decref: gcTools.decref,
});

const nodeSubprocessFactory = makeNodeSubprocessFactory({
startSubprocessWorker: startSubprocessWorkerNode,
kernelKeeper,
testLog: allVatPowers.testLog,
decref: gcTools.decref,
});

const xsWorkerFactory = makeNodeSubprocessFactory({
startSubprocessWorker: startSubprocessWorkerXS,
kernelKeeper,
testLog: allVatPowers.testLog,
decref: gcTools.decref,
});

function validateManagerOptions(managerOptions) {
Expand Down
7 changes: 6 additions & 1 deletion packages/SwingSet/src/kernel/vatManager/localVatManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export function makeLocalVatManagerFactory(tools) {
} = tools;

const { makeGetMeter, refillAllMeters, stopGlobalMeter } = meterManager;
const { WeakRef, FinalizationRegistry } = gcTools;
const baseVP = {
Remotable: allVatPowers.Remotable,
getInterfaceOf: allVatPowers.getInterfaceOf,
Expand Down Expand Up @@ -105,10 +106,14 @@ export function makeLocalVatManagerFactory(tools) {
vatParameters,
testLog: allVatPowers.testLog,
});
function vatDecref(vref, count) {
gcTools.decref(vatID, vref, count);
}
const lsgc = harden({ WeakRef, FinalizationRegistry, vatDecref });

// we might or might not use this, depending upon whether the vat exports
// 'buildRootObject' or a default 'setup' function
const ls = makeLiveSlots(syscall, vatID, vatPowers, vatParameters, gcTools);
const ls = makeLiveSlots(syscall, vatID, vatPowers, vatParameters, lsgc);

let meterRecord = null;
if (metered) {
Expand Down
9 changes: 8 additions & 1 deletion packages/SwingSet/src/kernel/vatManager/nodeWorker.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ function parentLog(first, ...args) {
}

export function makeNodeWorkerVatManagerFactory(tools) {
const { makeNodeWorker, kernelKeeper, testLog } = tools;
const { makeNodeWorker, kernelKeeper, testLog, decref } = tools;

function createFromBundle(vatID, bundle, managerOptions) {
const { vatParameters } = managerOptions;
Expand Down Expand Up @@ -68,6 +68,10 @@ export function makeNodeWorkerVatManagerFactory(tools) {
doSyscall(vatSyscallObject);
}

function vatDecref(vref, count) {
decref(vatID, vref, count);
}

// start the worker and establish a connection

const { promise: workerP, resolve: gotWorker } = makePromiseKit();
Expand Down Expand Up @@ -107,6 +111,9 @@ export function makeNodeWorkerVatManagerFactory(tools) {
const deliveryResult = args;
resolve(deliveryResult);
}
} else if (type === 'decref') {
const [vref, count] = args;
vatDecref(vref, count);
} else {
parentLog(`unrecognized uplink message ${type}`);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ function parentLog(first, ...args) {
}

export function makeNodeSubprocessFactory(tools) {
const { startSubprocessWorker, kernelKeeper, testLog } = tools;
const { startSubprocessWorker, kernelKeeper, testLog, decref } = tools;

function createFromBundle(vatID, bundle, managerOptions) {
const { vatParameters } = managerOptions;
Expand Down Expand Up @@ -71,6 +71,10 @@ export function makeNodeSubprocessFactory(tools) {
doSyscall(vatSyscallObject);
}

function vatDecref(vref, count) {
decref(vatID, vref, count);
}

// start the worker and establish a connection
const { fromChild, toChild, terminate, done } = startSubprocessWorker();

Expand Down Expand Up @@ -109,6 +113,9 @@ export function makeNodeSubprocessFactory(tools) {
const deliveryResult = args;
resolve(deliveryResult);
}
} else if (type === 'decref') {
const [vref, count] = args;
vatDecref(vref, count);
} else {
parentLog(`unrecognized uplink message ${type}`);
}
Expand Down
3 changes: 2 additions & 1 deletion packages/SwingSet/test/test-vpid-liveslots.js
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,8 @@ function resolutionOf(vpid, mode, targets) {
}

function makeDispatch(syscall, build) {
const gcTools = harden({ WeakRef, FinalizationRegistry });
function vatDecref() {}
const gcTools = harden({ WeakRef, FinalizationRegistry, vatDecref });
const { setBuildRootObject, dispatch } = makeLiveSlots(
syscall,
'vatA',
Expand Down

0 comments on commit f0721d9

Please sign in to comment.