Skip to content

Commit 35e35f5

Browse files
askeksaCommit Bot
authored andcommitted
[dart2wasm] Support different default values within the same selector
Default parameter values are implemented in dart2wasm via caller-side substitution. When the same parameter has different default values across different implementations within the same selector, a special sentinel value is passed by the caller, and the callee checks for this value and substitutes the actual default value. Change-Id: I8235145f93c2aee7e9ef603456380253b836fcef Cq-Include-Trybots: luci.dart.try:dart2wasm-linux-x64-d8-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/259040 Commit-Queue: Aske Simon Christensen <[email protected]> Reviewed-by: Joshua Litt <[email protected]>
1 parent 99ad190 commit 35e35f5

File tree

4 files changed

+57
-11
lines changed

4 files changed

+57
-11
lines changed

pkg/dart2wasm/lib/code_generator.dart

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -324,15 +324,37 @@ class CodeGenerator extends ExpressionVisitor1<w.ValueType, w.ValueType>
324324
ParameterInfo paramInfo = translator.paramInfoFor(reference);
325325
int parameterOffset = _initializeThis(member);
326326
int implicitParams = parameterOffset + paramInfo.typeParamCount;
327+
328+
void setupParamLocal(
329+
VariableDeclaration variable, int index, Constant? defaultValue) {
330+
w.Local local = paramLocals[implicitParams + index];
331+
locals[variable] = local;
332+
if (defaultValue == ParameterInfo.defaultValueSentinel) {
333+
// The default value for this parameter differs between implementations
334+
// within the same selector. This means that callers will pass the
335+
// default value sentinel to indicate that the parameter is not given.
336+
// The callee must check for the sentinel value and substitute the
337+
// actual default value.
338+
b.local_get(local);
339+
translator.constants.instantiateConstant(
340+
function, b, ParameterInfo.defaultValueSentinel, local.type);
341+
b.ref_eq();
342+
b.if_();
343+
wrap(variable.initializer!, local.type);
344+
b.local_set(local);
345+
b.end();
346+
}
347+
}
348+
327349
List<VariableDeclaration> positional =
328350
member.function!.positionalParameters;
329351
for (int i = 0; i < positional.length; i++) {
330-
locals[positional[i]] = paramLocals[implicitParams + i];
352+
setupParamLocal(positional[i], i, paramInfo.positional[i]);
331353
}
332354
List<VariableDeclaration> named = member.function!.namedParameters;
333355
for (var param in named) {
334-
locals[param] =
335-
paramLocals[implicitParams + paramInfo.nameIndex[param.name]!];
356+
setupParamLocal(
357+
param, paramInfo.nameIndex[param.name]!, paramInfo.named[param.name]);
336358
}
337359
List<TypeParameter> typeParameters = member is Constructor
338360
? member.enclosingClass.typeParameters

pkg/dart2wasm/lib/constants.dart

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import 'dart:typed_data';
77

88
import 'package:dart2wasm/class_info.dart';
99
import 'package:dart2wasm/closures.dart';
10+
import 'package:dart2wasm/param_info.dart';
1011
import 'package:dart2wasm/translator.dart';
1112
import 'package:dart2wasm/types.dart';
1213

@@ -335,6 +336,19 @@ class ConstantInstantiator extends ConstantVisitor<w.ValueType> {
335336
}
336337
}
337338

