Skip to content

Commit 203344c

Browse files
joshualittCommit Queue
authored and
Commit Queue
committed
[dart2wasm] Add support for runtime types for function types.
Change-Id: I3c446b8ef7dd9b1edc612b9e27893870a25c54d4 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/261160 Reviewed-by: Aske Simon Christensen <[email protected]> Commit-Queue: Joshua Litt <[email protected]>
1 parent 0e2483c commit 203344c

File tree

9 files changed

+54
-20
lines changed

9 files changed

+54
-20
lines changed

pkg/dart2wasm/lib/class_info.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ class FieldIndex {
2525
static const hashBaseData = 4;
2626
static const closureContext = 2;
2727
static const closureVtable = 3;
28+
static const closureRuntimeType = 4;
2829
static const typeIsNullable = 2;
2930
static const interfaceTypeTypeArguments = 4;
3031
static const functionTypeNamedParameters = 6;

pkg/dart2wasm/lib/closures.dart

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,6 @@ class ClosureLayouter extends RecursiveVisitor {
115115
Set<Constant> visitedConstants = Set.identity();
116116

117117
// Base struct for vtables.
118-
// TODO(joshualitt): Add function type metadata here.
119118
late final w.StructType vtableBaseStruct = m.addStructType("#VtableBase");
120119

121120
// Base struct for closures.
@@ -129,13 +128,15 @@ class ClosureLayouter extends RecursiveVisitor {
129128
// - An identity hash
130129
// - A context reference (used for `this` in tear-offs)
131130
// - A vtable reference
131+
// - A type
132132
return m.addStructType("#ClosureBase",
133133
fields: [
134134
w.FieldType(w.NumType.i32),
135135
w.FieldType(w.NumType.i32),
136136
w.FieldType(w.RefType.data(nullable: false)),
137137
w.FieldType(w.RefType.def(vtableStruct, nullable: false),
138-
mutable: false)
138+
mutable: false),
139+
w.FieldType(typeType, mutable: false)
139140
],
140141
superType: superType);
141142
}

pkg/dart2wasm/lib/code_generator.dart

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,9 @@ class CodeGenerator extends ExpressionVisitor1<w.ValueType, w.ValueType>
177177
}
178178

179179
void generateTearOffGetter(Procedure procedure) {
180+
_initializeThis(member);
181+
DartType functionType =
182+
procedure.function.computeThisFunctionType(Nullability.nonNullable);
180183
ClosureImplementation closure = translator.getTearOffClosure(procedure);
181184
w.StructType struct = closure.representation.closureStruct;
182185

@@ -187,6 +190,7 @@ class CodeGenerator extends ExpressionVisitor1<w.ValueType, w.ValueType>
187190
b.i32_const(initialIdentityHash);
188191
b.local_get(paramLocals[0]);
189192
b.global_get(closure.vtable);
193+
types.makeType(this, functionType);
190194
b.struct_new(struct);
191195
b.end();
192196
}
@@ -1752,6 +1756,7 @@ class CodeGenerator extends ExpressionVisitor1<w.ValueType, w.ValueType>
17521756
// Super tear-off
17531757
w.StructType closureStruct = _pushClosure(
17541758
translator.getTearOffClosure(target),
1759+
target.function.computeThisFunctionType(Nullability.nonNullable),
17551760
() => visitThis(w.RefType.data(nullable: false)));
17561761
return w.RefType.def(closureStruct, nullable: false);
17571762
}
@@ -1948,10 +1953,14 @@ class CodeGenerator extends ExpressionVisitor1<w.ValueType, w.ValueType>
19481953
lambda.function,
19491954
ParameterInfo.fromLocalFunction(functionNode),
19501955
"closure wrapper at ${functionNode.location}");
1951-
return _pushClosure(closure, () => _pushContext(functionNode));
1956+
return _pushClosure(
1957+
closure,
1958+
functionNode.computeThisFunctionType(Nullability.nonNullable),
1959+
() => _pushContext(functionNode));
19521960
}
19531961

