mirror of
https://github.com/dart-lang/sdk
synced 2024-09-18 20:01:19 +00:00
[dart2wasm] Use #ClosureBase
as representation type for Function
.
Also renamed the `_Function` class to `_Closure` and fixed the name of closure structs so they aren't all called `#ClosureBase`. Change-Id: I6b55cb9827fdffac751dfc3043f3a36e7a18f225 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/279091 Reviewed-by: Ömer Ağacan <omersa@google.com> Commit-Queue: Aske Simon Christensen <askesc@google.com>
This commit is contained in:
parent
5a5a83031b
commit
5d77ea8cfe
|
@ -61,7 +61,7 @@ class FieldIndex {
|
|||
check(translator.listBaseClass, "_data", FieldIndex.listArray);
|
||||
check(translator.hashFieldBaseClass, "_index", FieldIndex.hashBaseIndex);
|
||||
check(translator.hashFieldBaseClass, "_data", FieldIndex.hashBaseData);
|
||||
check(translator.functionClass, "context", FieldIndex.closureContext);
|
||||
check(translator.closureClass, "context", FieldIndex.closureContext);
|
||||
check(translator.typeClass, "isDeclaredNullable",
|
||||
FieldIndex.typeIsDeclaredNullable);
|
||||
check(translator.interfaceTypeClass, "typeArguments",
|
||||
|
@ -322,10 +322,10 @@ class ClassInfoCollector {
|
|||
void collect() {
|
||||
initializeTop();
|
||||
|
||||
// Subclasses of the `_Function` class are generated on the fly as fields
|
||||
// with function types are encountered. Therefore, `_Function` class must
|
||||
// Subclasses of the `_Closure` class are generated on the fly as fields
|
||||
// with function types are encountered. Therefore, `_Closure` class must
|
||||
// be early in the initialization order.
|
||||
initialize(translator.functionClass);
|
||||
initialize(translator.closureClass);
|
||||
|
||||
// Similarly `_Type` is needed for type parameter fields in classes and
|
||||
// needs to be initialized before we encounter a class with type
|
||||
|
|
|
@ -173,9 +173,7 @@ class ClosureLayouter extends RecursiveVisitor {
|
|||
|
||||
// Base struct for closures.
|
||||
late final w.StructType closureBaseStruct = _makeClosureStruct(
|
||||
"#ClosureBase",
|
||||
_vtableBaseStructBare,
|
||||
translator.classInfo[translator.functionClass]!.struct);
|
||||
"#ClosureBase", _vtableBaseStructBare, translator.closureInfo.struct);
|
||||
|
||||
late final w.RefType typeType =
|
||||
translator.classInfo[translator.typeClass]!.nonNullableType;
|
||||
|
@ -185,12 +183,12 @@ class ClosureLayouter extends RecursiveVisitor {
|
|||
w.StructType _makeClosureStruct(
|
||||
String name, w.StructType vtableStruct, w.StructType superType) {
|
||||
// A closure contains:
|
||||
// - A class ID (always the `_Function` class ID)
|
||||
// - A class ID (always the `_Closure` class ID)
|
||||
// - An identity hash
|
||||
// - A context reference (used for `this` in tear-offs)
|
||||
// - A vtable reference
|
||||
// - A `_FunctionType`
|
||||
return m.addStructType("#ClosureBase",
|
||||
return m.addStructType(name,
|
||||
fields: [
|
||||
w.FieldType(w.NumType.i32),
|
||||
w.FieldType(w.NumType.i32),
|
||||
|
@ -564,8 +562,6 @@ class ClosureLayouter extends RecursiveVisitor {
|
|||
ib.struct_new(instantiatedRepresentation.vtableStruct);
|
||||
ib.end();
|
||||
|
||||
ClassInfo info = translator.classInfo[translator.functionClass]!;
|
||||
|
||||
w.DefinedFunction instantiationFunction = m.addFunction(functionType, name);
|
||||
w.Local preciseClosure = instantiationFunction.addLocal(genericClosureType);
|
||||
w.Instructions b = instantiationFunction.body;
|
||||
|
@ -575,7 +571,7 @@ class ClosureLayouter extends RecursiveVisitor {
|
|||
w.Local typeParam(int i) => instantiationFunction.locals[1 + i];
|
||||
|
||||
// Header for the closure struct
|
||||
b.i32_const(info.classId);
|
||||
b.i32_const(translator.closureInfo.classId);
|
||||
b.i32_const(initialIdentityHash);
|
||||
|
||||
// Context for the instantiated closure, containing the original closure and
|
||||
|
|
|
@ -204,7 +204,7 @@ class CodeGenerator extends ExpressionVisitor1<w.ValueType, w.ValueType>
|
|||
ClosureImplementation closure = translator.getTearOffClosure(procedure);
|
||||
w.StructType struct = closure.representation.closureStruct;
|
||||
|
||||
ClassInfo info = translator.classInfo[translator.functionClass]!;
|
||||
ClassInfo info = translator.closureInfo;
|
||||
translator.functions.allocateClass(info.classId);
|
||||
|
||||
b.i32_const(info.classId);
|
||||
|
@ -2345,7 +2345,7 @@ class CodeGenerator extends ExpressionVisitor1<w.ValueType, w.ValueType>
|
|||
DartType functionType, void pushContext()) {
|
||||
w.StructType struct = closure.representation.closureStruct;
|
||||
|
||||
ClassInfo info = translator.classInfo[translator.functionClass]!;
|
||||
ClassInfo info = translator.closureInfo;
|
||||
translator.functions.allocateClass(info.classId);
|
||||
|
||||
b.i32_const(info.classId);
|
||||
|
|
|
@ -545,7 +545,7 @@ class ConstantCreator extends ConstantVisitor<ConstantInfo?> {
|
|||
w.StructType struct = closure.representation.closureStruct;
|
||||
w.RefType type = w.RefType.def(struct, nullable: false);
|
||||
return createConstant(constant, type, (function, b) {
|
||||
ClassInfo info = translator.classInfo[translator.functionClass]!;
|
||||
ClassInfo info = translator.closureInfo;
|
||||
translator.functions.allocateClass(info.classId);
|
||||
|
||||
b.i32_const(info.classId);
|
||||
|
@ -614,7 +614,7 @@ class ConstantCreator extends ConstantVisitor<ConstantInfo?> {
|
|||
final w.DefinedFunction dynamicCallEntry = makeDynamicCallEntry();
|
||||
|
||||
return createConstant(constant, type, (function, b) {
|
||||
ClassInfo info = translator.classInfo[translator.functionClass]!;
|
||||
ClassInfo info = translator.closureInfo;
|
||||
translator.functions.allocateClass(info.classId);
|
||||
|
||||
w.DefinedFunction makeTrampoline(
|
||||
|
|
|
@ -524,7 +524,7 @@ class Forwarder {
|
|||
|
||||
// Invoke "call" if the value is not a closure
|
||||
b.struct_get(translator.topInfo.struct, FieldIndex.classId);
|
||||
b.i32_const(translator.classInfo[translator.functionClass]!.classId);
|
||||
b.i32_const(translator.closureInfo.classId);
|
||||
b.i32_ne();
|
||||
b.if_();
|
||||
// Value is not a closure
|
||||
|
@ -539,8 +539,23 @@ class Forwarder {
|
|||
b.return_();
|
||||
b.end();
|
||||
|
||||
generateDynamicCall(translator, function, receiverLocal, typeArgsLocal,
|
||||
positionalArgsLocal, namedArgsLocal, noSuchMethodBlock);
|
||||
// Cast the closure to `#ClosureBase`
|
||||
final closureBaseType = w.RefType.def(
|
||||
translator.closureLayouter.closureBaseStruct,
|
||||
nullable: false);
|
||||
final closureLocal = function.addLocal(closureBaseType);
|
||||
b.local_get(receiverLocal);
|
||||
b.ref_cast(closureBaseType);
|
||||
b.local_set(closureLocal);
|
||||
|
||||
generateDynamicFunctionCall(
|
||||
translator,
|
||||
function,
|
||||
closureLocal,
|
||||
typeArgsLocal,
|
||||
positionalArgsLocal,
|
||||
namedArgsLocal,
|
||||
noSuchMethodBlock);
|
||||
b.return_();
|
||||
|
||||
b.end(); // class ID
|
||||
|
@ -592,15 +607,15 @@ enum _ForwarderKind {
|
|||
/// Generate code that checks shape and type of the closure and generate a call
|
||||
/// to its dynamic call vtable entry.
|
||||
///
|
||||
/// [closureLocal] should be a local with a closure value. Type of the local
|
||||
/// does not matter as long as it can be cast to `ref #ClosureBase`.
|
||||
/// [closureLocal] should be a local of type `ref #ClosureBase` containing a
|
||||
/// closure value.
|
||||
///
|
||||
/// [typeArgsLocal], [posArgsLocal], [namedArgsLocal] are the locals for type,
|
||||
/// positional, and named arguments, respectively. Types of these locals must
|
||||
/// be `ref _ListBase`.
|
||||
///
|
||||
/// [noSuchMethodBlock] is used as the `br` target when the shape check fails.
|
||||
void generateDynamicCall(
|
||||
void generateDynamicFunctionCall(
|
||||
Translator translator,
|
||||
w.DefinedFunction function,
|
||||
w.Local closureLocal,
|
||||
|
@ -617,19 +632,10 @@ void generateDynamicCall(
|
|||
|
||||
final b = function.body;
|
||||
|
||||
// Cast the closure to `#ClosureBase`
|
||||
final closureBaseType = w.RefType.def(
|
||||
translator.closureLayouter.closureBaseStruct,
|
||||
nullable: false);
|
||||
final closureBaseLocal = function.addLocal(closureBaseType);
|
||||
b.local_get(closureLocal);
|
||||
b.ref_cast(closureBaseType);
|
||||
b.local_set(closureBaseLocal);
|
||||
|
||||
// Read the `_FunctionType` field
|
||||
final functionTypeLocal =
|
||||
function.addLocal(translator.closureLayouter.functionTypeType);
|
||||
b.local_get(closureBaseLocal);
|
||||
b.local_get(closureLocal);
|
||||
b.struct_get(translator.closureLayouter.closureBaseStruct,
|
||||
FieldIndex.closureRuntimeType);
|
||||
b.local_tee(functionTypeLocal);
|
||||
|
@ -653,13 +659,13 @@ void generateDynamicCall(
|
|||
translator.functions.getFunction(translator.checkClosureType.reference));
|
||||
|
||||
// Type check passed, call vtable entry
|
||||
b.local_get(closureBaseLocal);
|
||||
b.local_get(closureLocal);
|
||||
b.local_get(typeArgsLocal);
|
||||
b.local_get(posArgsLocal);
|
||||
b.local_get(namedArgsLocal);
|
||||
|
||||
// Get vtable
|
||||
b.local_get(closureBaseLocal);
|
||||
b.local_get(closureLocal);
|
||||
b.struct_get(
|
||||
translator.closureLayouter.closureBaseStruct, FieldIndex.closureVtable);
|
||||
|
||||
|
|
|
@ -1486,8 +1486,7 @@ class Intrinsifier {
|
|||
}
|
||||
}
|
||||
|
||||
if (member.enclosingClass == translator.functionClass &&
|
||||
name == "_equals") {
|
||||
if (member.enclosingClass == translator.closureClass && name == "_equals") {
|
||||
// Function equality works like this:
|
||||
//
|
||||
// - Function literals and local functions are only equal if they're the
|
||||
|
@ -1595,7 +1594,7 @@ class Intrinsifier {
|
|||
name == "apply") {
|
||||
assert(function.type.inputs.length == 3);
|
||||
|
||||
final closureLocal = function.locals[0]; // ref Object
|
||||
final closureLocal = function.locals[0]; // ref #ClosureBase
|
||||
final posArgsNullableLocal = function.locals[1]; // ref null Object,
|
||||
final namedArgsLocal = function.locals[2]; // ref null Object
|
||||
|
||||
|
@ -1654,8 +1653,8 @@ class Intrinsifier {
|
|||
|
||||
final noSuchMethodBlock = b.block();
|
||||
|
||||
generateDynamicCall(translator, function, closureLocal, typeArgsLocal,
|
||||
posArgsLocal, namedArgsListLocal, noSuchMethodBlock);
|
||||
generateDynamicFunctionCall(translator, function, closureLocal,
|
||||
typeArgsLocal, posArgsLocal, namedArgsListLocal, noSuchMethodBlock);
|
||||
b.return_();
|
||||
|
||||
b.end(); // noSuchMethodBlock
|
||||
|
|
|
@ -36,7 +36,7 @@ mixin KernelNodes {
|
|||
late final Class boxedDoubleClass =
|
||||
index.getClass("dart:core", "_BoxedDouble");
|
||||
late final Class boxedIntClass = index.getClass("dart:core", "_BoxedInt");
|
||||
late final Class functionClass = index.getClass("dart:core", "_Function");
|
||||
late final Class closureClass = index.getClass("dart:core", "_Closure");
|
||||
late final Class listBaseClass = index.getClass("dart:core", "_ListBase");
|
||||
late final Class fixedLengthListClass = index.getClass("dart:core", "_List");
|
||||
late final Class growableListClass =
|
||||
|
|
|
@ -106,6 +106,7 @@ class Translator with KernelNodes {
|
|||
// 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]!;
|
||||
late final w.ArrayType listArrayType = (classInfo[listBaseClass]!
|
||||
.struct
|
||||
|
@ -468,6 +469,9 @@ class Translator with KernelNodes {
|
|||
} else if (isFfiCompound(cls)) {
|
||||
if (nullable) throw "FFI types can't be nullable";
|
||||
return w.NumType.i32;
|
||||
} else if (cls == coreTypes.functionClass) {
|
||||
return w.RefType.def(closureLayouter.closureBaseStruct,
|
||||
nullable: nullable);
|
||||
}
|
||||
}
|
||||
return w.RefType.def(info.repr.struct, nullable: nullable);
|
||||
|
|
|
@ -526,8 +526,7 @@ class Types {
|
|||
b.drop();
|
||||
b.i32_const(1);
|
||||
} else if (type.classNode == coreTypes.functionClass) {
|
||||
ClassInfo functionInfo = translator.classInfo[translator.functionClass]!;
|
||||
b.ref_test(functionInfo.nonNullableType);
|
||||
b.ref_test(translator.closureInfo.nonNullableType);
|
||||
} else if (concrete.isEmpty) {
|
||||
b.drop();
|
||||
b.i32_const(0);
|
||||
|
|
|
@ -32,8 +32,8 @@ class ClassID {
|
|||
external static int get cidFuture;
|
||||
@pragma("wasm:class-id", "dart.core#Function")
|
||||
external static int get cidFunction;
|
||||
@pragma("wasm:class-id", "dart.core#_Function")
|
||||
external static int get cid_Function;
|
||||
@pragma("wasm:class-id", "dart.core#_Closure")
|
||||
external static int get cid_Closure;
|
||||
@pragma("wasm:class-id", "dart.core#_List")
|
||||
external static int get cidFixedLengthList;
|
||||
@pragma("wasm:class-id", "dart.core#_ListBase")
|
||||
|
|
|
@ -1,26 +1,26 @@
|
|||
// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
|
||||
// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
part of "core_patch.dart";
|
||||
|
||||
/// Base class for closure objects.
|
||||
class _Function implements Function {
|
||||
class _Closure implements Function {
|
||||
@pragma("wasm:entry-point")
|
||||
WasmStructRef context;
|
||||
|
||||
@pragma("wasm:entry-point")
|
||||
_Function._(this.context);
|
||||
_Closure._(this.context);
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (other is! _Function) {
|
||||
if (other is! _Closure) {
|
||||
return false;
|
||||
}
|
||||
return _equals(this, other);
|
||||
}
|
||||
|
||||
external static bool _equals(_Function a, _Function b);
|
||||
external static bool _equals(_Closure a, _Closure b);
|
||||
|
||||
// Simple hash code for now, we can optimize later
|
||||
@override
|
||||
|
@ -28,5 +28,5 @@ class _Function implements Function {
|
|||
|
||||
// Support dynamic tear-off of `.call` on functions
|
||||
@pragma("wasm:entry-point")
|
||||
_Function get call => this;
|
||||
_Closure get call => this;
|
||||
}
|
|
@ -54,10 +54,10 @@ import "dart:typed_data" show Uint8List, Uint16List;
|
|||
import 'dart:wasm';
|
||||
|
||||
part "bool.dart";
|
||||
part "closure.dart";
|
||||
part "date_patch.dart";
|
||||
part "double.dart";
|
||||
part "errors_patch.dart";
|
||||
part "function.dart";
|
||||
part "growable_list.dart";
|
||||
part "identical_patch.dart";
|
||||
part "int.dart";
|
||||
|
|
|
@ -50,7 +50,7 @@ class Object {
|
|||
|
||||
@pragma("wasm:entry-point")
|
||||
_Type get _runtimeType {
|
||||
if (ClassID.getID(this) == ClassID.cid_Function) {
|
||||
if (ClassID.getID(this) == ClassID.cid_Closure) {
|
||||
return _getFunctionTypeRuntimeType(this);
|
||||
} else {
|
||||
return _getInterfaceTypeRuntimeType(this, _typeArguments);
|
||||
|
|
|
@ -519,7 +519,7 @@ class _TypeUniverse {
|
|||
|
||||
static bool isFunctionType(_Type t) =>
|
||||
isSpecificInterfaceType(t, ClassID.cidFunction) ||
|
||||
isSpecificInterfaceType(t, ClassID.cid_Function);
|
||||
isSpecificInterfaceType(t, ClassID.cid_Closure);
|
||||
|
||||
static _Type substituteInterfaceTypeParameter(
|
||||
_InterfaceTypeParameterType typeParameter, List<_Type> substitutions) {
|
||||
|
|
Loading…
Reference in a new issue