[dart2wasm] Some refactorings of the compiler

a) Usage of `ClassInfo.*`

We have an abstraction layer that translates dart types
to wasm types - which is the `Translator` object (it
has e.g. `Translator.translateType`).

=> We remove direct use of `ClassInfo.*` in most places
=> Instead of exposing `ClassInfo` for specific types
   (e.g. top type), we expose the wasm representation type

b) Type of `ClassInfo.repr`

Currently `ClassInfo.repr` is itself a `ClassInfo`, which is
rather confusing. We use `ClassInfo.repr` to determine how to
translate `InterfaceType`s of that class to the wasm type system.

=> We make `Class.repr` be an actual wasm representation type
   (we make it a `w.RefType`)

c) We create a macro assembler `loadClassId` method so we have
   one place where we load the class id and we verify in
   assertions that the receiver type is `ref #Top`.

Change-Id: Ie24008a98131dae34948406a1f5aec881499c1f0
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/431080
Commit-Queue: Martin Kustermann <kustermann@google.com>
Reviewed-by: Ömer Ağacan <omersa@google.com>
This commit is contained in:
Martin Kustermann
2025-05-28 01:12:19 -07:00
committed by Commit Queue
parent ac2fc57446
commit 2fc0c8bf08
15 changed files with 213 additions and 205 deletions
+10 -13
View File
@@ -55,9 +55,9 @@ mixin AsyncCodeGeneratorMixin on StateMachineEntryAstCodeGenerator {
// here.
b.local_get(asyncStateLocal);
b.ref_null(translator.topInfo.struct); // await value
b.ref_null(translator.topInfo.struct); // error value
b.ref_null(translator.stackTraceInfo.repr.struct); // stack trace
b.ref_null(translator.topType.heapType); // await value
b.ref_null(translator.topType.heapType); // error value
b.ref_null(translator.stackTraceType.heapType); // stack trace
translator.callFunction(resumeFun, b);
b.drop(); // drop null
@@ -79,15 +79,14 @@ mixin AsyncCodeGeneratorMixin on StateMachineEntryAstCodeGenerator {
b.module.functions.define(
translator.typesBuilder.defineFunction([
asyncSuspendStateInfo.nonNullableType, // _AsyncSuspendState
translator.topInfo.nullableType, // Object?, await value
translator.topInfo.nullableType, // Object?, error value
translator.stackTraceInfo.repr
.nullableType // StackTrace?, error stack trace
translator.topType, // Object?, await value
translator.topType, // Object?, error value
translator.stackTraceTypeNullable // StackTrace?, error stack trace
], [
// Inner function does not return a value, but it's Dart type is
// `void Function(...)` and all Dart functions return a value, so we
// add a return type.
translator.topInfo.nullableType
translator.topType
]),
"${function.functionName} inner");
}
@@ -254,17 +253,15 @@ class AsyncStateMachineCodeGenerator extends StateMachineCodeGenerator {
// Final state: return.
emitTargetLabel(targets.last);
b.local_get(_suspendStateLocal);
b.ref_null(translator.topInfo.struct);
b.ref_null(translator.topType.heapType);
call(translator.getFunctionEntry(
translator.asyncSuspendStateComplete.reference,
uncheckedEntry: true));
b.return_();
b.end(); // masterLoop
final stackTraceLocal =
addLocal(translator.stackTraceInfo.repr.nonNullableType);
final exceptionLocal = addLocal(translator.topInfo.nonNullableType);
final stackTraceLocal = addLocal(translator.stackTraceType);
final exceptionLocal = addLocal(translator.topTypeNonNullable);
void callCompleteError() {
b.local_get(_suspendStateLocal);
+13 -7
View File
@@ -183,11 +183,11 @@ class ClassInfo {
/// the superclass.
final Map<TypeParameter, TypeParameter> typeParameterMatch;
/// The class whose struct is used as the type for variables of this type.
/// This is a type which is a superclass of all subtypes of this type.
ClassInfo get repr => _repr!;
/// The wasm type used to represent values of a dart interface type of this
/// class.
w.RefType get repr => _repr!;
ClassInfo? _repr;
w.RefType? _repr;
/// Nullabe Wasm ref type for this class.
final w.RefType nullableType;
@@ -478,7 +478,7 @@ class ClassInfoCollector {
}
for (Field field in info.cls!.fields) {
info._addField(w.FieldType(topInfo.nullableType),
info._addField(w.FieldType(translator.topType),
fieldName: field.name.text);
}
}
@@ -548,7 +548,7 @@ class ClassInfoCollector {
// class maps to topInfo because boxed values are a subtype of Object in
// Dart but not of the object struct.
representation = cls == translator.coreTypes.objectClass
? translator.topInfo
? topInfo
: translator.objectInfo;
} else {
void addRanges(List<Range> ranges) {
@@ -581,7 +581,13 @@ class ClassInfoCollector {
}
}
final info = translator.classInfo[cls]!;
info._repr = representation ?? info;
representation ??= info;
if (representation == topInfo) {
info._repr = translator.topTypeNonNullable;
} else {
info._repr = representation!.nonNullableType;
}
}
// Now that the representation types for all classes have been computed,
+1 -1
View File
@@ -356,7 +356,7 @@ class ClosureLayouter extends RecursiveVisitor {
superType: superType);
}
w.ValueType get topType => translator.topInfo.nullableType;
w.ValueType get topType => translator.topType;
ClosureLayouter(this.translator)
: procedureAttributeMetadata =
+72 -78
View File
@@ -303,8 +303,8 @@ abstract class AstCodeGenerator
if (translator.needToCheckParameter(variable,
uncheckedEntry: canSafelyOmitImplicitChecks)) {
final boxedType = variable.type.isPotentiallyNullable
? translator.topInfo.nullableType
: translator.topInfo.nonNullableType;
? translator.topType
: translator.topTypeNonNullable;
w.Local operand = local;
if (!operand.type.isSubtypeOf(boxedType)) {
final boxedOperand = addLocal(boxedType);
@@ -862,14 +862,12 @@ abstract class AstCodeGenerator
Expression? message = node.message;
if (message != null) {
translateExpression(message, translator.topInfo.nullableType);
translateExpression(message, translator.topType);
} else {
b.ref_null(w.HeapType.none);
}
final Location? location = node.location;
final stringClass = translator.jsStringClass;
final w.RefType stringRefType =
translator.classInfo[stringClass]!.nullableType;
final w.RefType stringRefType = translator.stringTypeNullable;
if (location != null) {
translator.constants.instantiateConstant(
b,
@@ -915,9 +913,8 @@ abstract class AstCodeGenerator
// It is not valid Dart to have a try without a catch.
assert(node.catches.isNotEmpty);
final w.RefType exceptionType = translator.topInfo.nonNullableType;
final w.RefType stackTraceType =
translator.stackTraceInfo.repr.nonNullableType;
final w.RefType exceptionType = translator.topTypeNonNullable;
final w.RefType stackTraceType = translator.stackTraceType;
final w.Label wrapperBlock = b.block();
@@ -1421,7 +1418,7 @@ abstract class AstCodeGenerator
final dynamicTypeGuard = switchInfo.dynamicTypeGuard;
if (dynamicTypeGuard != null) {
final success = b.block(const [], [translator.topInfo.nonNullableType]);
final success = b.block(const [], [translator.topTypeNonNullable]);
dynamicTypeGuard(switchValueNonNullableLocal, success);
b.br(switchLabels[defaultCase] ?? doneLabel);
b.end();
@@ -1663,7 +1660,7 @@ abstract class AstCodeGenerator
_virtualCall(node, target, _VirtualCallKind.Call, (signature) {
done = b.block(const [], signature.outputs);
final w.Label nullReceiver = b.block();
translateExpression(node.receiver, translator.topInfo.nullableType);
translateExpression(node.receiver, translator.topType);
b.br_on_null(nullReceiver);
}, (w.FunctionType signature, ParameterInfo paramInfo) {
_visitArguments(node.arguments, signature, paramInfo, 1);
@@ -1690,7 +1687,7 @@ abstract class AstCodeGenerator
final paramInfo = translator.paramInfoForDirectCall(target);
// Object? receiver
b.ref_null(translator.topInfo.struct);
b.ref_null(translator.topType.heapType);
// Invocation invocation
_visitArguments(node.arguments, signature, paramInfo, 1);
call(translator.noSuchMethodErrorThrowWithInvocation.reference);
@@ -1750,8 +1747,8 @@ abstract class AstCodeGenerator
.getDynamicInvocationForwarder(memberName);
// Evaluate receiver
translateExpression(receiver, translator.topInfo.nullableType);
final nullableReceiverLocal = addLocal(translator.topInfo.nullableType);
translateExpression(receiver, translator.topType);
final nullableReceiverLocal = addLocal(translator.topType);
b.local_set(nullableReceiverLocal);
// Evaluate type arguments.
@@ -1776,8 +1773,8 @@ abstract class AstCodeGenerator
// each argument to allow adding values to the list in expected order.
final List<MapEntry<String, w.Local>> namedArgumentLocals = [];
for (final namedArgument in namedArguments) {
translateExpression(namedArgument.value, translator.topInfo.nullableType);
final argumentLocal = addLocal(translator.topInfo.nullableType);
translateExpression(namedArgument.value, translator.topType);
final argumentLocal = addLocal(translator.topType);
b.local_set(argumentLocal);
namedArgumentLocals.add(MapEntry(namedArgument.name, argumentLocal));
}
@@ -1800,7 +1797,7 @@ abstract class AstCodeGenerator
}));
b.local_set(namedArgsLocal);
final nullBlock = b.block([], [translator.topInfo.nonNullableType]);
final nullBlock = b.block([], [translator.topTypeNonNullable]);
b.local_get(nullableReceiverLocal);
b.br_on_non_null(nullBlock);
// Throw `NoSuchMethodError`. Normally this needs to happen via instance
@@ -1819,7 +1816,7 @@ abstract class AstCodeGenerator
b.local_get(namedArgsLocal);
translator.callFunction(forwarder.function, b);
return translator.topInfo.nullableType;
return translator.topType;
}
@override
@@ -1833,8 +1830,7 @@ abstract class AstCodeGenerator
// If leftType is not a Dart type (or builtin value type) then use
// reference equality (e.g. the vtable type is not a subtype of
// topType).
(leftType is w.RefType &&
!leftType.isSubtypeOf(translator.topInfo.nullableType))) {
(leftType is w.RefType && !leftType.isSubtypeOf(translator.topType))) {
// Plain reference comparison
translateExpression(node.left, w.RefType.eq(nullable: true));
translateExpression(node.right, w.RefType.eq(nullable: true));
@@ -1843,9 +1839,8 @@ abstract class AstCodeGenerator
// Check operands for null, then call implementation
bool leftNullable = dartTypeOf(node.left).isPotentiallyNullable;
bool rightNullable = dartTypeOf(node.right).isPotentiallyNullable;
w.RefType leftType = translator.topInfo.typeWithNullability(leftNullable);
w.RefType rightType =
translator.topInfo.typeWithNullability(rightNullable);
w.RefType leftType = translator.topType.withNullability(leftNullable);
w.RefType rightType = translator.topType.withNullability(rightNullable);
w.Local leftLocal = addLocal(leftType);
w.Local rightLocal = addLocal(rightType);
w.Label? operandNull;
@@ -1980,7 +1975,7 @@ abstract class AstCodeGenerator
assert(!receiverVar.type.nullable);
b.local_tee(receiverVar);
if (callPolymorphicDispatcher) {
b.struct_get(translator.topInfo.struct, FieldIndex.classId);
b.loadClassId(translator, receiverVar.type);
b.local_get(receiverVar);
}
pushArguments(signature, selector.paramInfo);
@@ -2127,7 +2122,7 @@ abstract class AstCodeGenerator
_virtualCall(node, target, _VirtualCallKind.Get, (signature) {
doneLabel = b.block(const [], signature.outputs);
w.Label nullLabel = b.block();
translateExpression(node.receiver, translator.topInfo.nullableType);
translateExpression(node.receiver, translator.topType);
b.br_on_null(nullLabel);
}, (_, __) {}, useUncheckedEntry: false);
b.br(doneLabel);
@@ -2176,11 +2171,11 @@ abstract class AstCodeGenerator
.getDynamicGetForwarder(memberName);
// Evaluate receiver
translateExpression(receiver, translator.topInfo.nullableType);
final nullableReceiverLocal = addLocal(translator.topInfo.nullableType);
translateExpression(receiver, translator.topType);
final nullableReceiverLocal = addLocal(translator.topType);
b.local_set(nullableReceiverLocal);
final nullBlock = b.block([], [translator.topInfo.nonNullableType]);
final nullBlock = b.block([], [translator.topTypeNonNullable]);
b.local_get(nullableReceiverLocal);
b.br_on_non_null(nullBlock);
// Throw `NoSuchMethodError`. Normally this needs to happen via instance
@@ -2196,7 +2191,7 @@ abstract class AstCodeGenerator
// Call get forwarder
translator.callFunction(forwarder.function, b);
return translator.topInfo.nullableType;
return translator.topType;
}
@override
@@ -2209,16 +2204,16 @@ abstract class AstCodeGenerator
.getDynamicSetForwarder(memberName);
// Evaluate receiver
translateExpression(receiver, translator.topInfo.nullableType);
final nullableReceiverLocal = addLocal(translator.topInfo.nullableType);
translateExpression(receiver, translator.topType);
final nullableReceiverLocal = addLocal(translator.topType);
b.local_set(nullableReceiverLocal);
// Evaluate positional arg
translateExpression(value, translator.topInfo.nullableType);
final positionalArgLocal = addLocal(translator.topInfo.nullableType);
translateExpression(value, translator.topType);
final positionalArgLocal = addLocal(translator.topType);
b.local_set(positionalArgLocal);
final nullBlock = b.block([], [translator.topInfo.nonNullableType]);
final nullBlock = b.block([], [translator.topTypeNonNullable]);
b.local_get(nullableReceiverLocal);
b.br_on_non_null(nullBlock);
// Throw `NoSuchMethodError`. Normally this needs to happen via instance
@@ -2235,7 +2230,7 @@ abstract class AstCodeGenerator
b.local_get(positionalArgLocal);
translator.callFunction(forwarder.function, b);
return translator.topInfo.nullableType;
return translator.topType;
}
w.ValueType _directGet(Member target, Expression receiver) {
@@ -2268,10 +2263,9 @@ abstract class AstCodeGenerator
_virtualCall(node, target, _VirtualCallKind.Get, (signature) {
doneLabel = b.block(const [], signature.outputs);
w.Label nullLabel = b.block();
translateExpression(node.receiver, translator.topInfo.nullableType);
translateExpression(node.receiver, translator.topType);
b.br_on_null(nullLabel);
translator.convertType(
b, translator.topInfo.nullableType, signature.inputs[0]);
translator.convertType(b, translator.topType, signature.inputs[0]);
}, (_, __) {}, useUncheckedEntry: false);
b.br(doneLabel);
b.end(); // nullLabel
@@ -2470,7 +2464,7 @@ abstract class AstCodeGenerator
// This is a dynamic function call with a signature that matches no
// functions in the program.
b.unreachable();
return translator.topInfo.nullableType;
return translator.topType;
}
final SingleClosureTarget? directClosureCall =
@@ -2533,7 +2527,7 @@ abstract class AstCodeGenerator
// Positional arguments
for (Expression arg in node.arguments.positional) {
translateExpression(arg, translator.topInfo.nullableType);
translateExpression(arg, translator.topType);
}
// Named arguments
@@ -2541,7 +2535,7 @@ abstract class AstCodeGenerator
node.arguments.named.map((a) => a.name).toList()..sort();
final Map<String, w.Local> namedLocals = {};
for (final namedArg in node.arguments.named) {
final w.Local namedLocal = addLocal(translator.topInfo.nullableType);
final w.Local namedLocal = addLocal(translator.topType);
namedLocals[namedArg.name] = namedLocal;
translateExpression(namedArg.value, namedLocal.type);
b.local_set(namedLocal);
@@ -2561,7 +2555,7 @@ abstract class AstCodeGenerator
b.struct_get(representation.vtableStruct, vtableFieldIndex);
b.call_ref(functionType);
return translator.topInfo.nullableType;
return translator.topType;
}
@override
@@ -2771,7 +2765,7 @@ abstract class AstCodeGenerator
// Front-end wraps the argument with `as Object` when necessary, so we can
// assume non-nullable here.
assert(!dartTypeOf(node.expression).isPotentiallyNullable);
translateExpression(node.expression, translator.topInfo.nonNullableType);
translateExpression(node.expression, translator.topTypeNonNullable);
call(translator.errorThrowWithCurrentStackTrace.reference);
b.unreachable();
return expectedType;
@@ -2955,8 +2949,8 @@ abstract class AstCodeGenerator
w.ValueType visitIsExpression(IsExpression node, w.ValueType expectedType) {
final operandType = dartTypeOf(node.operand);
final boxedOperandType = operandType.isPotentiallyNullable
? translator.topInfo.nullableType
: translator.topInfo.nonNullableType;
? translator.topType
: translator.topTypeNonNullable;
translateExpression(node.operand, boxedOperandType);
types.emitIsTest(this, node.type, operandType, node.location);
return w.NumType.i32;
@@ -2974,8 +2968,8 @@ abstract class AstCodeGenerator
final operandType = dartTypeOf(node.operand);
final boxedOperandType = operandType.isPotentiallyNullable
? translator.topInfo.nullableType
: translator.topInfo.nonNullableType;
? translator.topType
: translator.topTypeNonNullable;
translateExpression(node.operand, boxedOperandType);
return types.emitAsCheck(this, node.isCovarianceCheck, node.type,
operandType, boxedOperandType, node.location);
@@ -3030,10 +3024,10 @@ abstract class AstCodeGenerator
b.pushObjectHeaderFields(translator, recordClassInfo);
for (Expression positional in node.positional) {
translateExpression(positional, translator.topInfo.nullableType);
translateExpression(positional, translator.topType);
}
for (NamedExpression named in node.named) {
translateExpression(named.value, translator.topInfo.nullableType);
translateExpression(named.value, translator.topType);
}
b.struct_new(recordClassInfo.struct);
@@ -3047,12 +3041,12 @@ abstract class AstCodeGenerator
final ClassInfo recordClassInfo =
translator.getRecordClassInfo(node.receiverType);
translateExpression(node.receiver, translator.topInfo.nonNullableType);
translateExpression(node.receiver, translator.topTypeNonNullable);
b.ref_cast(w.RefType(recordClassInfo.struct, nullable: false));
b.struct_get(
recordClassInfo.struct, recordShape.getPositionalIndex(node.index));
return translator.topInfo.nullableType;
return translator.topType;
}
@override
@@ -3061,11 +3055,11 @@ abstract class AstCodeGenerator
final ClassInfo recordClassInfo =
translator.getRecordClassInfo(node.receiverType);
translateExpression(node.receiver, translator.topInfo.nonNullableType);
translateExpression(node.receiver, translator.topTypeNonNullable);
b.ref_cast(w.RefType(recordClassInfo.struct, nullable: false));
b.struct_get(recordClassInfo.struct, recordShape.getNameIndex(node.name));
return translator.topInfo.nullableType;
return translator.topType;
}
@override
@@ -3115,8 +3109,7 @@ abstract class AstCodeGenerator
DartType bound,
) {
b.local_get(typeLocal);
final boundLocal =
b.addLocal(translator.classInfo[translator.typeClass]!.nonNullableType);
final boundLocal = b.addLocal(translator.runtimeTypeType);
types.makeType(this, bound);
b.local_tee(boundLocal);
call(translator.isTypeSubtype.reference);
@@ -3550,8 +3543,7 @@ class TypeCheckerCodeGenerator extends AstCodeGenerator {
b.local_get(positionalArgsLocal);
b.i32_const(positionalParamIdx);
b.array_get(translator.nullableObjectArrayType);
_generateArgumentTypeCheck(
param.name!, translator.topInfo.nullableType, param.type);
_generateArgumentTypeCheck(param.name!, translator.topType, param.type);
}
// Check named argument types
@@ -3577,8 +3569,7 @@ class TypeCheckerCodeGenerator extends AstCodeGenerator {
b.local_get(namedArgsLocal);
b.i32_const(mapNamedParameterToArrayIndex(param.name!));
b.array_get(translator.nullableObjectArrayType);
_generateArgumentTypeCheck(
param.name!, translator.topInfo.nullableType, param.type);
_generateArgumentTypeCheck(param.name!, translator.topType, param.type);
}
}
@@ -3602,7 +3593,7 @@ class TypeCheckerCodeGenerator extends AstCodeGenerator {
b.i32_const(listIdx);
b.array_get(translator.nullableObjectArrayType);
translator.convertType(
b, translator.topInfo.nullableType, memberWasmInputs[wasmInputIdx]);
b, translator.topType, memberWasmInputs[wasmInputIdx]);
}
for (int positionalParamIdx = 0;
@@ -3624,7 +3615,7 @@ class TypeCheckerCodeGenerator extends AstCodeGenerator {
translator.convertType(
b,
translator.outputOrVoid(memberWasmFunctionType.outputs),
translator.topInfo.nullableType);
translator.topType);
b.return_();
b.end();
@@ -4191,12 +4182,12 @@ class ImplicitFieldAccessorCodeGenerator extends AstCodeGenerator {
// Implicit getter or setter
w.StructType struct = translator.classInfo[field.enclosingClass!]!.struct;
w.RefType structType = w.RefType.def(struct, nullable: false);
int fieldIndex = translator.fieldIndex[field]!;
w.ValueType fieldType = struct.fields[fieldIndex].type.unpacked;
void getThis() {
w.Local thisLocal = paramLocals[0];
w.RefType structType = w.RefType.def(struct, nullable: false);
b.local_get(thisLocal);
translator.convertType(b, thisLocal.type, structType);
}
@@ -4215,8 +4206,8 @@ class ImplicitFieldAccessorCodeGenerator extends AstCodeGenerator {
translator.needToCheckImplicitSetterValue(field,
uncheckedEntry: useUncheckedEntry)) {
final boxedType = field.type.isPotentiallyNullable
? translator.topInfo.nullableType
: translator.topInfo.nonNullableType;
? translator.topType
: translator.topTypeNonNullable;
w.Local operand = valueLocal;
if (!operand.type.isSubtypeOf(boxedType)) {
final boxedOperand = addLocal(boxedType);
@@ -4377,10 +4368,8 @@ class SwitchInfo {
compare = (switchExprLocal, pushCaseExpr) =>
throw "Comparison in default-only switch";
} else if (canInvokeTypeEquality()) {
nonNullableType = translator
.classInfo[translator.coreTypes.typeClass]!.repr.nonNullableType;
nullableType = translator
.classInfo[translator.coreTypes.typeClass]!.repr.nullableType;
nonNullableType = translator.runtimeTypeType;
nullableType = translator.runtimeTypeTypeNullable;
compare = (switchExprLocal, pushCaseExpr) {
// Virtual call to `Object.==`.
codeGen._virtualCall(
@@ -4393,8 +4382,8 @@ class SwitchInfo {
};
} else if (switchExprType is DynamicType) {
// Object equality switch
nonNullableType = translator.topInfo.nonNullableType;
nullableType = translator.topInfo.nullableType;
nonNullableType = translator.topTypeNonNullable;
nullableType = translator.topType;
// Per spec, compare with `<case expr> == <switch expr>`.
final Member equalsMember;
@@ -4459,10 +4448,8 @@ class SwitchInfo {
};
} else if (check<StringLiteral, StringConstant>()) {
// String switch
nonNullableType = translator
.classInfo[translator.coreTypes.stringClass]!.repr.nonNullableType;
nullableType = translator
.classInfo[translator.coreTypes.stringClass]!.repr.nullableType;
nonNullableType = translator.stringType;
nullableType = translator.stringTypeNullable;
compare = (switchExprLocal, pushCaseExpr) {
codeGen.b.local_get(switchExprLocal);
pushCaseExpr();
@@ -4470,8 +4457,8 @@ class SwitchInfo {
};
} else {
// Object identity switch
nonNullableType = translator.topInfo.nonNullableType;
nullableType = translator.topInfo.nullableType;
nonNullableType = translator.topTypeNonNullable;
nullableType = translator.topType;
compare = (switchExprLocal, pushCaseExpr) {
codeGen.b.local_get(switchExprLocal);
pushCaseExpr();
@@ -4801,7 +4788,7 @@ extension MacroAssembler on w.InstructionsBuilder {
nullable: false));
struct_get(translator.closureLayouter.closureBaseStruct,
FieldIndex.closureContext);
ref_test(translator.topInfo.nonNullableType);
ref_test(translator.topTypeNonNullable);
}
/// `[ref _Closure] -> [ref #Top]`
@@ -4812,7 +4799,7 @@ extension MacroAssembler on w.InstructionsBuilder {
nullable: false));
struct_get(translator.closureLayouter.closureBaseStruct,
FieldIndex.closureContext);
ref_cast(translator.topInfo.nonNullableType);
ref_cast(translator.topTypeNonNullable);
}
/// `[ref _Closure] -> [ref Any]
@@ -4952,6 +4939,13 @@ extension MacroAssembler on w.InstructionsBuilder {
translator.callReference(translator.globalizeClassId.reference, this);
}
}
void loadClassId(Translator translator, w.ValueType receiverType) {
assert(!receiverType.nullable);
assert(receiverType.isSubtypeOf(translator.topTypeNonNullable));
struct_get(
translator.classInfoCollector.topInfo.struct, FieldIndex.classId);
}
}
/// A call target that may be called with a direct call or may be inlined.
+2 -4
View File
@@ -1175,8 +1175,7 @@ class ConstantCreator extends ConstantVisitor<ConstantInfo?>
ConstantInfo? visitSymbolConstant(SymbolConstant constant) {
ClassInfo info = translator.classInfo[translator.symbolClass]!;
translator.functions.recordClassAllocation(info.classId);
w.RefType stringType = translator
.classInfo[translator.coreTypes.stringClass]!.repr.nonNullableType;
w.RefType stringType = translator.stringType;
final String symbolStringValue = constants.minifySymbol(constant.name);
StringConstant nameConstant = StringConstant(symbolStringValue);
bool lazy = ensureConstant(nameConstant)?.isLazy ?? false;
@@ -1205,8 +1204,7 @@ class ConstantCreator extends ConstantVisitor<ConstantInfo?>
(b) {
b.pushObjectHeaderFields(translator, recordClassInfo);
for (Constant argument in arguments) {
constants.instantiateConstant(
b, argument, translator.topInfo.nullableType);
constants.instantiateConstant(b, argument, translator.topType);
}
b.struct_new(recordClassInfo.struct);
});
+3 -5
View File
@@ -203,7 +203,7 @@ class SelectorInfo {
}
assert(returns.length <= outputSets.length);
inputSets[0].add(isDynamicSubmoduleOverridable
? translator.topInfo.nonNullableType
? translator.topTypeNonNullable
: translator.translateType(receiver));
for (int i = 0; i < positional.length; i++) {
DartType type = positional[i];
@@ -223,7 +223,7 @@ class SelectorInfo {
DartType type = returns[i];
outputSets[i].add(translator.translateReturnType(type));
} else {
outputSets[i].add(translator.topInfo.nullableType);
outputSets[i].add(translator.topType);
}
}
}
@@ -253,9 +253,7 @@ class SelectorInfo {
// create a dummy signature with top types. Receivers specifically should
// be non-nullable since we must be invoking a selector on some object.
assert(!isReceiver || isDynamicSubmoduleOverridable);
return isReceiver
? translator.topInfo.nonNullableType
: translator.topInfo.nullableType;
return isReceiver ? translator.topTypeNonNullable : translator.topType;
}
if (!ensureBoxed && types.length == 1 && types.single.isPrimitive) {
// Unboxed primitive.
+12 -12
View File
@@ -136,7 +136,7 @@ class _DynamicForwarderCodeGenerator extends CodeGenerator {
final b = function.body;
b.local_get(receiverLocal);
b.struct_get(translator.topInfo.struct, FieldIndex.classId);
b.loadClassId(translator, receiverLocal.type);
b.classIdSearch(ranges, outputs, (Reference target) {
final targetMember = target.asMember;
final Reference targetReference;
@@ -184,7 +184,7 @@ class _DynamicForwarderCodeGenerator extends CodeGenerator {
final b = function.body;
b.local_get(receiverLocal);
b.struct_get(translator.topInfo.struct, FieldIndex.classId);
b.loadClassId(translator, receiverLocal.type);
b.classIdSearch(ranges, [positionalArgLocal.type], (Reference target) {
final Member targetMember = target.asMember;
b.local_get(receiverLocal);
@@ -237,7 +237,7 @@ class _DynamicForwarderCodeGenerator extends CodeGenerator {
final targetMemberParamInfo = translator.paramInfoForDirectCall(target);
b.local_get(receiverLocal);
b.struct_get(translator.topInfo.struct, FieldIndex.classId);
b.loadClassId(translator, receiverLocal.type);
b.local_set(classIdLocal);
final classIdNoMatch = b.block();
@@ -350,7 +350,7 @@ class _DynamicForwarderCodeGenerator extends CodeGenerator {
b.local_get(adjustedPositionalArgsLocal);
b.i32_const(optionalParamIdx);
translator.constants
.instantiateConstant(b, param, translator.topInfo.nullableType);
.instantiateConstant(b, param, translator.topType);
b.array_set(translator.nullableObjectArrayType);
b.end();
}
@@ -458,13 +458,13 @@ class _DynamicForwarderCodeGenerator extends CodeGenerator {
translator.constants.instantiateConstant(
b,
(functionNodeDefaultValue as ConstantExpression).constant,
translator.topInfo.nullableType);
translator.topType);
} else {
// Not used by the member
translator.constants.instantiateConstant(
b,
paramInfoDefaultValue!,
translator.topInfo.nullableType,
translator.topType,
);
}
b.array_set(translator.nullableObjectArrayType);
@@ -503,7 +503,7 @@ class _DynamicForwarderCodeGenerator extends CodeGenerator {
}
}
final getterValueLocal = b.addLocal(translator.topInfo.nullableType);
final getterValueLocal = b.addLocal(translator.topType);
void handleGetterSelector(SelectorInfo selector) {
for (final (:range, :target)
in selector.targets(unchecked: false).targetRanges) {
@@ -516,7 +516,7 @@ class _DynamicForwarderCodeGenerator extends CodeGenerator {
}
b.local_get(receiverLocal);
b.struct_get(translator.topInfo.struct, FieldIndex.classId);
b.loadClassId(translator, receiverLocal.type);
b.i32_const(classId);
b.i32_eq();
b.if_();
@@ -539,8 +539,8 @@ class _DynamicForwarderCodeGenerator extends CodeGenerator {
translator.convertType(
b, receiverLocal.type, targetFunction.type.inputs.first);
translator.callFunction(targetFunction, b);
translator.convertType(b, targetFunction.type.outputs.single,
translator.topInfo.nullableType);
translator.convertType(
b, targetFunction.type.outputs.single, translator.topType);
b.local_tee(getterValueLocal);
// Throw `NoSuchMethodError` if the value is null
@@ -550,7 +550,7 @@ class _DynamicForwarderCodeGenerator extends CodeGenerator {
b.local_tee(receiverLocal);
// Invoke "call" if the value is not a closure
b.struct_get(translator.topInfo.struct, FieldIndex.classId);
b.loadClassId(translator, receiverLocal.type);
b.i32_const(
(translator.closureInfo.classId as AbsoluteClassId).value);
b.i32_ne();
@@ -799,7 +799,7 @@ void generateNoSuchMethodCall(
pushReceiver();
if (callPolymorphicDispatcher) {
b.struct_get(translator.topInfo.struct, FieldIndex.classId);
b.loadClassId(translator, translator.topTypeNonNullable);
pushReceiver();
}
pushInvocationObject();
+4 -5
View File
@@ -894,7 +894,7 @@ class DynamicModuleInfo {
// If any input is not a RefType (i.e. it's an unboxed value) then wrap it
// so the updated signature works.
if (localSignature.inputs.any((i) => i is! w.RefType)) {
final receiverLocal = b.addLocal(translator.topInfo.nullableType);
final receiverLocal = b.addLocal(translator.topTypeNonNullable);
b.local_set(receiverLocal);
final locals = <w.Local>[];
for (final input in localSignature.inputs.reversed) {
@@ -910,7 +910,7 @@ class DynamicModuleInfo {
}
final idLocal = b.addLocal(w.NumType.i32);
b.struct_get(translator.topInfo.struct, FieldIndex.classId);
b.loadClassId(translator, translator.topTypeNonNullable);
b.local_tee(idLocal);
b.i32_const(useUncheckedEntry ? 1 : 0);
b.local_get(idLocal);
@@ -967,8 +967,8 @@ class ConstantCanonicalizer extends ConstantVisitor<void> {
ConstantCanonicalizer(this.translator, this.b, this.valueLocal);
late final _checkerType = translator.typesBuilder.defineFunction([
translator.topInfo.nonNullableType,
translator.topInfo.nonNullableType,
translator.topTypeNonNullable,
translator.topTypeNonNullable,
], const [
w.NumType.i32
]);
@@ -1188,7 +1188,6 @@ class ConstantCanonicalizer extends ConstantVisitor<void> {
/// values are already canonicalized.
void _defaultChecker(w.InstructionsBuilder b, ClassInfo classInfo,
{Set<int>? fieldsToInclude}) {
classInfo = classInfo.repr;
final structType = classInfo.struct;
final structRefType = classInfo.nonNullableType;
final castedLocal1 = b.addLocal(structRefType);
+15 -17
View File
@@ -416,7 +416,7 @@ class Intrinsifier {
if (cls == translator.wasmAnyRefClass) {
if (name == "isObject") {
codeGen.translateExpression(receiver, w.RefType.any(nullable: false));
b.ref_test(translator.topInfo.nonNullableType);
b.ref_test(translator.topTypeNonNullable);
return w.NumType.i32;
} else if (name == "isI31") {
codeGen.translateExpression(receiver, w.RefType.any(nullable: false));
@@ -475,14 +475,14 @@ class Intrinsifier {
// WasmAnyRef.toObject
if (cls == translator.wasmAnyRefClass && name == "toObject") {
w.Label succeed = b.block(const [], [translator.topInfo.nonNullableType]);
w.Label succeed = b.block(const [], [translator.topTypeNonNullable]);
codeGen.translateExpression(
receiver, const w.RefType.any(nullable: false));
b.br_on_cast(succeed, const w.RefType.any(nullable: false),
translator.topInfo.nonNullableType);
translator.topTypeNonNullable);
codeGen.throwWasmRefError("a Dart object");
b.end(); // succeed
return translator.topInfo.nonNullableType;
return translator.topTypeNonNullable;
}
// Wasm(I32|I64|F32|F64) conversions
@@ -1203,14 +1203,13 @@ class Intrinsifier {
// Ensure we compile the target function & export it.
translator.functions.getFunction(target.reference);
final topType = translator.topInfo.nullableType;
final topType = translator.topType;
codeGen.translateExpression(NullLiteral(), topType);
return topType;
case StaticIntrinsic.getID:
ClassInfo info = translator.topInfo;
codeGen.translateExpression(
node.arguments.positional.single, info.nonNullableType);
b.struct_get(info.struct, FieldIndex.classId);
final type = translator.topTypeNonNullable;
codeGen.translateExpression(node.arguments.positional.single, type);
b.loadClassId(translator, type);
return w.NumType.i32;
// dart:ffi static functions
@@ -1504,8 +1503,8 @@ class Intrinsifier {
translator.classIdNumbering.getConcreteSubclassRanges(baseClass);
final object = node.arguments.positional.single;
codeGen.translateExpression(object, w.RefType.any(nullable: false));
b.struct_get(translator.topInfo.struct, FieldIndex.classId);
codeGen.translateExpression(object, translator.topTypeNonNullable);
b.loadClassId(translator, translator.topTypeNonNullable);
b.emitClassIdRangeCheck(ranges);
return w.NumType.i32;
@@ -1679,11 +1678,11 @@ class Intrinsifier {
// If either is `null`, or their class IDs are different, return false.
b.local_get(first);
b.br_on_null(fail);
b.struct_get(translator.topInfo.struct, FieldIndex.classId);
b.loadClassId(translator, translator.topTypeNonNullable);
b.local_tee(cid);
b.local_get(second);
b.br_on_null(fail);
b.struct_get(translator.topInfo.struct, FieldIndex.classId);
b.loadClassId(translator, translator.topTypeNonNullable);
b.i32_ne();
b.br_if(fail);
@@ -1737,8 +1736,7 @@ class Intrinsifier {
case MemberIntrinsic.identityHashCode:
final w.Local arg = paramLocals[0];
final w.Local nonNullArg =
b.addLocal(translator.topInfo.nonNullableType);
final w.Local nonNullArg = b.addLocal(translator.topTypeNonNullable);
final List<int> classIds = translator.valueClasses.keys
.map((cls) =>
(translator.classInfo[cls]!.classId as AbsoluteClassId).value)
@@ -1747,7 +1745,7 @@ class Intrinsifier {
// If the argument is `null`, return the hash code of `null`.
final w.Label notNull =
b.block(const [], [translator.topInfo.nonNullableType]);
b.block(const [], [translator.topTypeNonNullable]);
b.local_get(arg);
b.br_on_non_null(notNull);
b.i64_const(null.hashCode);
@@ -1760,7 +1758,7 @@ class Intrinsifier {
final List<w.Label> labels =
List.generate(classIds.length, (_) => b.block());
b.local_get(nonNullArg);
b.struct_get(translator.topInfo.struct, FieldIndex.classId);
b.loadClassId(translator, translator.topTypeNonNullable);
int labelIndex = 0;
final List<w.Label> targets = List.generate(classIds.last + 1, (id) {
return id == classIds[labelIndex]
+14 -18
View File
@@ -316,17 +316,14 @@ class ExceptionHandlerStack {
int nextHandlerIdx = _handlers.length - 1;
final b = codeGen.b;
for (final int nCoveredHandlers in _tryBlockNumHandlers.reversed) {
final stackTraceLocal =
b.addLocal(codeGen.translator.stackTraceInfo.repr.nonNullableType);
final stackTraceLocal = b.addLocal(codeGen.translator.stackTraceType);
final exceptionLocal =
b.addLocal(codeGen.translator.topInfo.nonNullableType);
final exceptionLocal = b.addLocal(codeGen.translator.topTypeNonNullable);
final previousException =
b.addLocal(codeGen.translator.topInfo.nullableType);
final previousException = b.addLocal(codeGen.translator.topType);
final previousStackTrace =
b.addLocal(codeGen.translator.stackTraceInfo.repr.nullableType);
b.addLocal(codeGen.translator.stackTraceTypeNullable);
_previousCatchLocals.add((previousException, previousStackTrace));
@@ -1049,7 +1046,7 @@ abstract class StateMachineCodeGenerator extends AstCodeGenerator {
setVariable(catch_.exception!, () {
getSuspendStateCurrentException();
// Type test already passed, convert the exception.
translator.convertType(b, translator.topInfo.nullableType,
translator.convertType(b, translator.topType,
translator.translateType(catch_.exception!.type));
});
setVariable(catch_.stackTrace!, () => getSuspendStateCurrentStackTrace());
@@ -1194,21 +1191,21 @@ abstract class StateMachineCodeGenerator extends AstCodeGenerator {
if (firstFinalizer == null) {
emitReturn(() {
if (value == null) {
b.ref_null(translator.topInfo.struct);
b.ref_null(translator.topType.heapType);
} else {
translateExpression(value, translator.topInfo.nullableType);
translateExpression(value, translator.topType);
}
});
return;
}
if (value == null) {
b.ref_null(translator.topInfo.struct);
b.ref_null(translator.topType.heapType);
} else {
translateExpression(value, translator.topInfo.nullableType);
translateExpression(value, translator.topType);
}
final returnValueLocal = addLocal(translator.topInfo.nullableType);
final returnValueLocal = addLocal(translator.topType);
b.local_set(returnValueLocal);
// Set return value for the last finalizer to return.
@@ -1230,12 +1227,11 @@ abstract class StateMachineCodeGenerator extends AstCodeGenerator {
@override
w.ValueType visitThrow(Throw node, w.ValueType expectedType) {
final exceptionLocal = addLocal(translator.topInfo.nonNullableType);
translateExpression(node.expression, translator.topInfo.nonNullableType);
final exceptionLocal = addLocal(translator.topTypeNonNullable);
translateExpression(node.expression, translator.topTypeNonNullable);
b.local_set(exceptionLocal);
final stackTraceLocal =
addLocal(translator.stackTraceInfo.repr.nonNullableType);
final stackTraceLocal = addLocal(translator.stackTraceType);
call(translator.stackTraceCurrent.reference);
b.local_set(stackTraceLocal);
@@ -1320,6 +1316,6 @@ abstract class StateMachineCodeGenerator extends AstCodeGenerator {
/// Same as [_getVariable], but boxes the value if it's not already boxed.
void _getVariableBoxed(VariableDeclaration variable) {
final varType = _getVariable(variable);
translator.convertType(b, varType, translator.topInfo.nullableType);
translator.convertType(b, varType, translator.topType);
}
}
+3 -4
View File
@@ -50,9 +50,8 @@ mixin SyncStarCodeGeneratorMixin on StateMachineEntryAstCodeGenerator {
translator.moduleForReference(enclosingMember.reference).functions.define(
translator.typesBuilder.defineFunction([
suspendStateInfo.nonNullableType, // _SuspendState
translator.topInfo.nullableType, // Object?, error value
translator.stackTraceInfo.repr
.nullableType // StackTrace?, error stack trace
translator.topType, // Object?, error value
translator.stackTraceTypeNullable // StackTrace?, error stack trace
], const [
// bool for whether the generator has more to do
w.NumType.i32
@@ -235,7 +234,7 @@ class SyncStarStateMachineCodeGenerator extends StateMachineCodeGenerator {
// `_yieldStarIterable` for `yield*`.
b.local_get(_suspendStateLocal);
b.struct_get(suspendStateInfo.struct, FieldIndex.suspendStateIterator);
translateExpression(node.expression, translator.topInfo.nullableType);
translateExpression(node.expression, translator.topType);
if (node.isYieldStar) {
b.ref_cast(translator.objectInfo.nonNullableType);
b.struct_set(syncStarIteratorInfo.struct,
+2 -4
View File
@@ -25,10 +25,8 @@ class ExceptionTag {
/// [stackTraceInfo.nonNullableType] to hold a stack trace. This single
/// exception tag is used to throw and catch all Dart exceptions.
w.Tag _defineExceptionTag() {
final w.FunctionType tagType = translator.typesBuilder.defineFunction([
translator.topInfo.nonNullableType,
translator.stackTraceInfo.repr.nonNullableType
], const []);
final w.FunctionType tagType = translator.typesBuilder.defineFunction(
[translator.topTypeNonNullable, translator.stackTraceType], const []);
return translator.mainModule.tags.define(tagType);
}
}
+53 -28
View File
@@ -228,7 +228,6 @@ class Translator with KernelNodes {
closureImplementations = {};
// Some convenience accessors for commonly used values.
late final ClassInfo topInfo = classes[0];
late final ClassInfo objectInfo = classInfo[coreTypes.objectClass]!;
late final ClassInfo closureInfo = classInfo[closureClass]!;
late final ClassInfo stackTraceInfo = classInfo[stackTraceClass]!;
@@ -254,6 +253,37 @@ class Translator with KernelNodes {
late final boxedDoubleType =
boxedDoubleClass.getThisType(coreTypes, Nullability.nonNullable);
// The wasm type used to hold values of Dart top types
// (e.g. `Object?`, `dynamic`)
late final w.RefType topType = classes[0].nullableType;
// The wasm type used to hold values of Dart top types excluding null
// (e.g. `Object`)
late final w.RefType topTypeNonNullable = topType.withNullability(false);
// The wasm type used to hold values of `StackTrace`
late final w.RefType stackTraceType =
translateType(coreTypes.stackTraceNonNullableRawType) as w.RefType;
// The wasm type used to hold values of `StackTrace?`
late final w.RefType stackTraceTypeNullable =
stackTraceType.withNullability(true);
// The wasm type used to hold values of `Type`
late final w.RefType runtimeTypeType =
translateType(coreTypes.typeNonNullableRawType) as w.RefType;
// The wasm type used to hold values of `Type?`
late final w.RefType runtimeTypeTypeNullable =
runtimeTypeType.withNullability(true);
// The wasm type used to hold values of `String`
late final w.RefType stringType =
translateType(coreTypes.stringNonNullableRawType) as w.RefType;
// The wasm type used to hold values of `String?`
late final w.RefType stringTypeNullable = stringType.withNullability(true);
final Map<w.ModuleBuilder, PartialInstantiator> _partialInstantiators = {};
PartialInstantiator getPartialInstantiatorForModule(w.ModuleBuilder module) {
return _partialInstantiators[module] ??= PartialInstantiator(this, module);
@@ -340,14 +370,14 @@ class Translator with KernelNodes {
// Named arguments, represented as array of symbol and object pairs
nullableObjectArrayTypeRef,
], [
topInfo.nullableType
topType,
]);
/// Type of a dynamic invocation forwarder function.
late final w.FunctionType dynamicInvocationForwarderFunctionType =
typesBuilder.defineFunction([
// Receiver
topInfo.nonNullableType,
topTypeNonNullable,
// Type arguments
typeArrayTypeRef,
@@ -358,28 +388,28 @@ class Translator with KernelNodes {
// Named arguments, represented as array of symbol and object pairs
nullableObjectArrayTypeRef,
], [
topInfo.nullableType
topType,
]);
/// Type of a dynamic get forwarder function.
late final w.FunctionType dynamicGetForwarderFunctionType =
typesBuilder.defineFunction([
// Receiver
topInfo.nonNullableType,
topTypeNonNullable,
], [
topInfo.nullableType
topType,
]);
/// Type of a dynamic set forwarder function.
late final w.FunctionType dynamicSetForwarderFunctionType =
typesBuilder.defineFunction([
// Receiver
topInfo.nonNullableType,
topTypeNonNullable,
// Positional argument
topInfo.nullableType,
topType,
], [
topInfo.nullableType
topType,
]);
// Module predicates and helpers
@@ -604,13 +634,14 @@ class Translator with KernelNodes {
dynamicModuleInfo!.callOverridableDispatch(b, selector, interfaceTarget!,
useUncheckedEntry: useUncheckedEntry);
} else {
b.struct_get(topInfo.struct, FieldIndex.classId);
final offset = selector.targets(unchecked: useUncheckedEntry).offset;
if (offset == null) {
b.unreachable();
return;
}
final receiverType = selector.signature.inputs.first;
b.loadClassId(this, receiverType);
if (offset != 0) {
b.i32_const(offset);
b.i32_add();
@@ -804,10 +835,10 @@ class Translator with KernelNodes {
}
// Regular class.
return classInfo[cls]!.repr.typeWithNullability(nullable);
return classInfo[cls]!.repr.withNullability(nullable);
}
if (type is DynamicType || type is VoidType) {
return topInfo.nullableType;
return topType;
}
if (type is NullType) {
return const w.RefType.none(nullable: true);
@@ -836,7 +867,7 @@ class Translator with KernelNodes {
return translateStorageType(type.left);
}
if (type is FutureOrType) {
return topInfo.typeWithNullability(nullable);
return topType.withNullability(nullable);
}
if (type is FunctionType) {
if (dynamicModuleSupportEnabled) {
@@ -1406,10 +1437,7 @@ class Translator with KernelNodes {
// Otherwise we use [boxClass] to represent `this`.
cls = boxClass;
}
final representationClassInfo = classInfo[cls]!.repr;
return nullable
? representationClassInfo.nullableType
: representationClassInfo.nonNullableType;
return classInfo[cls]!.repr.withNullability(nullable);
}
/// Get the Wasm table declared by [field], or `null` if [field] is not a
@@ -2074,8 +2102,7 @@ class _ClosureDynamicEntryGenerator implements CodeGenerator {
b.local_get(typeArgsListLocal);
b.i32_const(typeIdx);
b.array_get(translator.typeArrayType);
translator.convertType(
b, translator.topInfo.nullableType, targetInputs[inputIdx]);
translator.convertType(b, translator.topType, targetInputs[inputIdx]);
inputIdx += 1;
}
@@ -2092,17 +2119,16 @@ class _ClosureDynamicEntryGenerator implements CodeGenerator {
b.local_get(posArgsListLocal);
b.array_len();
b.i32_lt_u();
b.if_([], [translator.topInfo.nullableType]);
b.if_([], [translator.topType]);
b.local_get(posArgsListLocal);
b.i32_const(posIdx);
b.array_get(translator.nullableObjectArrayType);
b.else_();
translator.constants.instantiateConstant(
b, paramInfo.positional[posIdx]!, translator.topInfo.nullableType);
b, paramInfo.positional[posIdx]!, translator.topType);
b.end();
}
translator.convertType(
b, translator.topInfo.nullableType, targetInputs[inputIdx]);
translator.convertType(b, translator.topType, targetInputs[inputIdx]);
inputIdx += 1;
}
@@ -2149,19 +2175,19 @@ class _ClosureDynamicEntryGenerator implements CodeGenerator {
// Parameter may not be passed.
b.local_get(namedArgValueIndexLocal);
b.ref_is_null();
b.if_([], [translator.topInfo.nullableType]);
b.if_([], [translator.topType]);
if (functionNodeDefaultValue != null) {
// Used by the member, has a default value
translator.constants.instantiateConstant(
b,
(functionNodeDefaultValue as ConstantExpression).constant,
translator.topInfo.nullableType);
translator.topType);
} else {
// Not used by the member
translator.constants.instantiateConstant(
b,
paramInfoDefaultValue!,
translator.topInfo.nullableType,
translator.topType,
);
}
b.else_(); // value index not null
@@ -2171,8 +2197,7 @@ class _ClosureDynamicEntryGenerator implements CodeGenerator {
b.i32_wrap_i64();
b.array_get(translator.nullableObjectArrayType);
b.end();
translator.convertType(
b, translator.topInfo.nullableType, targetInputs[inputIdx]);
translator.convertType(b, translator.topType, targetInputs[inputIdx]);
}
inputIdx += 1;
}
+8 -8
View File
@@ -400,7 +400,7 @@ class Types {
b.comment("type check against $testedAgainstType");
w.Local? operandTemp;
if (translator.options.verifyTypeChecks) {
operandTemp = b.addLocal(translator.topInfo.nullableType);
operandTemp = b.addLocal(translator.topType);
b.local_tee(operandTemp);
}
final checkOnlyNullAssignability =
@@ -658,8 +658,8 @@ class IsCheckers extends _TypeCheckers {
return cache.putIfAbsent(testedAgainstType, () {
final typeType = translator.translateType(translator.typeType);
final argumentType = operandIsNullable
? translator.topInfo.nullableType
: translator.topInfo.nonNullableType;
? translator.topType
: translator.topTypeNonNullable;
final signature = w.FunctionType(
[argumentType, for (int i = 0; i < argumentCount; ++i) typeType],
[w.NumType.i32]);
@@ -701,8 +701,8 @@ class AsCheckers extends _TypeCheckers {
return cache.putIfAbsent(testedAgainstType, () {
final returnType = translator.translateType(testedAgainstType);
final argumentType = operandIsNullable
? translator.topInfo.nullableType
: translator.topInfo.nonNullableType;
? translator.topType
: translator.topTypeNonNullable;
final typeType = translator.translateType(translator.typeType);
final signature = w.FunctionType(
[argumentType, for (int i = 0; i < argumentCount; ++i) typeType],
@@ -812,7 +812,7 @@ class IsCheckerCodeGenerator implements CodeGenerator {
w.Label nullLabel = b.block(const [], const []);
b.local_get(operand);
b.br_on_null(nullLabel);
final nonNullableOperand = b.addLocal(translator.topInfo.nonNullableType);
final nonNullableOperand = b.addLocal(translator.topTypeNonNullable);
b.local_get(operand);
b.ref_cast(nonNullableOperand.type as w.RefType);
b.local_set(nonNullableOperand);
@@ -885,7 +885,7 @@ class IsCheckerCodeGenerator implements CodeGenerator {
final ranges = translator.classIdNumbering
.getConcreteClassIdRangeForClass(interfaceClass);
b.local_get(operand);
b.struct_get(translator.topInfo.struct, FieldIndex.classId);
b.loadClassId(translator, operand.type);
if (translator.isDynamicSubmodule) {
// Only types that are not dynamic module extendable can get here.
final classIdLocal = b.addLocal(w.NumType.i32);
@@ -1054,7 +1054,7 @@ class AsCheckerCodeGenerator implements CodeGenerator {
}
b.unreachable();
b.end();
b.end(); // asCheckBlock
b.local_get(b.locals[0]);
translator.convertType(b, signature.inputs.first, signature.outputs.single);
+1 -1
View File
@@ -7,7 +7,7 @@ part of "internal_patch.dart";
@pragma("wasm:entry-point")
class ClassID {
@pragma("wasm:intrinsic")
external static WasmI32 getID(Object? value);
external static WasmI32 getID(Object value);
@pragma("wasm:class-id", "dart.typed_data#_ExternalUint8Array")
external static WasmI32 get cidExternalUint8Array;