diff --git a/packages/SwingSet/src/kernel/state/kernelKeeper.js b/packages/SwingSet/src/kernel/state/kernelKeeper.js index c21a7a56de32..2405429c0078 100644 --- a/packages/SwingSet/src/kernel/state/kernelKeeper.js +++ b/packages/SwingSet/src/kernel/state/kernelKeeper.js @@ -2,6 +2,7 @@ import { Nat } from '@agoric/nat'; import { assert, details as X } from '@agoric/assert'; import { initializeVatState, makeVatKeeper } from './vatKeeper'; import { initializeDeviceState, makeDeviceKeeper } from './deviceKeeper'; +import { parseReachableAndVatSlot } from './reachable'; import { insistEnhancedStorageAPI } from '../../storageAPI'; import { insistKernelType, @@ -248,6 +249,11 @@ export default function makeKernelKeeper(kvStore, streamStore, kernelSlog) { setGCActions(actions); } + function getReachableAndVatSlot(vatID, kernelSlot) { + const kernelKey = `${vatID}.c.${kernelSlot}`; + return parseReachableAndVatSlot(kvStore.get(kernelKey)); + } + function addKernelObject(ownerID) { insistVatID(ownerID); const id = Nat(BigInt(getRequired('ko.nextID'))); @@ -707,6 +713,7 @@ export default function makeKernelKeeper(kvStore, streamStore, kernelSlog) { addKernelPromiseForVat, incrementRefCount, decrementRefCount, + getReachableAndVatSlot, incStat, decStat, getCrankNumber, diff --git a/packages/SwingSet/src/kernel/state/reachable.js b/packages/SwingSet/src/kernel/state/reachable.js new file mode 100644 index 000000000000..cc36c28173c8 --- /dev/null +++ b/packages/SwingSet/src/kernel/state/reachable.js @@ -0,0 +1,23 @@ +import { assert, details as X } from '@agoric/assert'; + +export function parseReachableAndVatSlot(value) { + assert.typeof(value, 'string', X`non-string value: ${value}`); + const flag = value.slice(0, 1); + assert.equal(value.slice(1, 2), ' '); + const vatSlot = value.slice(2); + let isReachable; + if (flag === 'R') { + isReachable = true; + } else if (flag === '_') { + isReachable = false; + } else { + assert(`flag (${flag}) must be 'R' or '_'`); + } + return { isReachable, vatSlot }; +} +harden(parseReachableAndVatSlot); + +export function buildReachableAndVatSlot(isReachable, vatSlot) { + return `${isReachable ? 'R' : '_'} ${vatSlot}`; +} +harden(buildReachableAndVatSlot); diff --git a/packages/SwingSet/src/kernel/state/vatKeeper.js b/packages/SwingSet/src/kernel/state/vatKeeper.js index 20a9c160240c..a585d105fe06 100644 --- a/packages/SwingSet/src/kernel/state/vatKeeper.js +++ b/packages/SwingSet/src/kernel/state/vatKeeper.js @@ -8,6 +8,10 @@ import { parseKernelSlot } from '../parseKernelSlots'; import { makeVatSlot, parseVatSlot } from '../../parseVatSlots'; import { insistVatID } from '../id'; import { kdebug } from '../kdebug'; +import { + parseReachableAndVatSlot, + buildReachableAndVatSlot, +} from './reachable'; // makeVatKeeper is a pure function: all state is kept in the argument object @@ -47,6 +51,7 @@ export function initializeVatState(kvStore, streamStore, vatID) { * kernel's mapping tables. * @param {*} incrementRefCount * @param {*} decrementRefCount + * @param {(vatID: string, kernelSlot: string) => {reachable: boolean, vatSlot: string}} getReachableAndVatSlot * @param {*} incStat * @param {*} decStat * @param {*} getCrankNumber @@ -61,6 +66,7 @@ export function makeVatKeeper( addKernelPromiseForVat, incrementRefCount, decrementRefCount, + getReachableAndVatSlot, incStat, decStat, getCrankNumber, @@ -84,40 +90,35 @@ export function makeVatKeeper( return harden({ source, options }); } - function parseReachableAndVatSlot(value) { - assert.typeof(value, 'string', X`non-string value: ${value}`); - const flag = value.slice(0, 1); - assert.equal(value.slice(1, 2), ' '); - const vatSlot = value.slice(2); - let reachable; - if (flag === 'R') { - reachable = true; - } else if (flag === '_') { - reachable = false; - } else { - assert(`flag (${flag}) must be 'R' or '_'`); - } - return { reachable, vatSlot }; - } - - function buildReachableAndVatSlot(reachable, vatSlot) { - return `${reachable ? 'R' : '_'} ${vatSlot}`; + function getReachableFlag(kernelSlot) { + const kernelKey = `${vatID}.c.${kernelSlot}`; + const data = kvStore.get(kernelKey); + const { isReachable } = parseReachableAndVatSlot(data); + return isReachable; } - function getReachableAndVatSlot(kernelSlot) { - const kernelKey = `${vatID}.c.${kernelSlot}`; - return parseReachableAndVatSlot(kvStore.get(kernelKey)); + function insistNotReachable(kernelSlot) { + const isReachable = getReachableFlag(kernelSlot); + assert.equal(isReachable, false, X`${kernelSlot} was reachable, oops`); } function setReachableFlag(kernelSlot) { + const { type } = parseKernelSlot(kernelSlot); const kernelKey = `${vatID}.c.${kernelSlot}`; - const { vatSlot } = parseReachableAndVatSlot(kvStore.get(kernelKey)); + const { isReachable, vatSlot } = parseReachableAndVatSlot( + kvStore.get(kernelKey), + ); + const { allocatedByVat } = parseVatSlot(vatSlot); kvStore.set(kernelKey, buildReachableAndVatSlot(true, vatSlot)); } function clearReachableFlag(kernelSlot) { + const { type } = parseKernelSlot(kernelSlot); const kernelKey = `${vatID}.c.${kernelSlot}`; - const { vatSlot } = parseReachableAndVatSlot(kvStore.get(kernelKey)); + const { isReachable, vatSlot } = parseReachableAndVatSlot( + kvStore.get(kernelKey), + ); + const { allocatedByVat } = parseVatSlot(vatSlot); kvStore.set(kernelKey, buildReachableAndVatSlot(false, vatSlot)); } @@ -181,8 +182,8 @@ export function makeVatKeeper( setReachableFlag(kernelSlot); } else { // imports must be reachable - const { reachable } = getReachableAndVatSlot(kernelSlot); - assert(reachable, X`vat tried to access unreachable import`); + const { isReachable } = getReachableAndVatSlot(vatID, kernelSlot); + assert(isReachable, X`vat tried to access unreachable import`); } } return kernelSlot; @@ -235,7 +236,7 @@ export function makeVatKeeper( kdebug(`Add mapping k->v ${kernelKey}<=>${vatKey}`); } - const { reachable, vatSlot } = getReachableAndVatSlot(kernelSlot); + const { isReachable, vatSlot } = getReachableAndVatSlot(vatID, kernelSlot); const { allocatedByVat } = parseVatSlot(vatSlot); if (setReachable) { if (!allocatedByVat) { @@ -244,7 +245,7 @@ export function makeVatKeeper( } else { // if the kernel is sending non-reachable exports back into // exporting vat, that's a kernel bug - assert(reachable, X`kernel sent unreachable export`); + assert(isReachable, X`kernel sent unreachable export ${kernelSlot}`); } } return vatSlot; @@ -383,6 +384,8 @@ export function makeVatKeeper( getSourceAndOptions, mapVatSlotToKernelSlot, mapKernelSlotToVatSlot, + getReachableFlag, + insistNotReachable, setReachableFlag, clearReachableFlag, hasCListEntry,