@metamask/ocap-kernel
Version:
OCap kernel core components
1 lines • 9.48 kB
Source Map (JSON)
{"version":3,"file":"garbage-collection.mjs","sourceRoot":"","sources":["../../src/services/garbage-collection.ts"],"names":[],"mappings":"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","sourcesContent":["import type { KernelStore } from '../store/index.ts';\nimport { insistKernelType } from '../store/utils/kernel-slots.ts';\nimport type {\n GCAction,\n GCActionType,\n KRef,\n RunQueueItem,\n VatId,\n} from '../types.ts';\nimport {\n actionTypePriorities,\n insistGCActionType,\n insistVatId,\n queueTypeFromActionType,\n} from '../types.ts';\nimport { assert } from '../utils/assert.ts';\n\n/**\n * Parsed representation of a GC action.\n */\ntype ParsedGCAction = Readonly<{\n vatId: VatId;\n type: GCActionType;\n kref: KRef;\n}>;\n\n/**\n * Parse a GC action string into a vat id, type, and kref.\n *\n * @param action - The GC action string to parse.\n * @returns The parsed GC action.\n */\nfunction parseAction(action: GCAction): ParsedGCAction {\n const [vatId, type, kref] = action.split(' ');\n insistVatId(vatId);\n insistGCActionType(type);\n insistKernelType('object', kref);\n return harden({ vatId, type, kref });\n}\n\n/**\n * Determines if a GC action should be processed based on current system state.\n *\n * @param storage - The kernel storage.\n * @param vatId - The vat id of the vat that owns the kref.\n * @param type - The type of GC action.\n * @param kref - The kref of the object in question.\n * @returns True if the action should be processed, false otherwise.\n */\nfunction shouldProcessAction(\n storage: KernelStore,\n vatId: VatId,\n type: GCActionType,\n kref: KRef,\n): boolean {\n const hasCList = storage.hasCListEntry(vatId, kref);\n const isReachable = hasCList\n ? storage.getReachableFlag(vatId, kref)\n : undefined;\n const exists = storage.kernelRefExists(kref);\n const { reachable, recognizable } = exists\n ? storage.getObjectRefCount(kref)\n : { reachable: 0, recognizable: 0 };\n\n switch (type) {\n case 'dropExport':\n return exists && reachable === 0 && hasCList && isReachable === true;\n\n case 'retireExport':\n return exists && reachable === 0 && recognizable === 0 && hasCList;\n\n case 'retireImport':\n return hasCList;\n\n default:\n return false;\n }\n}\n\n/**\n * Filters and processes a group of GC actions for a specific vat and action type.\n *\n * @param storage - The kernel storage.\n * @param vatId - The vat id of the vat that owns the krefs.\n * @param actions - The set of GC actions to process.\n * @param allActionsSet - The complete set of GC actions.\n * @returns Object containing the krefs to process and whether the action set was updated.\n */\nfunction filterActionsForProcessing(\n storage: KernelStore,\n vatId: VatId,\n actions: Set<GCAction>,\n allActionsSet: Set<GCAction>,\n): { krefs: KRef[]; actionSetUpdated: boolean } {\n const krefs: KRef[] = [];\n let actionSetUpdated = false;\n\n for (const action of actions) {\n const { type, kref } = parseAction(action);\n if (shouldProcessAction(storage, vatId, type, kref)) {\n krefs.push(kref);\n }\n allActionsSet.delete(action);\n actionSetUpdated = true;\n }\n\n return harden({ krefs, actionSetUpdated });\n}\n\n/**\n * Process the set of GC actions.\n *\n * @param storage - The kernel storage.\n * @returns The next action to process, or undefined if there are no actions to process.\n */\nexport function processGCActionSet(\n storage: KernelStore,\n): RunQueueItem | undefined {\n const allActionsSet = storage.getGCActions();\n let actionSetUpdated = false;\n\n // Group actions by vat and type\n const actionsByVat = new Map<VatId, Map<GCActionType, Set<GCAction>>>();\n\n for (const action of allActionsSet) {\n const { vatId, type } = parseAction(action);\n\n if (!actionsByVat.has(vatId)) {\n actionsByVat.set(vatId, new Map());\n }\n\n const actionsForVatByType = actionsByVat.get(vatId);\n assert(actionsForVatByType !== undefined, `No actions for vat: ${vatId}`);\n\n if (!actionsForVatByType.has(type)) {\n actionsForVatByType.set(type, new Set());\n }\n\n const actions = actionsForVatByType.get(type);\n assert(actions !== undefined, `No actions for type: ${type}`);\n actions.add(action);\n }\n\n // Process actions in priority order\n const vatIds = Array.from(actionsByVat.keys()).sort();\n\n for (const vatId of vatIds) {\n const actionsForVatByType = actionsByVat.get(vatId);\n assert(actionsForVatByType !== undefined, `No actions for vat: ${vatId}`);\n\n // Find the highest-priority type of work to do within this vat\n for (const type of actionTypePriorities) {\n if (actionsForVatByType.has(type)) {\n const actions = actionsForVatByType.get(type);\n assert(actions !== undefined, `No actions for type: ${type}`);\n const { krefs, actionSetUpdated: updated } = filterActionsForProcessing(\n storage,\n vatId,\n actions,\n allActionsSet,\n );\n\n actionSetUpdated = actionSetUpdated || updated;\n\n if (krefs.length > 0) {\n // We found actions to process\n krefs.sort();\n\n // Update the durable set before returning\n storage.setGCActions(allActionsSet);\n\n const queueType = queueTypeFromActionType.get(type);\n assert(queueType !== undefined, `Unknown action type: ${type}`);\n\n return harden({ type: queueType, vatId, krefs });\n }\n }\n }\n }\n\n if (actionSetUpdated) {\n // Remove negated items from the durable set\n storage.setGCActions(allActionsSet);\n }\n\n // No GC work to do\n return undefined;\n}\n\nharden(processGCActionSet);\n"]}