Skip to content

Commit

Permalink
Merge branch 'master' into remote-style
Browse files Browse the repository at this point in the history
  • Loading branch information
erights committed Aug 26, 2020
2 parents 6ef3e4b + 3365e64 commit 4644648
Show file tree
Hide file tree
Showing 58 changed files with 1,801 additions and 279 deletions.
4 changes: 4 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[submodule "packages/xs-vat-worker/moddable"]
path = packages/xs-vat-worker/moddable
url = https://github.com/agoric-labs/moddable.git
branch = ag-linux-cli
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@
"packages/cosmic-swingset",
"packages/agoric-cli",
"packages/deployment",
"packages/notifier"
"packages/notifier",
"packages/xs-vat-worker"
],
"devDependencies": {
"ava": "^3.11.1",
Expand Down
1 change: 1 addition & 0 deletions packages/SwingSet/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
"@agoric/tame-metering": "^1.2.3",
"@agoric/transform-eventual-send": "^1.3.1",
"@agoric/transform-metering": "^1.3.0",
"@agoric/xs-vat-worker": "^0.1.0",
"@babel/core": "^7.5.0",
"@babel/generator": "^7.6.4",
"anylogger": "^0.21.0",
Expand Down
23 changes: 15 additions & 8 deletions packages/SwingSet/src/controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { importBundle } from '@agoric/import-bundle';
import { initSwingStore } from '@agoric/swing-store-simple';
import { makeMeteringTransformer } from '@agoric/transform-metering';
import { makeTransform } from '@agoric/transform-eventual-send';
import { locateWorkerBin } from '@agoric/xs-vat-worker';

import { startSubprocessWorker } from './spawnSubprocessWorker';
import { assertKnownOptions } from './assertOptions';
Expand All @@ -32,7 +33,6 @@ function makeConsole(tag) {
}
return harden(cons);
}
const console = makeConsole('SwingSet:controller');

