[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:
committed by
Commit Queue
parent
ac2fc57446
commit
2fc0c8bf08
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 =
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user