@agoric/swingset-vat 0.33.0-u16.1 → 0.33.0-u17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/package.json +31 -30
- package/src/controller/controller.js +48 -1
- package/src/controller/initializeKernel.js +35 -10
- package/src/controller/initializeSwingset.js +6 -3
- package/src/controller/startXSnap.js +1 -1
- package/src/controller/upgradeSwingset.js +212 -0
- package/src/devices/bridge/device-bridge.js +1 -1
- package/src/devices/bundle/device-bundle.js +1 -1
- package/src/devices/command/command.js +1 -2
- package/src/devices/command/device-command.js +1 -2
- package/src/devices/lib/deviceTools.js +1 -1
- package/src/devices/loopbox/device-loopbox.js +1 -1
- package/src/devices/loopbox/loopbox.js +1 -1
- package/src/devices/mailbox/device-mailbox.js +1 -2
- package/src/devices/mailbox/mailbox.js +1 -2
- package/src/devices/plugin/device-plugin.js +1 -1
- package/src/devices/timer/device-timer.js +1 -1
- package/src/devices/timer/timer.js +1 -1
- package/src/devices/vat-admin/device-vat-admin.js +4 -2
- package/src/index.js +1 -1
- package/src/kernel/deviceManager.js +1 -1
- package/src/kernel/deviceSlots.js +1 -1
- package/src/kernel/deviceTranslator.js +1 -1
- package/src/kernel/dummyMeterControl.js +1 -1
- package/src/kernel/gc-actions.js +55 -34
- package/src/kernel/kernel.js +216 -51
- package/src/kernel/kernelSyscall.js +2 -13
- package/src/kernel/parseKernelSlots.js +1 -1
- package/src/kernel/slogger.js +2 -2
- package/src/kernel/state/deviceKeeper.js +1 -1
- package/src/kernel/state/kernelKeeper.js +427 -81
- package/src/kernel/state/reachable.js +1 -1
- package/src/kernel/state/stats.js +1 -1
- package/src/kernel/state/storageHelper.js +1 -1
- package/src/kernel/state/vatKeeper.js +159 -44
- package/src/kernel/vat-admin-hooks.js +4 -1
- package/src/kernel/vat-loader/manager-factory.js +1 -2
- package/src/kernel/vat-loader/manager-helper.js +1 -1
- package/src/kernel/vat-loader/manager-local.js +1 -1
- package/src/kernel/vat-loader/manager-subprocess-node.js +1 -1
- package/src/kernel/vat-loader/manager-subprocess-xsnap.js +1 -1
- package/src/kernel/vat-loader/vat-loader.js +2 -2
- package/src/kernel/vat-warehouse.js +5 -1
- package/src/kernel/vatTranslator.js +1 -4
- package/src/lib/assertOptions.js +1 -1
- package/src/lib/capdata.js +1 -1
- package/src/lib/id.js +1 -1
- package/src/lib/message.js +1 -1
- package/src/lib/parseVatSlots.js +1 -1
- package/src/lib/recordVatOptions.js +18 -6
- package/src/lib/runPolicies.js +50 -4
- package/src/lib/storageAPI.js +1 -1
- package/src/lib/workerOptions.js +1 -1
- package/src/supervisors/subprocess-node/supervisor-subprocess-node.js +1 -1
- package/src/types-external.js +71 -22
- package/src/types-internal.js +56 -3
- package/src/vats/comms/clist-inbound.js +1 -1
- package/src/vats/comms/clist-kernel.js +1 -1
- package/src/vats/comms/clist-outbound.js +1 -1
- package/src/vats/comms/controller.js +1 -1
- package/src/vats/comms/delivery.js +1 -1
- package/src/vats/comms/dispatch.js +1 -1
- package/src/vats/comms/gc-comms.js +1 -1
- package/src/vats/comms/parseLocalSlots.js +1 -1
- package/src/vats/comms/parseRemoteSlot.js +1 -1
- package/src/vats/comms/remote.js +1 -1
- package/src/vats/comms/state.js +1 -1
- package/src/vats/timer/vat-timer.js +9 -9
- package/src/vats/vat-admin/vat-vat-admin.js +23 -8
- package/src/vats/vattp/vat-vattp.js +1 -1
- package/tools/bootstrap-relay.js +1 -3
- package/tools/bundleTool.js +9 -1
- package/tools/dvo-test-harness.js +1 -1
- package/tools/manual-timer.js +1 -1
- package/tools/run-utils.js +1 -1
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Kernel's keeper of persistent state for a vat.
|
|
3
3
|
*/
|
|
4
|
-
import { Nat
|
|
5
|
-
import { assert, q, Fail } from '@
|
|
4
|
+
import { Nat } from '@endo/nat';
|
|
5
|
+
import { assert, q, Fail } from '@endo/errors';
|
|
6
|
+
import { isObject } from '@endo/marshal';
|
|
6
7
|
import { parseKernelSlot } from '../parseKernelSlots.js';
|
|
7
8
|
import { makeVatSlot, parseVatSlot } from '../../lib/parseVatSlots.js';
|
|
8
9
|
import { insistVatID } from '../../lib/id.js';
|
|
@@ -18,7 +19,9 @@ import { enumeratePrefixedKeys } from './storageHelper.js';
|
|
|
18
19
|
* @typedef { import('../../types-external.js').SnapStore } SnapStore
|
|
19
20
|
* @typedef { import('../../types-external.js').SourceOfBundle } SourceOfBundle
|
|
20
21
|
* @typedef { import('../../types-external.js').TranscriptStore } TranscriptStore
|
|
22
|
+
* @typedef { import('../../types-internal.js').Dirt } Dirt
|
|
21
23
|
* @typedef { import('../../types-internal.js').VatManager } VatManager
|
|
24
|
+
* @typedef { import('../../types-internal.js').ReapDirtThreshold } ReapDirtThreshold
|
|
22
25
|
* @typedef { import('../../types-internal.js').RecordedVatOptions } RecordedVatOptions
|
|
23
26
|
* @typedef { import('../../types-internal.js').TranscriptEntry } TranscriptEntry
|
|
24
27
|
* @import {TranscriptDeliverySaveSnapshot} from '../../types-internal.js'
|
|
@@ -32,18 +35,50 @@ const FIRST_OBJECT_ID = 50n;
|
|
|
32
35
|
const FIRST_PROMISE_ID = 60n;
|
|
33
36
|
const FIRST_DEVICE_ID = 70n;
|
|
34
37
|
|
|
38
|
+
// TODO: we export this from vatKeeper.js, and import it from
|
|
39
|
+
// kernelKeeper.js, because both files need it, and we want to avoid
|
|
40
|
+
// an import cycle (kernelKeeper imports other things from vatKeeper),
|
|
41
|
+
// but it really wants to live in kernelKeeper not vatKeeper
|
|
42
|
+
export const DEFAULT_REAP_DIRT_THRESHOLD_KEY =
|
|
43
|
+
'kernel.defaultReapDirtThreshold';
|
|
44
|
+
|
|
45
|
+
const isBundleSource = source => {
|
|
46
|
+
return (
|
|
47
|
+
isObject(source) &&
|
|
48
|
+
(isObject(source.bundle) ||
|
|
49
|
+
typeof source.bundleName === 'string' ||
|
|
50
|
+
typeof source.bundleID === 'string')
|
|
51
|
+
);
|
|
52
|
+
};
|
|
53
|
+
|
|
35
54
|
/**
|
|
36
55
|
* Establish a vat's state.
|
|
37
56
|
*
|
|
38
57
|
* @param {*} kvStore The key-value store in which the persistent state will be kept
|
|
39
58
|
* @param {*} transcriptStore Accompanying transcript store
|
|
40
59
|
* @param {string} vatID The vat ID string of the vat in question
|
|
41
|
-
*
|
|
60
|
+
* @param {SourceOfBundle} source
|
|
61
|
+
* @param {RecordedVatOptions} options
|
|
42
62
|
*/
|
|
43
|
-
export function initializeVatState(
|
|
63
|
+
export function initializeVatState(
|
|
64
|
+
kvStore,
|
|
65
|
+
transcriptStore,
|
|
66
|
+
vatID,
|
|
67
|
+
source,
|
|
68
|
+
options,
|
|
69
|
+
) {
|
|
70
|
+
assert(isBundleSource(source), `vat ${vatID} source has wrong shape`);
|
|
71
|
+
assert(
|
|
72
|
+
isObject(options) && isObject(options.workerOptions),
|
|
73
|
+
`vat ${vatID} options is missing workerOptions`,
|
|
74
|
+
);
|
|
75
|
+
|
|
44
76
|
kvStore.set(`${vatID}.o.nextID`, `${FIRST_OBJECT_ID}`);
|
|
45
77
|
kvStore.set(`${vatID}.p.nextID`, `${FIRST_PROMISE_ID}`);
|
|
46
78
|
kvStore.set(`${vatID}.d.nextID`, `${FIRST_DEVICE_ID}`);
|
|
79
|
+
kvStore.set(`${vatID}.reapDirt`, JSON.stringify({}));
|
|
80
|
+
kvStore.set(`${vatID}.source`, JSON.stringify(source));
|
|
81
|
+
kvStore.set(`${vatID}.options`, JSON.stringify(options));
|
|
47
82
|
transcriptStore.initTranscript(vatID);
|
|
48
83
|
}
|
|
49
84
|
|
|
@@ -68,6 +103,7 @@ export function initializeVatState(kvStore, transcriptStore, vatID) {
|
|
|
68
103
|
* @param {*} incStat
|
|
69
104
|
* @param {*} decStat
|
|
70
105
|
* @param {*} getCrankNumber
|
|
106
|
+
* @param {*} scheduleReap
|
|
71
107
|
* @param {SnapStore} [snapStore]
|
|
72
108
|
* returns an object to hold and access the kernel's state for the given vat
|
|
73
109
|
*/
|
|
@@ -88,10 +124,16 @@ export function makeVatKeeper(
|
|
|
88
124
|
incStat,
|
|
89
125
|
decStat,
|
|
90
126
|
getCrankNumber,
|
|
127
|
+
scheduleReap,
|
|
91
128
|
snapStore = undefined,
|
|
92
129
|
) {
|
|
93
130
|
insistVatID(vatID);
|
|
94
131
|
|
|
132
|
+
// note: calling makeVatKeeper() does not change the DB. Any
|
|
133
|
+
// initialization or upgrade must be complete before it is
|
|
134
|
+
// called. Only the methods returned by makeVatKeeper() will change
|
|
135
|
+
// the DB.
|
|
136
|
+
|
|
95
137
|
function getRequired(key) {
|
|
96
138
|
const value = kvStore.get(key);
|
|
97
139
|
if (value === undefined) {
|
|
@@ -100,6 +142,8 @@ export function makeVatKeeper(
|
|
|
100
142
|
return value;
|
|
101
143
|
}
|
|
102
144
|
|
|
145
|
+
const reapDirtKey = `${vatID}.reapDirt`;
|
|
146
|
+
|
|
103
147
|
/**
|
|
104
148
|
* @param {SourceOfBundle} source
|
|
105
149
|
* @param {RecordedVatOptions} options
|
|
@@ -125,45 +169,80 @@ export function makeVatKeeper(
|
|
|
125
169
|
|
|
126
170
|
function getOptions() {
|
|
127
171
|
/** @type { RecordedVatOptions } */
|
|
128
|
-
const options = JSON.parse(
|
|
172
|
+
const options = JSON.parse(getRequired(`${vatID}.options`));
|
|
129
173
|
return harden(options);
|
|
130
174
|
}
|
|
131
175
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
}
|
|
176
|
+
// This is named "addDirt" because it should increment all dirt
|
|
177
|
+
// counters (both for reap/BOYD and for heap snapshotting). We don't
|
|
178
|
+
// have `heapSnapshotDirt` yet, but when we do, it should get
|
|
179
|
+
// incremented here.
|
|
137
180
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
181
|
+
/**
|
|
182
|
+
* Add some "dirt" to the vat, possibly triggering a reap/BOYD.
|
|
183
|
+
*
|
|
184
|
+
* @param {Dirt} moreDirt
|
|
185
|
+
*/
|
|
186
|
+
function addDirt(moreDirt) {
|
|
187
|
+
assert.typeof(moreDirt, 'object');
|
|
188
|
+
const reapDirt = JSON.parse(getRequired(reapDirtKey));
|
|
189
|
+
const thresholds = {
|
|
190
|
+
...JSON.parse(getRequired(DEFAULT_REAP_DIRT_THRESHOLD_KEY)),
|
|
191
|
+
...JSON.parse(getRequired(`${vatID}.options`)).reapDirtThreshold,
|
|
192
|
+
};
|
|
193
|
+
let reap = false;
|
|
194
|
+
for (const key of Object.keys(moreDirt)) {
|
|
195
|
+
const threshold = thresholds[key];
|
|
196
|
+
// Don't accumulate dirt if it can't eventually trigger a
|
|
197
|
+
// BOYD. This is mainly to keep comms from counting upwards
|
|
198
|
+
// forever. TODO revisit this when we add heapSnapshotDirt,
|
|
199
|
+
// maybe check both thresholds and accumulate the dirt if either
|
|
200
|
+
// one is non-'never'.
|
|
201
|
+
if (threshold && threshold !== 'never') {
|
|
202
|
+
const oldDirt = reapDirt[key] || 0;
|
|
203
|
+
// The 'moreDirt' value might be Number or BigInt (eg
|
|
204
|
+
// .computrons). We coerce to Number so we can JSON-stringify.
|
|
205
|
+
const newDirt = oldDirt + Number(moreDirt[key]);
|
|
206
|
+
reapDirt[key] = newDirt;
|
|
207
|
+
if (newDirt >= threshold) {
|
|
208
|
+
reap = true;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
145
211
|
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
if (rawCount === 'never') {
|
|
151
|
-
return false;
|
|
152
|
-
} else {
|
|
153
|
-
const count = Number.parseInt(rawCount, 10);
|
|
154
|
-
if (count === 1) {
|
|
155
|
-
kvStore.set(
|
|
156
|
-
`${vatID}.reapCountdown`,
|
|
157
|
-
getRequired(`${vatID}.reapInterval`),
|
|
158
|
-
);
|
|
159
|
-
return true;
|
|
160
|
-
} else {
|
|
161
|
-
kvStore.set(`${vatID}.reapCountdown`, `${count - 1}`);
|
|
162
|
-
return false;
|
|
212
|
+
if (!thresholds.never) {
|
|
213
|
+
kvStore.set(reapDirtKey, JSON.stringify(reapDirt));
|
|
214
|
+
if (reap) {
|
|
215
|
+
scheduleReap(vatID);
|
|
163
216
|
}
|
|
164
217
|
}
|
|
165
218
|
}
|
|
166
219
|
|
|
220
|
+
function getReapDirt() {
|
|
221
|
+
return JSON.parse(getRequired(reapDirtKey));
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function clearReapDirt() {
|
|
225
|
+
// This is only called after a BOYD, so it should only clear the
|
|
226
|
+
// reap/BOYD counters. If/when we add heap-snapshot counters,
|
|
227
|
+
// those should get cleared in a separate clearHeapSnapshotDirt()
|
|
228
|
+
// function.
|
|
229
|
+
const reapDirt = {};
|
|
230
|
+
kvStore.set(reapDirtKey, JSON.stringify(reapDirt));
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
function getReapDirtThreshold() {
|
|
234
|
+
return getOptions().reapDirtThreshold;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* @param {ReapDirtThreshold} reapDirtThreshold
|
|
239
|
+
*/
|
|
240
|
+
function setReapDirtThreshold(reapDirtThreshold) {
|
|
241
|
+
assert.typeof(reapDirtThreshold, 'object');
|
|
242
|
+
const options = { ...getOptions(), reapDirtThreshold };
|
|
243
|
+
kvStore.set(`${vatID}.options`, JSON.stringify(options));
|
|
244
|
+
}
|
|
245
|
+
|
|
167
246
|
function nextDeliveryNum() {
|
|
168
247
|
const { endPos } = transcriptStore.getCurrentSpanBounds(vatID);
|
|
169
248
|
return Nat(endPos);
|
|
@@ -576,7 +655,7 @@ export function makeVatKeeper(
|
|
|
576
655
|
addToTranscript(makeSaveSnapshotItem(snapshotID));
|
|
577
656
|
|
|
578
657
|
// then start a new transcript span
|
|
579
|
-
transcriptStore.rolloverSpan(vatID);
|
|
658
|
+
await transcriptStore.rolloverSpan(vatID);
|
|
580
659
|
|
|
581
660
|
// then push a load-snapshot entry, so that the current span
|
|
582
661
|
// always starts with an initialize-worker or load-snapshot
|
|
@@ -596,14 +675,47 @@ export function makeVatKeeper(
|
|
|
596
675
|
});
|
|
597
676
|
}
|
|
598
677
|
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
678
|
+
/**
|
|
679
|
+
* Perform some (possibly-limited) cleanup work for a vat. Returns
|
|
680
|
+
* 'done' (where false means "please call me again", and true means
|
|
681
|
+
* "you can delete the vatID now"), and a count of how much work was
|
|
682
|
+
* done (so the runPolicy can decide when to stop).
|
|
683
|
+
*
|
|
684
|
+
* @param {number} [budget]
|
|
685
|
+
* @returns {{ done: boolean, cleanups: number }}
|
|
686
|
+
*
|
|
687
|
+
*/
|
|
688
|
+
function deleteSnapshots(budget = undefined) {
|
|
689
|
+
// Each budget=1 allows us to delete one snapshot entry.
|
|
690
|
+
if (!snapStore) {
|
|
691
|
+
return { done: true, cleanups: 0 };
|
|
602
692
|
}
|
|
603
|
-
|
|
693
|
+
// initially uses 2+2*budget DB statements, then just 1 when done
|
|
694
|
+
return snapStore.deleteVatSnapshots(vatID, budget);
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
/**
|
|
698
|
+
* Perform some (possibly-limited) cleanup work for a vat. Returns
|
|
699
|
+
* 'done' (where false means "please call me again", and true means
|
|
700
|
+
* "you can delete the vatID now"), and a count of how much work was
|
|
701
|
+
* done (so the runPolicy can decide when to stop).
|
|
702
|
+
*
|
|
703
|
+
* @param {number} [budget]
|
|
704
|
+
* @returns {{ done: boolean, cleanups: number }}
|
|
705
|
+
*
|
|
706
|
+
*/
|
|
707
|
+
function deleteTranscripts(budget = undefined) {
|
|
708
|
+
// Each budget=1 allows us to delete one transcript span and any
|
|
709
|
+
// transcript items associated with that span. Some nodes will
|
|
710
|
+
// have historical transcript items, some will not. Using budget=5
|
|
711
|
+
// and snapshotInterval=200 means we delete 5 span records and
|
|
712
|
+
// maybe 1000 span items.
|
|
713
|
+
|
|
714
|
+
// initially uses 2+3*budget DB statements, then just 1 when done
|
|
715
|
+
return transcriptStore.deleteVatTranscripts(vatID, budget);
|
|
604
716
|
}
|
|
605
717
|
|
|
606
|
-
function beginNewIncarnation() {
|
|
718
|
+
async function beginNewIncarnation() {
|
|
607
719
|
if (snapStore) {
|
|
608
720
|
snapStore.stopUsingLastSnapshot(vatID);
|
|
609
721
|
}
|
|
@@ -656,9 +768,11 @@ export function makeVatKeeper(
|
|
|
656
768
|
setSourceAndOptions,
|
|
657
769
|
getSourceAndOptions,
|
|
658
770
|
getOptions,
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
771
|
+
addDirt,
|
|
772
|
+
getReapDirt,
|
|
773
|
+
clearReapDirt,
|
|
774
|
+
getReapDirtThreshold,
|
|
775
|
+
setReapDirtThreshold,
|
|
662
776
|
nextDeliveryNum,
|
|
663
777
|
getIncarnationNumber,
|
|
664
778
|
importsKernelSlot,
|
|
@@ -680,7 +794,8 @@ export function makeVatKeeper(
|
|
|
680
794
|
dumpState,
|
|
681
795
|
saveSnapshot,
|
|
682
796
|
getSnapshotInfo,
|
|
683
|
-
|
|
797
|
+
deleteSnapshots,
|
|
798
|
+
deleteTranscripts,
|
|
684
799
|
beginNewIncarnation,
|
|
685
800
|
});
|
|
686
801
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { assert } from '@
|
|
1
|
+
import { assert } from '@endo/errors';
|
|
2
2
|
import { kser, kunser } from '@agoric/kmarshal';
|
|
3
3
|
import { insistVatID } from '../lib/id.js';
|
|
4
4
|
|
|
@@ -94,6 +94,9 @@ export function makeVatAdminHooks(tools) {
|
|
|
94
94
|
// we don't need to incrementRefCount because if terminateVat sends
|
|
95
95
|
// 'reason' to vat-admin, it uses notifyTermination / queueToKref /
|
|
96
96
|
// doSend, and doSend() does its own incref
|
|
97
|
+
// FIXME: This assumes that most work of terminateVat happens in the
|
|
98
|
+
// synchronous prelude, which should be made more obvious. For details,
|
|
99
|
+
// see https://github.com/Agoric/agoric-sdk/pull/10055#discussion_r1754918394
|
|
97
100
|
void terminateVat(vatID, true, marshalledReason);
|
|
98
101
|
// TODO: terminateVat is async, result doesn't fire until worker
|
|
99
102
|
// is dead. To fix this we'll probably need to move termination
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { assert, Fail } from '@
|
|
1
|
+
import { assert, Fail } from '@endo/errors';
|
|
2
2
|
import { assertKnownOptions } from '../../lib/assertOptions.js';
|
|
3
3
|
import { makeLocalVatManagerFactory } from './manager-local.js';
|
|
4
4
|
import { makeNodeSubprocessFactory } from './manager-subprocess-node.js';
|
|
@@ -45,7 +45,6 @@ export function makeVatManagerFactory({
|
|
|
45
45
|
'enableSetup',
|
|
46
46
|
'useTranscript',
|
|
47
47
|
'critical',
|
|
48
|
-
'reapInterval',
|
|
49
48
|
'sourcedConsole',
|
|
50
49
|
'name',
|
|
51
50
|
]);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/* global globalThis */
|
|
2
2
|
|
|
3
|
-
import { assert, Fail } from '@
|
|
3
|
+
import { assert, Fail } from '@endo/errors';
|
|
4
4
|
import { importBundle } from '@endo/import-bundle';
|
|
5
5
|
import { makeLiveSlots } from '@agoric/swingset-liveslots';
|
|
6
6
|
import { makeManagerKit } from './manager-helper.js';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// import { spawn } from 'child_process'; // not from Compartment
|
|
2
2
|
|
|
3
|
-
import { assert, Fail } from '@
|
|
3
|
+
import { assert, Fail } from '@endo/errors';
|
|
4
4
|
import { E } from '@endo/eventual-send';
|
|
5
5
|
import { makePromiseKit } from '@endo/promise-kit';
|
|
6
6
|
import { makeManagerKit } from './manager-helper.js';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { assert, Fail } from '@
|
|
1
|
+
import { assert, Fail } from '@endo/errors';
|
|
2
2
|
import { assertKnownOptions } from '../../lib/assertOptions.js';
|
|
3
3
|
import { makeVatSlot } from '../../lib/parseVatSlots.js';
|
|
4
4
|
|
|
@@ -26,7 +26,7 @@ export function makeVatLoader(stuff) {
|
|
|
26
26
|
'enablePipelining',
|
|
27
27
|
'useTranscript',
|
|
28
28
|
'critical',
|
|
29
|
-
'
|
|
29
|
+
'reapDirtThreshold',
|
|
30
30
|
];
|
|
31
31
|
|
|
32
32
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { assert, Fail,
|
|
1
|
+
import { assert, Fail, q } from '@endo/errors';
|
|
2
2
|
import { isNat } from '@endo/nat';
|
|
3
3
|
import { makeVatTranslators } from './vatTranslator.js';
|
|
4
4
|
import { insistVatDeliveryResult } from '../lib/message.js';
|
|
@@ -544,6 +544,10 @@ export function makeVatWarehouse({
|
|
|
544
544
|
vatKeeper.addToTranscript(getTranscriptEntry(vd, deliveryResult));
|
|
545
545
|
}
|
|
546
546
|
|
|
547
|
+
if (kd[0] === 'bringOutYourDead') {
|
|
548
|
+
vatKeeper.clearReapDirt(); // BOYD zeros out the when-to-BOYD counters
|
|
549
|
+
}
|
|
550
|
+
|
|
547
551
|
// TODO: if per-vat policy decides it wants a BOYD or heap snapshot,
|
|
548
552
|
// now is the time to do it, or to ask the kernel to schedule it
|
|
549
553
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { assert, Fail } from '@
|
|
1
|
+
import { assert, Fail } from '@endo/errors';
|
|
2
2
|
import { insistMessage } from '../lib/message.js';
|
|
3
3
|
import { insistKernelType, parseKernelSlot } from './parseKernelSlots.js';
|
|
4
4
|
import { insistVatType, parseVatSlot } from '../lib/parseVatSlots.js';
|
|
@@ -481,9 +481,6 @@ function makeTranslateVatSyscallToKernelSyscall(vatID, kernelKeeper) {
|
|
|
481
481
|
assert.equal(allocatedByVat, true); // abandon *exports*, not imports
|
|
482
482
|
// kref must already be in the clist
|
|
483
483
|
const kref = mapVatSlotToKernelSlot(vref, gcSyscallMapOpts);
|
|
484
|
-
// note that this is effectful and also performed outside of a syscall
|
|
485
|
-
// by processUpgradeVat in {@link ./kernel.js}
|
|
486
|
-
vatKeeper.deleteCListEntry(kref, vref);
|
|
487
484
|
return kref;
|
|
488
485
|
});
|
|
489
486
|
kdebug(`syscall[${vatID}].abandonExports(${krefs.join(' ')})`);
|
package/src/lib/assertOptions.js
CHANGED
package/src/lib/capdata.js
CHANGED
package/src/lib/id.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Nat } from '@endo/nat';
|
|
2
2
|
|
|
3
|
-
import { Fail } from '@
|
|
3
|
+
import { Fail } from '@endo/errors';
|
|
4
4
|
|
|
5
5
|
// Vats are identified by an integer index, which (for typechecking purposes)
|
|
6
6
|
// is encoded as `vNN`. Devices are similarly identified as `dNN`. Both have
|
package/src/lib/message.js
CHANGED
package/src/lib/parseVatSlots.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Nat } from '@endo/nat';
|
|
2
|
-
import { assert, Fail } from '@
|
|
2
|
+
import { assert, Fail } from '@endo/errors';
|
|
3
3
|
|
|
4
4
|
// NOTE: confusing terminology: "slot" vs. "reference". All these things
|
|
5
5
|
// called "slots" are references, but the word "slot" suggests something into
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Fail } from '@
|
|
1
|
+
import { Fail } from '@endo/errors';
|
|
2
2
|
import { makeWorkerOptions } from './workerOptions.js';
|
|
3
3
|
|
|
4
4
|
export const makeVatOptionRecorder = (kernelKeeper, bundleHandler) => {
|
|
@@ -10,7 +10,9 @@ export const makeVatOptionRecorder = (kernelKeeper, bundleHandler) => {
|
|
|
10
10
|
enablePipelining = false,
|
|
11
11
|
enableDisavow = false,
|
|
12
12
|
useTranscript = true,
|
|
13
|
-
reapInterval
|
|
13
|
+
reapInterval,
|
|
14
|
+
reapGCKrefs,
|
|
15
|
+
neverReap = false,
|
|
14
16
|
critical = false,
|
|
15
17
|
meterID = undefined,
|
|
16
18
|
managerType = kernelKeeper.getDefaultManagerType(),
|
|
@@ -21,6 +23,17 @@ export const makeVatOptionRecorder = (kernelKeeper, bundleHandler) => {
|
|
|
21
23
|
if (unused.length) {
|
|
22
24
|
Fail`OptionRecorder: ${vatID} unused options ${unused.join(',')}`;
|
|
23
25
|
}
|
|
26
|
+
const reapDirtThreshold = {};
|
|
27
|
+
if (reapInterval !== undefined) {
|
|
28
|
+
reapDirtThreshold.deliveries = reapInterval;
|
|
29
|
+
}
|
|
30
|
+
if (reapGCKrefs !== undefined) {
|
|
31
|
+
reapDirtThreshold.gcKrefs = reapGCKrefs;
|
|
32
|
+
}
|
|
33
|
+
if (neverReap) {
|
|
34
|
+
reapDirtThreshold.never = true;
|
|
35
|
+
}
|
|
36
|
+
// TODO no computrons knob?
|
|
24
37
|
const workerOptions = await makeWorkerOptions(
|
|
25
38
|
managerType,
|
|
26
39
|
bundleHandler,
|
|
@@ -35,13 +48,12 @@ export const makeVatOptionRecorder = (kernelKeeper, bundleHandler) => {
|
|
|
35
48
|
enablePipelining,
|
|
36
49
|
enableDisavow,
|
|
37
50
|
useTranscript,
|
|
38
|
-
|
|
51
|
+
reapDirtThreshold,
|
|
39
52
|
critical,
|
|
40
53
|
meterID,
|
|
41
54
|
});
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
vatKeeper.initializeReapCountdown(vatOptions.reapInterval);
|
|
55
|
+
// want vNN.options to be in place before provideVatKeeper, so it can cache reapDirtThreshold in RAM, so:
|
|
56
|
+
kernelKeeper.createVatState(vatID, source, vatOptions);
|
|
45
57
|
};
|
|
46
58
|
|
|
47
59
|
/**
|
package/src/lib/runPolicies.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
import { assert } from '@
|
|
1
|
+
import { assert } from '@endo/errors';
|
|
2
2
|
|
|
3
3
|
export function foreverPolicy() {
|
|
4
4
|
/** @type { RunPolicy } */
|
|
5
5
|
return harden({
|
|
6
|
+
allowCleanup() {
|
|
7
|
+
return true; // unlimited budget
|
|
8
|
+
},
|
|
6
9
|
vatCreated(_details) {
|
|
7
10
|
return true;
|
|
8
11
|
},
|
|
@@ -27,6 +30,9 @@ export function crankCounter(
|
|
|
27
30
|
let vats = 0;
|
|
28
31
|
/** @type { RunPolicy } */
|
|
29
32
|
const policy = harden({
|
|
33
|
+
allowCleanup() {
|
|
34
|
+
return { default: 100 }; // limited budget
|
|
35
|
+
},
|
|
30
36
|
vatCreated() {
|
|
31
37
|
vats += 1;
|
|
32
38
|
return vats < maxCreateVats;
|
|
@@ -47,13 +53,21 @@ export function crankCounter(
|
|
|
47
53
|
return policy;
|
|
48
54
|
}
|
|
49
55
|
|
|
50
|
-
export function computronCounter(limit) {
|
|
56
|
+
export function computronCounter(limit, options = {}) {
|
|
51
57
|
assert.typeof(limit, 'bigint');
|
|
58
|
+
const {
|
|
59
|
+
cleanupBudget = 100,
|
|
60
|
+
vatCreatedComputrons = 100_000n, // pretend that's the cost
|
|
61
|
+
crankFailedComputrons = 1_000_000n,
|
|
62
|
+
} = options;
|
|
52
63
|
let total = 0n;
|
|
53
64
|
/** @type { RunPolicy } */
|
|
54
65
|
const policy = harden({
|
|
66
|
+
allowCleanup() {
|
|
67
|
+
return { default: cleanupBudget }; // limited budget
|
|
68
|
+
},
|
|
55
69
|
vatCreated() {
|
|
56
|
-
total +=
|
|
70
|
+
total += vatCreatedComputrons;
|
|
57
71
|
return total < limit;
|
|
58
72
|
},
|
|
59
73
|
crankComplete(details = {}) {
|
|
@@ -65,7 +79,7 @@ export function computronCounter(limit) {
|
|
|
65
79
|
return total < limit;
|
|
66
80
|
},
|
|
67
81
|
crankFailed() {
|
|
68
|
-
total +=
|
|
82
|
+
total += crankFailedComputrons;
|
|
69
83
|
return total < limit;
|
|
70
84
|
},
|
|
71
85
|
emptyCrank() {
|
|
@@ -79,6 +93,7 @@ export function wallClockWaiter(seconds) {
|
|
|
79
93
|
const timeout = Date.now() + 1000 * seconds;
|
|
80
94
|
/** @type { RunPolicy } */
|
|
81
95
|
const policy = harden({
|
|
96
|
+
allowCleanup: () => true, // unlimited budget
|
|
82
97
|
vatCreated: () => Date.now() < timeout,
|
|
83
98
|
crankComplete: () => Date.now() < timeout,
|
|
84
99
|
crankFailed: () => Date.now() < timeout,
|
|
@@ -86,3 +101,34 @@ export function wallClockWaiter(seconds) {
|
|
|
86
101
|
});
|
|
87
102
|
return policy;
|
|
88
103
|
}
|
|
104
|
+
|
|
105
|
+
export function noCleanup() {
|
|
106
|
+
/** @type { RunPolicy } */
|
|
107
|
+
const policy = harden({
|
|
108
|
+
allowCleanup: () => false,
|
|
109
|
+
vatCreated: () => true,
|
|
110
|
+
crankComplete: () => true,
|
|
111
|
+
crankFailed: () => true,
|
|
112
|
+
emptyCrank: () => true,
|
|
113
|
+
});
|
|
114
|
+
return policy;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export function someCleanup(budget) {
|
|
118
|
+
let once = true;
|
|
119
|
+
/** @type { RunPolicy } */
|
|
120
|
+
const policy = harden({
|
|
121
|
+
allowCleanup: () => {
|
|
122
|
+
if (once) {
|
|
123
|
+
once = false;
|
|
124
|
+
return { default: budget };
|
|
125
|
+
}
|
|
126
|
+
return false;
|
|
127
|
+
},
|
|
128
|
+
vatCreated: () => true,
|
|
129
|
+
crankComplete: () => true,
|
|
130
|
+
crankFailed: () => true,
|
|
131
|
+
emptyCrank: () => true,
|
|
132
|
+
});
|
|
133
|
+
return policy;
|
|
134
|
+
}
|
package/src/lib/storageAPI.js
CHANGED
package/src/lib/workerOptions.js
CHANGED
|
@@ -8,7 +8,7 @@ import fs from 'fs';
|
|
|
8
8
|
import { Buffer } from 'buffer';
|
|
9
9
|
import process from 'node:process';
|
|
10
10
|
|
|
11
|
-
import { assert,
|
|
11
|
+
import { assert, X, Fail } from '@endo/errors';
|
|
12
12
|
import { importBundle } from '@endo/import-bundle';
|
|
13
13
|
import { makeMarshal } from '@endo/marshal';
|
|
14
14
|
import {
|