Skip to content

Commit 527b44a

Browse files
authored
fix: add vatDecRef to kernel, offer to liveslots (#1926)
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
1 parent b765066 commit 527b44a

File tree

7 files changed

+50
-10
lines changed

7 files changed

+50
-10
lines changed

packages/SwingSet/src/controller.js

+9-3
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,12 @@ export async function makeSwingsetController(
4646
insistStorageAPI(hostStorage);
4747

4848
// build console early so we can add console.log to diagnose early problems
49-
const { verbose, debugPrefix = '', slogFile } = runtimeOptions;
49+
const {
50+
verbose,
51+
debugPrefix = '',
52+
slogFile,
53+
testTrackDecref,
54+
} = runtimeOptions;
5055
if (typeof Compartment === 'undefined') {
5156
throw Error('SES must be installed before calling makeSwingsetController');
5257
}
@@ -188,7 +193,7 @@ export async function makeSwingsetController(
188193
FinalizationRegistry,
189194
};
190195

191-
const kernelOptions = { verbose };
196+
const kernelOptions = { verbose, testTrackDecref };
192197
const kernel = buildKernel(kernelEndowments, deviceEndowments, kernelOptions);
193198

194199
if (runtimeOptions.verbose) {
@@ -280,8 +285,9 @@ export async function buildVatController(
280285
verbose,
281286
kernelBundles,
282287
debugPrefix,
288+
testTrackDecref,
283289
} = runtimeOptions;
284-
const actualRuntimeOptions = { verbose, debugPrefix };
290+
const actualRuntimeOptions = { verbose, debugPrefix, testTrackDecref };
285291
const initializationOptions = { verbose, kernelBundles };
286292
let bootstrapResult;
287293
if (!swingsetIsInitialized(hostStorage)) {

packages/SwingSet/src/kernel/kernel.js

+14-3
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ export default function buildKernel(
103103
FinalizationRegistry,
104104
} = kernelEndowments;
105105
deviceEndowments = { ...deviceEndowments }; // copy so we can modify
106-
const { verbose } = kernelOptions;
106+
const { verbose, testTrackDecref = false } = kernelOptions;
107107
const logStartup = verbose ? console.debug : () => 0;
108108

109109
insistStorageAPI(hostStorage);
@@ -144,6 +144,17 @@ export default function buildKernel(
144144
return kernelSlog.vatConsole(vatID, origConsole);
145145
}
146146

147+
const pendingDecrefs = [];
148+
function decref(vatID, vref, count) {
149+
assert(ephemeral.vats.has(vatID), `unknown vatID ${vatID}`);
150+
assert(count > 0, `bad count ${count}`);
151+
// TODO: decrement the clist import counter by 'count', then GC if zero
152+
if (testTrackDecref) {
153+
console.log(`kernel decref [${vatID}].${vref} -= ${count}`);
154+
pendingDecrefs.push({ vatID, vref, count });
155+
}
156+
}
157+
147158
// runQueue entries are {type, vatID, more..}. 'more' depends on type:
148159
// * deliver: target, msg
149160
// * notifyFulfillToData/notifyFulfillToPresence/notifyReject:
@@ -531,7 +542,7 @@ export default function buildKernel(
531542
}
532543
}
533544

534-
const gcTools = harden({ WeakRef, FinalizationRegistry });
545+
const gcTools = harden({ WeakRef, FinalizationRegistry, decref });
535546
const vatManagerFactory = makeVatManagerFactory({
536547
allVatPowers,
537548
kernelKeeper,
@@ -955,7 +966,7 @@ export default function buildKernel(
955966
// a time, so any log() calls that were interleaved during their
956967
// original execution will be sorted by vat in the replace). Logs are
957968
// not kept in the persistent state, only in ephemeral state.
958-
return { log: ephemeral.log, ...kernelKeeper.dump() };
969+
return { log: ephemeral.log, pendingDecrefs, ...kernelKeeper.dump() };
959970
},
960971
kdebugEnable,
961972

packages/SwingSet/src/kernel/vatManager/factory.js

+3
Original file line numberDiff line numberDiff line change
@@ -30,18 +30,21 @@ export function makeVatManagerFactory({
3030
makeNodeWorker,
3131
kernelKeeper,
3232
testLog: allVatPowers.testLog,
33+
decref: gcTools.decref,
3334
});
3435

3536
const nodeSubprocessFactory = makeNodeSubprocessFactory({
3637
startSubprocessWorker: startSubprocessWorkerNode,
3738
kernelKeeper,
3839
testLog: allVatPowers.testLog,
40+
decref: gcTools.decref,
3941
});
4042

4143
const xsWorkerFactory = makeNodeSubprocessFactory({
4244
startSubprocessWorker: startSubprocessWorkerXS,
4345
kernelKeeper,
4446
testLog: allVatPowers.testLog,
47+
decref: gcTools.decref,
4548
});
4649

4750
function validateManagerOptions(managerOptions) {

packages/SwingSet/src/kernel/vatManager/localVatManager.js

+6-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export function makeLocalVatManagerFactory(tools) {
1717
} = tools;
1818

1919
const { makeGetMeter, refillAllMeters, stopGlobalMeter } = meterManager;
20+
const { WeakRef, FinalizationRegistry } = gcTools;
2021
const baseVP = {
2122
Remotable: allVatPowers.Remotable,
2223
getInterfaceOf: allVatPowers.getInterfaceOf,
@@ -105,10 +106,14 @@ export function makeLocalVatManagerFactory(tools) {
105106
vatParameters,
106107
testLog: allVatPowers.testLog,
107108
});
109+
function vatDecref(vref, count) {
110+
gcTools.decref(vatID, vref, count);
111+
}
112+
const lsgc = harden({ WeakRef, FinalizationRegistry, vatDecref });
108113

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

113118
let meterRecord = null;
114119
if (metered) {

packages/SwingSet/src/kernel/vatManager/nodeWorker.js

+8-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ function parentLog(first, ...args) {
2323
}
2424

2525
export function makeNodeWorkerVatManagerFactory(tools) {
26-
const { makeNodeWorker, kernelKeeper, testLog } = tools;
26+
const { makeNodeWorker, kernelKeeper, testLog, decref } = tools;
2727

2828
function createFromBundle(vatID, bundle, managerOptions) {
2929
const { vatParameters } = managerOptions;
@@ -68,6 +68,10 @@ export function makeNodeWorkerVatManagerFactory(tools) {
6868
doSyscall(vatSyscallObject);
6969
}
7070

71+
function vatDecref(vref, count) {
72+
decref(vatID, vref, count);
73+
}
74+
7175
// start the worker and establish a connection
7276

7377
const { promise: workerP, resolve: gotWorker } = makePromiseKit();
@@ -107,6 +111,9 @@ export function makeNodeWorkerVatManagerFactory(tools) {
107111
const deliveryResult = args;
108112
resolve(deliveryResult);
109113
}
114+
} else if (type === 'decref') {
115+
const [vref, count] = args;
116+
vatDecref(vref, count);
110117
} else {
111118
parentLog(`unrecognized uplink message ${type}`);
112119
}

packages/SwingSet/src/kernel/vatManager/worker-subprocess-node.js

+8-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ function parentLog(first, ...args) {
2424
}
2525

2626
export function makeNodeSubprocessFactory(tools) {
27-
const { startSubprocessWorker, kernelKeeper, testLog } = tools;
27+
const { startSubprocessWorker, kernelKeeper, testLog, decref } = tools;
2828

2929
function createFromBundle(vatID, bundle, managerOptions) {
3030
const { vatParameters } = managerOptions;
@@ -71,6 +71,10 @@ export function makeNodeSubprocessFactory(tools) {
7171
doSyscall(vatSyscallObject);
7272
}
7373

74+
function vatDecref(vref, count) {
75+
decref(vatID, vref, count);
76+
}
77+
7478
// start the worker and establish a connection
7579
const { fromChild, toChild, terminate, done } = startSubprocessWorker();
7680

@@ -109,6 +113,9 @@ export function makeNodeSubprocessFactory(tools) {
109113
const deliveryResult = args;
110114
resolve(deliveryResult);
111115
}
116+
} else if (type === 'decref') {
117+
const [vref, count] = args;
118+
vatDecref(vref, count);
112119
} else {
113120
parentLog(`unrecognized uplink message ${type}`);
114121
}

packages/SwingSet/test/test-vpid-liveslots.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,8 @@ function resolutionOf(vpid, mode, targets) {
191191
}
192192

193193
function makeDispatch(syscall, build) {
194-
const gcTools = harden({ WeakRef, FinalizationRegistry });
194+
function vatDecref() {}
195+
const gcTools = harden({ WeakRef, FinalizationRegistry, vatDecref });
195196
const { setBuildRootObject, dispatch } = makeLiveSlots(
196197
syscall,
197198
'vatA',

0 commit comments

Comments
 (0)