| // Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file | |
| // for details. All rights reserved. Use of this source code is governed by a | |
| // BSD-style license that can be found in the LICENSE file. | |
| import 'package:wasm_builder/wasm_builder.dart' as w; | |
| import 'translator.dart'; | |
| /// Builds a table of functions that can be used across modules. | |
| class CrossModuleFunctionTable { | |
| static const w.HeapType _tableHeapType = w.HeapType.func; | |
| final Translator translator; | |
| /// Contents of wasm table. | |
| final Map<w.BaseFunction, int> _table = {}; | |
| late final w.Table _definedWasmTable = translator.mainModule.tables.define( | |
| w.RefType(_tableHeapType, nullable: true), | |
| _table.length, | |
| ); | |
| final WasmTableImporter _importedWasmTables; | |
| CrossModuleFunctionTable(this.translator) | |
| : _importedWasmTables = WasmTableImporter( | |
| translator, | |
| 'cross-module-funcs-', | |
| ); | |
| /// Gets the wasm table used to reference this table in [module]. | |
| /// | |
| /// This can either be the table definition itself or an import of it. Imports | |
| /// the table into [module] if it is not imported yet. | |
| w.Table getWasmTable(w.ModuleBuilder module) { | |
| return _importedWasmTables.get(_definedWasmTable, module); | |
| } | |
| /// Returns the index for [function] in the table allocating one if necessary. | |
| int indexForFunction(w.BaseFunction function) { | |
| assert(function.type.isStructuralSubtypeOf(_tableHeapType)); | |
| return _table[function] ??= _table.length; | |
| } | |
| void output() { | |
| final importedTables = _importedWasmTables; | |
| _table.forEach((fun, index) { | |
| final targetModule = translator.moduleToBuilder[fun.enclosingModule]!; | |
| if (translator.isMainModule(targetModule)) { | |
| translator.mainModule.elements | |
| .activeFunctionSegmentBuilderFor(_definedWasmTable) | |
| .setFunctionAt(index, fun); | |
| } else { | |
| // This will generate the imported table if it doesn't already exist. | |
| final importedTable = getWasmTable(targetModule) as w.ImportedTable; | |
| targetModule.elements | |
| .activeFunctionSegmentBuilderFor(importedTable) | |
| .setFunctionAt(index, fun); | |
| } | |
| }); | |
| _definedWasmTable.minSize = _table.length; | |
| for (final table in importedTables.imports) { | |
| table.minSize = _table.length; | |
| } | |
| } | |
| } |