@agoric/swingset-vat 0.33.0-u16.0 → 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.
Files changed (76) hide show
  1. package/README.md +1 -1
  2. package/package.json +31 -30
  3. package/src/controller/controller.js +48 -1
  4. package/src/controller/initializeKernel.js +35 -10
  5. package/src/controller/initializeSwingset.js +6 -3
  6. package/src/controller/startXSnap.js +1 -1
  7. package/src/controller/upgradeSwingset.js +212 -0
  8. package/src/devices/bridge/device-bridge.js +1 -1
  9. package/src/devices/bundle/device-bundle.js +1 -1
  10. package/src/devices/command/command.js +1 -2
  11. package/src/devices/command/device-command.js +1 -2
  12. package/src/devices/lib/deviceTools.js +1 -1
  13. package/src/devices/loopbox/device-loopbox.js +1 -1
  14. package/src/devices/loopbox/loopbox.js +1 -1
  15. package/src/devices/mailbox/device-mailbox.js +1 -2
  16. package/src/devices/mailbox/mailbox.js +1 -2
  17. package/src/devices/plugin/device-plugin.js +1 -1
  18. package/src/devices/timer/device-timer.js +1 -1
  19. package/src/devices/timer/timer.js +1 -1
  20. package/src/devices/vat-admin/device-vat-admin.js +4 -2
  21. package/src/index.js +1 -1
  22. package/src/kernel/deviceManager.js +1 -1
  23. package/src/kernel/deviceSlots.js +1 -1
  24. package/src/kernel/deviceTranslator.js +1 -1
  25. package/src/kernel/dummyMeterControl.js +1 -1
  26. package/src/kernel/gc-actions.js +55 -34
  27. package/src/kernel/kernel.js +216 -51
  28. package/src/kernel/kernelSyscall.js +2 -13
  29. package/src/kernel/parseKernelSlots.js +1 -1
  30. package/src/kernel/slogger.js +2 -2
  31. package/src/kernel/state/deviceKeeper.js +1 -1
  32. package/src/kernel/state/kernelKeeper.js +427 -81
  33. package/src/kernel/state/reachable.js +1 -1
  34. package/src/kernel/state/stats.js +1 -1
  35. package/src/kernel/state/storageHelper.js +1 -1
  36. package/src/kernel/state/vatKeeper.js +159 -44
  37. package/src/kernel/vat-admin-hooks.js +4 -1
  38. package/src/kernel/vat-loader/manager-factory.js +1 -2
  39. package/src/kernel/vat-loader/manager-helper.js +1 -1
  40. package/src/kernel/vat-loader/manager-local.js +1 -1
  41. package/src/kernel/vat-loader/manager-subprocess-node.js +1 -1
  42. package/src/kernel/vat-loader/manager-subprocess-xsnap.js +1 -1
  43. package/src/kernel/vat-loader/vat-loader.js +2 -2
  44. package/src/kernel/vat-warehouse.js +5 -1
  45. package/src/kernel/vatTranslator.js +1 -4
  46. package/src/lib/assertOptions.js +1 -1
  47. package/src/lib/capdata.js +1 -1
  48. package/src/lib/id.js +1 -1
  49. package/src/lib/message.js +1 -1
  50. package/src/lib/parseVatSlots.js +1 -1
  51. package/src/lib/recordVatOptions.js +18 -6
  52. package/src/lib/runPolicies.js +50 -4
  53. package/src/lib/storageAPI.js +1 -1
  54. package/src/lib/workerOptions.js +1 -1
  55. package/src/supervisors/subprocess-node/supervisor-subprocess-node.js +1 -1
  56. package/src/types-external.js +71 -22
  57. package/src/types-internal.js +56 -3
  58. package/src/vats/comms/clist-inbound.js +1 -1
  59. package/src/vats/comms/clist-kernel.js +1 -1
  60. package/src/vats/comms/clist-outbound.js +1 -1
  61. package/src/vats/comms/controller.js +1 -1
  62. package/src/vats/comms/delivery.js +1 -1
  63. package/src/vats/comms/dispatch.js +1 -1
  64. package/src/vats/comms/gc-comms.js +1 -1
  65. package/src/vats/comms/parseLocalSlots.js +1 -1
  66. package/src/vats/comms/parseRemoteSlot.js +1 -1
  67. package/src/vats/comms/remote.js +1 -1
  68. package/src/vats/comms/state.js +1 -1
  69. package/src/vats/timer/vat-timer.js +9 -9
  70. package/src/vats/vat-admin/vat-vat-admin.js +23 -8
  71. package/src/vats/vattp/vat-vattp.js +1 -1
  72. package/tools/bootstrap-relay.js +1 -3
  73. package/tools/bundleTool.js +9 -1
  74. package/tools/dvo-test-harness.js +1 -1
  75. package/tools/manual-timer.js +1 -1
  76. package/tools/run-utils.js +1 -1
@@ -1,4 +1,4 @@
1
- import { assert, Fail } from '@agoric/assert';
1
+ import { assert, Fail } from '@endo/errors';
2
2
 
