Skip to content

Commit

Permalink
fix(SwingSet): Introduce a termination-dedicated "VatUndertaker" anal…
Browse files Browse the repository at this point in the history
…og to "VatKeeper"
  • Loading branch information
gibson042 committed Nov 9, 2024
1 parent d7c2872 commit b786414
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 63 deletions.
79 changes: 54 additions & 25 deletions packages/SwingSet/src/kernel/state/kernelKeeper.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ const enableKernelGC = true;
* @typedef { import('../../types-external.js').SnapStore } SnapStore
* @typedef { import('../../types-external.js').TranscriptStore } TranscriptStore
* @typedef { import('../../types-external.js').VatKeeper } VatKeeper
* @typedef { Pick<VatKeeper, 'deleteCListEntry' | 'deleteSnapshots' | 'deleteTranscripts'> } VatUndertaker
* @typedef { import('../../types-internal.js').InternalKernelOptions } InternalKernelOptions
* @typedef { import('../../types-internal.js').ReapDirtThreshold } ReapDirtThreshold
* @import {PromiseRecord} from '../../types-internal.js';
Expand Down Expand Up @@ -422,6 +423,8 @@ export default function makeKernelKeeper(
const ephemeral = harden({
/** @type { Map<string, VatKeeper> } */
vatKeepers: new Map(),
/** @type { Map<string, VatUndertaker> } */
vatUndertakers: new Map(),
deviceKeepers: new Map(), // deviceID -> deviceKeeper
});

Expand Down Expand Up @@ -1044,7 +1047,7 @@ export default function makeKernelKeeper(
// first or vref first), and delete the other one in the same
// call, so we don't wind up with half an entry.

const vatKeeper = provideVatKeeper(vatID);
const undertaker = provideVatUndertaker(vatID);
const clistPrefix = `${vatID}.c.`;
const exportPrefix = `${clistPrefix}o+`;
const importPrefix = `${clistPrefix}o-`;
Expand Down Expand Up @@ -1092,7 +1095,7 @@ export default function makeKernelKeeper(
// drop+retire
const kref = kvStore.get(k) || Fail`getNextKey ensures get`;
const vref = stripPrefix(clistPrefix, k);
vatKeeper.deleteCListEntry(kref, vref);
undertaker.deleteCListEntry(kref, vref);
// that will also delete both db keys
work.imports += 1;
remaining -= 1;
Expand All @@ -1109,7 +1112,7 @@ export default function makeKernelKeeper(
for (const k of enumeratePrefixedKeys(kvStore, promisePrefix)) {
const kref = kvStore.get(k) || Fail`getNextKey ensures get`;
const vref = stripPrefix(clistPrefix, k);
vatKeeper.deleteCListEntry(kref, vref);
undertaker.deleteCListEntry(kref, vref);
// that will also delete both db keys
work.promises += 1;
remaining -= 1;
Expand All @@ -1131,7 +1134,7 @@ export default function makeKernelKeeper(

// this will internally loop through 'budget' deletions
remaining = budget.snapshots ?? budget.default;
const dsc = vatKeeper.deleteSnapshots(remaining);
const dsc = undertaker.deleteSnapshots(remaining);
work.snapshots += dsc.cleanups;
remaining -= dsc.cleanups;
if (remaining <= 0) {
Expand All @@ -1140,7 +1143,7 @@ export default function makeKernelKeeper(

// same
remaining = budget.transcripts ?? budget.default;
const dts = vatKeeper.deleteTranscripts(remaining);
const dts = undertaker.deleteTranscripts(remaining);
work.transcripts += dts.cleanups;
remaining -= dts.cleanups;
// last task, so increment cleanups, but dc.done is authoritative
Expand Down Expand Up @@ -1697,37 +1700,63 @@ export default function makeKernelKeeper(
initializeVatState(kvStore, transcriptStore, vatID, source, options);
}

/** @type {import('./vatKeeper.js').VatKeeperPowers} */
const vatKeeperPowers = {
transcriptStore,
kernelSlog,
addKernelObject,
addKernelPromiseForVat,
kernelObjectExists,
incrementRefCount,
decrementRefCount,
getObjectRefCount,
setObjectRefCount,
getReachableAndVatSlot,
addMaybeFreeKref,
incStat,
decStat,
getCrankNumber,
scheduleReap,
snapStore,
};

function provideVatKeeper(vatID) {
insistVatID(vatID);
const found = ephemeral.vatKeepers.get(vatID);
if (found !== undefined) {
return found;
}
assert(kvStore.has(`${vatID}.o.nextID`), `${vatID} was not initialized`);
const vk = makeVatKeeper(
kvStore,
transcriptStore,
kernelSlog,
vatID,
addKernelObject,
addKernelPromiseForVat,
kernelObjectExists,
incrementRefCount,
decrementRefCount,
getObjectRefCount,
setObjectRefCount,
getReachableAndVatSlot,
addMaybeFreeKref,
incStat,
decStat,
getCrankNumber,
scheduleReap,
snapStore,
);
const vk = makeVatKeeper(vatID, kvStore, vatKeeperPowers);
ephemeral.vatKeepers.set(vatID, vk);
return vk;
}

/**
* Produce an attenuated vatKeeper for slow vat termination (and that
* therefore does not insist on liveness, unlike provideVatKeeper).
*
* @param {string} vatID
*/
function provideVatUndertaker(vatID) {
insistVatID(vatID);
const found = ephemeral.vatUndertakers.get(vatID);
if (found !== undefined) {
return found;
}
const { deleteCListEntry, deleteSnapshots, deleteTranscripts } =
ephemeral.vatKeepers.get(vatID) ||
makeVatKeeper(vatID, kvStore, vatKeeperPowers);
/** @type {VatUndertaker} */
const undertaker = harden({
deleteCListEntry,
deleteSnapshots,
deleteTranscripts,
});
ephemeral.vatUndertakers.set(vatID, undertaker);
return undertaker;
}

function vatIsAlive(vatID) {
insistVatID(vatID);
return kvStore.has(`${vatID}.o.nextID`) && !terminatedVats.includes(vatID);
Expand Down
80 changes: 42 additions & 38 deletions packages/SwingSet/src/kernel/state/vatKeeper.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,49 +84,53 @@ export function initializeVatState(
}

/**
* Produce a vat keeper for a vat.
* @typedef {object} VatKeeperPowers
* @property {TranscriptStore} transcriptStore Accompanying transcript store, for the transcripts
* @property {*} kernelSlog
* @property {*} addKernelObject Kernel function to add a new object to the kernel's mapping tables.
* @property {*} addKernelPromiseForVat Kernel function to add a new promise to the kernel's mapping tables.
* @property {(kernelSlot: string) => boolean} kernelObjectExists
* @property {*} incrementRefCount
* @property {*} decrementRefCount
* @property {(kernelSlot: string) => {reachable: number, recognizable: number}} getObjectRefCount
* @property {(kernelSlot: string, o: { reachable: number, recognizable: number }) => void} setObjectRefCount
* @property {(vatID: string, kernelSlot: string) => {isReachable: boolean, vatSlot: string}} getReachableAndVatSlot
* @property {(kernelSlot: string) => void} addMaybeFreeKref
* @property {*} incStat
* @property {*} decStat
* @property {*} getCrankNumber
* @property {*} scheduleReap
* @property {SnapStore} snapStore
*/

/**
* Produce a "vat keeper" for the kernel state of a vat.
*
* @param {KVStore} kvStore The keyValue store in which the persistent state will be kept
* @param {TranscriptStore} transcriptStore Accompanying transcript store, for the transcripts
* @param {*} kernelSlog
* @param {string} vatID The vat ID string of the vat in question
* @param {*} addKernelObject Kernel function to add a new object to the kernel's
* mapping tables.
* @param {*} addKernelPromiseForVat Kernel function to add a new promise to the
* kernel's mapping tables.
* @param {(kernelSlot: string) => boolean} kernelObjectExists
* @param {*} incrementRefCount
* @param {*} decrementRefCount
* @param {(kernelSlot: string) => {reachable: number, recognizable: number}} getObjectRefCount
* @param {(kernelSlot: string, o: { reachable: number, recognizable: number }) => void} setObjectRefCount
* @param {(vatID: string, kernelSlot: string) => {isReachable: boolean, vatSlot: string}} getReachableAndVatSlot
* @param {(kernelSlot: string) => void} addMaybeFreeKref
* @param {*} incStat
* @param {*} decStat
* @param {*} getCrankNumber
* @param {*} scheduleReap
* @param {SnapStore} [snapStore]
* returns an object to hold and access the kernel's state for the given vat
* @param {KVStore} kvStore The keyValue store in which the persistent state will be kept
* @param {VatKeeperPowers} powers
*/
export function makeVatKeeper(
kvStore,
transcriptStore,
kernelSlog,
vatID,
addKernelObject,
addKernelPromiseForVat,
kernelObjectExists,
incrementRefCount,
decrementRefCount,
getObjectRefCount,
setObjectRefCount,
getReachableAndVatSlot,
addMaybeFreeKref,
incStat,
decStat,
getCrankNumber,
scheduleReap,
snapStore = undefined,
kvStore,
{
transcriptStore,
kernelSlog,
addKernelObject,
addKernelPromiseForVat,
kernelObjectExists,
incrementRefCount,
decrementRefCount,
getObjectRefCount,
setObjectRefCount,
getReachableAndVatSlot,
addMaybeFreeKref,
incStat,
decStat,
getCrankNumber,
scheduleReap,
snapStore,
},
) {
insistVatID(vatID);

Expand Down

0 comments on commit b786414

Please sign in to comment.