Skip to content

Commit

Permalink
feat(metering): allow the metering vat to register refill functions
Browse files Browse the repository at this point in the history
These functions are run at the end of the crank (empty Promise queue).
  • Loading branch information
michaelfig committed Feb 26, 2020
1 parent 829cebb commit ce077a3
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 4 deletions.
2 changes: 2 additions & 0 deletions packages/SwingSet/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@
"@agoric/nat": "^2.0.1",
"@agoric/swing-store-simple": "^0.1.0",
"@agoric/tame-metering": "^1.0.0",
"@agoric/transform-metering": "^1.1.0",
"@babel/core": "^7.5.0",
"rollup": "^1.23.1",
"rollup-plugin-node-resolve": "^5.2.0",
"semver": "^6.3.0",
Expand Down
40 changes: 37 additions & 3 deletions packages/SwingSet/src/controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ import {
SES1TameMeteringShim,
} from '@agoric/tame-metering';

import { makeMeteringTransformer } from '@agoric/transform-metering';
import * as babelCore from '@babel/core';

// eslint-disable-next-line import/extensions
import kernelSourceFunc from './bundles/kernel';
import buildKernelNonSES from './kernel/index';
Expand Down Expand Up @@ -134,12 +137,16 @@ function makeEvaluate(e) {
});
}


function makeSESEvaluator() {
const evaluateOptions = makeDefaultEvaluateOptions();
const { transforms, shims = [], ...otherOptions } = evaluateOptions;
const { transforms = [], shims = [], ...otherOptions } = evaluateOptions;
// The metering transform only activates when a getGlobalMeter endowment
// is provided.
const meteringTransformer = makeMeteringTransformer(babelCore);
const s = SES.makeSESRootRealm({
...otherOptions,
transforms,
transforms: [...transforms, meteringTransformer],
consoleMode: 'allow',
errorStackMode: 'allow',
shims: [SES1TameMeteringShim, ...shims],
Expand Down Expand Up @@ -178,13 +185,40 @@ function makeSESEvaluator() {
'@agoric/harden': true,
'@agoric/nat': Nat,
});

// Augment the global meter with one that integrates refilling.
const refillers = new Set();
const refillingReplaceGlobalMeter = (meter, refillFn = undefined) => {
let ret;
if (meter === null) {
// Install the null meter right away.
ret = replaceGlobalMeter(meter);
}
if (refillFn === true) {
// Magic value to indicate the end of the turn.
refillers.forEach(refiller => refiller());
refillers.clear();
} else if (refillFn) {
// Just add us to the list for later refilling.
refillers.add(refillFn);
}
if (meter !== null) {
// Install the non-null meter as late as possible.
ret = replaceGlobalMeter(meter);
}
return ret;
};

return src => {
// FIXME: Note that this replaceGlobalMeter endowment is not any
// worse than before metering existed. However, it probably is
// only necessary to be added to the kernel, rather than all
// static vats once we add metering support to the dynamic vat
// implementation.
return s.evaluate(src, { require: r, replaceGlobalMeter })().default;
return s.evaluate(src, {
require: r,
replaceGlobalMeter: refillingReplaceGlobalMeter,
})().default;
};
}

Expand Down
3 changes: 2 additions & 1 deletion packages/SwingSet/src/kernel/kernel.js
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,8 @@ export default function buildKernel(kernelEndowments) {
await queueEmptyP;
if (typeof replaceGlobalMeter !== 'undefined') {
// Turn off the global meter now that we've run the user code.
replaceGlobalMeter(null);
// Also indicate that we should run the refillers.
replaceGlobalMeter(null, true);
}
whenDone();
}
Expand Down

0 comments on commit ce077a3

Please sign in to comment.