Path: blob/main/core/dylink/src/function-table.ts
1396 views
import debug from "debug";1import { nonzeroPositions } from "./util";23const log = debug("dylink:function-table");45const GROW_THRESH = 50;67export default class FunctionTable {8public readonly table: WebAssembly.Table;910// indexes into the function table that are null, but11// maybe less than nextTablePos.12private availableTableIndexes: Set<number> = new Set<number>();1314// next available table position at the very end. Use this if15// availableTableIndexes is empty.16private nextTablePos: number = 0;1718constructor(table: WebAssembly.Table) {19log("constructor");20this.table = table;21}2223updateAfterImport(): void {24this.nextTablePos = Math.max(0, ...nonzeroPositions(this.table)) + 1;25}2627prepareForImport(tableSize: number): void {28this.nextTablePos += tableSize;29if (this.table.length <= this.nextTablePos + GROW_THRESH) {30this.table.grow(this.nextTablePos + GROW_THRESH - this.table.length);31}32}3334getNextTablePos(): number {35return this.nextTablePos;36}3738// gets the next available index, then marks it39// as no longer available, so it can be used.40private getNextAvailableIndex(): number {41for (const index of this.availableTableIndexes) {42this.availableTableIndexes.delete(index);43log("getNextAvailableIndex: from availableTableIndexes", index);4445return index;46}47const index = this.nextTablePos;48log("getNextAvailableIndex: from nextTablePos", index);49this.nextTablePos += 1;50if (this.table.length <= this.nextTablePos + GROW_THRESH) {51this.table.grow(this.nextTablePos + GROW_THRESH - this.table.length);52}53return index;54}5556setLater(): { index: number; set: (f: Function) => void } {57const index = this.getNextAvailableIndex();58return {59index,60set: (f) => {61this.set(f, index);62},63};64}6566set(f: Function, _index?: number): number {67const index = _index ?? this.getNextAvailableIndex();68if (this.table.get(index) != null) {69throw Error("BUG: trying to set a table index that is already set");70}71this.table.set(index, f);72return index;73}7475get(index: number): Function | null | undefined {76return this.table.get(index);77}7879delete(index: number): void {80this.table.set(index, null);81this.availableTableIndexes.add(index);82}83}848586