Skip to content

Commit bc76743

Browse files
mkustermannCommit Queue
authored andcommitted
[dart2wasm] Move canonicalization of symbols to one place
Only in `Function.apply` we have the problem of determining the order of named parameters for calling the closure. In all other cases, the compiler can ensure the caller and callee agree on the order. There's one place where we determine this order. That place can also be used to swap out user-provided `new Symbol()`s that were passed to `Function.apply` with the canonicalized `const Symbol()` instances the compiler uses for the closure functions. Doing so allows us to use `identical()` for symbol comparisons everywhere else in the system. Change-Id: Ib9833e708ba197c8b9ef18ef4bf9e7a64bdf9a40 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/419201 Reviewed-by: Ömer Ağacan <[email protected]> Commit-Queue: Martin Kustermann <[email protected]>
1 parent e40980c commit bc76743

File tree

2 files changed

+62
-21
lines changed

2 files changed

+62
-21
lines changed

pkg/dart2wasm/lib/intrinsics.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1994,6 +1994,7 @@ class Intrinsifier {
19941994
final namedArgsListLocal =
19951995
b.addLocal(translator.nullableObjectArrayTypeRef);
19961996
b.local_get(namedArgsLocal);
1997+
b.local_get(closureLocal);
19971998
codeGen.call(translator.namedParameterMapToArray.reference);
19981999
b.local_set(namedArgsListLocal);
19992000

sdk/lib/_internal/wasm/lib/named_parameters.dart

Lines changed: 61 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,24 +5,17 @@
55
part of "core_patch.dart";
66

77
/// Finds a named parameter in a named parameter list passed to a dynamic
8-
/// forwarder or `Function.apply` and returns the index of the value of that
9-
/// named parameter. Returns `null` if the name is not in the list.
8+
/// forwarder or `Function.apply` (in which case the `Symbol` will be canonical
9+
/// iff the target function accepts it).
10+
///
11+
/// Returns `null` if the name is not in the list.
1012
@pragma("wasm:entry-point")
1113
int? _getNamedParameterIndex(
1214
WasmArray<Object?> namedArguments,
1315
Symbol paramName,
1416
) {
1517
for (int i = 0; i < namedArguments.length; i += 2) {
16-
// `Symbol.==` does not check identity so we have a fast path here checking
17-
// identities.
18-
//
19-
// We can't check just identities as the symbols in the list may not be
20-
// constants in `Function.apply`.
21-
//
22-
// Also, `paramName` will always be a constant, so with `--minify` it can
23-
// only be equal to a symbol in the list if it's also identical to it.
24-
if (identical(namedArguments[i], paramName) ||
25-
(!minify && unsafeCast<Symbol>(namedArguments[i]) == paramName)) {
18+
if (identical(namedArguments[i], paramName)) {
2619
return i + 1;
2720
}
2821
}
@@ -57,33 +50,80 @@ List<Object?> _positionalParametersToList(WasmArray<Object?> positional) {
5750
Map<Symbol, Object?> _namedParametersToMap(WasmArray<Object?> namedArguments) {
5851
final Map<Symbol, Object?> map = {};
5952
for (int i = 0; i < namedArguments.length; i += 2) {
60-
map[namedArguments[i] as Symbol] = namedArguments[i + 1];
53+
map[unsafeCast<Symbol>(namedArguments[i])] = namedArguments[i + 1];
6154
}
6255
return map;
6356
}
6457

6558
/// Converts a named parameter map passed to `Function.apply` to a list that
6659
/// can be passed to dynamic call vtable entries.
60+
///
61+
/// The resulting array contains (symbol, value) pairs where
62+
/// * the symbol is canonicalized iff the target closure has that symbol
63+
/// * all symbols the target closure accepts will have the same order as the
64+
/// target expects them
6765
@pragma("wasm:entry-point")
6866
WasmArray<Object?> _namedParameterMapToArray(
6967
Map<Symbol, Object?>? namedArguments,
68+
_Closure targetClosure,
7069
) {
7170
if (namedArguments == null || namedArguments.isEmpty) {
7271
return const WasmArray.literal([]);
7372
}
7473

75-
final List<MapEntry<Symbol, Object?>> entries =
76-
namedArguments.entries.toList()..sort(
77-
(entry1, entry2) =>
78-
_symbolToString(entry1.key).compareTo(_symbolToString(entry2.key)),
74+
final targetFunctionType = _Closure._getClosureRuntimeType(targetClosure);
75+
final targetNamedParameters = targetFunctionType.namedParameters;
76+
77+
List<_NamedParameterValue>? entries;
78+
int i = 0;
79+
namedArguments.forEach((symbol, value) {
80+
int position = _findSymbolPosition(symbol, targetNamedParameters);
81+
82+
// If the target knows about [symbol] then we use it's canonicalized
83+
// [Symbol] object to ensure any following code can use `identical()`.
84+
if (position != -1) symbol = targetNamedParameters[position].name;
85+
86+
final entry = _NamedParameterValue(symbol, value, position);
87+
if (entries == null) {
88+
i++;
89+
entries ??= List<_NamedParameterValue>.filled(
90+
namedArguments.length,
91+
entry,
7992
);
93+
return;
94+
}
95+
entries![i++] = entry;
96+
});
8097

81-
final WasmArray<Object?> result = WasmArray<Object?>(2 * entries.length);
98+
final entriesNonNullable = entries!;
99+
entriesNonNullable.sort((a, b) => a.position.compareTo(b.position));
82100

83-
for (int i = 0; i < entries.length; ++i) {
84-
result[2 * i] = entries[i].key;
85-
result[2 * i + 1] = entries[i].value;
101+
final WasmArray<Object?> result = WasmArray<Object?>(
102+
2 * entriesNonNullable.length,
103+
);
104+
for (int i = 0; i < entriesNonNullable.length; ++i) {
105+
final entry = entriesNonNullable[i];
106+
result[2 * i] = entry.symbol;
107+
result[2 * i + 1] = entry.value;
86108
}
87109

88110
return result;
89111
}
112+
113+
int _findSymbolPosition(Symbol symbol, WasmArray<_NamedParameter> named) {
114+
for (int i = 0; i < named.length; ++i) {
115+
final targetSymbol = named[i].name;
116+
if (identical(targetSymbol, symbol) ||
117+
(!minify && targetSymbol == symbol)) {
118+
return i;
119+
}
120+
}
121+
return -1;
122+
}
123+
124+
class _NamedParameterValue {
125+
final Symbol symbol;
126+
final Object? value;
127+
final int position;
128+
_NamedParameterValue(this.symbol, this.value, this.position);
129+
}

0 commit comments

Comments
 (0)