Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prune resolved promises (recipient side) #799

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/SwingSet/.eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ module.exports = {
'function-paren-newline': 'off',
'arrow-parens': 'off',
strict: 'off',
'prefer-destructuring': 'off',
'no-else-return': 'off',
'no-console': 'off',
'no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
Expand Down
2 changes: 1 addition & 1 deletion packages/SwingSet/src/kernel/deviceManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { insistKernelType } from './parseKernelSlots';
import { insistVatType, parseVatSlot } from '../parseVatSlots';
import { insistCapData } from '../capdata';
import { insistMessage } from '../message';
import kdebug from './kdebug';
import { kdebug } from './kdebug';

/**
* Produce an object that will serve as the kernel's handle onto a device.
Expand Down
53 changes: 52 additions & 1 deletion packages/SwingSet/src/kernel/kdebug.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,58 @@
const enableKDebug = false;

export default function kdebug(...args) {
export function kdebug(...args) {
if (enableKDebug) {
console.log(...args);
}
}

function legibilizeValue(val, slots) {
if (Array.isArray(val)) {
let result = '[';
for (const elem of val) {
if (result.length !== 1) {
result += ', ';
}
result += legibilizeValue(elem, slots);
}
result += ']';
return result;
} else if (val && typeof val === 'object' && val.constructor === Object) {
const qClass = val['@qclass'];
if (qClass) {
switch (qClass) {
case 'undefined':
case 'NaN':
case 'Infinity':
case '-Infinity':
return qClass;
case 'bigint':
return val.digits;
case 'slot':
return `@${slots[val.index]}`;
case 'error':
return `new ${val.name}('${val.message}')`;
case 'ibid':
return `ibid(${val.index})`;
default:
throw new Error(`unknown qClass ${qClass} in legibilizeValue`);
}
} else {
let result = '{';
for (const prop of Object.getOwnPropertyNames(val)) {
if (result.length !== 1) {
result += ', ';
}
result += `${prop}: ${legibilizeValue(val[prop], slots)}`;
}
result += '}';
return result;
}
} else {
return JSON.stringify(val);
}
}

export function legibilizeMessageArgs(args) {
return JSON.parse(args.body).map(arg => legibilizeValue(arg, args.slots));
}
17 changes: 16 additions & 1 deletion packages/SwingSet/src/kernel/kernel.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { makeDeviceSlots } from './deviceSlots';
import makeDeviceManager from './deviceManager';
import { wrapStorage } from './state/storageWrapper';
import makeKernelKeeper from './state/kernelKeeper';
import kdebug from './kdebug';
import { kdebug, legibilizeMessageArgs } from './kdebug';
import { insistKernelType, parseKernelSlot } from './parseKernelSlots';
import { makeVatSlot, parseVatSlot } from '../parseVatSlots';
import { insistStorageAPI } from '../storageAPI';
Expand Down Expand Up @@ -364,9 +364,23 @@ export default function buildKernel(kernelEndowments) {
}
}

function legibilizeMessage(message) {
if (message.type === 'send') {
const msg = message.msg;
const argList = legibilizeMessageArgs(msg.args).join(', ');
const result = msg.result ? msg.result : 'null';
return `@${message.target} <- ${msg.method}(${argList}) : @${result}`;
} else if (message.type === 'notify') {
return `notify(vatID: ${message.vatID}, kpid: @${message.kpid})`;
} else {
return `unknown message type ${message.type}`;
}
}

let processQueueRunning;
async function processQueueMessage(message) {
kdebug(`processQ ${JSON.stringify(message)}`);
kdebug(legibilizeMessage(message));
if (processQueueRunning) {
console.error(`We're currently already running at`, processQueueRunning);
throw Error(`Kernel reentrancy is forbidden`);
Expand Down Expand Up @@ -688,6 +702,7 @@ export default function buildKernel(kernelEndowments) {
const bootstrapVatID = vatNameToID(bootstrapVatName);
console.log(`=> queueing bootstrap()`);
callBootstrap(bootstrapVatID, argvString);
commitCrank();
}

// if it *was* initialized, replay the transcripts
Expand Down
10 changes: 10 additions & 0 deletions packages/SwingSet/src/kernel/liveSlots.js
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,13 @@ function build(syscall, _state, makeRoot, forVatID) {
};
}

function retirePromiseID(promiseID) {
importedPromisesByPromiseID.delete(promiseID);
const p = slotToVal.get(promiseID);
valToSlot.delete(p);
slotToVal.delete(promiseID);
}

function notifyFulfillToData(promiseID, data) {
insistCapData(data);
lsdebug(
Expand All @@ -342,6 +349,7 @@ function build(syscall, _state, makeRoot, forVatID) {
}
const val = m.unserialize(data);
importedPromisesByPromiseID.get(promiseID).res(val);
retirePromiseID(promiseID);
}

function notifyFulfillToPresence(promiseID, slot) {
Expand All @@ -352,6 +360,7 @@ function build(syscall, _state, makeRoot, forVatID) {
}
const val = convertSlotToVal(slot);
importedPromisesByPromiseID.get(promiseID).res(val);
retirePromiseID(promiseID);
}

function notifyReject(promiseID, data) {
Expand All @@ -365,6 +374,7 @@ function build(syscall, _state, makeRoot, forVatID) {
}
const val = m.unserialize(data);
importedPromisesByPromiseID.get(promiseID).rej(val);
retirePromiseID(promiseID);
}

// here we finally invoke the vat code, and get back the root object
Expand Down
6 changes: 4 additions & 2 deletions packages/SwingSet/src/kernel/state/kernelKeeper.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
} from '../parseKernelSlots';
import { insistCapData } from '../../capdata';
import { insistDeviceID, insistVatID, makeDeviceID, makeVatID } from '../id';
import kdebug from '../kdebug';
import { kdebug } from '../kdebug';

// This holds all the kernel state, including that of each Vat and Device, in
// a single JSON-serializable object. At any moment (well, really only
Expand Down Expand Up @@ -126,7 +126,7 @@ export default function makeKernelKeeper(storage) {
function addKernelObject(ownerID) {
insistVatID(ownerID);
const id = Nat(Number(getRequired('ko.nextID')));
kdebug(`Adding kernel object ${id} for ${ownerID}`);
kdebug(`Adding kernel object ko${id} for ${ownerID}`);
storage.set('ko.nextID', `${id + 1}`);
const s = makeKernelSlot('object', id);
storage.set(`${s}.owner`, ownerID);
Expand All @@ -143,6 +143,7 @@ export default function makeKernelKeeper(storage) {
function addKernelDeviceNode(deviceID) {
insistDeviceID(deviceID);
const id = Nat(Number(getRequired('kd.nextID')));
kdebug(`Adding kernel device kd${id} for ${deviceID}`);
storage.set('kd.nextID', `${id + 1}`);
const s = makeKernelSlot('device', id);
storage.set(`${s}.owner`, deviceID);
Expand All @@ -159,6 +160,7 @@ export default function makeKernelKeeper(storage) {
function addKernelPromise(deciderVatID) {
insistVatID(deciderVatID);
const kpid = Nat(Number(getRequired('kp.nextID')));
kdebug(`Adding kernel promise kp${kpid} for ${deciderVatID}`);
storage.set('kp.nextID', `${kpid + 1}`);
const s = makeKernelSlot('promise', kpid);
storage.set(`${s}.state`, 'unresolved');
Expand Down
20 changes: 18 additions & 2 deletions packages/SwingSet/src/kernel/state/vatKeeper.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { assert, details } from '@agoric/assert';
import { parseKernelSlot } from '../parseKernelSlots';
import { makeVatSlot, parseVatSlot } from '../../parseVatSlots';
import { insistVatID } from '../id';
import kdebug from '../kdebug';
import { kdebug } from '../kdebug';

// makeVatKeeper is a pure function: all state is kept in the argument object

Expand Down Expand Up @@ -84,7 +84,7 @@ export function makeVatKeeper(
const kernelKey = `${vatID}.c.${kernelSlot}`;
storage.set(kernelKey, vatSlot);
storage.set(vatKey, kernelSlot);
kdebug(`Mapping ${kernelKey}<=>${vatKey}`);
kdebug(`Add mapping v->k ${kernelKey}<=>${vatKey}`);
} else {
// the vat didn't allocate it, and the kernel didn't allocate it
// (else it would have been in the c-list), so it must be bogus
Expand Down Expand Up @@ -130,11 +130,26 @@ export function makeVatKeeper(
const vatKey = `${vatID}.c.${vatSlot}`;
storage.set(vatKey, kernelSlot);
storage.set(kernelKey, vatSlot);
kdebug(`Add mapping k->v ${kernelKey}<=>${vatKey}`);
}

return storage.get(kernelKey);
}

/**
* Remove an entry from the vat's c-list.
*
* @param kernelSlot The kernel slot being removed
* @param vatSlot The vat slot being removed
*/
function deleteCListEntry(kernelSlot, vatSlot) {
const kernelKey = `${vatID}.c.${kernelSlot}`;
const vatKey = `${vatID}.c.${vatSlot}`;
kdebug(`Delete mapping ${kernelKey}<=>${vatKey}`);
storage.delete(kernelKey);
storage.delete(vatKey);
}

/**
* Generator function to return the vat's transcript, one entry at a time.
*/
Expand Down Expand Up @@ -197,6 +212,7 @@ export function makeVatKeeper(
return harden({
mapVatSlotToKernelSlot,
mapKernelSlotToVatSlot,
deleteCListEntry,
getTranscript,
addToTranscript,
vatStats,
Expand Down
17 changes: 9 additions & 8 deletions packages/SwingSet/src/kernel/vatManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { insistKernelType, parseKernelSlot } from './parseKernelSlots';
import { insistVatType, parseVatSlot } from '../parseVatSlots';
import { insistCapData } from '../capdata';
import { insistMessage } from '../message';
import kdebug from './kdebug';
import { kdebug, legibilizeMessageArgs } from './kdebug';

export default function makeVatManager(
vatID,
Expand Down Expand Up @@ -82,11 +82,6 @@ export default function makeVatManager(
function mapKernelSlotToVatSlot(kernelSlot) {
assert(`${kernelSlot}` === kernelSlot, 'non-string kernelSlot');
const vatSlot = vatKeeper.mapKernelSlotToVatSlot(kernelSlot);
kdebug(
`mapKernelSlotToVatSlot for ${vatID} of ${JSON.stringify(
kernelSlot,
)} to ${vatSlot}`,
);
return vatSlot;
}

Expand Down Expand Up @@ -116,7 +111,9 @@ export default function makeVatManager(
insistCapData(args);
// TODO: disable send-to-self for now, qv issue #43
const target = mapVatSlotToKernelSlot(targetSlot);
kdebug(`syscall[${vatID}].send(vat:${targetSlot}=ker:${target}).${method}`);
const argList = legibilizeMessageArgs(args).join(', ');
// prettier-ignore
kdebug(`syscall[${vatID}].send(vat:${targetSlot}=ker:${target}).${method}(${argList})`);
const kernelSlots = args.slots.map(slot => mapVatSlotToKernelSlot(slot));
const kernelArgs = harden({ ...args, slots: kernelSlots });
let result = null;
Expand Down Expand Up @@ -206,7 +203,8 @@ export default function makeVatManager(
}
const kernelSlots = args.slots.map(slot => mapVatSlotToKernelSlot(slot));
const kernelData = harden({ ...args, slots: kernelSlots });
kdebug(`syscall[${vatID}].callNow(${target}/${dev}).${method}`);
// prettier-ignore
kdebug(`syscall[${vatID}].callNow(${target}/${dev}).${method}(${JSON.stringify(args)})`);
const ret = syscallManager.invoke(dev, method, kernelData);
const retSlots = ret.slots.map(slot => mapKernelSlotToVatSlot(slot));
return harden({ ...ret, slots: retSlots });
Expand Down Expand Up @@ -347,6 +345,7 @@ export default function makeVatManager(
['notifyFulfillToPresence', vpid, slot],
`vat[${vatID}].promise[${vpid}] fulfillToPresence failed`,
);
vatKeeper.deleteCListEntry(kpid, vpid);
} else if (kp.state === 'redirected') {
throw new Error('not implemented yet');
} else if (kp.state === 'fulfilledToData') {
Expand All @@ -359,6 +358,7 @@ export default function makeVatManager(
['notifyFulfillToData', vpid, vatData],
`vat[${vatID}].promise[${vpid}] fulfillToData failed`,
);
vatKeeper.deleteCListEntry(kpid, vpid);
} else if (kp.state === 'rejected') {
const vpid = mapKernelSlotToVatSlot(kpid);
const vatData = harden({
Expand All @@ -369,6 +369,7 @@ export default function makeVatManager(
['notifyReject', vpid, vatData],
`vat[${vatID}].promise[${vpid}] reject failed`,
);
vatKeeper.deleteCListEntry(kpid, vpid);
} else {
throw new Error(`unknown kernelPromise state '${kp.state}'`);
}
Expand Down
2 changes: 2 additions & 0 deletions packages/swingset-runner/bin/runner
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#!/usr/bin/env -S node --expose-gc -r esm

// #!/usr/bin/env -S node --inspect-brk --expose-gc -r esm

/**
* Simple boilerplate program providing linkage to launch an application written using modules within the
* as yet not-entirely-ESM-supporting version of NodeJS.
Expand Down
28 changes: 28 additions & 0 deletions packages/swingset-runner/demo/justReply/bootstrap.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import harden from '@agoric/harden';

console.log(`=> loading bootstrap.js`);

export default function setup(syscall, state, helpers) {
function log(what) {
helpers.log(what);
console.log(what);
}
log(`=> setup called`);
return helpers.makeLiveSlots(
syscall,
state,
E =>
harden({
bootstrap(argv, vats) {
console.log('=> bootstrap() called');
E(vats.alice)
.sayHelloTo(vats.bob)
.then(
r => log(`=> alice.hello(bob) resolved to '${r}'`),
e => log(`=> alice.hello(bob) rejected as '${e}'`),
);
},
}),
helpers.vatID,
);
}
28 changes: 28 additions & 0 deletions packages/swingset-runner/demo/justReply/vat-alice.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import harden from '@agoric/harden';

function build(E, log) {
return harden({
sayHelloTo(other) {
log(`=> Alice.sayHelloTo`);
const answer = E(other).hello();
answer.then(
r => log(`=> alice.hello() answer resolved to '${r}'`),
e => log(`=> alice.hello() answer rejected as '${e}'`),
);
return `Alice started\n`;
},
});
}

export default function setup(syscall, state, helpers) {
function log(what) {
helpers.log(what);
console.log(what);
}
return helpers.makeLiveSlots(
syscall,
state,
E => build(E, log),
helpers.vatID,
);
}
23 changes: 23 additions & 0 deletions packages/swingset-runner/demo/justReply/vat-bob.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import harden from '@agoric/harden';

function build(_E, log) {
return harden({
hello() {
log(`=> Somebody said hello to Bob`);
return 'hi there!';
},
});
}

export default function setup(syscall, state, helpers) {
function log(what) {
helpers.log(what);
console.log(what);
}
return helpers.makeLiveSlots(
syscall,
state,
E => build(E, log),
helpers.vatID,
);
}
Loading