339+
@override
340+
w.ValueType visitUnevaluatedConstant(UnevaluatedConstant constant) {
341+
if (constant == ParameterInfo.defaultValueSentinel) {
342+
// Instantiate a sentinel value specific to the parameter type.
343+
w.ValueType sentinelType = expectedType.withNullability(false);
344+
assert(sentinelType is w.RefType,
345+
"Default value sentinel for unboxed parameter");
346+
translator.globals.instantiateDummyValue(b, sentinelType);
347+
return sentinelType;
348+
}
349+
return super.visitUnevaluatedConstant(constant);
350+
}
351+
338352
@override
339353
w.ValueType visitNullConstant(NullConstant node) {
340354
w.ValueType? expectedType = this.expectedType;

pkg/dart2wasm/lib/dispatch_table.dart

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ class SelectorInfo {
6060
List.generate(1 + paramInfo.paramCount, (_) => {});
6161
List<Set<ClassInfo>> outputSets = List.generate(returnCount, (_) => {});
6262
List<bool> inputNullable = List.filled(1 + paramInfo.paramCount, false);
63+
List<bool> ensureBoxed = List.filled(1 + paramInfo.paramCount, false);
6364
List<bool> outputNullable = List.filled(returnCount, false);
6465
targets.forEach((id, target) {
6566
ClassInfo receiver = translator.classes[id];
@@ -99,18 +100,23 @@ class SelectorInfo {
99100
}
100101
assert(returns.length <= outputSets.length);
101102
inputSets[0].add(receiver);
103+
ensureBoxed[0] = true;
102104
for (int i = 0; i < positional.length; i++) {
103105
DartType type = positional[i];
104106
inputSets[1 + i]
105107
.add(translator.classInfo[translator.classForType(type)]!);
106108
inputNullable[1 + i] |= type.isPotentiallyNullable;
109+
ensureBoxed[1 + i] |=
110+
paramInfo.positional[i] == ParameterInfo.defaultValueSentinel;
107111
}
108112
for (String name in named.keys) {
109113
int i = nameIndex[name]!;
110114
DartType type = named[name]!;
111115
inputSets[1 + i]
112116
.add(translator.classInfo[translator.classForType(type)]!);
113117
inputNullable[1 + i] |= type.isPotentiallyNullable;
118+
ensureBoxed[1 + i] |=
119+
paramInfo.named[name] == ParameterInfo.defaultValueSentinel;
114120
}
115121
for (int i = 0; i < returnCount; i++) {
116122
if (i < returns.length) {
@@ -128,8 +134,8 @@ class SelectorInfo {
128134
List<w.ValueType> inputs = List.generate(
129135
inputSets.length,
130136
(i) => translator.typeForInfo(
131-
upperBound(inputSets[i]), inputNullable[i], ensureBoxed: i == 0)
132-
as w.ValueType);
137+
upperBound(inputSets[i]), inputNullable[i],
138+
ensureBoxed: ensureBoxed[i]) as w.ValueType);
133139
if (name == '==') {
134140
// == can't be called with null
135141
inputs[1] = inputs[1].withNullability(false);

pkg/dart2wasm/lib/param_info.dart

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@ class ParameterInfo {
2020
for (int i = 0; i < names.length; i++) names[i]: positional.length + i
2121
};
2222

23+
/// A special marker value to use for default parameter values to indicate
24+
/// that different implementations within the same selector have different
25+
/// default values.
26+
static final Constant defaultValueSentinel =
27+
UnevaluatedConstant(InvalidExpression("Default value sentinel"));
28+
2329
int get paramCount => positional.length + named.length;
2430

2531
static Constant? defaultValue(VariableDeclaration param) {
@@ -82,9 +88,8 @@ class ParameterInfo {
8288
positional[i] = other.positional[i];
8389
} else if (other.positional[i] != null) {
8490
if (positional[i] != other.positional[i]) {
85-
print("Mismatching default value for parameter $i: "
86-
"${member}: ${positional[i]} vs "
87-
"${other.member}: ${other.positional[i]}");
91+
// Default value differs between implementations.
92+
positional[i] = defaultValueSentinel;
8893
}
8994
}
9095
}
@@ -96,9 +101,8 @@ class ParameterInfo {
96101
named[name] = otherValue;
97102
} else if (otherValue != null) {
98103
if (value != otherValue) {
99-
print("Mismatching default value for parameter '$name': "
100-
"${member}: ${value} vs "
101-
"${other.member}: ${otherValue}");
104+
// Default value differs between implementations.
105+
named[name] = defaultValueSentinel;
102106
}
103107
}
104108
}

0 commit comments

Comments
 (0)