UNPKG

@metamask/ocap-kernel

Version:
128 lines 5.32 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.processGCActionSet = processGCActionSet; const kernel_slots_ts_1 = require("../store/utils/kernel-slots.cjs"); const types_ts_1 = require("../types.cjs"); const assert_ts_1 = require("../utils/assert.cjs"); /** * Parse a GC action string into a vat id, type, and kref. * * @param action - The GC action string to parse. * @returns The parsed GC action. */ function parseAction(action) { const [vatId, type, kref] = action.split(' '); (0, types_ts_1.insistVatId)(vatId); (0, types_ts_1.insistGCActionType)(type); (0, kernel_slots_ts_1.insistKernelType)('object', kref); return harden({ vatId, type, kref }); } /** * Determines if a GC action should be processed based on current system state. * * @param storage - The kernel storage. * @param vatId - The vat id of the vat that owns the kref. * @param type - The type of GC action. * @param kref - The kref of the object in question. * @returns True if the action should be processed, false otherwise. */ function shouldProcessAction(storage, vatId, type, kref) { const hasCList = storage.hasCListEntry(vatId, kref); const isReachable = hasCList ? storage.getReachableFlag(vatId, kref) : undefined; const exists = storage.kernelRefExists(kref); const { reachable, recognizable } = exists ? storage.getObjectRefCount(kref) : { reachable: 0, recognizable: 0 }; switch (type) { case 'dropExport': return exists && reachable === 0 && hasCList && isReachable === true; case 'retireExport': return exists && reachable === 0 && recognizable === 0 && hasCList; case 'retireImport': return hasCList; default: return false; } } /** * Filters and processes a group of GC actions for a specific vat and action type. * * @param storage - The kernel storage. * @param vatId - The vat id of the vat that owns the krefs. * @param actions - The set of GC actions to process. * @param allActionsSet - The complete set of GC actions. * @returns Object containing the krefs to process and whether the action set was updated. */ function filterActionsForProcessing(storage, vatId, actions, allActionsSet) { const krefs = []; let actionSetUpdated = false; for (const action of actions) { const { type, kref } = parseAction(action); if (shouldProcessAction(storage, vatId, type, kref)) { krefs.push(kref); } allActionsSet.delete(action); actionSetUpdated = true; } return harden({ krefs, actionSetUpdated }); } /** * Process the set of GC actions. * * @param storage - The kernel storage. * @returns The next action to process, or undefined if there are no actions to process. */ function processGCActionSet(storage) { const allActionsSet = storage.getGCActions(); let actionSetUpdated = false; // Group actions by vat and type const actionsByVat = new Map(); for (const action of allActionsSet) { const { vatId, type } = parseAction(action); if (!actionsByVat.has(vatId)) { actionsByVat.set(vatId, new Map()); } const actionsForVatByType = actionsByVat.get(vatId); (0, assert_ts_1.assert)(actionsForVatByType !== undefined, `No actions for vat: ${vatId}`); if (!actionsForVatByType.has(type)) { actionsForVatByType.set(type, new Set()); } const actions = actionsForVatByType.get(type); (0, assert_ts_1.assert)(actions !== undefined, `No actions for type: ${type}`); actions.add(action); } // Process actions in priority order const vatIds = Array.from(actionsByVat.keys()).sort(); for (const vatId of vatIds) { const actionsForVatByType = actionsByVat.get(vatId); (0, assert_ts_1.assert)(actionsForVatByType !== undefined, `No actions for vat: ${vatId}`); // Find the highest-priority type of work to do within this vat for (const type of types_ts_1.actionTypePriorities) { if (actionsForVatByType.has(type)) { const actions = actionsForVatByType.get(type); (0, assert_ts_1.assert)(actions !== undefined, `No actions for type: ${type}`); const { krefs, actionSetUpdated: updated } = filterActionsForProcessing(storage, vatId, actions, allActionsSet); actionSetUpdated = actionSetUpdated || updated; if (krefs.length > 0) { // We found actions to process krefs.sort(); // Update the durable set before returning storage.setGCActions(allActionsSet); const queueType = types_ts_1.queueTypeFromActionType.get(type); (0, assert_ts_1.assert)(queueType !== undefined, `Unknown action type: ${type}`); return harden({ type: queueType, vatId, krefs }); } } } } if (actionSetUpdated) { // Remove negated items from the durable set storage.setGCActions(allActionsSet); } // No GC work to do return undefined; } harden(processGCActionSet); //# sourceMappingURL=garbage-collection.cjs.map