Skip to content

Commit

Permalink
feat(swingset): implement comms GC, wire everything into place
Browse files Browse the repository at this point in the history
This is the big switch to activate comms GC. All the new code is in
`gc-comms.js`, which creates the "gcKit".

`dispatch()` was changed to assemble GC actions arriving from the kernel into
a single "GC" structure, with all three kinds of actions.

* this anticipates a future kernel change that lumps all three GC-related
  dispatch types into a single message, and mirrors the remote protocol
  which does exactly that
* we first filter out any kfrefs (vrefs) for meta-objects, like the
  "controller" (root object) and the receivers, because we aren't prepared
  to drop these
* after all dispatch operations (message send, promise resolution
  notification, and all GC operations), we call the new `processGC()` to
  perform any necessary GC actiity

`gc-comms.js` follows the same pattern as `delivery.js`:

* two inbound conversion functions (`gcFromKernel` and `gcFromRemote`) to
handle GC requests arriving from either source
* two outbound conversion functions (`gcToKernel` and `gcToRemote`) to emit
syscalls or remote-protocol messages that express GC requests
* the end-of-crank `processGC()` function
  * this calls `processMaybeFree()` to check on everything whose refcount
    touched zero during the crank
  * that returns a set of actions which need to be taken
  * the actions are sorted into the kernel or remote that is affected, then
    request messages are generated for syscalls and/or transmission

refs #3306
  • Loading branch information
warner committed Jun 20, 2021
1 parent 4b5a103 commit 36ebdd0
Show file tree
Hide file tree
Showing 3 changed files with 363 additions and 17 deletions.
11 changes: 10 additions & 1 deletion packages/SwingSet/src/vats/comms/delivery.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,13 @@ const UNDEFINED = harden({
slots: [],
});

export function makeDeliveryKit(state, syscall, transmit, clistKit) {
export function makeDeliveryKit(
state,
syscall,
transmit,
clistKit,
gcFromRemote,
) {
const {
getRemoteForLocal,
provideRemoteForLocal,
Expand Down Expand Up @@ -158,6 +164,9 @@ export function makeDeliveryKit(state, syscall, transmit, clistKit) {
if (command === 'resolve') {
return resolveFromRemote(remoteID, msgBody);
}
if (command === 'gc') {
return gcFromRemote(remoteID, msgBody, ackSeqNum);
}
assert.fail(X`unrecognized '${command}' in received message ${msgBody}`);
}

Expand Down
45 changes: 29 additions & 16 deletions packages/SwingSet/src/vats/comms/dispatch.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
import { assert, details as X } from '@agoric/assert';
import {
makeVatSlot,
insistVatType,
parseVatSlot,
} from '../../parseVatSlots.js';
import { makeVatSlot } from '../../parseVatSlots.js';
import { insistMessage } from '../../message.js';
import { makeState } from './state.js';
import { deliverToController } from './controller.js';
import { insistCapData } from '../../capdata.js';

import { makeCListKit } from './clist.js';
import { makeDeliveryKit } from './delivery.js';
import { makeGCKit } from './gc-comms.js';
import { cdebug } from './cdebug.js';

export const debugState = new WeakMap();
Expand Down Expand Up @@ -40,8 +37,16 @@ export function buildCommsDispatch(
syscall.send(remote.transmitterID(), 'transmit', args); // sendOnly
}

const deliveryKit = makeDeliveryKit(state, syscall, transmit, clistKit);
const gcKit = makeGCKit(state, syscall, transmit);
const { gcFromRemote, gcFromKernel, processGC } = gcKit;

const deliveryKit = makeDeliveryKit(
state,
syscall,
transmit,
clistKit,
gcFromRemote,
);
const { sendFromKernel, resolveFromKernel, messageFromRemote } = deliveryKit;

// our root object (o+0) is the Comms Controller
Expand Down Expand Up @@ -141,6 +146,20 @@ export function buildCommsDispatch(
return sendFromKernel(target, method, args, result);
}

function filterMetaObjects(vrefs) {
// Sometimes the bootstrap vat doesn't care very much about comms and
// allows the root object (the "controller") to be dropped, or one of the
// receiver objects we create during addRemote(). gc-comms.js doesn't
// know about these meta objects, so filter them out. Also, always filter
// out the controller (o+0) even if it isn't in the meta table, because
// some unit tests (test-demos-comms.js) create a comms vat but never
// talk to it, which means we never get a delivery, so initializeState()
// is never called, so o+0 is never added to the meta table.
return vrefs.filter(
vref => !(vref === controller || state.hasMetaObject(vref)),
);
}

function doDispatch(vatDeliveryObject) {
const [type, ...args] = vatDeliveryObject;
switch (type) {
Expand All @@ -158,31 +177,25 @@ export function buildCommsDispatch(
case 'dropExports': {
const [vrefs] = args;
assert(Array.isArray(vrefs));
vrefs.map(vref => insistVatType('object', vref));
vrefs.map(vref => assert(parseVatSlot(vref).allocatedByVat));
// console.log(`-- comms ignoring dropExports`);
gcFromKernel({ dropExports: filterMetaObjects(vrefs) });
break;
}
case 'retireExports': {
const [vrefs] = args;
assert(Array.isArray(vrefs));
vrefs.map(vref => insistVatType('object', vref));
vrefs.map(vref => assert(parseVatSlot(vref).allocatedByVat));
// console.log(`-- comms ignoring retireExports`);
gcFromKernel({ retireExports: filterMetaObjects(vrefs) });
break;
}
case 'retireImports': {
const [vrefs] = args;
assert(Array.isArray(vrefs));
vrefs.map(vref => insistVatType('object', vref));
vrefs.map(vref => assert(!parseVatSlot(vref).allocatedByVat));
// console.log(`-- comms ignoring retireImports`);
gcFromKernel({ retireImports: filterMetaObjects(vrefs) });
break;
}
default:
assert.fail(X`unknown delivery type ${type}`);
}
state.processMaybeFree();
processGC();
}

function dispatch(vatDeliveryObject) {
Expand Down
Loading

0 comments on commit 36ebdd0

Please sign in to comment.