Skip to content

Commit 160026d

Browse files
committed
feat(swingset): comms: enable object tracking in processMaybeFree()
* populate `maybeFree` with object references whose refcounts touch zero * update `processMaybeFree` to examine object refcounts * Promises continue to be freed immediately * for objects, we accumulate a set of "actions" that need to be taken * these actions will be executed by an upcoming patch * add `getOwnerAndStatus` helper function
1 parent a3bf097 commit 160026d

File tree

1 file changed

+57
-3
lines changed
  • packages/SwingSet/src/vats/comms

1 file changed

+57
-3
lines changed

packages/SwingSet/src/vats/comms/state.js

+57-3
Original file line numberDiff line numberDiff line change
@@ -307,25 +307,27 @@ export function makeState(syscall, identifierBase = 0) {
307307
if (mode === 'clist-import' || mode === 'data') {
308308
const recognizable = changeRecognizable(lref, -1n);
309309
if (!recognizable) {
310-
// maybeFree.add(lref);
310+
maybeFree.add(lref);
311311
}
312312
}
313313
if (mode === 'data') {
314314
const reachable = changeReachable(lref, -1n);
315315
if (!reachable) {
316-
// maybeFree.add(lref);
316+
maybeFree.add(lref);
317317
}
318318
}
319319
}
320320
}
321321

322322
/**
323-
* Delete any local promises that have zero references.
323+
* Delete any local promises that have zero references. Return a list of
324+
* work for unreachable/unrecognizable objects.
324325
*
325326
* Note that this should only be called *after* all work for a crank is done,
326327
* because transient zero refCounts are possible during the middle of a crank.
327328
*/
328329
function processMaybeFree() {
330+
const actions = new Set();
329331
// We make a copy of the set, iterate over that, then try again, until
330332
// the set is empty. TC39 went to a lot of trouble to make sure you can
331333
// add things to a Set while iterating over it, but I think our
@@ -353,8 +355,44 @@ export function makeState(syscall, identifierBase = 0) {
353355
}
354356
}
355357
}
358+
if (type === 'object') {
359+
// don't do anything if importers can still reach it
360+
const reaKey = `${lref}.reachable`;
361+
const reachable = Nat(BigInt(store.getRequired(reaKey)));
362+
if (!reachable) {
363+
// the object is unreachable
364+
365+
// eslint-disable-next-line no-use-before-define
366+
const { owner, isReachable, isRecognizable } = getOwnerAndStatus(
367+
lref,
368+
);
369+
if (isReachable) {
370+
// but the exporter doesn't realize it yet, so schedule a
371+
// dropExport to them, which will clear the isReachable flag at
372+
// the end of the turn
373+
actions.add(`${owner} dropExport ${lref}`);
374+
}
375+
376+
const recKey = `${lref}.recognizable`;
377+
const recognizable = Nat(BigInt(store.getRequired(recKey)));
378+
if (!recognizable && isRecognizable) {
379+
// all importers have given up, but the exporter is still
380+
// exporting, so schedule a retireExport to them, which will
381+
// delete the clist entry after it's translated.
382+
actions.add(`${owner} retireExport ${lref}`);
383+
}
384+
if (!isRecognizable) {
385+
// the exporter has given up, so tell all importers to give up
386+
for (const importer of getImporters(lref)) {
387+
actions.add(`${importer} retireImport ${lref}`);
388+
}
389+
}
390+
}
391+
}
356392
}
357393
}
394+
395+
return actions;
358396
}
359397

360398
function mapFromKernel(kfref) {
@@ -482,6 +520,22 @@ export function makeState(syscall, identifierBase = 0) {
482520
return lpid;
483521
}
484522

523+
function getOwnerAndStatus(lref) {
524+
const owner = getObject(lref);
525+
let isReachable;
526+
let isRecognizable;
527+
if (owner === 'kernel') {
528+
isReachable = isReachableByKernel(lref);
529+
isRecognizable = !!mapToKernel(lref);
530+
} else {
531+
// eslint-disable-next-line no-use-before-define
532+
const remote = getRemote(owner);
533+
isReachable = remote.isReachable(lref);
534+
isRecognizable = !!remote.mapToRemote(lref);
535+
}
536+
return { owner, isReachable, isRecognizable };
537+
}
538+
485539
function deciderIsKernel(lpid) {
486540
const decider = store.getRequired(`${lpid}.decider`);
487541
return decider === KERNEL;

0 commit comments

Comments
 (0)