Remove ElementCreatorMixin from JsKernelToElementMap
Change-Id: I2ff9014305177a1f0060626062fadf8276b74979
Reviewed-on: https://dart-review.googlesource.com/74400
Reviewed-by: Stephen Adams <sra@google.com>
Commit-Queue: Johnni Winther <johnniwinther@google.com>
diff --git a/pkg/compiler/lib/src/ir/element_map.dart b/pkg/compiler/lib/src/ir/element_map.dart
index 16de410..250c391 100644
--- a/pkg/compiler/lib/src/ir/element_map.dart
+++ b/pkg/compiler/lib/src/ir/element_map.dart
@@ -53,6 +53,10 @@
/// Returns the [CallStructure] corresponding to the [arguments].
CallStructure getCallStructure(ir.Arguments arguments);
+ /// Returns the [TypeVariableEntity] corresponding to the type parameter
+ /// [node].
+ TypeVariableEntity getTypeVariable(ir.TypeParameter node);
+
CommonElements get commonElements;
DiagnosticReporter get reporter;
InterfaceType getThisType(IndexedClass cls);
diff --git a/pkg/compiler/lib/src/ir/visitors.dart b/pkg/compiler/lib/src/ir/visitors.dart
index 5c0ab85..3e97494 100644
--- a/pkg/compiler/lib/src/ir/visitors.dart
+++ b/pkg/compiler/lib/src/ir/visitors.dart
@@ -507,3 +507,116 @@
}
}
}
+
+/// Visitor that converts kernel dart types into [DartType].
+class DartTypeConverter extends ir.DartTypeVisitor<DartType> {
+ final IrToElementMap elementMap;
+ final Map<ir.TypeParameter, DartType> currentFunctionTypeParameters =
+ <ir.TypeParameter, DartType>{};
+ bool topLevel = true;
+
+ DartTypeConverter(this.elementMap);
+
+ DartType convert(ir.DartType type) {
+ topLevel = true;
+ return type.accept(this);
+ }
+
+ /// Visit a inner type.
+ DartType visitType(ir.DartType type) {
+ topLevel = false;
+ return type.accept(this);
+ }
+
+ InterfaceType visitSupertype(ir.Supertype node) {
+ ClassEntity cls = elementMap.getClass(node.classNode);
+ return new InterfaceType(cls, visitTypes(node.typeArguments));
+ }
+
+ List<DartType> visitTypes(List<ir.DartType> types) {
+ topLevel = false;
+ return new List.generate(
+ types.length, (int index) => types[index].accept(this));
+ }
+
+ @override
+ DartType visitTypeParameterType(ir.TypeParameterType node) {
+ DartType typeParameter = currentFunctionTypeParameters[node.parameter];
+ if (typeParameter != null) {
+ return typeParameter;
+ }
+ if (node.parameter.parent is ir.Typedef) {
+ // Typedefs are only used in type literals so we never need their type
+ // variables.
+ return const DynamicType();
+ }
+ return new TypeVariableType(elementMap.getTypeVariable(node.parameter));
+ }
+
+ @override
+ DartType visitFunctionType(ir.FunctionType node) {
+ int index = 0;
+ List<FunctionTypeVariable> typeVariables;
+ for (ir.TypeParameter typeParameter in node.typeParameters) {
+ FunctionTypeVariable typeVariable = new FunctionTypeVariable(index);
+ currentFunctionTypeParameters[typeParameter] = typeVariable;
+ typeVariables ??= <FunctionTypeVariable>[];
+ typeVariables.add(typeVariable);
+ index++;
+ }
+ if (typeVariables != null) {
+ for (int index = 0; index < typeVariables.length; index++) {
+ typeVariables[index].bound =
+ node.typeParameters[index].bound.accept(this);
+ }
+ }
+
+ FunctionType type = new FunctionType(
+ visitType(node.returnType),
+ visitTypes(node.positionalParameters
+ .take(node.requiredParameterCount)
+ .toList()),
+ visitTypes(node.positionalParameters
+ .skip(node.requiredParameterCount)
+ .toList()),
+ node.namedParameters.map((n) => n.name).toList(),
+ node.namedParameters.map((n) => visitType(n.type)).toList(),
+ typeVariables ?? const <FunctionTypeVariable>[]);
+ for (ir.TypeParameter typeParameter in node.typeParameters) {
+ currentFunctionTypeParameters.remove(typeParameter);
+ }
+ return type;
+ }
+
+ @override
+ DartType visitInterfaceType(ir.InterfaceType node) {
+ ClassEntity cls = elementMap.getClass(node.classNode);
+ if (cls.name == 'FutureOr' &&
+ cls.library == elementMap.commonElements.asyncLibrary) {
+ return new FutureOrType(visitTypes(node.typeArguments).single);
+ }
+ return new InterfaceType(cls, visitTypes(node.typeArguments));
+ }
+
+ @override
+ DartType visitVoidType(ir.VoidType node) {
+ return const VoidType();
+ }
+
+ @override
+ DartType visitDynamicType(ir.DynamicType node) {
+ return const DynamicType();
+ }
+
+ @override
+ DartType visitInvalidType(ir.InvalidType node) {
+ // Root uses such a `o is Unresolved` and `o as Unresolved` must be special
+ // cased in the builder, nested invalid types are treated as `dynamic`.
+ return const DynamicType();
+ }
+
+ @override
+ DartType visitBottomType(ir.BottomType node) {
+ return elementMap.commonElements.nullType;
+ }
+}
diff --git a/pkg/compiler/lib/src/js_model/element_map_impl.dart b/pkg/compiler/lib/src/js_model/element_map_impl.dart
index 0cafcf5..ccce835 100644
--- a/pkg/compiler/lib/src/js_model/element_map_impl.dart
+++ b/pkg/compiler/lib/src/js_model/element_map_impl.dart
@@ -46,20 +46,28 @@
}
class JsKernelToElementMap extends KernelToElementMapBase
- with
- JsElementCreatorMixin,
- // TODO(johnniwinther): Avoid mixing in [ElementCreatorMixin]. The
- // codegen world should be a strict subset of the resolution world and
- // creating elements for IR nodes should therefore not be needed.
- // Currently some are created purely for testing (like
- // `element == commonElements.foo`, where 'foo' might not be live).
- // Others are created because we do a
- // `elementEnvironment.forEachLibraryMember(...)` call on each emitted
- // library.
- ElementCreatorMixin
- implements
- KernelToWorldBuilder,
- JsToElementMap {
+ with JsElementCreatorMixin
+ implements KernelToWorldBuilder, JsToElementMap {
+ Map<ir.Library, IndexedLibrary> libraryMap = <ir.Library, IndexedLibrary>{};
+ Map<ir.Class, IndexedClass> classMap = <ir.Class, IndexedClass>{};
+ Map<ir.Typedef, IndexedTypedef> typedefMap = <ir.Typedef, IndexedTypedef>{};
+
+ /// Map from [ir.TypeParameter] nodes to the corresponding
+ /// [TypeVariableEntity].
+ ///
+ /// Normally the type variables are [IndexedTypeVariable]s, but for type
+ /// parameters on local function (in the frontend) these are _not_ since
+ /// their type declaration is neither a class nor a member. In the backend,
+ /// these type parameters belong to the call-method and are therefore indexed.
+ Map<ir.TypeParameter, TypeVariableEntity> typeVariableMap =
+ <ir.TypeParameter, TypeVariableEntity>{};
+ Map<ir.Member, IndexedConstructor> constructorMap =
+ <ir.Member, IndexedConstructor>{};
+ Map<ir.Procedure, IndexedFunction> methodMap =
+ <ir.Procedure, IndexedFunction>{};
+ Map<ir.Field, IndexedField> fieldMap = <ir.Field, IndexedField>{};
+ Map<ir.TreeNode, Local> localFunctionMap = <ir.TreeNode, Local>{};
+
/// Map from members to the call methods created for their nested closures.
Map<MemberEntity, List<FunctionEntity>> _nestedClosureMap =
<MemberEntity, List<FunctionEntity>>{};
@@ -166,11 +174,13 @@
}
IndexedTypeVariable newTypeVariable = createTypeVariable(
newTypeDeclaration, oldTypeVariable.name, oldTypeVariable.index);
- typeVariables.register<IndexedTypeVariable, TypeVariableData>(
- newTypeVariable, oldTypeVariableData.copy());
+ typeVariableMap[oldTypeVariableData.node] =
+ typeVariables.register<IndexedTypeVariable, TypeVariableData>(
+ newTypeVariable, oldTypeVariableData.copy());
assert(newTypeVariable.typeVariableIndex ==
oldTypeVariable.typeVariableIndex);
}
+ //typeVariableMap.keys.forEach((n) => print(n.parent));
// TODO(johnniwinther): We should close the environment in the beginning of
// this constructor but currently we need the [MemberEntity] to query if the
// member is live, thus potentially creating the [MemberEntity] in the
@@ -179,11 +189,6 @@
}
@override
- Entity getClosure(ir.FunctionDeclaration node) {
- throw new UnsupportedError('JsKernelToElementMap.getClosure');
- }
-
- @override
void forEachNestedClosure(
MemberEntity member, void f(FunctionEntity closure)) {
assert(checkFamily(member));
@@ -239,8 +244,6 @@
return cls;
}
- // TODO(johnniwinther): Reinsert these when [ElementCreatorMixin] is no longer
- // mixed in.
@override
FieldEntity getFieldInternal(ir.Field node) {
FieldEntity field = fieldMap[node];
@@ -263,6 +266,40 @@
}
@override
+ TypeVariableEntity getTypeVariableInternal(ir.TypeParameter node) {
+ TypeVariableEntity typeVariable = typeVariableMap[node];
+ if (typeVariable == null) {
+ if (node.parent is ir.FunctionNode) {
+ ir.FunctionNode func = node.parent;
+ int index = func.typeParameters.indexOf(node);
+ if (func.parent is ir.Constructor) {
+ ir.Constructor constructor = func.parent;
+ ir.Class cls = constructor.enclosingClass;
+ typeVariableMap[node] =
+ typeVariable = getTypeVariableInternal(cls.typeParameters[index]);
+ } else if (func.parent is ir.Procedure) {
+ ir.Procedure procedure = func.parent;
+ if (procedure.kind == ir.ProcedureKind.Factory) {
+ ir.Class cls = procedure.enclosingClass;
+ typeVariableMap[node] = typeVariable =
+ getTypeVariableInternal(cls.typeParameters[index]);
+ }
+ }
+ }
+ }
+ assert(typeVariable != null,
+ "No type variable entity for $node on ${node.parent is ir.FunctionNode ? node.parent.parent : node.parent}");
+ return typeVariable;
+ }
+
+ @override
+ TypedefEntity getTypedefInternal(ir.Typedef node) {
+ TypedefEntity typedef = typedefMap[node];
+ assert(typedef != null, "No typedef entity for $node");
+ return typedef;
+ }
+
+ @override
FunctionEntity getConstructorBody(ir.Constructor node) {
ConstructorEntity constructor = getConstructor(node);
return _getConstructorBody(node, constructor);
diff --git a/pkg/compiler/lib/src/kernel/element_map_impl.dart b/pkg/compiler/lib/src/kernel/element_map_impl.dart
index 72d76ae..4e66347 100644
--- a/pkg/compiler/lib/src/kernel/element_map_impl.dart
+++ b/pkg/compiler/lib/src/kernel/element_map_impl.dart
@@ -751,6 +751,20 @@
argumentCount, namedArguments, arguments.types.length);
}
+ ParameterStructure getParameterStructure(ir.FunctionNode node,
+ // TODO(johnniwinther): Remove this when type arguments are passed to
+ // constructors like calling a generic method.
+ {bool includeTypeParameters: true}) {
+ // TODO(johnniwinther): Cache the computed function type.
+ int requiredParameters = node.requiredParameterCount;
+ int positionalParameters = node.positionalParameters.length;
+ int typeParameters = node.typeParameters.length;
+ List<String> namedParameters =
+ node.namedParameters.map((p) => p.name).toList()..sort();
+ return new ParameterStructure(requiredParameters, positionalParameters,
+ namedParameters, includeTypeParameters ? typeParameters : 0);
+ }
+
Selector getSelector(ir.Expression node) {
// TODO(efortuna): This is screaming for a common interface between
// PropertyGet and SuperPropertyGet (and same for *Get). Talk to kernel
@@ -1257,52 +1271,61 @@
}
FunctionEntity getMethodInternal(ir.Procedure node) {
- return methodMap[node] ??= _getMethodCreate(node);
- }
-
- FunctionEntity _getMethodCreate(ir.Procedure node) {
- assert(
- !envIsClosed,
- "Environment of $this is closed. Trying to create "
- "function for $node.");
- LibraryEntity library;
- ClassEntity enclosingClass;
- if (node.enclosingClass != null) {
- enclosingClass = getClassInternal(node.enclosingClass);
- library = enclosingClass.library;
- } else {
- library = getLibraryInternal(node.enclosingLibrary);
+ IndexedFunction function = methodMap[node];
+ if (function == null) {
+ assert(
+ !envIsClosed,
+ "Environment of $this is closed. Trying to create "
+ "function for $node.");
+ LibraryEntity library;
+ ClassEntity enclosingClass;
+ if (node.enclosingClass != null) {
+ enclosingClass = getClassInternal(node.enclosingClass);
+ library = enclosingClass.library;
+ } else {
+ library = getLibraryInternal(node.enclosingLibrary);
+ }
+ Name name = getName(node.name);
+ bool isStatic = node.isStatic;
+ bool isExternal = node.isExternal;
+ // TODO(johnniwinther): Remove `&& !node.isExternal` when #31233 is fixed.
+ bool isAbstract = node.isAbstract && !node.isExternal;
+ AsyncMarker asyncMarker = getAsyncMarker(node.function);
+ switch (node.kind) {
+ case ir.ProcedureKind.Factory:
+ throw new UnsupportedError("Cannot create method from factory.");
+ case ir.ProcedureKind.Getter:
+ function = createGetter(library, enclosingClass, name, asyncMarker,
+ isStatic: isStatic,
+ isExternal: isExternal,
+ isAbstract: isAbstract);
+ break;
+ case ir.ProcedureKind.Method:
+ case ir.ProcedureKind.Operator:
+ function = createMethod(library, enclosingClass, name,
+ getParameterStructure(node.function), asyncMarker,
+ isStatic: isStatic,
+ isExternal: isExternal,
+ isAbstract: isAbstract);
+ break;
+ case ir.ProcedureKind.Setter:
+ assert(asyncMarker == AsyncMarker.SYNC);
+ function = createSetter(library, enclosingClass, name.setter,
+ isStatic: isStatic,
+ isExternal: isExternal,
+ isAbstract: isAbstract);
+ break;
+ }
+ members.register<IndexedFunction, FunctionData>(
+ function,
+ new FunctionDataImpl(node, node.function,
+ new RegularMemberDefinition(function, node)));
+ methodMap[node] = function;
+ for (ir.TypeParameter typeParameter in node.function.typeParameters) {
+ getTypeVariable(typeParameter);
+ }
}
- Name name = getName(node.name);
- bool isStatic = node.isStatic;
- bool isExternal = node.isExternal;
- // TODO(johnniwinther): Remove `&& !node.isExternal` when #31233 is fixed.
- bool isAbstract = node.isAbstract && !node.isExternal;
- AsyncMarker asyncMarker = getAsyncMarker(node.function);
- IndexedFunction function;
- switch (node.kind) {
- case ir.ProcedureKind.Factory:
- throw new UnsupportedError("Cannot create method from factory.");
- case ir.ProcedureKind.Getter:
- function = createGetter(library, enclosingClass, name, asyncMarker,
- isStatic: isStatic, isExternal: isExternal, isAbstract: isAbstract);
- break;
- case ir.ProcedureKind.Method:
- case ir.ProcedureKind.Operator:
- function = createMethod(library, enclosingClass, name,
- getParameterStructure(node.function), asyncMarker,
- isStatic: isStatic, isExternal: isExternal, isAbstract: isAbstract);
- break;
- case ir.ProcedureKind.Setter:
- assert(asyncMarker == AsyncMarker.SYNC);
- function = createSetter(library, enclosingClass, name.setter,
- isStatic: isStatic, isExternal: isExternal, isAbstract: isAbstract);
- break;
- }
- return members.register<IndexedFunction, FunctionData>(
- function,
- new FunctionDataImpl(
- node, node.function, new RegularMemberDefinition(function, node)));
+ return function;
}
FieldEntity getFieldInternal(ir.Field node) {
@@ -1332,20 +1355,6 @@
new FieldDataImpl(node, new RegularMemberDefinition(field, node)));
}
- ParameterStructure getParameterStructure(ir.FunctionNode node,
- // TODO(johnniwinther): Remove this when type arguments are passed to
- // constructors like calling a generic method.
- {bool includeTypeParameters: true}) {
- // TODO(johnniwinther): Cache the computed function type.
- int requiredParameters = node.requiredParameterCount;
- int positionalParameters = node.positionalParameters.length;
- int typeParameters = node.typeParameters.length;
- List<String> namedParameters =
- node.namedParameters.map((p) => p.name).toList()..sort();
- return new ParameterStructure(requiredParameters, positionalParameters,
- namedParameters, includeTypeParameters ? typeParameters : 0);
- }
-
IndexedLibrary createLibrary(String name, Uri canonicalUri);
IndexedClass createClass(LibraryEntity library, String name,
@@ -2039,119 +2048,6 @@
}
}
-/// Visitor that converts kernel dart types into [DartType].
-class DartTypeConverter extends ir.DartTypeVisitor<DartType> {
- final KernelToElementMapBase elementMap;
- final Map<ir.TypeParameter, DartType> currentFunctionTypeParameters =
- <ir.TypeParameter, DartType>{};
- bool topLevel = true;
-
- DartTypeConverter(this.elementMap);
-
- DartType convert(ir.DartType type) {
- topLevel = true;
- return type.accept(this);
- }
-
- /// Visit a inner type.
- DartType visitType(ir.DartType type) {
- topLevel = false;
- return type.accept(this);
- }
-
- InterfaceType visitSupertype(ir.Supertype node) {
- ClassEntity cls = elementMap.getClass(node.classNode);
- return new InterfaceType(cls, visitTypes(node.typeArguments));
- }
-
- List<DartType> visitTypes(List<ir.DartType> types) {
- topLevel = false;
- return new List.generate(
- types.length, (int index) => types[index].accept(this));
- }
-
- @override
- DartType visitTypeParameterType(ir.TypeParameterType node) {
- DartType typeParameter = currentFunctionTypeParameters[node.parameter];
- if (typeParameter != null) {
- return typeParameter;
- }
- if (node.parameter.parent is ir.Typedef) {
- // Typedefs are only used in type literals so we never need their type
- // variables.
- return const DynamicType();
- }
- return new TypeVariableType(elementMap.getTypeVariable(node.parameter));
- }
-
- @override
- DartType visitFunctionType(ir.FunctionType node) {
- int index = 0;
- List<FunctionTypeVariable> typeVariables;
- for (ir.TypeParameter typeParameter in node.typeParameters) {
- FunctionTypeVariable typeVariable = new FunctionTypeVariable(index);
- currentFunctionTypeParameters[typeParameter] = typeVariable;
- typeVariables ??= <FunctionTypeVariable>[];
- typeVariables.add(typeVariable);
- index++;
- }
- if (typeVariables != null) {
- for (int index = 0; index < typeVariables.length; index++) {
- typeVariables[index].bound =
- node.typeParameters[index].bound.accept(this);
- }
- }
-
- FunctionType type = new FunctionType(
- visitType(node.returnType),
- visitTypes(node.positionalParameters
- .take(node.requiredParameterCount)
- .toList()),
- visitTypes(node.positionalParameters
- .skip(node.requiredParameterCount)
- .toList()),
- node.namedParameters.map((n) => n.name).toList(),
- node.namedParameters.map((n) => visitType(n.type)).toList(),
- typeVariables ?? const <FunctionTypeVariable>[]);
- for (ir.TypeParameter typeParameter in node.typeParameters) {
- currentFunctionTypeParameters.remove(typeParameter);
- }
- return type;
- }
-
- @override
- DartType visitInterfaceType(ir.InterfaceType node) {
- ClassEntity cls = elementMap.getClass(node.classNode);
- if (cls.name == 'FutureOr' &&
- cls.library == elementMap.commonElements.asyncLibrary) {
- return new FutureOrType(visitTypes(node.typeArguments).single);
- }
- return new InterfaceType(cls, visitTypes(node.typeArguments));
- }
-
- @override
- DartType visitVoidType(ir.VoidType node) {
- return const VoidType();
- }
-
- @override
- DartType visitDynamicType(ir.DynamicType node) {
- return const DynamicType();
- }
-
- @override
- DartType visitInvalidType(ir.InvalidType node) {
- // Root uses such a `o is Unresolved` and `o as Unresolved` must be special
- // cased in the builder, nested invalid types are treated as `dynamic`.
- return const DynamicType();
- }
-
- @override
- DartType visitBottomType(ir.BottomType node) {
- return elementMap.commonElements.nullType;
- }
-}
-
/// [native.BehaviorBuilder] for kernel based elements.
class KernelBehaviorBuilder extends native.BehaviorBuilder {
final ElementEnvironment elementEnvironment;
diff --git a/pkg/compiler/lib/src/ssa/kernel_impact.dart b/pkg/compiler/lib/src/ssa/kernel_impact.dart
index 75b41d1..a1d6c47 100644
--- a/pkg/compiler/lib/src/ssa/kernel_impact.dart
+++ b/pkg/compiler/lib/src/ssa/kernel_impact.dart
@@ -812,6 +812,13 @@
void visitTypeLiteral(ir.TypeLiteral node) {
impactBuilder.registerTypeUse(
new TypeUse.typeLiteral(elementMap.getDartType(node.type)));
+ if (node.type is ir.FunctionType) {
+ ir.FunctionType functionType = node.type;
+ assert(functionType.typedef != null);
+ // TODO(johnniwinther): Can we avoid the typedef type altogether?
+ // We need to ensure that the typedef is live.
+ elementMap.getTypedefType(functionType.typedef);
+ }
}
@override