[dart2wasm] Improve cases where we use cid-based range checks for is/as

This removes an expensive type check for `is GlobalKey` in flutter code
where the `GlobalKey` has non-trivial bound.

  abstract class GlobalKey<T extends State<StatefulWidget>> { ... }

Change-Id: Ia685c0b528fdfe93d7a50685d2ba38b216277e15
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/353740
Reviewed-by: Ömer Ağacan <omersa@google.com>
Commit-Queue: Martin Kustermann <kustermann@google.com>
This commit is contained in:
Martin Kustermann 2024-02-22 22:15:17 +00:00 committed by Commit Queue
parent 19d11a70af
commit a21fec815a

View file

@ -631,8 +631,8 @@ class Types {
if (_canUseAsCheckHelper(codeGen, type, operandType)) return true;
if (type is! InterfaceType) return false;
if (type.typeArguments.any((t) => t is! DynamicType)) {
// Type has at least one type argument that is not `dynamic`.
if (_hasNonDefaultTypeArguments(type)) {
// Type has at least one type argument that is not default.
//
// In cases like `x is List<T>` where `x : Iterable<T>` (tested-against
// type is a subtype of the operand's static type and the types have same
@ -658,9 +658,19 @@ class Types {
bool _canUseAsCheckHelper(
CodeGenerator codeGen, DartType type, DartType operandType) {
if (type is! InterfaceType) return false;
// TODO: Should be rather defaults to bounds instead of `dynamic`.
// (assuming omitting bound will make it dynamic rather than void/Object?)
return type.typeArguments.every((t) => t is DynamicType);
return !_hasNonDefaultTypeArguments(type);
}
bool _hasNonDefaultTypeArguments(InterfaceType type) {
if (type.typeArguments.isEmpty) return false;
final parameters = type.classNode.typeParameters;
final arguments = type.typeArguments;
assert(parameters.length == arguments.length);
for (int i = 0; i < arguments.length; ++i) {
if (arguments[i] != parameters[i].defaultType) return true;
}
return false;
}
final Map<DartType, w.BaseFunction> _nullableIsCheckers = {};
@ -682,7 +692,7 @@ class Types {
[argumentType],
[w.NumType.i32],
),
'<obj> is <$type>');
'<obj> is ${type.classNode}');
final b = function.body;
b.local_get(b.locals[0]);
@ -744,7 +754,7 @@ class Types {
[argumentType],
[returnType],
),
'<obj> as <$type>');
'<obj> as ${type.classNode}');
final b = function.body;
w.Label asCheckBlock = b.block();