Skip to content

Commit 59499d3

Browse files
natebiggsCommit Queue
authored andcommitted
[dart2wasm] Add support for declaring functions as module elements.
Allows functions to be referenced in a constant context (via ref_func) without needing to bind the function to a global. Uses format 3 supported by the element section: https://webassembly.github.io/gc/core/binary/modules.html#element-section Change-Id: Ifb68800c480b14acfa3432eae80396be4e9c8a6e Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/400900 Commit-Queue: Nate Biggs <[email protected]> Reviewed-by: Martin Kustermann <[email protected]>
1 parent 96fbc26 commit 59499d3

File tree

4 files changed

+51
-11
lines changed

4 files changed

+51
-11
lines changed

pkg/wasm_builder/lib/src/builder/functions.dart

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ class FunctionsBuilder with Builder<ir.Functions> {
1313
final ModuleBuilder _module;
1414
final _functionBuilders = <FunctionBuilder>[];
1515
final _importedFunctions = <ir.ImportedFunction>[];
16+
final _declaredFunctions = <ir.BaseFunction>{};
1617
int _nameCount = 0;
1718
ir.BaseFunction? _start;
1819

@@ -61,10 +62,17 @@ class FunctionsBuilder with Builder<ir.Functions> {
6162
return function;
6263
}
6364

65+
/// Declare [function] as a module element so it can be used in a constant
66+
/// context.
67+
void declare(ir.BaseFunction function) {
68+
_declaredFunctions.add(function);
69+
}
70+
6471
@override
6572
ir.Functions forceBuild() {
6673
final built = finalizeImportsAndBuilders<ir.DefinedFunction>(
6774
_importedFunctions, _functionBuilders);
68-
return ir.Functions(_start, _importedFunctions, built, _nameCount);
75+
return ir.Functions(
76+
_start, _importedFunctions, built, [..._declaredFunctions], _nameCount);
6977
}
7078
}

pkg/wasm_builder/lib/src/ir/functions.dart

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,12 @@ class Functions {
1919
/// Defined functions.
2020
final List<DefinedFunction> defined;
2121

22+
/// Declared functions.
23+
final List<BaseFunction> declared;
24+
2225
/// Named functions.
2326
final int namedCount;
2427

25-
Functions(this.start, this.imported, this.defined, this.namedCount);
28+
Functions(
29+
this.start, this.imported, this.defined, this.declared, this.namedCount);
2630
}

pkg/wasm_builder/lib/src/ir/module.dart

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,9 @@ class Module implements Serializable {
5151
GlobalSection(globals.defined, watchPoints).serialize(s);
5252
ExportSection(exports.exported, watchPoints).serialize(s);
5353
StartSection(functions.start, watchPoints).serialize(s);
54-
ElementSection(tables.defined, tables.imported, watchPoints).serialize(s);
54+
ElementSection(
55+
tables.defined, tables.imported, functions.declared, watchPoints)
56+
.serialize(s);
5557
DataCountSection(dataSegments.defined, watchPoints).serialize(s);
5658
CodeSection(functions.defined, watchPoints).serialize(s);
5759
DataSection(dataSegments.defined, watchPoints).serialize(s);

pkg/wasm_builder/lib/src/serialize/sections.dart

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -216,12 +216,14 @@ class StartSection extends Section {
216216
}
217217
}
218218

219-
class _Element implements Serializable {
219+
sealed class _Element implements Serializable {}
220+
221+
class _TableElement implements _Element {
220222
final ir.Table table;
221223
final int startIndex;
222224
final List<ir.BaseFunction> entries = [];
223225

224-
_Element(this.table, this.startIndex);
226+
_TableElement(this.table, this.startIndex);
225227

226228
@override
227229
void serialize(Serializer s) {
@@ -250,32 +252,53 @@ class _Element implements Serializable {
250252
}
251253
}
252254

255+
class _DeclaredElement implements _Element {
256+
final List<ir.BaseFunction> entries;
257+
258+
_DeclaredElement(this.entries);
259+
260+
@override
261+
void serialize(Serializer s) {
262+
if (entries.isEmpty) return;
263+
s.writeByte(0x03);
264+
s.writeByte(0x00);
265+
266+
s.writeUnsigned(entries.length);
267+
for (final entry in entries) {
268+
s.writeUnsigned(entry.index);
269+
}
270+
}
271+
}
272+
253273
class ElementSection extends Section {
254274
final List<ir.DefinedTable> definedTables;
255275
final List<ir.ImportedTable> importedTables;
276+
final List<ir.BaseFunction> declaredFunctions;
256277

257-
ElementSection(this.definedTables, this.importedTables, super.watchPoints);
278+
ElementSection(this.definedTables, this.importedTables,
279+
this.declaredFunctions, super.watchPoints);
258280

259281
@override
260282
int get id => 9;
261283

262284
@override
263285
bool get isNotEmpty =>
264286
definedTables.any((table) => table.elements.any((e) => e != null)) ||
265-
importedTables.any((table) => table.setElements.isNotEmpty);
287+
importedTables.any((table) => table.setElements.isNotEmpty) ||
288+
declaredFunctions.isNotEmpty;
266289

267290
@override
268291
void serializeContents(Serializer s) {
269292
// Group nonempty element entries into contiguous stretches and serialize
270293
// each stretch as an element.
271294
List<_Element> elements = [];
272295
for (final table in definedTables) {
273-
_Element? current;
296+
_TableElement? current;
274297
for (int i = 0; i < table.elements.length; i++) {
275298
ir.BaseFunction? function = table.elements[i];
276299
if (function != null) {
277300
if (current == null) {
278-
current = _Element(table, i);
301+
current = _TableElement(table, i);
279302
elements.add(current);
280303
}
281304
current.entries.add(function);
@@ -288,19 +311,22 @@ class ElementSection extends Section {
288311
final entries = [...table.setElements.entries]
289312
..sort((a, b) => a.key.compareTo(b.key));
290313

291-
_Element? current;
314+
_TableElement? current;
292315
int lastIndex = -2;
293316
for (final entry in entries) {
294317
final index = entry.key;
295318
final function = entry.value;
296319
if (index != lastIndex + 1) {
297-
current = _Element(table, index);
320+
current = _TableElement(table, index);
298321
elements.add(current);
299322
}
300323
current!.entries.add(function);
301324
lastIndex = index;
302325
}
303326
}
327+
for (final func in declaredFunctions) {
328+
elements.add(_DeclaredElement([func]));
329+
}
304330
s.writeList(elements);
305331
}
306332
}

0 commit comments

Comments
 (0)