const ADMIN_DEVICE_PATH = require.resolve('./kernel/vatAdmin/vatAdmin-src');
const ADMIN_VAT_PATH = require.resolve('./kernel/vatAdmin/vatAdminWrapper');
Expand Down Expand Up @@ -80,7 +80,6 @@ const KNOWN_CREATION_OPTIONS = harden([
* Swingsets defined by scanning a directory in this manner define no devices.
*/
export function loadBasedir(basedir) {
console.debug(`= loading config from basedir ${basedir}`);
const vats = {};
const subs = fs.readdirSync(basedir, { withFileTypes: true });
subs.sort(byName);
Expand All @@ -99,8 +98,6 @@ export function loadBasedir(basedir) {
const name = dirent.name.slice('vat-'.length, -'.js'.length);
const vatSourcePath = path.resolve(basedir, dirent.name);
vats[name] = { sourceSpec: vatSourcePath, parameters: {} };
} else {
console.debug(`ignoring file ${dirent.name} in ${basedir}`);
}
});
let bootstrapPath = path.resolve(basedir, 'bootstrap.js');
Expand Down Expand Up @@ -213,7 +210,7 @@ export async function buildVatController(
argv = [],
runtimeOptions = {},
) {
const { debugPrefix = '' } = runtimeOptions;
const { debugPrefix = '', verbose = false } = runtimeOptions;
if (typeof Compartment === 'undefined') {
throw Error('SES must be installed before calling buildVatController');
}
Expand Down Expand Up @@ -325,6 +322,12 @@ export async function buildVatController(
// console.log(`--slog ${JSON.stringify(obj)}`);
}

const startSubprocessWorkerNode = () => startSubprocessWorker();
const xsWorkerBin = locateWorkerBin({ resolve: path.resolve });
const startSubprocessWorkerXS = fs.existsSync(xsWorkerBin)
? () => startSubprocessWorker({ execPath: xsWorkerBin, args: [] })
: undefined;

const kernelEndowments = {
waitUntilQuiescent,
hostStorage,
Expand All @@ -335,11 +338,13 @@ export async function buildVatController(
transformMetering,
transformTildot,
makeNodeWorker,
startSubprocessWorker,
startSubprocessWorkerNode,
startSubprocessWorkerXS,
writeSlogObject,
};

const kernel = buildKernel(kernelEndowments);
const kernelOptions = { verbose };
const kernel = buildKernel(kernelEndowments, kernelOptions);

if (runtimeOptions.verbose) {
kernel.kdebugEnable(true);
Expand Down Expand Up @@ -384,7 +389,9 @@ export async function buildVatController(
vatParameters = {},
creationOptions = {},
) {
console.debug(`= adding vat '${name}' from bundle ${bundleName}`);
if (verbose) {
console.debug(`= adding vat '${name}' from bundle ${bundleName}`);
}
const bundle = kernel.getBundle(bundleName);
kernel.addGenesisVat(name, bundle, vatParameters, creationOptions);
}
Expand Down
2 changes: 1 addition & 1 deletion packages/SwingSet/src/kernel/dynamicVat.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export function makeDynamicVatCreator(stuff) {
function createVatDynamically(source, dynamicOptions = {}) {
const vatID = allocateUnusedVatID();
kernelKeeper.addDynamicVatID(vatID);
const vatKeeper = kernelKeeper.allocateVatKeeperIfNeeded(vatID);
const vatKeeper = kernelKeeper.allocateVatKeeper(vatID);
vatKeeper.setSourceAndOptions(source, dynamicOptions);
// eslint-disable-next-line no-use-before-define
return create(vatID, source, dynamicOptions, true);
Expand Down
110 changes: 58 additions & 52 deletions packages/SwingSet/src/kernel/kernel.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@ function makeError(s) {
return harden({ body: JSON.stringify(s), slots: [] });
}

export default function buildKernel(kernelEndowments) {
const VAT_TERMINATION_ERROR = makeError('vat terminated');

export default function buildKernel(kernelEndowments, kernelOptions = {}) {
const {
waitUntilQuiescent,
hostStorage,
Expand All @@ -50,9 +52,13 @@ export default function buildKernel(kernelEndowments) {
transformMetering,
transformTildot,
makeNodeWorker,
startSubprocessWorker,
startSubprocessWorkerNode,
startSubprocessWorkerXS,
writeSlogObject,
} = kernelEndowments;
const { verbose } = kernelOptions;
const logStartup = verbose ? console.debug : () => 0;

insistStorageAPI(hostStorage);
const { enhancedCrankBuffer, commitCrank } = wrapStorage(hostStorage);

Expand Down Expand Up @@ -169,7 +175,7 @@ export default function buildKernel(kernelEndowments) {
insistVatID(forVatID);
const kernelSlot = `${what}`;
parseKernelSlot(what);
const vatKeeper = kernelKeeper.allocateVatKeeperIfNeeded(forVatID);
const vatKeeper = kernelKeeper.getVatKeeper(forVatID);
return vatKeeper.mapKernelSlotToVatSlot(kernelSlot);
}

Expand All @@ -180,7 +186,7 @@ export default function buildKernel(kernelEndowments) {
}
insistVatID(fromVatID);
assert(parseVatSlot(vatSlot).allocatedByVat);
const vatKeeper = kernelKeeper.allocateVatKeeperIfNeeded(fromVatID);
const vatKeeper = kernelKeeper.getVatKeeper(fromVatID);
return vatKeeper.mapVatSlotToKernelSlot(vatSlot);
}

Expand Down Expand Up @@ -305,8 +311,8 @@ export default function buildKernel(kernelEndowments) {
const vat = ephemeral.vats.get(vatID);
kernelKeeper.incStat('dispatches');
kernelKeeper.incStat('dispatchDeliver');
if (!vat || vat.dead) {
resolveToError(msg.result, makeError('unknown vat'));
if (!vat) {
resolveToError(msg.result, VAT_TERMINATION_ERROR);
} else {
const kd = harden(['message', target, msg]);
const vd = vat.translators.kernelDeliveryToVatDelivery(kd);
Expand All @@ -319,8 +325,11 @@ export default function buildKernel(kernelEndowments) {
const { type } = parseKernelSlot(target);
if (type === 'object') {
const vatID = kernelKeeper.ownerOfKernelObject(target);
insistVatID(vatID);
await deliverToVat(vatID, target, msg);
if (vatID) {
await deliverToVat(vatID, target, msg);
} else {
resolveToError(msg.result, VAT_TERMINATION_ERROR);
}
} else if (type === 'promise') {
const kp = kernelKeeper.getKernelPromise(target);
if (kp.state === 'fulfilledToPresence') {
Expand All @@ -344,11 +353,15 @@ export default function buildKernel(kernelEndowments) {
kernelKeeper.addMessageToPromiseQueue(target, msg);
} else {
insistVatID(kp.decider);
const vat = ephemeral.vats.get(kp.decider);
if (vat.enablePipelining) {
await deliverToVat(kp.decider, target, msg);
const deciderVat = ephemeral.vats.get(kp.decider);
if (deciderVat) {
if (deciderVat.enablePipelining) {
await deliverToVat(kp.decider, target, msg);
} else {
kernelKeeper.addMessageToPromiseQueue(target, msg);
}
} else {
kernelKeeper.addMessageToPromiseQueue(target, msg);
resolveToError(msg.result, VAT_TERMINATION_ERROR);
}
}
} else {
Expand Down Expand Up @@ -378,7 +391,7 @@ export default function buildKernel(kernelEndowments) {
insistKernelType('promise', kpid);
const vat = ephemeral.vats.get(vatID);
kernelKeeper.incStat('dispatches');
if (!vat || vat.dead) {
if (!vat) {
kdebug(`dropping notify of ${kpid} to ${vatID} because vat is dead`);
} else {
const p = kernelKeeper.getKernelPromise(kpid);
Expand Down Expand Up @@ -504,7 +517,7 @@ export default function buildKernel(kernelEndowments) {
}

function addGenesisDevice(name, bundle, endowments) {
console.debug(`kernel.addDevice(${name})`);
logStartup(`kernel.addDevice(${name})`);
if (typeof bundle !== 'object') {
throw Error(`bundle is not an object, rather ${bundle}`);
}
Expand Down Expand Up @@ -549,10 +562,10 @@ export default function buildKernel(kernelEndowments) {
},
}); // marker
vatObj0s[name] = vref;
const vatKeeper = kernelKeeper.allocateVatKeeperIfNeeded(vatID);
const vatKeeper = kernelKeeper.getVatKeeper(vatID);
const kernelSlot = vatKeeper.mapVatSlotToKernelSlot(vatSlot);
vrefs.set(vref, kernelSlot);
console.debug(`adding vref ${name} [${vatID}]`);
logStartup(`adding vref ${name} [${vatID}]`);
});

const drefs = new Map();
Expand All @@ -570,7 +583,7 @@ export default function buildKernel(kernelEndowments) {
const devKeeper = kernelKeeper.allocateDeviceKeeperIfNeeded(deviceID);
const kernelSlot = devKeeper.mapDeviceSlotToKernelSlot(devSlot);
drefs.set(dref, kernelSlot);
console.debug(`adding dref ${name} [${deviceID}]`);
logStartup(`adding dref ${name} [${deviceID}]`);
});
if (Object.getOwnPropertyNames(deviceObj0s) === 0) {
throw new Error('pass-by-copy rules require at least one device');
Expand Down Expand Up @@ -609,7 +622,8 @@ export default function buildKernel(kernelEndowments) {
transformMetering,
waitUntilQuiescent,
makeNodeWorker,
startSubprocessWorker,
startSubprocessWorkerNode,
startSubprocessWorkerXS,
});

function buildVatSyscallHandler(vatID, translators) {
Expand All @@ -620,7 +634,7 @@ export default function buildKernel(kernelEndowments) {
// the VatManager+VatWorker will see the error case, but liveslots will
// not
function vatSyscallHandler(vatSyscallObject) {
if (ephemeral.vats.get(vatID).dead) {
if (!ephemeral.vats.get(vatID)) {
// This is a safety check -- this case should never happen unless the
// vatManager is somehow confused.
console.error(`vatSyscallHandler invoked on dead vat ${vatID}`);
Expand Down Expand Up @@ -685,9 +699,7 @@ export default function buildKernel(kernelEndowments) {
enablePipelining = false,
notifyTermination = () => {},
} = managerOptions;
// This should create the vatKeeper. Other users get it from the
// kernelKeeper, so we don't need a reference ourselves.
kernelKeeper.allocateVatKeeperIfNeeded(vatID);
kernelKeeper.getVatKeeper(vatID);
const translators = makeVatTranslators(vatID, kernelKeeper);

ephemeral.vats.set(
Expand All @@ -706,7 +718,7 @@ export default function buildKernel(kernelEndowments) {

function removeVatManager(vatID) {
const old = ephemeral.vats.get(vatID);
ephemeral.vats.set(vatID, harden({ dead: true }));
ephemeral.vats.delete(vatID);
old.notifyTermination(null);
return old.manager.shutdown();
}
Expand Down Expand Up @@ -783,7 +795,7 @@ export default function buildKernel(kernelEndowments) {

function collectVatStats(vatID) {
insistVatID(vatID);
const vatKeeper = kernelKeeper.allocateVatKeeperIfNeeded(vatID);
const vatKeeper = kernelKeeper.getVatKeeper(vatID);
return vatKeeper.vatStats();
}

Expand All @@ -793,7 +805,7 @@ export default function buildKernel(kernelEndowments) {
}
started = true;
const wasInitialized = kernelKeeper.getInitialized();
console.debug(`wasInitialized = ${wasInitialized}`);
logStartup(`wasInitialized = ${wasInitialized}`);

// if the state is not yet initialized, populate the starting state
if (!wasInitialized) {
Expand All @@ -803,8 +815,9 @@ export default function buildKernel(kernelEndowments) {
// instantiate all genesis vats
for (const name of genesisVats.keys()) {
const vatID = kernelKeeper.allocateVatIDForNameIfNeeded(name);
console.debug(`Assigned VatID ${vatID} for genesis vat ${name}`);
logStartup(`Assigned VatID ${vatID} for genesis vat ${name}`);
kernelSlog.addVat(vatID, false, name);
kernelKeeper.allocateVatKeeper(vatID);
const managerOptions = harden({
...genesisVats.get(name),
vatConsole: makeVatConsole(vatID),
Expand All @@ -818,34 +831,27 @@ export default function buildKernel(kernelEndowments) {

// instantiate all dynamic vats
for (const vatID of kernelKeeper.getAllDynamicVatIDs()) {
console.debug(`Loading dynamic vat ${vatID}`);
const vatKeeper = kernelKeeper.allocateVatKeeperIfNeeded(vatID);
if (vatKeeper.isDead()) {
kernelKeeper.forgetVat(vatID);
} else {
const {
source,
options: dynamicOptions,
} = vatKeeper.getSourceAndOptions();
// eslint-disable-next-line no-await-in-loop
await recreateVatDynamically(vatID, source, dynamicOptions);
// now the vatManager is attached and ready for transcript replay
}
logStartup(`Loading dynamic vat ${vatID}`);
const vatKeeper = kernelKeeper.allocateVatKeeper(vatID);
const {
source,
options: dynamicOptions,
} = vatKeeper.getSourceAndOptions();
// eslint-disable-next-line no-await-in-loop
await recreateVatDynamically(vatID, source, dynamicOptions);
// now the vatManager is attached and ready for transcript replay
}

function terminateVat(vatID) {
const vatKeeper = kernelKeeper.allocateVatKeeperIfNeeded(vatID);
if (!vatKeeper.isDead()) {
vatKeeper.markAsDead();
const err = makeError('vat terminated');
for (const kpid of kernelKeeper.findPromisesDecidedByVat(vatID)) {
resolveToError(kpid, err, vatID);
if (kernelKeeper.getVatKeeper(vatID)) {
const promisesToReject = kernelKeeper.cleanupAfterTerminatedVat(vatID);
for (const kpid of promisesToReject) {
resolveToError(kpid, VAT_TERMINATION_ERROR, vatID);
}
removeVatManager(vatID).then(
() => kdebug(`terminated vat ${vatID}`),
e => console.error(`problem terminating vat ${vatID}`, e),
);
kernelKeeper.forgetVat(vatID);
}
}

Expand All @@ -865,7 +871,7 @@ export default function buildKernel(kernelEndowments) {
// instantiate all devices
for (const name of genesisDevices.keys()) {
const deviceID = kernelKeeper.allocateDeviceIDForNameIfNeeded(name);
console.debug(`Assigned DeviceID ${deviceID} for genesis device ${name}`);
logStartup(`Assigned DeviceID ${deviceID} for genesis device ${name}`);
const { bundle, endowments: devEndowments } = genesisDevices.get(name);
const devConsole = makeConsole(`${debugPrefix}SwingSet:dev-${name}`);
// eslint-disable-next-line no-await-in-loop
Expand All @@ -892,7 +898,7 @@ export default function buildKernel(kernelEndowments) {
let bootstrapResult = null;
if (!wasInitialized && bootstrapVatName) {
const bootstrapVatID = vatNameToID(bootstrapVatName);
console.debug(`=> queueing bootstrap()`);
logStartup(`=> queueing bootstrap()`);
bootstrapResult = callBootstrap(bootstrapVatID);
}

Expand All @@ -901,14 +907,14 @@ export default function buildKernel(kernelEndowments) {
console.info('Replaying SwingSet transcripts');
const oldLength = kernelKeeper.getRunQueueLength();
for (const vatID of ephemeral.vats.keys()) {
console.debug(`Replaying transcript of vatID ${vatID}`);
logStartup(`Replaying transcript of vatID ${vatID}`);
const vat = ephemeral.vats.get(vatID);
if (vat.dead) {
console.debug(`skipping reload of dead vat ${vatID}`);
if (!vat) {
logStartup(`skipping reload of dead vat ${vatID}`);
} else {
// eslint-disable-next-line no-await-in-loop
await vat.manager.replayTranscript();
console.debug(`finished replaying vatID ${vatID} transcript `);
logStartup(`finished replaying vatID ${vatID} transcript `);
const newLength = kernelKeeper.getRunQueueLength();
if (newLength !== oldLength) {
console.log(`SPURIOUS RUNQUEUE`, kernelKeeper.dump().runQueue);
Expand Down
Loading

0 comments on commit 4644648

Please sign in to comment.