Skip to content

Commit

Permalink
[dart2wasm] Make implicit arguments check use optimized is/as helpers
Browse files Browse the repository at this point in the history
The implicit covariance type checks are currently performed by always
calling out to RTT. Those can use our existing optimized implementation
for is/as checks.

This reduces code size of -O2 mode as well as makes certain
benchmarks significantly faster (e.g. UIMatrix* 2x faster)

Change-Id: Ib5224a310b2188b9edb2de1e800d2e60010d11f1
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/370280
Reviewed-by: Srujan Gaddam <[email protected]>
Commit-Queue: Martin Kustermann <[email protected]>
  • Loading branch information
mkustermann committed Jun 8, 2024
1 parent 07d2288 commit dd89732
Showing 1 changed file with 41 additions and 58 deletions.
99 changes: 41 additions & 58 deletions pkg/dart2wasm/lib/code_generator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -325,8 +325,6 @@ class CodeGenerator extends ExpressionVisitor1<w.ValueType, w.ValueType>
}
}

w.Local? tempLocalForType;

void setupParamLocal(VariableDeclaration variable, int index,
Constant? defaultValue, bool isRequired) {
w.Local local = paramLocals[implicitParams + index];
Expand Down Expand Up @@ -362,9 +360,6 @@ class CodeGenerator extends ExpressionVisitor1<w.ValueType, w.ValueType>
}
if (!translator.options.omitImplicitTypeChecks) {
if (variable.isCovariantByClass || variable.isCovariantByDeclaration) {
final typeLocal = tempLocalForType ??= addLocal(
translator.classInfo[translator.typeClass]!.nonNullableType);

final boxedType = variable.type.isPotentiallyNullable
? translator.topInfo.nullableType
: translator.topInfo.nonNullableType;
Expand All @@ -379,9 +374,8 @@ class CodeGenerator extends ExpressionVisitor1<w.ValueType, w.ValueType>
_generateArgumentTypeCheck(
variable.name!,
() => b.local_get(operand),
() => types.makeType(this, variable.type),
variable.type,
operand,
typeLocal,
);
}
}
Expand Down Expand Up @@ -3348,11 +3342,6 @@ class CodeGenerator extends ExpressionVisitor1<w.ValueType, w.ValueType>
// Local for the argument.
final argLocal = addLocal(translator.topInfo.nullableType);

// Local for the expected type of the argument.
final typeType =
translator.classInfo[translator.typeClass]!.nonNullableType;
final argTypeLocal = addLocal(typeType);

final member_ = member;
DartType paramType;
if (member_ is Field) {
Expand All @@ -3361,13 +3350,14 @@ class CodeGenerator extends ExpressionVisitor1<w.ValueType, w.ValueType>
paramType = (member_ as Procedure).setterType;
}

_generateArgumentTypeCheck(
member.name.text,
() => b.local_get(positionalArgLocal),
() => types.makeType(this, paramType),
argLocal,
argTypeLocal,
);
if (!translator.options.omitImplicitTypeChecks) {
_generateArgumentTypeCheck(
member.name.text,
() => b.local_get(positionalArgLocal),
paramType,
argLocal,
);
}

ClassInfo info = translator.classInfo[member_.enclosingClass]!;
if (member_ is Field) {
Expand Down Expand Up @@ -3465,14 +3455,10 @@ class CodeGenerator extends ExpressionVisitor1<w.ValueType, w.ValueType>
final List<VariableDeclaration> memberPositionalParams =
procedure.function.positionalParameters;

// Local for the current argument being checked. Used to avoid indexing the
// positional parameters array again when throwing type error.
// Local for the current argument being checked. Used to avoid indexing
// the positional parameters array again when throwing type error.
final argLocal = addLocal(translator.topInfo.nullableType);

// Local for the expected type of the current positional arguments. Used to
// avoid generating the type again when throwing type error.
final argTypeLocal = addLocal(typeType);

for (int positionalParamIdx = 0;
positionalParamIdx < memberPositionalParams.length;
positionalParamIdx += 1) {
Expand All @@ -3484,11 +3470,8 @@ class CodeGenerator extends ExpressionVisitor1<w.ValueType, w.ValueType>
b.i32_const(positionalParamIdx);
b.array_get(translator.nullableObjectArrayType);
},
() {
types.makeType(this, param.type);
},
param.type,
argLocal,
argTypeLocal,
);
}

Expand Down Expand Up @@ -3519,11 +3502,8 @@ class CodeGenerator extends ExpressionVisitor1<w.ValueType, w.ValueType>
b.i32_const(mapNamedParameterToArrayIndex(param.name!));
b.array_get(translator.nullableObjectArrayType);
},
() {
types.makeType(this, param.type);
},
param.type,
argLocal,
argTypeLocal,
);
}
}
Expand Down Expand Up @@ -3582,39 +3562,42 @@ class CodeGenerator extends ExpressionVisitor1<w.ValueType, w.ValueType>
/// Does not expect any values on stack and does not leave any values on
/// stack.
///
/// Locals [argLocal] and [argExpectedTypeLocal] are used to store values
/// pushed by [pushArg] and [pushArgExpectedType] and reuse the values.
/// Locals [argLocal] are used to store values pushed by [pushArg]
/// and reuse the values.
///
/// [argName] is used in the type error as the name of the argument that
/// doesn't match the expected type.
void _generateArgumentTypeCheck(
String argName,
void Function() pushArg,
void Function() pushArgExpectedType,
DartType testedAgainstType,
w.Local argLocal,
w.Local argExpectedTypeLocal,
) {
// Argument
pushArg();
b.local_tee(argLocal);

// Expected type
pushArgExpectedType();
b.local_tee(argExpectedTypeLocal);

// Check that argument type is subtype of expected type
call(translator.isSubtype.reference);

b.i32_eqz();
b.if_();
// Type check failed
b.local_get(argLocal);
b.local_get(argExpectedTypeLocal);
_emitString(argName);
call(translator.stackTraceCurrent.reference);
call(translator.throwArgumentTypeCheckError.reference);
b.unreachable();
b.end();
if (translator.options.minify) {
// We don't need to include the name in the error message, so we can use
// the optimized `as` checks.
pushArg();
types.emitAsCheck(
this,
testedAgainstType,
translator.coreTypes.objectNullableRawType,
argLocal.type as w.RefType);
b.drop();
} else {
pushArg();
b.local_tee(argLocal);
types.emitIsTest(
this, testedAgainstType, translator.coreTypes.objectNullableRawType);
b.i32_eqz();
b.if_();
b.local_get(argLocal);
types.makeType(this, testedAgainstType);
_emitString(argName);
call(translator.stackTraceCurrent.reference);
call(translator.throwArgumentTypeCheckError.reference);
b.unreachable();
b.end();
}
}

void _generateTypeArgumentBoundCheck(
Expand Down

0 comments on commit dd89732

Please sign in to comment.