Skip to content

Commit d8e046c

Browse files
natebiggsCommit Queue
authored andcommitted
[dart2wasm] Add wrapper functions to settle type differences between main module and dynamic module dispatch tables.
Due to new overrides being introduced, the expected type of a function in the dispatch table can change between the main module and dynamic module. For functions imported from the main module into the dynamic module and included in the dynamic module's dispatch table, this can lead to type errors. This change introduces a wrapper that casts any differing types to the type expected by the dyanmic module and includes the wrapper in the dispatch table instead. Only creates the wrapper when the function types differ. The wrapper will only contains casts for the parameters (or return type) that differ, the others will be passed through without a cast. Change-Id: I7265693adcd5d8f831b36ed1c8960fbf363b908c Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/422345 Reviewed-by: Ömer Ağacan <[email protected]> Reviewed-by: Martin Kustermann <[email protected]>
1 parent 6750538 commit d8e046c

File tree

1 file changed

+64
-0
lines changed

1 file changed

+64
-0
lines changed

pkg/dart2wasm/lib/dispatch_table.dart

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -765,6 +765,7 @@ class DispatchTable {
765765
}
766766

767767
void output() {
768+
final Map<w.BaseFunction, w.BaseFunction> wrappedDynamicModuleImports = {};
768769
for (int i = 0; i < _table.length; i++) {
769770
Reference? target = _table[i];
770771
if (target != null) {
@@ -780,6 +781,14 @@ class DispatchTable {
780781
if (fun != null) {
781782
final targetModule = fun.enclosingModule;
782783
if (targetModule == _definedWasmTable.enclosingModule) {
784+
if (isDynamicModuleTable &&
785+
targetModule == translator.dynamicModule &&
786+
fun is w.ImportedFunction) {
787+
// Functions imported into dynamic modules may need to be wrapped
788+
// to match the updated dispatch table signature.
789+
fun = wrappedDynamicModuleImports[fun] ??=
790+
_wrapDynamicModuleFunction(target, fun);
791+
}
783792
_definedWasmTable.setElement(i, fun);
784793
} else {
785794
// This will generate the imported table if it doesn't already
@@ -791,6 +800,61 @@ class DispatchTable {
791800
}
792801
}
793802
}
803+
804+
w.BaseFunction _wrapDynamicModuleFunction(
805+
Reference target, w.BaseFunction importedFunction) {
806+
final mainSelector =
807+
translator.dynamicMainModuleDispatchTable!.selectorForTarget(target);
808+
final mainSignature = translator.signatureForMainModule(target);
809+
final localSelector = translator.dispatchTable.selectorForTarget(target);
810+
final localSignature = localSelector.signature;
811+
812+
// If the type is the same in both the main module and the dynamic module,
813+
// use the imported function itself.
814+
if (mainSignature.isStructurallyEqualTo(localSignature)) {
815+
return importedFunction;
816+
}
817+
818+
// Otherwise we need to create a wrapper to handle the differing types.
819+
// The local signature should include all the parameters necessary to call
820+
// the target in main since the local signature must include the target
821+
// member itself and any other members in the main module's selector range.
822+
final wrapper = translator.dynamicModule.functions
823+
.define(localSignature, '${target.asMember} wrapper');
824+
825+
final ib = wrapper.body;
826+
827+
assert(mainSignature.inputs.length <= localSignature.inputs.length);
828+
829+
final mainModulePreParamCount =
830+
(mainSelector.paramInfo.takesContextOrReceiver ? 1 : 0) +
831+
mainSelector.paramInfo.typeParamCount;
832+
final mainModuleBeforeNamedCount =
833+
mainModulePreParamCount + mainSelector.paramInfo.positional.length;
834+
int mainIndex = 0;
835+
for (; mainIndex < mainModuleBeforeNamedCount; mainIndex++) {
836+
final local = ib.locals[mainIndex];
837+
ib.local_get(local);
838+
translator.convertType(ib, local.type, mainSignature.inputs[mainIndex]);
839+
}
840+
841+
final localPreParamCount =
842+
(localSelector.paramInfo.takesContextOrReceiver ? 1 : 0) +
843+
localSelector.paramInfo.typeParamCount;
844+
845+
for (final name in mainSelector.paramInfo.names) {
846+
final namedIndex = localSelector.paramInfo.nameIndex[name]!;
847+
final local = ib.locals[localPreParamCount + namedIndex];
848+
ib.local_get(local);
849+
translator.convertType(ib, local.type, mainSignature.inputs[mainIndex++]);
850+
}
851+
ib.call(importedFunction);
852+
translator.convertType(
853+
ib, mainSignature.outputs.single, localSignature.outputs.single);
854+
ib.end();
855+
856+
return wrapper;
857+
}
794858
}
795859

796860
bool _isUsedViaDispatchTableCall(SelectorInfo selector) {

0 commit comments

Comments
 (0)