Skip to content

Commit

Permalink
chore(swingset): refactor reachable flag handling
Browse files Browse the repository at this point in the history
The c-list kernel-to-vat direction uses a value that holds a composite of a
"isReachable" flag and the actual vref. This refactors the handling of this
composite value to make it easier for upcoming code to query the isReachable
status.

refs #3108
  • Loading branch information
warner committed Jun 3, 2021
1 parent 57f0ef8 commit 3e9190d
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 25 deletions.
7 changes: 7 additions & 0 deletions packages/SwingSet/src/kernel/state/kernelKeeper.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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')));
Expand Down Expand Up @@ -707,6 +713,7 @@ export default function makeKernelKeeper(kvStore, streamStore, kernelSlog) {
addKernelPromiseForVat,
incrementRefCount,
decrementRefCount,
getReachableAndVatSlot,
incStat,
decStat,
getCrankNumber,
Expand Down
23 changes: 23 additions & 0 deletions packages/SwingSet/src/kernel/state/reachable.js
Original file line number Diff line number Diff line change
@@ -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);
49 changes: 24 additions & 25 deletions packages/SwingSet/src/kernel/state/vatKeeper.js
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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
Expand All @@ -61,6 +66,7 @@ export function makeVatKeeper(
addKernelPromiseForVat,
incrementRefCount,
decrementRefCount,
getReachableAndVatSlot,
incStat,
decStat,
getCrankNumber,
Expand All @@ -84,40 +90,31 @@ 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 { 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 { allocatedByVat } = parseVatSlot(vatSlot);
kvStore.set(kernelKey, buildReachableAndVatSlot(false, vatSlot));
}

Expand Down Expand Up @@ -181,8 +178,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;
Expand Down Expand Up @@ -235,7 +232,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) {
Expand All @@ -244,7 +241,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;
Expand Down Expand Up @@ -383,6 +380,8 @@ export function makeVatKeeper(
getSourceAndOptions,
mapVatSlotToKernelSlot,
mapKernelSlotToVatSlot,
getReachableFlag,
insistNotReachable,
setReachableFlag,
clearReachableFlag,
hasCListEntry,
Expand Down

0 comments on commit 3e9190d

Please sign in to comment.