3
3
  export function parseReachableAndVatSlot(value) {
4
4
  typeof value === 'string' || Fail`non-string value: ${value}`;
@@ -1,4 +1,4 @@
1
- import { Fail } from '@agoric/assert';
1
+ import { Fail } from '@endo/errors';
2
2
 
3
3
  /** @typedef {'counter' | 'gauge'} KernelStatsMetricType */
4
4
  /**
@@ -1,6 +1,6 @@
1
1
  // @ts-check
2
2
 
3
- import { Fail } from '@agoric/assert';
3
+ import { Fail } from '@endo/errors';
4
4
 
5
5
  /**
6
6
  * Iterate over keys with a given prefix, in lexicographic order,
@@ -1,8 +1,9 @@
1
1
  /**
2
2
  * Kernel's keeper of persistent state for a vat.
3
3
  */
4
- import { Nat, isNat } from '@endo/nat';
5
- import { assert, q, Fail } from '@agoric/assert';
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
- * TODO: consider making this part of makeVatKeeper
60
+ * @param {SourceOfBundle} source
61
+ * @param {RecordedVatOptions} options
42
62
  */
43
- export function initializeVatState(kvStore, transcriptStore, vatID) {
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(kvStore.get(`${vatID}.options`) || '{}');
172
+ const options = JSON.parse(getRequired(`${vatID}.options`));
129
173
  return harden(options);
130
174
  }
131
175
 
132
- function initializeReapCountdown(count) {
133
- count === 'never' || isNat(count) || Fail`bad reapCountdown ${count}`;
134
- kvStore.set(`${vatID}.reapInterval`, `${count}`);
135
- kvStore.set(`${vatID}.reapCountdown`, `${count}`);
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
- function updateReapInterval(reapInterval) {
139
- reapInterval === 'never' ||
140
- isNat(reapInterval) ||
141
- Fail`bad reapInterval ${reapInterval}`;
142
- kvStore.set(`${vatID}.reapInterval`, `${reapInterval}`);
143
- if (reapInterval === 'never') {
144
- kvStore.set(`${vatID}.reapCountdown`, 'never');
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
- function countdownToReap() {
149
- const rawCount = getRequired(`${vatID}.reapCountdown`);
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
- function deleteSnapshotsAndTranscript() {
600
- if (snapStore) {
601
- snapStore.deleteVatSnapshots(vatID);
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
- transcriptStore.deleteVatTranscripts(vatID);
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
- initializeReapCountdown,
660
- countdownToReap,
661
- updateReapInterval,
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
- deleteSnapshotsAndTranscript,
797
+ deleteSnapshots,
798
+ deleteTranscripts,
684
799
  beginNewIncarnation,
685
800
  });
686
801
  }
@@ -1,4 +1,4 @@
1
- import { assert } from '@agoric/assert';
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 '@agoric/assert';
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,4 +1,4 @@
1
- import { assert } from '@agoric/assert';
1
+ import { assert } from '@endo/errors';
2
2
  import '../../types-ambient.js';
3
3
  import {
4
4
  insistVatDeliveryResult,
@@ -1,6 +1,6 @@
1
1
  /* global globalThis */
2
2
 
3
- import { assert, Fail } from '@agoric/assert';
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 '@agoric/assert';
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,5 +1,5 @@
1
1
  import { synchronizedTee } from '@agoric/internal';
2
- import { assert, Fail, q } from '@agoric/assert';
2
+ import { assert, Fail, q } from '@endo/errors';
3
3
  import { ExitCode } from '@agoric/xsnap/api.js';
4
4
  import { makeManagerKit } from './manager-helper.js';
5
5
 
@@ -1,4 +1,4 @@
1
- import { assert, Fail } from '@agoric/assert';
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
- 'reapInterval',
29
+ 'reapDirtThreshold',
30
30
  ];
31
31
 
32
32
  /**
@@ -1,4 +1,4 @@
1
- import { assert, Fail, quote as q } from '@agoric/assert';
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 '@agoric/assert';
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(' ')})`);
@@ -1,4 +1,4 @@
1
- import { assert, Fail } from '@agoric/assert';
1
+ import { assert, Fail } from '@endo/errors';
2
2
 
3
3
  export function assertKnownOptions(options, knownNames) {
4
4
  assert(knownNames instanceof Array);
@@ -1,4 +1,4 @@
1
- import { Fail } from '@agoric/assert';
1
+ import { Fail } from '@endo/errors';
2
2
  import { passStyleOf } from '@endo/far';
3
3
  import { kunser, krefOf } from '@agoric/kmarshal';
4
4
 
package/src/lib/id.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Nat } from '@endo/nat';
2
2
 
3
- import { Fail } from '@agoric/assert';
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
@@ -1,4 +1,4 @@
1
- import { assert, Fail } from '@agoric/assert';
1
+ import { assert, Fail } from '@endo/errors';
2
2
  import { insistCapData } from './capdata.js';
3
3
 
4
4
  /**
@@ -1,5 +1,5 @@
1
1
  import { Nat } from '@endo/nat';
2
- import { assert, Fail } from '@agoric/assert';
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 '@agoric/assert';
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 = kernelKeeper.getDefaultReapInterval(),
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
- reapInterval,
51
+ reapDirtThreshold,
39
52
  critical,
40
53
  meterID,
41
54
  });
42
- const vatKeeper = kernelKeeper.provideVatKeeper(vatID);
43
- vatKeeper.setSourceAndOptions(source, vatOptions);
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
  /**
@@ -1,8 +1,11 @@
1
- import { assert } from '@agoric/assert';
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 += 100000n; // pretend vat creation takes 100k computrons
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 += 1000000n; // who knows, 1M is as good as anything
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
+ }
@@ -1,4 +1,4 @@
1
- import { Fail } from '@agoric/assert';
1
+ import { Fail } from '@endo/errors';
2
2
 
3
3
  /**
4
4
  * Assert function to ensure that an object implements the StorageAPI
@@ -1,4 +1,4 @@
1
- import { Fail } from '@agoric/assert';
1
+ import { Fail } from '@endo/errors';
2
2
 
3
3
  /**
4
4
  * @param {string} managerType
@@ -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, details as X, Fail } from '@agoric/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 {