[dart2wasm] Minor refactoring in `ClassInfoCollector`
The interaction between `Translator` and other types like
`ClassInfoCollector` is quite complicated. This patch refactors a few
things to make it slightly simpler.
Changes:
- Add documentation to a few fields, minor rewording in a few other
field documentation.
- Make `ClassInfoCollector`'s `nextClassId`, `computeRepresentation`,
`addTypedDataFields` private.
- Initialize of `ClassInfo`'s `nullableType`, `nonNullableType` in
constructor.
Change-Id: I48e55029844ff41d9f043aac004a1abad8df83dd
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/265281
Reviewed-by: Aske Simon Christensen <askesc@google.com>
Reviewed-by: Joshua Litt <joshualitt@google.com>
Commit-Queue: Ömer Ağacan <omersa@google.com>
diff --git a/pkg/dart2wasm/lib/class_info.dart b/pkg/dart2wasm/lib/class_info.dart
index ecdaf44..b217f05 100644
--- a/pkg/dart2wasm/lib/class_info.dart
+++ b/pkg/dart2wasm/lib/class_info.dart
@@ -104,15 +104,20 @@
/// All classes which implement this class. This is used to compute `repr`.
final List<ClassInfo> implementedBy = [];
- late final w.RefType nullableType = w.RefType.def(struct, nullable: true);
- late final w.RefType nonNullableType = w.RefType.def(struct, nullable: false);
+ /// Nullabe Wasm ref type for this class.
+ final w.RefType nullableType;
+ /// Non-nullable Wasm ref type for this class.
+ final w.RefType nonNullableType;
+
+ /// Get Wasm ref type for this class with given nullability.
w.RefType typeWithNullability(bool nullable) =>
nullable ? nullableType : nonNullableType;
ClassInfo(this.cls, this.classId, this.depth, this.struct, this.superInfo,
- ClassInfoCollector collector,
- {this.typeParameterMatch = const {}}) {
+ {this.typeParameterMatch = const {}})
+ : nullableType = w.RefType.def(struct, nullable: true),
+ nonNullableType = w.RefType.def(struct, nullable: false) {
implementedBy.add(this);
}
@@ -146,9 +151,15 @@
/// Constructs the Wasm type hierarchy.
class ClassInfoCollector {
final Translator translator;
- int nextClassId = 0;
+ int _nextClassId = 0;
late final ClassInfo topInfo;
+ /// Wasm field type for fields with type [_Type]. Fields of this type are
+ /// added to classes for type parameters.
+ ///
+ /// This field is initialized when a class with a type parameter is first
+ /// encountered. Initialization depends on [Translator] visiting the [_Type]
+ /// class first and creating a [ClassInfo] for it.
late final w.FieldType typeType =
w.FieldType(translator.classInfo[translator.typeClass]!.nullableType);
@@ -160,7 +171,7 @@
void initializeTop() {
final w.StructType struct = m.addStructType("#Top");
- topInfo = ClassInfo(null, nextClassId++, 0, struct, null, this);
+ topInfo = ClassInfo(null, _nextClassId++, 0, struct, null);
translator.classes.add(topInfo);
translator.classForHeapType[struct] = topInfo;
}
@@ -174,7 +185,7 @@
final w.StructType struct =
m.addStructType(cls.name, superType: superInfo.struct);
info = ClassInfo(
- cls, nextClassId++, superInfo.depth + 1, struct, superInfo, this);
+ cls, _nextClassId++, superInfo.depth + 1, struct, superInfo);
// Mark Top type as implementing Object to force the representation
// type of Object to be Top.
info.implementedBy.add(topInfo);
@@ -235,7 +246,7 @@
? superInfo.struct
: m.addStructType(cls.name, superType: superInfo.struct);
info = ClassInfo(
- cls, nextClassId++, superInfo.depth + 1, struct, superInfo, this,
+ cls, _nextClassId++, superInfo.depth + 1, struct, superInfo,
typeParameterMatch: typeParameterMatch);
// Mark all interfaces as being implemented by this class. This is
@@ -254,7 +265,7 @@
}
}
- void computeRepresentation(ClassInfo info) {
+ void _computeRepresentation(ClassInfo info) {
info.repr = upperBound(info.implementedBy);
}
@@ -305,13 +316,20 @@
}
}
+ /// Create class info and Wasm struct for all classes.
void collect() {
- // Create class info and Wasm structs for all classes.
initializeTop();
- // Subclasses of the [_Function] class are generated on the fly as fields
- // with function types are encountered. Therefore, this class must be early
- // in the initialization order.
+
+ // Subclasses of the `_Function` class are generated on the fly as fields
+ // with function types are encountered. Therefore, `_Function` class must
+ // be early in the initialization order.
initialize(translator.functionClass);
+
+ // Similarly `_Type` is needed for type parameter fields in classes and
+ // needs to be initialized before we encounter a class with type
+ // parameters.
+ initialize(translator.typeClass);
+
for (Library library in translator.component.libraries) {
for (Class cls in library.classes) {
initialize(cls);
@@ -320,10 +338,10 @@
// For each class, compute which Wasm struct should be used for the type of
// variables bearing that class as their Dart type. This is the struct
- // corresponding to the least common supertype of all Dart classes
- // implementing this class.
+ // corresponding to the least common (most specific) supertype of all Dart
+ // classes implementing this class.
for (ClassInfo info in translator.classes) {
- computeRepresentation(info);
+ _computeRepresentation(info);
}
// Now that the representation types for all classes have been computed,
@@ -333,13 +351,13 @@
}
// Add hidden fields of typed_data classes.
- addTypedDataFields();
+ _addTypedDataFields();
// Validate that all internally used fields have the expected indices.
FieldIndex.validate(translator);
}
- void addTypedDataFields() {
+ void _addTypedDataFields() {
ClassInfo typedListBaseInfo =
translator.classInfo[translator.typedListBaseClass]!;
typedListBaseInfo.addField(w.FieldType(w.NumType.i32, mutable: false),
diff --git a/pkg/dart2wasm/lib/translator.dart b/pkg/dart2wasm/lib/translator.dart
index 5c4edad..7a651c7 100644
--- a/pkg/dart2wasm/lib/translator.dart
+++ b/pkg/dart2wasm/lib/translator.dart
@@ -153,8 +153,16 @@
late final DynamicDispatcher dynamics;
// Information about the program used and updated by the various phases.
+
+ /// [ClassInfo]s of classes in the compilation unit and the [ClassInfo] for
+ /// the `#Top` struct. Indexed by class ID. Entries added by
+ /// [ClassInfoCollector].
final List<ClassInfo> classes = [];
+
+ /// [ClassInfo]s of classes in the compilation unit. Entries added by
+ /// [ClassInfoCollector].
final Map<Class, ClassInfo> classInfo = {};
+
final Map<w.HeapType, ClassInfo> classForHeapType = {};
final Map<Field, int> fieldIndex = {};
final Map<TypeParameter, int> typeParameterIndex = {};
diff --git a/pkg/dart2wasm/lib/types.dart b/pkg/dart2wasm/lib/types.dart
index 9b15b86..e2484c1 100644
--- a/pkg/dart2wasm/lib/types.dart
+++ b/pkg/dart2wasm/lib/types.dart
@@ -136,8 +136,8 @@
List<List<int>> _buildTypeRulesSupers() {
List<List<int>> typeRulesSupers = [];
- for (int i = 0; i < translator.classInfoCollector.nextClassId; i++) {
- List<int>? superclassIds = typeRules[i]?.keys.toList();
+ for (int classId = 0; classId < translator.classes.length; classId++) {
+ List<int>? superclassIds = typeRules[classId]?.keys.toList();
if (superclassIds == null) {
typeRulesSupers.add(const []);
} else {
@@ -150,12 +150,12 @@
List<List<List<DartType>>> _buildTypeRulesSubstitutions() {
List<List<List<DartType>>> typeRulesSubstitutions = [];
- for (int i = 0; i < translator.classInfoCollector.nextClassId; i++) {
- List<int> supers = typeRulesSupers[i];
+ for (int classId = 0; classId < translator.classes.length; classId++) {
+ List<int> supers = typeRulesSupers[classId];
typeRulesSubstitutions.add(supers.isEmpty ? const [] : []);
for (int j = 0; j < supers.length; j++) {
int superId = supers[j];
- typeRulesSubstitutions.last.add(typeRules[i]![superId]!);
+ typeRulesSubstitutions.last.add(typeRules[classId]![superId]!);
}
}
return typeRulesSubstitutions;
diff --git a/pkg/wasm_builder/lib/src/types.dart b/pkg/wasm_builder/lib/src/types.dart
index 498978d..5a3360c 100644
--- a/pkg/wasm_builder/lib/src/types.dart
+++ b/pkg/wasm_builder/lib/src/types.dart
@@ -592,7 +592,7 @@
/// A type for a struct field or an array element.
///
-/// It consists of a type and a mutability.
+/// It consists of a value type and a mutability.
class FieldType extends _WithMutability<StorageType> {
FieldType(super.type, {super.mutable = true});