1954-
w.StructType _pushClosure(ClosureImplementation closure, void pushContext()) {
1962+
w.StructType _pushClosure(ClosureImplementation closure,
1963+
DartType functionType, void pushContext()) {
19551964
w.StructType struct = closure.representation.closureStruct;
19561965

19571966
ClassInfo info = translator.classInfo[translator.functionClass]!;
@@ -1961,6 +1970,7 @@ class CodeGenerator extends ExpressionVisitor1<w.ValueType, w.ValueType>
19611970
b.i32_const(initialIdentityHash);
19621971
pushContext();
19631972
b.global_get(closure.vtable);
1973+
types.makeType(this, functionType);
19641974
b.struct_new(struct);
19651975

19661976
return struct;

pkg/dart2wasm/lib/constants.dart

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import 'package:dart2wasm/translator.dart';
1212
import 'package:dart2wasm/types.dart';
1313

1414
import 'package:kernel/ast.dart';
15-
import 'package:kernel/type_algebra.dart' show substitute;
15+
import 'package:kernel/type_algebra.dart' show substitute, Substitution;
1616

1717
import 'package:wasm_builder/wasm_builder.dart' as w;
1818

@@ -698,6 +698,9 @@ class ConstantCreator extends ConstantVisitor<ConstantInfo?> {
698698
@override
699699
ConstantInfo? visitStaticTearOffConstant(StaticTearOffConstant constant) {
700700
Procedure member = constant.targetReference.asProcedure;
701+
Constant functionTypeConstant = TypeLiteralConstant(
702+
member.function.computeThisFunctionType(Nullability.nonNullable));
703+
ensureConstant(functionTypeConstant);
701704
ClosureImplementation closure = translator.getTearOffClosure(member);
702705
w.StructType struct = closure.representation.closureStruct;
703706
w.RefType type = w.RefType.def(struct, nullable: false);
@@ -709,6 +712,8 @@ class ConstantCreator extends ConstantVisitor<ConstantInfo?> {
709712
b.i32_const(initialIdentityHash);
710713
b.global_get(translator.globals.dummyGlobal); // Dummy context
711714
b.global_get(closure.vtable);
715+
constants.instantiateConstant(
716+
function, b, functionTypeConstant, this.types.nonNullableTypeType);
712717
b.struct_new(struct);
713718
});
714719
}
@@ -720,8 +725,17 @@ class ConstantCreator extends ConstantVisitor<ConstantInfo?> {
720725
List<ConstantInfo> types = constant.types
721726
.map((c) => ensureConstant(TypeLiteralConstant(c))!)
722727
.toList();
723-
ClosureImplementation tearOffClosure = translator
724-
.getTearOffClosure(tearOffConstant.targetReference.asProcedure);
728+
Procedure tearOffProcedure = tearOffConstant.targetReference.asProcedure;
729+
FunctionType tearOffFunctionType = tearOffProcedure.function
730+
.computeThisFunctionType(Nullability.nonNullable);
731+
FunctionType instantiatedFunctionType = Substitution.fromPairs(
732+
tearOffFunctionType.typeParameters, constant.types)
733+
.substituteType(tearOffFunctionType) as FunctionType;
734+
Constant functionTypeConstant =
735+
TypeLiteralConstant(instantiatedFunctionType);
736+
ensureConstant(functionTypeConstant);
737+
ClosureImplementation tearOffClosure =
738+
translator.getTearOffClosure(tearOffProcedure);
725739
int positionalCount = tearOffConstant.function.positionalParameters.length;
726740
List<String> names =
727741
tearOffConstant.function.namedParameters.map((p) => p.name!).toList();
@@ -771,7 +785,6 @@ class ConstantCreator extends ConstantVisitor<ConstantInfo?> {
771785
}
772786

773787
void makeVtable() {
774-
// TODO(joshualitt): Generate function type metadata here.
775788
for (int posArgCount = 0;
776789
posArgCount <= positionalCount;
777790
posArgCount++) {
@@ -787,6 +800,8 @@ class ConstantCreator extends ConstantVisitor<ConstantInfo?> {
787800
b.i32_const(initialIdentityHash);
788801
b.global_get(translator.globals.dummyGlobal); // Dummy context
789802
makeVtable();
803+
constants.instantiateConstant(
804+
function, b, functionTypeConstant, this.types.nonNullableTypeType);
790805
b.struct_new(struct);
791806
});
792807
}

pkg/dart2wasm/lib/intrinsics.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -716,6 +716,13 @@ class Intrinsifier {
716716
return translator.types.makeTypeRulesSubstitutions(b);
717717
case "_getTypeNames":
718718
return translator.types.makeTypeNames(b);
719+
case "_getFunctionTypeRuntimeType":
720+
Expression object = node.arguments.positional[0];
721+
w.StructType closureBase =
722+
translator.closureLayouter.closureBaseStruct;
723+
codeGen.wrap(object, w.RefType.def(closureBase, nullable: true));
724+
b.struct_get(closureBase, FieldIndex.closureRuntimeType);
725+
return translator.types.typeClassInfo.nonNullableType;
719726
case "_getInterfaceTypeRuntimeType":
720727
Expression object = node.arguments.positional[0];
721728
Expression typeArguments = node.arguments.positional[1];

pkg/dart2wasm/lib/translator.dart

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -801,7 +801,6 @@ class Translator {
801801
w.RefType.def(representation.vtableStruct, nullable: false),
802802
mutable: false));
803803
w.Instructions ib = vtable.initializer;
804-
// TODO(joshualitt): Generate function type metadata here.
805804
for (int posArgCount = 0; posArgCount <= positionalCount; posArgCount++) {
806805
fillVtableEntry(ib, posArgCount, const []);
807806
}

pkg/dart2wasm/lib/types.dart

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -431,10 +431,9 @@ class Types {
431431
void emitTypeTest(CodeGenerator codeGen, DartType type, DartType operandType,
432432
TreeNode node) {
433433
w.Instructions b = codeGen.b;
434-
if (type is FunctionType) {
435-
// TODO(joshualitt): We can enable type tests for [FunctionType] after
436-
// enabling `.runtimeType` for [FunctionType].
437-
print("Not implemented: Type test with function type $type"
434+
if (type is FunctionType && isGenericFunction(type)) {
435+
// TODO(joshualitt): Finish generic function types.
436+
print("Not implemented: Type test with generic function type $type"
438437
" at ${node.location}");
439438
b.drop();
440439
b.i32_const(1);

sdk/lib/_internal/wasm/lib/object_patch.dart

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ external void _setHash(Object obj, int hash);
1111
external _Type _getInterfaceTypeRuntimeType(
1212
Object object, List<Type> typeArguments);
1313

14+
external _Type _getFunctionTypeRuntimeType(Object object);
15+
1416
@patch
1517
class Object {
1618
@patch
@@ -47,7 +49,13 @@ class Object {
4749
external Type get runtimeType;
4850

4951
@pragma("wasm:entry-point")
50-
_Type get _runtimeType => _getInterfaceTypeRuntimeType(this, _typeArguments);
52+
_Type get _runtimeType {
53+
if (ClassID.getID(this) == ClassID.cid_Function) {
54+
return _getFunctionTypeRuntimeType(this);
55+
} else {
56+
return _getInterfaceTypeRuntimeType(this, _typeArguments);
57+
}
58+
}
5159

5260
@patch
5361
String toString() => _toString(this);

sdk/lib/_internal/wasm/lib/type.dart

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -659,12 +659,6 @@ class _TypeUniverse {
659659
return true;
660660
}
661661

662-
// TODO(joshualitt): This is not correct, but it is necessary until we fully
663-
// implement RTI for FunctionTypes.
664-
if (isFunctionType(s) && (t.isFunction || t.isGenericFunction)) {
665-
return true;
666-
}
667-
668662
// Positional Function Types + Named Function Types:
669663
if (s.isGenericFunction && t.isGenericFunction) {
670664
// TODO(joshualitt): Implement case.

0 commit comments

Comments
 (0)