Skip to content

Commit

Permalink
update docstring and some types
Browse files Browse the repository at this point in the history
  • Loading branch information
warner committed Aug 27, 2024
1 parent 5c551bb commit 114a64c
Showing 1 changed file with 63 additions and 18 deletions.
81 changes: 63 additions & 18 deletions packages/swingset-liveslots/src/virtualReferences.js
Original file line number Diff line number Diff line change
Expand Up @@ -500,26 +500,52 @@ export function makeVirtualReferenceManager(
}

/**
* A vref is "recognizable" when it is used as the key of a weak Map
* or Set: that Map/Set can be used to query whether a future
* specimen matches the original or not, without holding onto the
* original.
* A vref is "recognizable" when it is used as the key of a weak
* collection, like a virtual/durable WeakMapStore or WeakSetStore,
* or the ephemeral voAwareWeakMap/Set that we impose upon userspace
* as "WeakMap/WeakSet". The collection can be used to query whether
* a future specimen matches the original or not, without holding
* onto the original.
*
* This 'vrefRecognizers' is a Map from those vrefs to the set of
* recognizing weak collections, for virtual keys and non-virtual
* collections. Specifically, the vrefs correspond to imported
* Presences or virtual-object Representatives (Remotables do not
* participate: they are keyed by the actual Remotable object, not
* its vref). The collections are either a VirtualObjectAwareWeakMap
* or a VirtualObjectAwareWeakSet. We remove the entry when the key
* is removed from the collection, and when the entire collection is
* deleted.
* We need "recognition records" to map from the vref to the
* collection that can recognize it. When the vref is retired, we
* use the record to find all the collections from which we need to
* delete entries, so we can release the matching values. This might
* happen because the vref was for a Presence and the kernel just
* told us the upstream vat has deleted it (dispatch.retireImports),
* or because it was for a locally-managed object (an ephemeral
* Remotable or a virtual/durable Representative) and we decided to
* delete it.
*
* It is critical that each collection have exactly one recognizer that is
* unique to that collection, because the recognizers themselves will be
* tracked by their object identities, but the recognizer cannot be the
* collection itself else it would prevent the collection from being garbage
* collected.
* The virtual/durable collections track their "recognition records"
* in the vatstore, in keys like "vom.ir.${vref}|${collectionID}".
* These records do not contribute to our RAM usage.
*
* voAwareWeakMap and voAwareWeakSet store their recognition records
* in RAM, using this Map named 'vrefRecognizers'. Each key is a
* vref, and the value is a Set of recognizers. Each recognizer is
* the internal 'virtualObjectMap' in which the collection maps from
* vref to value. These in-RAM collections only use virtualObjectMap
* to track Presence-style (imports) and Representative-style
* (virtual/durable) vrefs: any Remotable-style keys are stored in
* the collection's internal (real) WeakMap under the Remotable
* object itself (because the engine handles the bookkeeping, and
* there is no virtual data in the value that we need to clean up at
* deletion time).
*
* It is critical that each collection have exactly one recognizer
* that is unique to that collection, because the recognizers
* themselves will be tracked by their object identities, but the
* recognizer cannot be the collection itself else it would prevent
* the collection from being garbage collected.
*
* When an individual entry is deleted from the weak collection, we
* must also delete the recognition record. When the collection
* itself is deleted (i.e. because nothing was referencing it), we
* must both delete all recognition records and also notify the
* kernel about any Presence-style vrefs that we can no longer
* recognize (syscall.retireImports). The kernel doesn't care about
* Remotable- or Representative- style vrefs, only the imports.
*
* TODO: all the "recognizers" in principle could be, and probably should be,
* reduced to deleter functions. However, since the VirtualObjectAware
Expand All @@ -535,6 +561,11 @@ export function makeVirtualReferenceManager(
/** @type {Map<string, Set<Recognizer>>} */
const vrefRecognizers = new Map();

/**
* @param {*} value The vref-bearing object used as the collection key
* @param {string|Recognizer} recognizer The collectionID or virtualObjectMap for the collection
* @param {boolean} [recognizerIsVirtual] true for virtual/durable Stores, false for voAwareWeakMap/Set
*/
function addRecognizableValue(value, recognizer, recognizerIsVirtual) {
const vref = getSlotForVal(value);
if (vref) {
Expand All @@ -544,8 +575,10 @@ export function makeVirtualReferenceManager(
const notRemotable = !allocatedByVat || virtual || durable;

if (recognizerIsVirtual) {
assert.typeof(recognizer, 'string');
syscall.vatstoreSet(`vom.ir.${vref}|${recognizer}`, '1');
} else if (notRemotable) {
assert.typeof(recognizer, 'object');
let recognizerSet = vrefRecognizers.get(vref);
if (!recognizerSet) {
recognizerSet = new Set();
Expand All @@ -557,6 +590,11 @@ export function makeVirtualReferenceManager(
}
}

/**
* @param {string} vref The vref or the object used as the collection key
* @param {string|Recognizer} recognizer The collectionID or virtualObjectMap for the collection
* @param {boolean} [recognizerIsVirtual] true for virtual/durable Stores, false for voAwareWeakMap/Set
*/
function removeRecognizableVref(vref, recognizer, recognizerIsVirtual) {
const { type, allocatedByVat, virtual, durable } = parseVatSlot(vref);
if (type === 'object') {
Expand All @@ -566,11 +604,13 @@ export function makeVirtualReferenceManager(
const notRemotable = !allocatedByVat || virtual || durable;

if (recognizerIsVirtual) {
assert.typeof(recognizer, 'string');
syscall.vatstoreDelete(`vom.ir.${vref}|${recognizer}`);
if (isPresence) {
addToPossiblyRetiredSet(vref);
}
} else if (notRemotable) {
assert.typeof(recognizer, 'object');
const recognizerSet = vrefRecognizers.get(vref);
assert(recognizerSet && recognizerSet.has(recognizer));
recognizerSet.delete(recognizer);
Expand All @@ -584,6 +624,11 @@ export function makeVirtualReferenceManager(
}
}

/**
* @param {*} value The vref-bearing object used as the collection key
* @param {string|Recognizer} recognizer The collectionID or virtualObjectMap for the collection
* @param {boolean} [recognizerIsVirtual] true for virtual/durable Stores, false for voAwareWeakMap/Set
*/
function removeRecognizableValue(value, recognizer, recognizerIsVirtual) {
const vref = getSlotForVal(value);
if (vref) {
Expand Down

0 comments on commit 114a64c

Please sign in to comment.