@agoric/swingset-liveslots 0.10.3-u16.1 → 0.10.3-u17.1
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/package.json +17 -18
- package/src/boyd-gc.js +598 -0
- package/src/cache.js +1 -1
- package/src/capdata.js +1 -1
- package/src/collectionManager.js +65 -21
- package/src/facetiousness.js +1 -1
- package/src/liveslots.js +83 -202
- package/src/message.js +1 -1
- package/src/parseVatSlots.js +1 -1
- package/src/vatDataTypes.d.ts +7 -2
- package/src/virtualObjectManager.js +1 -6
- package/src/virtualReferences.js +83 -25
- package/src/watchedPromises.js +7 -2
- package/test/clear-collection.test.js +586 -0
- package/test/collections.test.js +41 -0
- package/test/dropped-weakset-9939.test.js +80 -0
- package/test/dummyMeterControl.js +1 -1
- package/test/durabilityChecks.test.js +1 -1
- package/test/gc-before-finalizer.test.js +230 -0
- package/test/handled-promises.test.js +266 -50
- package/test/liveslots-helpers.js +6 -1
- package/test/liveslots-mock-gc.test.js +99 -0
- package/test/liveslots-real-gc.test.js +18 -2
- package/test/liveslots.test.js +1 -1
- package/test/vat-environment.test.js +65 -0
- package/test/vat-util.js +1 -1
- package/test/virtual-objects/rep-tostring.test.js +1 -2
- package/test/vpid-liveslots.test.js +102 -1
- package/test/weakset-dropped-remotable.test.js +50 -0
- package/tools/fakeVirtualSupport.js +1 -3
- package/tools/setup-vat-data.js +10 -3
package/src/virtualReferences.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/* eslint-disable no-use-before-define, jsdoc/require-returns-type */
|
|
2
2
|
|
|
3
|
-
import { assert, Fail } from '@
|
|
3
|
+
import { assert, Fail } from '@endo/errors';
|
|
4
4
|
import { Nat } from '@endo/nat';
|
|
5
5
|
import { parseVatSlot } from './parseVatSlots.js';
|
|
6
6
|
import {
|
|
@@ -290,7 +290,10 @@ export function makeVirtualReferenceManager(
|
|
|
290
290
|
*/
|
|
291
291
|
function isDurable(vref) {
|
|
292
292
|
const { type, id, virtual, durable, allocatedByVat } = parseVatSlot(vref);
|
|
293
|
-
if (
|
|
293
|
+
if (type === 'promise') {
|
|
294
|
+
// promises are not durable even if `relaxDurabilityRules === true`
|
|
295
|
+
return false;
|
|
296
|
+
} else if (relaxDurabilityRules) {
|
|
294
297
|
// we'll pretend an object is durable if running with relaxed rules
|
|
295
298
|
return true;
|
|
296
299
|
} else if (type === 'device') {
|
|
@@ -497,26 +500,51 @@ export function makeVirtualReferenceManager(
|
|
|
497
500
|
}
|
|
498
501
|
|
|
499
502
|
/**
|
|
500
|
-
* A vref is "recognizable" when it is used as the key of a weak
|
|
501
|
-
*
|
|
502
|
-
*
|
|
503
|
-
*
|
|
503
|
+
* A vref is "recognizable" when it is used as the key of a weak
|
|
504
|
+
* collection, like a virtual/durable WeakMapStore or WeakSetStore,
|
|
505
|
+
* or the ephemeral voAwareWeakMap/Set that we impose upon userspace
|
|
506
|
+
* as "WeakMap/WeakSet". The collection can be used to query whether
|
|
507
|
+
* a future specimen matches the original or not, without holding
|
|
508
|
+
* onto the original.
|
|
509
|
+
*
|
|
510
|
+
* We need "recognition records" to map from the vref to the
|
|
511
|
+
* collection that can recognize it. When the vref is retired, we
|
|
512
|
+
* use the record to find all the collections from which we need to
|
|
513
|
+
* delete entries, so we can release the matching values. This might
|
|
514
|
+
* happen because the vref was for a Presence and the kernel just
|
|
515
|
+
* told us the upstream vat has deleted it (dispatch.retireImports),
|
|
516
|
+
* or because it was for a locally-managed object (an ephemeral
|
|
517
|
+
* Remotable or a virtual/durable Representative) and we decided to
|
|
518
|
+
* delete it.
|
|
519
|
+
*
|
|
520
|
+
* The virtual/durable collections track their "recognition records"
|
|
521
|
+
* in the vatstore, in keys like "vom.ir.${vref}|${collectionID}".
|
|
522
|
+
* These records do not contribute to our RAM usage.
|
|
523
|
+
*
|
|
524
|
+
* voAwareWeakMap and voAwareWeakSet store their recognition records
|
|
525
|
+
* in RAM, using this Map named 'vrefRecognizers'. Each key is a
|
|
526
|
+
* vref, and the value is a Set of recognizers. Each recognizer is
|
|
527
|
+
* the internal 'virtualObjectMap' in which the collection maps from
|
|
528
|
+
* vref to value. These in-RAM collections only use virtualObjectMap
|
|
529
|
+
* to track Presence-style (imports) and Representative-style
|
|
530
|
+
* (virtual/durable) vrefs: any Remotable-style keys are stored in
|
|
531
|
+
* the collection's internal (real) WeakMap under the Remotable
|
|
532
|
+
* object itself (because the engine handles the bookkeeping, and
|
|
533
|
+
* there is no virtual data in the value that we need to clean up at
|
|
534
|
+
* deletion time).
|
|
504
535
|
*
|
|
505
|
-
*
|
|
506
|
-
*
|
|
507
|
-
*
|
|
508
|
-
*
|
|
509
|
-
* participate: they are keyed by the actual Remotable object, not
|
|
510
|
-
* its vref). The collections are either a VirtualObjectAwareWeakMap
|
|
511
|
-
* or a VirtualObjectAwareWeakSet. We remove the entry when the key
|
|
512
|
-
* is removed from the collection, and when the entire collection is
|
|
513
|
-
* deleted.
|
|
536
|
+
* Each voAwareWeakMap/Set must have a distinct recognizer, so we
|
|
537
|
+
* can remove the key from the right ones. The recognizer is held
|
|
538
|
+
* strongly by the recognition record, so it must not be the
|
|
539
|
+
* voAwareWeakMap/Set itself (which would inhibit GC).
|
|
514
540
|
*
|
|
515
|
-
*
|
|
516
|
-
*
|
|
517
|
-
*
|
|
518
|
-
*
|
|
519
|
-
*
|
|
541
|
+
* When an individual entry is deleted from the weak collection, we
|
|
542
|
+
* must also delete the recognition record. When the collection
|
|
543
|
+
* itself is deleted (i.e. because nothing was referencing it), we
|
|
544
|
+
* must both delete all recognition records and also notify the
|
|
545
|
+
* kernel about any Presence-style vrefs that we can no longer
|
|
546
|
+
* recognize (syscall.retireImports). The kernel doesn't care about
|
|
547
|
+
* Remotable- or Representative- style vrefs, only the imports.
|
|
520
548
|
*
|
|
521
549
|
* TODO: all the "recognizers" in principle could be, and probably should be,
|
|
522
550
|
* reduced to deleter functions. However, since the VirtualObjectAware
|
|
@@ -532,14 +560,24 @@ export function makeVirtualReferenceManager(
|
|
|
532
560
|
/** @type {Map<string, Set<Recognizer>>} */
|
|
533
561
|
const vrefRecognizers = new Map();
|
|
534
562
|
|
|
563
|
+
/**
|
|
564
|
+
* @param {*} value The vref-bearing object used as the collection key
|
|
565
|
+
* @param {string|Recognizer} recognizer The collectionID or virtualObjectMap for the collection
|
|
566
|
+
* @param {boolean} [recognizerIsVirtual] true for virtual/durable Stores, false for voAwareWeakMap/Set
|
|
567
|
+
*/
|
|
535
568
|
function addRecognizableValue(value, recognizer, recognizerIsVirtual) {
|
|
536
569
|
const vref = getSlotForVal(value);
|
|
537
570
|
if (vref) {
|
|
538
571
|
const { type, allocatedByVat, virtual, durable } = parseVatSlot(vref);
|
|
539
|
-
if (type === 'object'
|
|
572
|
+
if (type === 'object') {
|
|
573
|
+
// recognizerSet (voAwareWeakMap/Set) doesn't track Remotables
|
|
574
|
+
const notRemotable = !allocatedByVat || virtual || durable;
|
|
575
|
+
|
|
540
576
|
if (recognizerIsVirtual) {
|
|
577
|
+
assert.typeof(recognizer, 'string');
|
|
541
578
|
syscall.vatstoreSet(`vom.ir.${vref}|${recognizer}`, '1');
|
|
542
|
-
} else {
|
|
579
|
+
} else if (notRemotable) {
|
|
580
|
+
assert.typeof(recognizer, 'object');
|
|
543
581
|
let recognizerSet = vrefRecognizers.get(vref);
|
|
544
582
|
if (!recognizerSet) {
|
|
545
583
|
recognizerSet = new Set();
|
|
@@ -551,18 +589,33 @@ export function makeVirtualReferenceManager(
|
|
|
551
589
|
}
|
|
552
590
|
}
|
|
553
591
|
|
|
592
|
+
/**
|
|
593
|
+
* @param {string} vref The vref or the object used as the collection key
|
|
594
|
+
* @param {string|Recognizer} recognizer The collectionID or virtualObjectMap for the collection
|
|
595
|
+
* @param {boolean} [recognizerIsVirtual] true for virtual/durable Stores, false for voAwareWeakMap/Set
|
|
596
|
+
*/
|
|
554
597
|
function removeRecognizableVref(vref, recognizer, recognizerIsVirtual) {
|
|
555
598
|
const { type, allocatedByVat, virtual, durable } = parseVatSlot(vref);
|
|
556
|
-
if (type === 'object'
|
|
599
|
+
if (type === 'object') {
|
|
600
|
+
// addToPossiblyDeadSet only needs Presence-style vrefs
|
|
601
|
+
const isPresence = !allocatedByVat;
|
|
602
|
+
// recognizerSet (voAwareWeakMap/Set) doesn't track Remotables
|
|
603
|
+
const notRemotable = !allocatedByVat || virtual || durable;
|
|
604
|
+
|
|
557
605
|
if (recognizerIsVirtual) {
|
|
606
|
+
assert.typeof(recognizer, 'string');
|
|
558
607
|
syscall.vatstoreDelete(`vom.ir.${vref}|${recognizer}`);
|
|
559
|
-
|
|
608
|
+
if (isPresence) {
|
|
609
|
+
addToPossiblyRetiredSet(vref);
|
|
610
|
+
}
|
|
611
|
+
} else if (notRemotable) {
|
|
612
|
+
assert.typeof(recognizer, 'object');
|
|
560
613
|
const recognizerSet = vrefRecognizers.get(vref);
|
|
561
614
|
assert(recognizerSet && recognizerSet.has(recognizer));
|
|
562
615
|
recognizerSet.delete(recognizer);
|
|
563
616
|
if (recognizerSet.size === 0) {
|
|
564
617
|
vrefRecognizers.delete(vref);
|
|
565
|
-
if (
|
|
618
|
+
if (isPresence) {
|
|
566
619
|
addToPossiblyRetiredSet(vref);
|
|
567
620
|
}
|
|
568
621
|
}
|
|
@@ -570,6 +623,11 @@ export function makeVirtualReferenceManager(
|
|
|
570
623
|
}
|
|
571
624
|
}
|
|
572
625
|
|
|
626
|
+
/**
|
|
627
|
+
* @param {*} value The vref-bearing object used as the collection key
|
|
628
|
+
* @param {string|Recognizer} recognizer The collectionID or virtualObjectMap for the collection
|
|
629
|
+
* @param {boolean} [recognizerIsVirtual] true for virtual/durable Stores, false for voAwareWeakMap/Set
|
|
630
|
+
*/
|
|
573
631
|
function removeRecognizableValue(value, recognizer, recognizerIsVirtual) {
|
|
574
632
|
const vref = getSlotForVal(value);
|
|
575
633
|
if (vref) {
|
package/src/watchedPromises.js
CHANGED
|
@@ -2,9 +2,8 @@
|
|
|
2
2
|
// no-lonely-if is a stupid rule that really should be disabled globally
|
|
3
3
|
/* eslint-disable no-lonely-if */
|
|
4
4
|
|
|
5
|
-
import { Fail } from '@endo/errors';
|
|
5
|
+
import { Fail, assert } from '@endo/errors';
|
|
6
6
|
import { E } from '@endo/eventual-send';
|
|
7
|
-
import { assert } from '@agoric/assert';
|
|
8
7
|
import { initEmpty, M } from '@agoric/store';
|
|
9
8
|
import { parseVatSlot } from './parseVatSlots.js';
|
|
10
9
|
|
|
@@ -140,6 +139,12 @@ export function makeWatchedPromiseManager({
|
|
|
140
139
|
*/
|
|
141
140
|
function loadWatchedPromiseTable(revivePromise) {
|
|
142
141
|
for (const vpid of watchedPromiseTable.keys()) {
|
|
142
|
+
if (promiseRegistrations.has(vpid)) {
|
|
143
|
+
// We're only interested in reconnecting the promises from the previous
|
|
144
|
+
// incarnation. Any promise watched during buildRootObject would have
|
|
145
|
+
// already created a registration.
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
143
148
|
const p = revivePromise(vpid);
|
|
144
149
|
promiseRegistrations.init(vpid, p);
|
|
145
150
|
pseudoThen(p, vpid);
|