Index: pkg/compiler/lib/src/kernel/element_map_impl.dart |
diff --git a/pkg/compiler/lib/src/kernel/element_map_impl.dart b/pkg/compiler/lib/src/kernel/element_map_impl.dart |
index fc663e4fd02d2c885c3808680ae67f60ed7ae59d..f638db42bcc5c22ac7ba82e92e1d92e6a6ccc296 100644 |
--- a/pkg/compiler/lib/src/kernel/element_map_impl.dart |
+++ b/pkg/compiler/lib/src/kernel/element_map_impl.dart |
@@ -5,8 +5,6 @@ |
library dart2js.kernel.element_map; |
import 'package:kernel/ast.dart' as ir; |
-import 'package:kernel/clone.dart'; |
-import 'package:kernel/type_algebra.dart'; |
import '../common.dart'; |
import '../common/names.dart' show Identifiers; |
@@ -33,7 +31,6 @@ import '../js_model/elements.dart'; |
import '../native/native.dart' as native; |
import '../native/resolver.dart'; |
import '../ordered_typeset.dart'; |
-import '../ssa/kernel_impact.dart'; |
import '../universe/class_set.dart'; |
import '../universe/function_set.dart'; |
import '../universe/selector.dart'; |
@@ -43,6 +40,8 @@ import '../util/util.dart' show Link, LinkBuilder; |
import 'element_map.dart'; |
import 'element_map_mixins.dart'; |
import 'elements.dart'; |
+import 'env.dart'; |
+import 'kelements.dart'; |
part 'native_basic_data.dart'; |
part 'no_such_method_resolver.dart'; |
@@ -62,99 +61,85 @@ abstract class KernelToWorldBuilder implements KernelToElementMapForBuilding { |
void f(DartType type, String name, ConstantValue defaultValue)); |
} |
-class KernelToElementMapBase extends KernelToElementMapBaseMixin { |
+abstract class KernelToElementMapBase extends KernelToElementMapBaseMixin { |
final DiagnosticReporter reporter; |
CommonElements _commonElements; |
ElementEnvironment _elementEnvironment; |
DartTypeConverter _typeConverter; |
KernelConstantEnvironment _constantEnvironment; |
+ _KernelDartTypes _types; |
/// Library environment. Used for fast lookup. |
- _KEnv _env = new _KEnv(); |
+ ProgramEnv _env = new ProgramEnv(); |
- /// List of library environments by `KLibrary.libraryIndex`. This is used for |
- /// fast lookup into library classes and members. |
- List<_KLibraryEnv> _libraryEnvs = <_KLibraryEnv>[]; |
+ /// List of library environments by `IndexedLibrary.libraryIndex`. This is |
+ /// used for fast lookup into library classes and members. |
+ List<LibraryEnv> _libraryEnvs = <LibraryEnv>[]; |
- /// List of class environments by `KClass.classIndex`. This is used for |
+ /// List of class environments by `IndexedClass.classIndex`. This is used for |
/// fast lookup into class members. |
- List<_KClassEnv> _classEnvs = <_KClassEnv>[]; |
- |
- Map<ir.Library, KLibrary> _libraryMap = <ir.Library, KLibrary>{}; |
- Map<ir.Class, KClass> _classMap = <ir.Class, KClass>{}; |
- Map<ir.TypeParameter, KTypeVariable> _typeVariableMap = |
- <ir.TypeParameter, KTypeVariable>{}; |
- |
- List<_MemberData> _memberList = <_MemberData>[]; |
+ List<ClassEnv> _classEnvs = <ClassEnv>[]; |
- Map<ir.Member, KConstructor> _constructorMap = <ir.Member, KConstructor>{}; |
- Map<ir.Procedure, KFunction> _methodMap = <ir.Procedure, KFunction>{}; |
- Map<ir.Field, KField> _fieldMap = <ir.Field, KField>{}; |
- |
- Map<ir.TreeNode, KLocalFunction> _localFunctionMap = |
- <ir.TreeNode, KLocalFunction>{}; |
+ /// List of member data by `IndexedMember.classIndex`. This is used for |
+ /// fast lookup into member properties. |
+ List<MemberData> _memberList = <MemberData>[]; |
KernelToElementMapBase(this.reporter, Environment environment) { |
_elementEnvironment = new KernelElementEnvironment(this); |
_commonElements = new CommonElements(_elementEnvironment); |
_constantEnvironment = new KernelConstantEnvironment(this, environment); |
_typeConverter = new DartTypeConverter(this); |
+ _types = new _KernelDartTypes(this); |
} |
+ DartTypes get types => _types; |
+ |
@override |
ElementEnvironment get elementEnvironment => _elementEnvironment; |
@override |
CommonElements get commonElements => _commonElements; |
- KMethod get _mainFunction { |
+ FunctionEntity get _mainFunction { |
return _env.mainMethod != null ? _getMethod(_env.mainMethod) : null; |
} |
- KLibrary get _mainLibrary { |
+ LibraryEntity get _mainLibrary { |
return _env.mainMethod != null |
? _getLibrary(_env.mainMethod.enclosingLibrary) |
: null; |
} |
- Iterable<LibraryEntity> get _libraries { |
- if (_env.length != _libraryMap.length) { |
- // Create a [KLibrary] for each library. |
- _env.forEachLibrary((_KLibraryEnv env) { |
- _getLibrary(env.library, env); |
- }); |
- } |
- return _libraryMap.values; |
- } |
+ Iterable<LibraryEntity> get _libraries; |
LibraryEntity lookupLibrary(Uri uri) { |
- _KLibraryEnv libraryEnv = _env.lookupLibrary(uri); |
+ LibraryEnv libraryEnv = _env.lookupLibrary(uri); |
if (libraryEnv == null) return null; |
return _getLibrary(libraryEnv.library, libraryEnv); |
} |
String _getLibraryName(KLibrary library) { |
- _KLibraryEnv libraryEnv = _libraryEnvs[library.libraryIndex]; |
+ LibraryEnv libraryEnv = _libraryEnvs[library.libraryIndex]; |
return libraryEnv.library.name ?? ''; |
} |
MemberEntity lookupLibraryMember(KLibrary library, String name, |
{bool setter: false}) { |
- _KLibraryEnv libraryEnv = _libraryEnvs[library.libraryIndex]; |
+ LibraryEnv libraryEnv = _libraryEnvs[library.libraryIndex]; |
ir.Member member = libraryEnv.lookupMember(name, setter: setter); |
return member != null ? getMember(member) : null; |
} |
void _forEachLibraryMember(KLibrary library, void f(MemberEntity member)) { |
- _KLibraryEnv libraryEnv = _libraryEnvs[library.libraryIndex]; |
+ LibraryEnv libraryEnv = _libraryEnvs[library.libraryIndex]; |
libraryEnv.forEachMember((ir.Member node) { |
f(getMember(node)); |
}); |
} |
ClassEntity lookupClass(KLibrary library, String name) { |
- _KLibraryEnv libraryEnv = _libraryEnvs[library.libraryIndex]; |
- _KClassEnv classEnv = libraryEnv.lookupClass(name); |
+ LibraryEnv libraryEnv = _libraryEnvs[library.libraryIndex]; |
+ ClassEnv classEnv = libraryEnv.lookupClass(name); |
if (classEnv != null) { |
return _getClass(classEnv.cls, classEnv); |
} |
@@ -162,23 +147,23 @@ class KernelToElementMapBase extends KernelToElementMapBaseMixin { |
} |
void _forEachClass(KLibrary library, void f(ClassEntity cls)) { |
- _KLibraryEnv libraryEnv = _libraryEnvs[library.libraryIndex]; |
- libraryEnv.forEachClass((_KClassEnv classEnv) { |
+ LibraryEnv libraryEnv = _libraryEnvs[library.libraryIndex]; |
+ libraryEnv.forEachClass((ClassEnv classEnv) { |
if (!classEnv.isUnnamedMixinApplication) { |
f(_getClass(classEnv.cls, classEnv)); |
} |
}); |
} |
- MemberEntity lookupClassMember(KClass cls, String name, |
+ MemberEntity lookupClassMember(IndexedClass cls, String name, |
{bool setter: false}) { |
- _KClassEnv classEnv = _classEnvs[cls.classIndex]; |
+ ClassEnv classEnv = _classEnvs[cls.classIndex]; |
ir.Member member = classEnv.lookupMember(name, setter: setter); |
return member != null ? getMember(member) : null; |
} |
- ConstructorEntity lookupConstructor(KClass cls, String name) { |
- _KClassEnv classEnv = _classEnvs[cls.classIndex]; |
+ ConstructorEntity lookupConstructor(IndexedClass cls, String name) { |
+ ClassEnv classEnv = _classEnvs[cls.classIndex]; |
ir.Member member = classEnv.lookupConstructor(name); |
return member != null ? getConstructor(member) : null; |
} |
@@ -191,42 +176,20 @@ class KernelToElementMapBase extends KernelToElementMapBaseMixin { |
LibraryEntity getLibrary(ir.Library node) => _getLibrary(node); |
- KLibrary _getLibrary(ir.Library node, [_KLibraryEnv libraryEnv]) { |
- return _libraryMap.putIfAbsent(node, () { |
- Uri canonicalUri = node.importUri; |
- _libraryEnvs.add(libraryEnv ?? _env.lookupLibrary(canonicalUri)); |
- String name = node.name; |
- if (name == null) { |
- // Use the file name as script name. |
- String path = canonicalUri.path; |
- name = path.substring(path.lastIndexOf('/') + 1); |
- } |
- return new KLibrary(_libraryMap.length, name, canonicalUri); |
- }); |
- } |
+ LibraryEntity _getLibrary(ir.Library node, [LibraryEnv libraryEnv]); |
@override |
ClassEntity getClass(ir.Class node) => _getClass(node); |
- KClass _getClass(ir.Class node, [_KClassEnv classEnv]) { |
- return _classMap.putIfAbsent(node, () { |
- KLibrary library = _getLibrary(node.enclosingLibrary); |
- if (classEnv == null) { |
- classEnv = _libraryEnvs[library.libraryIndex].lookupClass(node.name); |
- } |
- _classEnvs.add(classEnv); |
- return new KClass(library, _classMap.length, node.name, |
- isAbstract: node.isAbstract); |
- }); |
- } |
+ ClassEntity _getClass(ir.Class node, [ClassEnv classEnv]); |
- InterfaceType _getSuperType(KClass cls) { |
- _KClassEnv env = _classEnvs[cls.classIndex]; |
+ InterfaceType _getSuperType(IndexedClass cls) { |
+ ClassEnv env = _classEnvs[cls.classIndex]; |
_ensureSupertypes(cls, env); |
return env.supertype; |
} |
- void _ensureThisAndRawType(KClass cls, _KClassEnv env) { |
+ void _ensureThisAndRawType(ClassEntity cls, ClassEnv env) { |
if (env.thisType == null) { |
ir.Class node = env.cls; |
// TODO(johnniwinther): Add the type argument to the list literal when we |
@@ -253,36 +216,9 @@ class KernelToElementMapBase extends KernelToElementMapBaseMixin { |
TypeVariableEntity getTypeVariable(ir.TypeParameter node) => |
_getTypeVariable(node); |
- KTypeVariable _getTypeVariable(ir.TypeParameter node) { |
- return _typeVariableMap.putIfAbsent(node, () { |
- if (node.parent is ir.Class) { |
- ir.Class cls = node.parent; |
- int index = cls.typeParameters.indexOf(node); |
- return new KTypeVariable(_getClass(cls), node.name, index); |
- } |
- 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; |
- return _getTypeVariable(cls.typeParameters[index]); |
- } |
- if (func.parent is ir.Procedure) { |
- ir.Procedure procedure = func.parent; |
- if (procedure.kind == ir.ProcedureKind.Factory) { |
- ir.Class cls = procedure.enclosingClass; |
- return _getTypeVariable(cls.typeParameters[index]); |
- } else { |
- return new KTypeVariable(_getMethod(procedure), node.name, index); |
- } |
- } |
- } |
- throw new UnsupportedError('Unsupported type parameter type node $node.'); |
- }); |
- } |
+ TypeVariableEntity _getTypeVariable(ir.TypeParameter node); |
- void _ensureSupertypes(KClass cls, _KClassEnv env) { |
+ void _ensureSupertypes(ClassEntity cls, ClassEnv env) { |
if (env.orderedTypeSet == null) { |
_ensureThisAndRawType(cls, env); |
@@ -295,8 +231,8 @@ class KernelToElementMapBase extends KernelToElementMapBaseMixin { |
} else { |
InterfaceType processSupertype(ir.Supertype node) { |
InterfaceType type = _typeConverter.visitSupertype(node); |
- KClass superclass = type.element; |
- _KClassEnv env = _classEnvs[superclass.classIndex]; |
+ IndexedClass superclass = type.element; |
+ ClassEnv env = _classEnvs[superclass.classIndex]; |
_ensureSupertypes(superclass, env); |
return type; |
} |
@@ -345,10 +281,10 @@ class KernelToElementMapBase extends KernelToElementMapBaseMixin { |
if (target != null) { |
return getMember(target); |
} |
- KClass cls = getMember(context).enclosingClass; |
- KClass superclass = _getSuperType(cls)?.element; |
+ ClassEntity cls = getMember(context).enclosingClass; |
+ IndexedClass superclass = _getSuperType(cls)?.element; |
while (superclass != null) { |
- _KClassEnv env = _classEnvs[superclass.classIndex]; |
+ ClassEnv env = _classEnvs[superclass.classIndex]; |
ir.Member superMember = env.lookupMember(name.name, setter: setter); |
if (superMember != null) { |
return getMember(superMember); |
@@ -362,51 +298,19 @@ class KernelToElementMapBase extends KernelToElementMapBaseMixin { |
@override |
ConstructorEntity getConstructor(ir.Member node) => _getConstructor(node); |
- KConstructor _getConstructor(ir.Member node) { |
- return _constructorMap.putIfAbsent(node, () { |
- int memberIndex = _memberList.length; |
- KConstructor constructor; |
- KClass enclosingClass = _getClass(node.enclosingClass); |
- Name name = getName(node.name); |
- bool isExternal = node.isExternal; |
- |
- ir.FunctionNode functionNode; |
- if (node is ir.Constructor) { |
- functionNode = node.function; |
- constructor = new KGenerativeConstructor(memberIndex, enclosingClass, |
- name, _getParameterStructure(functionNode), |
- isExternal: isExternal, isConst: node.isConst); |
- } else if (node is ir.Procedure) { |
- functionNode = node.function; |
- bool isFromEnvironment = isExternal && |
- name.text == 'fromEnvironment' && |
- const ['int', 'bool', 'String'].contains(enclosingClass.name); |
- constructor = new KFactoryConstructor(memberIndex, enclosingClass, name, |
- _getParameterStructure(functionNode), |
- isExternal: isExternal, |
- isConst: node.isConst, |
- isFromEnvironmentConstructor: isFromEnvironment); |
- } else { |
- // TODO(johnniwinther): Convert `node.location` to a [SourceSpan]. |
- throw new SpannableAssertionFailure( |
- NO_LOCATION_SPANNABLE, "Unexpected constructor node: ${node}."); |
- } |
- _memberList.add(new _ConstructorData(node, functionNode)); |
- return constructor; |
- }); |
- } |
+ ConstructorEntity _getConstructor(ir.Member node); |
ConstructorEntity getSuperConstructor( |
ir.Constructor sourceNode, ir.Member targetNode) { |
- KConstructor source = getConstructor(sourceNode); |
- KClass sourceClass = source.enclosingClass; |
- KConstructor target = getConstructor(targetNode); |
- KClass targetClass = target.enclosingClass; |
- KClass superClass = _getSuperType(sourceClass)?.element; |
+ ConstructorEntity source = getConstructor(sourceNode); |
+ ClassEntity sourceClass = source.enclosingClass; |
+ ConstructorEntity target = getConstructor(targetNode); |
+ ClassEntity targetClass = target.enclosingClass; |
+ IndexedClass superClass = _getSuperType(sourceClass)?.element; |
if (superClass == targetClass) { |
return target; |
} |
- _KClassEnv env = _classEnvs[superClass.classIndex]; |
+ ClassEnv env = _classEnvs[superClass.classIndex]; |
ir.Member member = env.lookupConstructor(target.name); |
if (member != null) { |
return getConstructor(member); |
@@ -418,140 +322,17 @@ class KernelToElementMapBase extends KernelToElementMapBaseMixin { |
@override |
FunctionEntity getMethod(ir.Procedure node) => _getMethod(node); |
- KFunction _getMethod(ir.Procedure node) { |
- return _methodMap.putIfAbsent(node, () { |
- int memberIndex = _memberList.length; |
- KLibrary library; |
- KClass enclosingClass; |
- if (node.enclosingClass != null) { |
- enclosingClass = _getClass(node.enclosingClass); |
- library = enclosingClass.library; |
- } else { |
- library = _getLibrary(node.enclosingLibrary); |
- } |
- Name name = getName(node.name); |
- bool isStatic = node.isStatic; |
- bool isExternal = node.isExternal; |
- bool isAbstract = node.isAbstract; |
- KFunction function; |
- AsyncMarker asyncMarker; |
- switch (node.function.asyncMarker) { |
- case ir.AsyncMarker.Async: |
- asyncMarker = AsyncMarker.ASYNC; |
- break; |
- case ir.AsyncMarker.AsyncStar: |
- asyncMarker = AsyncMarker.ASYNC_STAR; |
- break; |
- case ir.AsyncMarker.Sync: |
- asyncMarker = AsyncMarker.SYNC; |
- break; |
- case ir.AsyncMarker.SyncStar: |
- asyncMarker = AsyncMarker.SYNC_STAR; |
- break; |
- case ir.AsyncMarker.SyncYielding: |
- throw new UnsupportedError( |
- "Async marker ${node.function.asyncMarker} is not supported."); |
- } |
- switch (node.kind) { |
- case ir.ProcedureKind.Factory: |
- throw new UnsupportedError("Cannot create method from factory."); |
- case ir.ProcedureKind.Getter: |
- function = new KGetter( |
- memberIndex, library, enclosingClass, name, asyncMarker, |
- isStatic: isStatic, |
- isExternal: isExternal, |
- isAbstract: isAbstract); |
- break; |
- case ir.ProcedureKind.Method: |
- case ir.ProcedureKind.Operator: |
- function = new KMethod(memberIndex, library, enclosingClass, name, |
- _getParameterStructure(node.function), asyncMarker, |
- isStatic: isStatic, |
- isExternal: isExternal, |
- isAbstract: isAbstract); |
- break; |
- case ir.ProcedureKind.Setter: |
- assert(asyncMarker == AsyncMarker.SYNC); |
- function = new KSetter( |
- memberIndex, library, enclosingClass, getName(node.name).setter, |
- isStatic: isStatic, |
- isExternal: isExternal, |
- isAbstract: isAbstract); |
- break; |
- } |
- _memberList.add(new _FunctionData(node, node.function)); |
- return function; |
- }); |
- } |
+ FunctionEntity _getMethod(ir.Procedure node); |
@override |
FieldEntity getField(ir.Field node) => _getField(node); |
- KField _getField(ir.Field node) { |
- return _fieldMap.putIfAbsent(node, () { |
- int memberIndex = _memberList.length; |
- KLibrary library; |
- KClass enclosingClass; |
- if (node.enclosingClass != null) { |
- enclosingClass = _getClass(node.enclosingClass); |
- library = enclosingClass.library; |
- } else { |
- library = _getLibrary(node.enclosingLibrary); |
- } |
- Name name = getName(node.name); |
- bool isStatic = node.isStatic; |
- _memberList.add(new _FieldData(node)); |
- return new KField(memberIndex, library, enclosingClass, name, |
- isStatic: isStatic, |
- isAssignable: node.isMutable, |
- isConst: node.isConst); |
- }); |
- } |
- |
- ParameterStructure _getParameterStructure(ir.FunctionNode node) { |
- // TODO(johnniwinther): Cache the computed function type. |
- int requiredParameters = node.requiredParameterCount; |
- int positionalParameters = node.positionalParameters.length; |
- List<String> namedParameters = |
- node.namedParameters.map((p) => p.name).toList()..sort(); |
- return new ParameterStructure( |
- requiredParameters, positionalParameters, namedParameters); |
- } |
+ FieldEntity _getField(ir.Field node); |
@override |
- Local getLocalFunction(ir.TreeNode node) => _getLocal(node); |
+ Local getLocalFunction(ir.TreeNode node) => _getLocalFunction(node); |
- KLocalFunction _getLocal(ir.TreeNode node) { |
- return _localFunctionMap.putIfAbsent(node, () { |
- MemberEntity memberContext; |
- Entity executableContext; |
- ir.TreeNode parent = node.parent; |
- while (parent != null) { |
- if (parent is ir.Member) { |
- executableContext = memberContext = getMember(parent); |
- break; |
- } |
- if (parent is ir.FunctionDeclaration || |
- parent is ir.FunctionExpression) { |
- KLocalFunction localFunction = _getLocal(parent); |
- executableContext = localFunction; |
- memberContext = localFunction.memberContext; |
- break; |
- } |
- parent = parent.parent; |
- } |
- String name; |
- FunctionType functionType; |
- if (node is ir.FunctionDeclaration) { |
- name = node.variable.name; |
- functionType = getFunctionType(node.function); |
- } else if (node is ir.FunctionExpression) { |
- functionType = getFunctionType(node.function); |
- } |
- return new KLocalFunction( |
- name, memberContext, executableContext, functionType); |
- }); |
- } |
+ Local _getLocalFunction(ir.TreeNode node); |
@override |
DartType getDartType(ir.DartType type) => _typeConverter.convert(type); |
@@ -605,50 +386,50 @@ class KernelToElementMapBase extends KernelToElementMapBaseMixin { |
context.typeArguments, _getThisType(context.element).typeArguments); |
} |
- InterfaceType _getThisType(KClass cls) { |
- _KClassEnv env = _classEnvs[cls.classIndex]; |
+ InterfaceType _getThisType(IndexedClass cls) { |
+ ClassEnv env = _classEnvs[cls.classIndex]; |
_ensureThisAndRawType(cls, env); |
return env.thisType; |
} |
- InterfaceType _getRawType(KClass cls) { |
- _KClassEnv env = _classEnvs[cls.classIndex]; |
+ InterfaceType _getRawType(IndexedClass cls) { |
+ ClassEnv env = _classEnvs[cls.classIndex]; |
_ensureThisAndRawType(cls, env); |
return env.rawType; |
} |
- FunctionType _getFunctionType(KFunction function) { |
- _FunctionData data = _memberList[function.memberIndex]; |
+ FunctionType _getFunctionType(IndexedMember function) { |
+ FunctionData data = _memberList[function.memberIndex]; |
return data.getFunctionType(this); |
} |
- ClassEntity _getAppliedMixin(KClass cls) { |
- _KClassEnv env = _classEnvs[cls.classIndex]; |
+ ClassEntity _getAppliedMixin(IndexedClass cls) { |
+ ClassEnv env = _classEnvs[cls.classIndex]; |
_ensureSupertypes(cls, env); |
return env.mixedInType?.element; |
} |
- bool _isMixinApplication(KClass cls) { |
- _KClassEnv env = _classEnvs[cls.classIndex]; |
+ bool _isMixinApplication(IndexedClass cls) { |
+ ClassEnv env = _classEnvs[cls.classIndex]; |
_ensureSupertypes(cls, env); |
return env.isMixinApplication; |
} |
- bool _isUnnamedMixinApplication(KClass cls) { |
- _KClassEnv env = _classEnvs[cls.classIndex]; |
+ bool _isUnnamedMixinApplication(IndexedClass cls) { |
+ ClassEnv env = _classEnvs[cls.classIndex]; |
_ensureSupertypes(cls, env); |
return env.isUnnamedMixinApplication; |
} |
- void _forEachSupertype(KClass cls, void f(InterfaceType supertype)) { |
- _KClassEnv env = _classEnvs[cls.classIndex]; |
+ void _forEachSupertype(IndexedClass cls, void f(InterfaceType supertype)) { |
+ ClassEnv env = _classEnvs[cls.classIndex]; |
_ensureSupertypes(cls, env); |
env.orderedTypeSet.supertypes.forEach(f); |
} |
- void _forEachMixin(KClass cls, void f(ClassEntity mixin)) { |
+ void _forEachMixin(IndexedClass cls, void f(ClassEntity mixin)) { |
while (cls != null) { |
- _KClassEnv env = _classEnvs[cls.classIndex]; |
+ ClassEnv env = _classEnvs[cls.classIndex]; |
_ensureSupertypes(cls, env); |
if (env.mixedInType != null) { |
f(env.mixedInType.element); |
@@ -657,16 +438,16 @@ class KernelToElementMapBase extends KernelToElementMapBaseMixin { |
} |
} |
- void _forEachConstructor(KClass cls, void f(ConstructorEntity member)) { |
- _KClassEnv env = _classEnvs[cls.classIndex]; |
+ void _forEachConstructor(IndexedClass cls, void f(ConstructorEntity member)) { |
+ ClassEnv env = _classEnvs[cls.classIndex]; |
env.forEachConstructor((ir.Member member) { |
f(getConstructor(member)); |
}); |
} |
void _forEachClassMember( |
- KClass cls, void f(ClassEntity cls, MemberEntity member)) { |
- _KClassEnv env = _classEnvs[cls.classIndex]; |
+ IndexedClass cls, void f(ClassEntity cls, MemberEntity member)) { |
+ ClassEnv env = _classEnvs[cls.classIndex]; |
env.forEachMember((ir.Member member) { |
f(cls, getMember(member)); |
}); |
@@ -676,42 +457,318 @@ class KernelToElementMapBase extends KernelToElementMapBaseMixin { |
} |
} |
- ConstantConstructor _getConstructorConstant(KConstructor constructor) { |
- _ConstructorData data = _memberList[constructor.memberIndex]; |
- return data.getConstructorConstant(this, constructor); |
+ ConstantConstructor _getConstructorConstant(IndexedConstructor constructor) { |
+ ConstructorData data = _memberList[constructor.memberIndex]; |
+ return data.getConstructorConstant(this, constructor); |
+ } |
+ |
+ ConstantExpression _getFieldConstant(IndexedField field) { |
+ FieldData data = _memberList[field.memberIndex]; |
+ return data.getFieldConstant(this, field); |
+ } |
+ |
+ InterfaceType _asInstanceOf(InterfaceType type, ClassEntity cls) { |
+ OrderedTypeSet orderedTypeSet = _getOrderedTypeSet(type.element); |
+ InterfaceType supertype = |
+ orderedTypeSet.asInstanceOf(cls, _getHierarchyDepth(cls)); |
+ if (supertype != null) { |
+ supertype = _substByContext(supertype, type); |
+ } |
+ return supertype; |
+ } |
+ |
+ OrderedTypeSet _getOrderedTypeSet(IndexedClass cls) { |
+ ClassEnv env = _classEnvs[cls.classIndex]; |
+ _ensureSupertypes(cls, env); |
+ return env.orderedTypeSet; |
+ } |
+ |
+ int _getHierarchyDepth(IndexedClass cls) { |
+ ClassEnv env = _classEnvs[cls.classIndex]; |
+ _ensureSupertypes(cls, env); |
+ return env.orderedTypeSet.maxDepth; |
+ } |
+ |
+ Iterable<InterfaceType> _getInterfaces(IndexedClass cls) { |
+ ClassEnv env = _classEnvs[cls.classIndex]; |
+ _ensureSupertypes(cls, env); |
+ return env.interfaces; |
+ } |
+ |
+ Spannable _getSpannable(MemberEntity member, ir.Node node) { |
+ return member; |
+ } |
+ |
+ ir.Member _getMemberNode(covariant IndexedMember member) { |
+ return _memberList[member.memberIndex].node; |
+ } |
+ |
+ ir.Class _getClassNode(covariant IndexedClass cls) { |
+ return _classEnvs[cls.classIndex].cls; |
+ } |
+} |
+ |
+/// Mixin that implements the abstract methods in [KernelToElementMapBase] by |
+/// creating K-model elements. |
+abstract class KElementCreatorMixin { |
+ ProgramEnv get _env; |
+ List<LibraryEnv> get _libraryEnvs; |
+ List<ClassEnv> get _classEnvs; |
+ List<MemberData> get _memberList; |
+ |
+ Map<ir.Library, KLibrary> _libraryMap = <ir.Library, KLibrary>{}; |
+ Map<ir.Class, KClass> _classMap = <ir.Class, KClass>{}; |
+ Map<ir.TypeParameter, KTypeVariable> _typeVariableMap = |
+ <ir.TypeParameter, KTypeVariable>{}; |
+ Map<ir.Member, KConstructor> _constructorMap = <ir.Member, KConstructor>{}; |
+ Map<ir.Procedure, KFunction> _methodMap = <ir.Procedure, KFunction>{}; |
+ Map<ir.Field, KField> _fieldMap = <ir.Field, KField>{}; |
+ Map<ir.TreeNode, KLocalFunction> _localFunctionMap = |
+ <ir.TreeNode, KLocalFunction>{}; |
+ |
+ Name getName(ir.Name node); |
+ FunctionType getFunctionType(ir.FunctionNode node); |
+ MemberEntity getMember(ir.Member node); |
+ |
+ Iterable<LibraryEntity> get _libraries { |
+ if (_env.length != _libraryMap.length) { |
+ // Create a [KLibrary] for each library. |
+ _env.forEachLibrary((LibraryEnv env) { |
+ _getLibrary(env.library, env); |
+ }); |
+ } |
+ return _libraryMap.values; |
+ } |
+ |
+ LibraryEntity _getLibrary(ir.Library node, [LibraryEnv libraryEnv]) { |
+ return _libraryMap.putIfAbsent(node, () { |
+ Uri canonicalUri = node.importUri; |
+ _libraryEnvs.add(libraryEnv ?? _env.lookupLibrary(canonicalUri)); |
+ String name = node.name; |
+ if (name == null) { |
+ // Use the file name as script name. |
+ String path = canonicalUri.path; |
+ name = path.substring(path.lastIndexOf('/') + 1); |
+ } |
+ return new KLibrary(_libraryMap.length, name, canonicalUri); |
+ }); |
+ } |
+ |
+ ClassEntity _getClass(ir.Class node, [ClassEnv classEnv]) { |
+ return _classMap.putIfAbsent(node, () { |
+ KLibrary library = _getLibrary(node.enclosingLibrary); |
+ if (classEnv == null) { |
+ classEnv = _libraryEnvs[library.libraryIndex].lookupClass(node.name); |
+ } |
+ _classEnvs.add(classEnv); |
+ return new KClass(library, _classMap.length, node.name, |
+ isAbstract: node.isAbstract); |
+ }); |
+ } |
+ |
+ TypeVariableEntity _getTypeVariable(ir.TypeParameter node) { |
+ return _typeVariableMap.putIfAbsent(node, () { |
+ if (node.parent is ir.Class) { |
+ ir.Class cls = node.parent; |
+ int index = cls.typeParameters.indexOf(node); |
+ return new KTypeVariable(_getClass(cls), node.name, index); |
+ } |
+ 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; |
+ return _getTypeVariable(cls.typeParameters[index]); |
+ } |
+ if (func.parent is ir.Procedure) { |
+ ir.Procedure procedure = func.parent; |
+ if (procedure.kind == ir.ProcedureKind.Factory) { |
+ ir.Class cls = procedure.enclosingClass; |
+ return _getTypeVariable(cls.typeParameters[index]); |
+ } else { |
+ return new KTypeVariable(_getMethod(procedure), node.name, index); |
+ } |
+ } |
+ } |
+ throw new UnsupportedError('Unsupported type parameter type node $node.'); |
+ }); |
+ } |
+ |
+ ConstructorEntity _getConstructor(ir.Member node) { |
+ return _constructorMap.putIfAbsent(node, () { |
+ int memberIndex = _memberList.length; |
+ KConstructor constructor; |
+ KClass enclosingClass = _getClass(node.enclosingClass); |
+ Name name = getName(node.name); |
+ bool isExternal = node.isExternal; |
+ |
+ ir.FunctionNode functionNode; |
+ if (node is ir.Constructor) { |
+ functionNode = node.function; |
+ constructor = new KGenerativeConstructor(memberIndex, enclosingClass, |
+ name, _getParameterStructure(functionNode), |
+ isExternal: isExternal, isConst: node.isConst); |
+ } else if (node is ir.Procedure) { |
+ functionNode = node.function; |
+ bool isFromEnvironment = isExternal && |
+ name.text == 'fromEnvironment' && |
+ const ['int', 'bool', 'String'].contains(enclosingClass.name); |
+ constructor = new KFactoryConstructor(memberIndex, enclosingClass, name, |
+ _getParameterStructure(functionNode), |
+ isExternal: isExternal, |
+ isConst: node.isConst, |
+ isFromEnvironmentConstructor: isFromEnvironment); |
+ } else { |
+ // TODO(johnniwinther): Convert `node.location` to a [SourceSpan]. |
+ throw new SpannableAssertionFailure( |
+ NO_LOCATION_SPANNABLE, "Unexpected constructor node: ${node}."); |
+ } |
+ _memberList.add(new ConstructorData(node, functionNode)); |
+ return constructor; |
+ }); |
+ } |
+ |
+ FunctionEntity _getMethod(ir.Procedure node) { |
+ return _methodMap.putIfAbsent(node, () { |
+ int memberIndex = _memberList.length; |
+ LibraryEntity library; |
+ ClassEntity enclosingClass; |
+ if (node.enclosingClass != null) { |
+ enclosingClass = _getClass(node.enclosingClass); |
+ library = enclosingClass.library; |
+ } else { |
+ library = _getLibrary(node.enclosingLibrary); |
+ } |
+ Name name = getName(node.name); |
+ bool isStatic = node.isStatic; |
+ bool isExternal = node.isExternal; |
+ bool isAbstract = node.isAbstract; |
+ KFunction function; |
+ AsyncMarker asyncMarker; |
+ switch (node.function.asyncMarker) { |
+ case ir.AsyncMarker.Async: |
+ asyncMarker = AsyncMarker.ASYNC; |
+ break; |
+ case ir.AsyncMarker.AsyncStar: |
+ asyncMarker = AsyncMarker.ASYNC_STAR; |
+ break; |
+ case ir.AsyncMarker.Sync: |
+ asyncMarker = AsyncMarker.SYNC; |
+ break; |
+ case ir.AsyncMarker.SyncStar: |
+ asyncMarker = AsyncMarker.SYNC_STAR; |
+ break; |
+ case ir.AsyncMarker.SyncYielding: |
+ throw new UnsupportedError( |
+ "Async marker ${node.function.asyncMarker} is not supported."); |
+ } |
+ switch (node.kind) { |
+ case ir.ProcedureKind.Factory: |
+ throw new UnsupportedError("Cannot create method from factory."); |
+ case ir.ProcedureKind.Getter: |
+ function = new KGetter( |
+ memberIndex, library, enclosingClass, name, asyncMarker, |
+ isStatic: isStatic, |
+ isExternal: isExternal, |
+ isAbstract: isAbstract); |
+ break; |
+ case ir.ProcedureKind.Method: |
+ case ir.ProcedureKind.Operator: |
+ function = new KMethod(memberIndex, library, enclosingClass, name, |
+ _getParameterStructure(node.function), asyncMarker, |
+ isStatic: isStatic, |
+ isExternal: isExternal, |
+ isAbstract: isAbstract); |
+ break; |
+ case ir.ProcedureKind.Setter: |
+ assert(asyncMarker == AsyncMarker.SYNC); |
+ function = new KSetter( |
+ memberIndex, library, enclosingClass, getName(node.name).setter, |
+ isStatic: isStatic, |
+ isExternal: isExternal, |
+ isAbstract: isAbstract); |
+ break; |
+ } |
+ _memberList.add(new FunctionData(node, node.function)); |
+ return function; |
+ }); |
+ } |
+ |
+ FieldEntity _getField(ir.Field node) { |
+ return _fieldMap.putIfAbsent(node, () { |
+ int memberIndex = _memberList.length; |
+ LibraryEntity library; |
+ ClassEntity enclosingClass; |
+ if (node.enclosingClass != null) { |
+ enclosingClass = _getClass(node.enclosingClass); |
+ library = enclosingClass.library; |
+ } else { |
+ library = _getLibrary(node.enclosingLibrary); |
+ } |
+ Name name = getName(node.name); |
+ bool isStatic = node.isStatic; |
+ _memberList.add(new FieldData(node)); |
+ return new KField(memberIndex, library, enclosingClass, name, |
+ isStatic: isStatic, |
+ isAssignable: node.isMutable, |
+ isConst: node.isConst); |
+ }); |
} |
- ConstantExpression _getFieldConstant(KField field) { |
- _FieldData data = _memberList[field.memberIndex]; |
- return data.getFieldConstant(this, field); |
+ ParameterStructure _getParameterStructure(ir.FunctionNode node) { |
+ // TODO(johnniwinther): Cache the computed function type. |
+ int requiredParameters = node.requiredParameterCount; |
+ int positionalParameters = node.positionalParameters.length; |
+ List<String> namedParameters = |
+ node.namedParameters.map((p) => p.name).toList()..sort(); |
+ return new ParameterStructure( |
+ requiredParameters, positionalParameters, namedParameters); |
} |
-} |
- |
-class KernelToElementMapForImpactImpl extends KernelToElementMapBase |
- with KernelToElementMapForImpactMixin { |
- native.BehaviorBuilder _nativeBehaviorBuilder; |
- KernelToElementMapForImpactImpl( |
- DiagnosticReporter reporter, Environment environment) |
- : super(reporter, environment) { |
- _nativeBehaviorBuilder = new KernelBehaviorBuilder(_commonElements); |
+ Local _getLocalFunction(ir.TreeNode node) { |
+ return _localFunctionMap.putIfAbsent(node, () { |
+ MemberEntity memberContext; |
+ Entity executableContext; |
+ ir.TreeNode parent = node.parent; |
+ while (parent != null) { |
+ if (parent is ir.Member) { |
+ executableContext = memberContext = getMember(parent); |
+ break; |
+ } |
+ if (parent is ir.FunctionDeclaration || |
+ parent is ir.FunctionExpression) { |
+ KLocalFunction localFunction = _getLocalFunction(parent); |
+ executableContext = localFunction; |
+ memberContext = localFunction.memberContext; |
+ break; |
+ } |
+ parent = parent.parent; |
+ } |
+ String name; |
+ FunctionType functionType; |
+ if (node is ir.FunctionDeclaration) { |
+ name = node.variable.name; |
+ functionType = getFunctionType(node.function); |
+ } else if (node is ir.FunctionExpression) { |
+ functionType = getFunctionType(node.function); |
+ } |
+ return new KLocalFunction( |
+ name, memberContext, executableContext, functionType); |
+ }); |
} |
- |
- @override |
- native.BehaviorBuilder get nativeBehaviorBuilder => _nativeBehaviorBuilder; |
} |
-/// Element builder used for creating elements and types corresponding to Kernel |
-/// IR nodes. |
-class KernelToElementMapImpl extends KernelToElementMapForImpactImpl |
- with KernelToElementMapForBuildingMixin |
- implements KernelToWorldBuilder { |
- _KernelDartTypes _types; |
- |
- KernelToElementMapImpl(DiagnosticReporter reporter, Environment environment) |
- : super(reporter, environment) { |
- _types = new _KernelDartTypes(this); |
- } |
+/// Implementation of [KernelToElementMapForImpact] that only supports world |
+/// impact computation. |
+// TODO(johnniwinther): Merge this with [KernelToElementMapForImpactImpl] when |
+// [JsStrategy] is the default. |
+abstract class KernelToElementMapForImpactImpl |
+ implements |
+ KernelToElementMapBase, |
+ KernelToElementMapForImpact, |
+ KernelToElementMapForImpactMixin { |
+ native.BehaviorBuilder _nativeBehaviorBuilder; |
/// Adds libraries in [program] to the set of libraries. |
/// |
@@ -721,19 +778,12 @@ class KernelToElementMapImpl extends KernelToElementMapForImpactImpl |
_env.addProgram(program); |
} |
- ConstantEnvironment get constantEnvironment => _constantEnvironment; |
- |
- DartTypes get types => _types; |
- |
@override |
- ConstantValue getFieldConstantValue(ir.Field field) { |
- // TODO(johnniwinther): Cache the result in [_FieldData]. |
- return getConstantValue(field.initializer, |
- requireConstant: field.isConst, implicitNull: !field.isConst); |
- } |
+ native.BehaviorBuilder get nativeBehaviorBuilder => |
+ _nativeBehaviorBuilder ??= new KernelBehaviorBuilder(commonElements); |
- Iterable<ConstantValue> _getClassMetadata(KClass cls) { |
- return _classEnvs[cls.classIndex].getMetadata(this); |
+ ResolutionImpact computeWorldImpact(KMember member) { |
+ return _memberList[member.memberIndex].getWorldImpact(this); |
} |
/// Returns the kernel [ir.Procedure] node for the [method]. |
@@ -741,32 +791,42 @@ class KernelToElementMapImpl extends KernelToElementMapForImpactImpl |
return _memberList[method.memberIndex].node; |
} |
- InterfaceType _asInstanceOf(InterfaceType type, KClass cls) { |
- OrderedTypeSet orderedTypeSet = _getOrderedTypeSet(type.element); |
- InterfaceType supertype = |
- orderedTypeSet.asInstanceOf(cls, _getHierarchyDepth(cls)); |
- if (supertype != null) { |
- supertype = _substByContext(supertype, type); |
- } |
- return supertype; |
+ Iterable<ConstantValue> _getClassMetadata(KClass cls) { |
+ return _classEnvs[cls.classIndex].getMetadata(this); |
} |
+} |
- OrderedTypeSet _getOrderedTypeSet(KClass cls) { |
- _KClassEnv env = _classEnvs[cls.classIndex]; |
- _ensureSupertypes(cls, env); |
- return env.orderedTypeSet; |
- } |
+/// Implementation of [KernelToElementMapForImpact] that only supports world |
+/// impact computation. |
+// TODO(johnniwinther): Merge this with [KernelToElementMapForImpactImpl] when |
+// [JsStrategy] is the default. |
+class KernelToElementMapForImpactImpl2 extends KernelToElementMapBase |
+ with |
+ KernelToElementMapForImpactMixin, |
+ KernelToElementMapForImpactImpl, |
+ KElementCreatorMixin { |
+ KernelToElementMapForImpactImpl2( |
+ DiagnosticReporter reporter, Environment environment) |
+ : super(reporter, environment); |
+} |
- int _getHierarchyDepth(KClass cls) { |
- _KClassEnv env = _classEnvs[cls.classIndex]; |
- _ensureSupertypes(cls, env); |
- return env.orderedTypeSet.maxDepth; |
- } |
+/// Element builder used for creating elements and types corresponding to Kernel |
+/// IR nodes. |
+// TODO(johnniwinther): Use this in the JsStrategy |
+class KernelToElementMapForBuildingImpl extends KernelToElementMapBase |
+ with KernelToElementMapForBuildingMixin, KElementCreatorMixin |
+ implements KernelToWorldBuilder { |
+ KernelToElementMapForBuildingImpl( |
+ DiagnosticReporter reporter, Environment environment) |
+ : super(reporter, environment); |
- Iterable<InterfaceType> _getInterfaces(KClass cls) { |
- _KClassEnv env = _classEnvs[cls.classIndex]; |
- _ensureSupertypes(cls, env); |
- return env.interfaces; |
+ ConstantEnvironment get constantEnvironment => _constantEnvironment; |
+ |
+ @override |
+ ConstantValue getFieldConstantValue(ir.Field field) { |
+ // TODO(johnniwinther): Cache the result in [FieldData]. |
+ return getConstantValue(field.initializer, |
+ requireConstant: field.isConst, implicitNull: !field.isConst); |
} |
ir.Library getKernelLibrary(KLibrary entity) => |
@@ -775,12 +835,12 @@ class KernelToElementMapImpl extends KernelToElementMapForImpactImpl |
ir.Class getKernelClass(KClass entity) => _classEnvs[entity.classIndex].cls; |
bool hasConstantFieldInitializer(covariant KField field) { |
- _FieldData data = _memberList[field.memberIndex]; |
+ FieldData data = _memberList[field.memberIndex]; |
return getFieldConstantValue(data.node) != null; |
} |
ConstantValue getConstantFieldInitializer(covariant KField field) { |
- _FieldData data = _memberList[field.memberIndex]; |
+ FieldData data = _memberList[field.memberIndex]; |
ConstantValue value = getFieldConstantValue(data.node); |
assert(value != null, |
failedAt(field, "Field $field doesn't have a constant initial value.")); |
@@ -789,415 +849,37 @@ class KernelToElementMapImpl extends KernelToElementMapForImpactImpl |
void forEachParameter(covariant KFunction function, |
void f(DartType type, String name, ConstantValue defaultValue)) { |
- _FunctionData data = _memberList[function.memberIndex]; |
+ FunctionData data = _memberList[function.memberIndex]; |
data.forEachParameter(this, f); |
} |
- ResolutionImpact computeWorldImpact(KMember member) { |
- return _memberList[member.memberIndex].getWorldImpact(this); |
- } |
- |
@override |
Spannable getSpannable(MemberEntity member, ir.Node node) { |
- return member; |
+ return _getSpannable(member, node); |
} |
@override |
- ir.Member getMemberNode(covariant KMember member) { |
- return _memberList[member.memberIndex].node; |
- } |
- |
- /// Returns the kernel IR node that defines the [cls]. |
- ir.Class getClassNode(KClass cls) { |
- return _classEnvs[cls.classIndex].cls; |
- } |
-} |
- |
-/// Environment for fast lookup of program libraries. |
-class _KEnv { |
- final Set<ir.Program> programs = new Set<ir.Program>(); |
- |
- Map<Uri, _KLibraryEnv> _libraryMap; |
- |
- /// TODO(johnniwinther): Handle arbitrary load order if needed. |
- ir.Member get mainMethod => programs.first?.mainMethod; |
- |
- void addProgram(ir.Program program) { |
- if (programs.add(program)) { |
- if (_libraryMap != null) { |
- _addLibraries(program); |
- } |
- } |
- } |
- |
- void _addLibraries(ir.Program program) { |
- for (ir.Library library in program.libraries) { |
- _libraryMap[library.importUri] = new _KLibraryEnv(library); |
- } |
- } |
- |
- void _ensureLibraryMap() { |
- if (_libraryMap == null) { |
- _libraryMap = <Uri, _KLibraryEnv>{}; |
- for (ir.Program program in programs) { |
- _addLibraries(program); |
- } |
- } |
- } |
- |
- /// Return the [_KLibraryEnv] for the library with the canonical [uri]. |
- _KLibraryEnv lookupLibrary(Uri uri) { |
- _ensureLibraryMap(); |
- return _libraryMap[uri]; |
- } |
- |
- /// Calls [f] for each library in this environment. |
- void forEachLibrary(void f(_KLibraryEnv library)) { |
- _ensureLibraryMap(); |
- _libraryMap.values.forEach(f); |
- } |
- |
- /// Returns the number of libraries in this environment. |
- int get length { |
- _ensureLibraryMap(); |
- return _libraryMap.length; |
- } |
-} |
- |
-/// Environment for fast lookup of library classes and members. |
-class _KLibraryEnv { |
- final ir.Library library; |
- |
- Map<String, _KClassEnv> _classMap; |
- Map<String, ir.Member> _memberMap; |
- Map<String, ir.Member> _setterMap; |
- |
- _KLibraryEnv(this.library); |
- |
- void _ensureClassMap() { |
- if (_classMap == null) { |
- _classMap = <String, _KClassEnv>{}; |
- for (ir.Class cls in library.classes) { |
- _classMap[cls.name] = new _KClassEnv(cls); |
- } |
- } |
- } |
- |
- /// Return the [_KClassEnv] for the class [name] in [library]. |
- _KClassEnv lookupClass(String name) { |
- _ensureClassMap(); |
- return _classMap[name]; |
- } |
- |
- /// Calls [f] for each class in this library. |
- void forEachClass(void f(_KClassEnv cls)) { |
- _ensureClassMap(); |
- _classMap.values.forEach(f); |
- } |
- |
- void _ensureMemberMaps() { |
- if (_memberMap == null) { |
- _memberMap = <String, ir.Member>{}; |
- _setterMap = <String, ir.Member>{}; |
- for (ir.Member member in library.members) { |
- if (member is ir.Procedure) { |
- if (member.kind == ir.ProcedureKind.Setter) { |
- _setterMap[member.name.name] = member; |
- } else { |
- _memberMap[member.name.name] = member; |
- } |
- } else if (member is ir.Field) { |
- _memberMap[member.name.name] = member; |
- if (member.isMutable) { |
- _setterMap[member.name.name] = member; |
- } |
- } else { |
- throw new SpannableAssertionFailure( |
- NO_LOCATION_SPANNABLE, "Unexpected library member node: $member"); |
- } |
- } |
- } |
- } |
- |
- /// Return the [ir.Member] for the member [name] in [library]. |
- ir.Member lookupMember(String name, {bool setter: false}) { |
- _ensureMemberMaps(); |
- return setter ? _setterMap[name] : _memberMap[name]; |
- } |
- |
- void forEachMember(void f(ir.Member member)) { |
- _ensureMemberMaps(); |
- _memberMap.values.forEach(f); |
- for (ir.Member member in _setterMap.values) { |
- if (member is ir.Procedure) { |
- f(member); |
- } else { |
- // Skip fields; these are also in _memberMap. |
- } |
- } |
- } |
-} |
- |
-/// Environment for fast lookup of class members. |
-class _KClassEnv { |
- final ir.Class cls; |
- bool isMixinApplication; |
- final bool isUnnamedMixinApplication; |
- |
- InterfaceType thisType; |
- InterfaceType rawType; |
- InterfaceType supertype; |
- InterfaceType mixedInType; |
- List<InterfaceType> interfaces; |
- OrderedTypeSet orderedTypeSet; |
- |
- Map<String, ir.Member> _constructorMap; |
- Map<String, ir.Member> _memberMap; |
- Map<String, ir.Member> _setterMap; |
- |
- Iterable<ConstantValue> _metadata; |
- |
- _KClassEnv(this.cls) |
- // TODO(johnniwinther): Change this to use a property on [cls] when such |
- // is added to kernel. |
- : isUnnamedMixinApplication = |
- cls.name.contains('+') || cls.name.contains('&'); |
- |
- /// Copied from 'package:kernel/transformations/mixin_full_resolution.dart'. |
- ir.Constructor _buildForwardingConstructor( |
- CloneVisitor cloner, ir.Constructor superclassConstructor) { |
- var superFunction = superclassConstructor.function; |
- |
- // We keep types and default values for the parameters but always mark the |
- // parameters as final (since we just forward them to the super |
- // constructor). |
- ir.VariableDeclaration cloneVariable(ir.VariableDeclaration variable) { |
- ir.VariableDeclaration clone = cloner.clone(variable); |
- clone.isFinal = true; |
- return clone; |
- } |
- |
- // Build a [FunctionNode] which has the same parameters as the one in the |
- // superclass constructor. |
- var positionalParameters = |
- superFunction.positionalParameters.map(cloneVariable).toList(); |
- var namedParameters = |
- superFunction.namedParameters.map(cloneVariable).toList(); |
- var function = new ir.FunctionNode(new ir.EmptyStatement(), |
- positionalParameters: positionalParameters, |
- namedParameters: namedParameters, |
- requiredParameterCount: superFunction.requiredParameterCount, |
- returnType: const ir.VoidType()); |
- |
- // Build a [SuperInitializer] which takes all positional/named parameters |
- // and forward them to the super class constructor. |
- var positionalArguments = <ir.Expression>[]; |
- for (var variable in positionalParameters) { |
- positionalArguments.add(new ir.VariableGet(variable)); |
- } |
- var namedArguments = <ir.NamedExpression>[]; |
- for (var variable in namedParameters) { |
- namedArguments.add( |
- new ir.NamedExpression(variable.name, new ir.VariableGet(variable))); |
- } |
- var superInitializer = new ir.SuperInitializer(superclassConstructor, |
- new ir.Arguments(positionalArguments, named: namedArguments)); |
- |
- // Assemble the constructor. |
- return new ir.Constructor(function, |
- name: superclassConstructor.name, |
- initializers: <ir.Initializer>[superInitializer]); |
- } |
- |
- void _ensureMaps() { |
- if (_memberMap == null) { |
- _memberMap = <String, ir.Member>{}; |
- _setterMap = <String, ir.Member>{}; |
- _constructorMap = <String, ir.Member>{}; |
- |
- void addMembers(ir.Class c, {bool includeStatic}) { |
- for (ir.Member member in c.members) { |
- if (member is ir.Constructor || |
- member is ir.Procedure && |
- member.kind == ir.ProcedureKind.Factory) { |
- if (!includeStatic) continue; |
- _constructorMap[member.name.name] = member; |
- } else if (member is ir.Procedure) { |
- if (!includeStatic && member.isStatic) continue; |
- if (member.kind == ir.ProcedureKind.Setter) { |
- _setterMap[member.name.name] = member; |
- } else { |
- _memberMap[member.name.name] = member; |
- } |
- } else if (member is ir.Field) { |
- if (!includeStatic && member.isStatic) continue; |
- _memberMap[member.name.name] = member; |
- if (member.isMutable) { |
- _setterMap[member.name.name] = member; |
- } |
- _memberMap[member.name.name] = member; |
- } else { |
- throw new SpannableAssertionFailure( |
- NO_LOCATION_SPANNABLE, "Unexpected class member node: $member"); |
- } |
- } |
- } |
- |
- if (cls.mixedInClass != null) { |
- addMembers(cls.mixedInClass, includeStatic: false); |
- } |
- addMembers(cls, includeStatic: true); |
- |
- if (isUnnamedMixinApplication && _constructorMap.isEmpty) { |
- // Unnamed mixin applications have no constructors when read from .dill. |
- // For each generative constructor in the superclass we make a |
- // corresponding forwarding constructor in the subclass. |
- // |
- // This code is copied from |
- // 'package:kernel/transformations/mixin_full_resolution.dart' |
- var superclassSubstitution = getSubstitutionMap(cls.supertype); |
- var superclassCloner = |
- new CloneVisitor(typeSubstitution: superclassSubstitution); |
- for (var superclassConstructor in cls.superclass.constructors) { |
- var forwardingConstructor = _buildForwardingConstructor( |
- superclassCloner, superclassConstructor); |
- cls.addMember(forwardingConstructor); |
- _constructorMap[forwardingConstructor.name.name] = |
- forwardingConstructor; |
- } |
- } |
- } |
- } |
- |
- /// Return the [ir.Member] for the member [name] in [library]. |
- ir.Member lookupMember(String name, {bool setter: false}) { |
- _ensureMaps(); |
- return setter ? _setterMap[name] : _memberMap[name]; |
- } |
- |
- /// Return the [ir.Member] for the member [name] in [library]. |
- ir.Member lookupConstructor(String name) { |
- _ensureMaps(); |
- return _constructorMap[name]; |
- } |
- |
- void forEachMember(void f(ir.Member member)) { |
- _ensureMaps(); |
- _memberMap.values.forEach(f); |
- for (ir.Member member in _setterMap.values) { |
- if (member is ir.Procedure) { |
- f(member); |
- } else { |
- // Skip fields; these are also in _memberMap. |
- } |
- } |
- } |
- |
- void forEachConstructor(void f(ir.Member member)) { |
- _ensureMaps(); |
- _constructorMap.values.forEach(f); |
- } |
- |
- Iterable<ConstantValue> getMetadata(KernelToElementMapImpl elementMap) { |
- return _metadata ??= elementMap.getMetadata(cls.annotations); |
- } |
-} |
- |
-class _MemberData { |
- final ir.Member node; |
- Iterable<ConstantValue> _metadata; |
- |
- _MemberData(this.node); |
- |
- ResolutionImpact getWorldImpact(KernelToElementMapImpl elementMap) { |
- return buildKernelImpact(node, elementMap); |
- } |
- |
- Iterable<ConstantValue> getMetadata(KernelToElementMapImpl elementMap) { |
- return _metadata ??= elementMap.getMetadata(node.annotations); |
- } |
-} |
- |
-class _FunctionData extends _MemberData { |
- final ir.FunctionNode functionNode; |
- FunctionType _type; |
- |
- _FunctionData(ir.Member node, this.functionNode) : super(node); |
- |
- FunctionType getFunctionType(KernelToElementMapImpl elementMap) { |
- return _type ??= elementMap.getFunctionType(functionNode); |
- } |
- |
- void forEachParameter(KernelToElementMapForBuilding elementMap, |
- void f(DartType type, String name, ConstantValue defaultValue)) { |
- void handleParameter(ir.VariableDeclaration node, {bool isOptional: true}) { |
- DartType type = elementMap.getDartType(node.type); |
- String name = node.name; |
- ConstantValue defaultValue; |
- if (isOptional) { |
- if (node.initializer != null) { |
- defaultValue = elementMap.getConstantValue(node.initializer); |
- } else { |
- defaultValue = new NullConstantValue(); |
- } |
- } |
- f(type, name, defaultValue); |
- } |
- |
- for (int i = 0; i < functionNode.positionalParameters.length; i++) { |
- handleParameter(functionNode.positionalParameters[i], |
- isOptional: i < functionNode.requiredParameterCount); |
- } |
- functionNode.namedParameters.toList() |
- ..sort(namedOrdering) |
- ..forEach(handleParameter); |
+ ir.Member getMemberNode(MemberEntity member) { |
+ return _getMemberNode(member); |
} |
-} |
- |
-class _ConstructorData extends _FunctionData { |
- ConstantConstructor _constantConstructor; |
- |
- _ConstructorData(ir.Member node, ir.FunctionNode functionNode) |
- : super(node, functionNode); |
- ConstantConstructor getConstructorConstant( |
- KernelToElementMapImpl elementMap, KConstructor constructor) { |
- if (_constantConstructor == null) { |
- if (node is ir.Constructor && constructor.isConst) { |
- _constantConstructor = |
- new Constantifier(elementMap).computeConstantConstructor(node); |
- } else { |
- throw new SpannableAssertionFailure( |
- constructor, |
- "Unexpected constructor $constructor in " |
- "KernelWorldBuilder._getConstructorConstant"); |
- } |
- } |
- return _constantConstructor; |
+ @override |
+ ir.Class getClassNode(ClassEntity cls) { |
+ return _getClassNode(cls); |
} |
} |
-class _FieldData extends _MemberData { |
- ConstantExpression _constant; |
- |
- _FieldData(ir.Field node) : super(node); |
- |
- ir.Field get node => super.node; |
- |
- ConstantExpression getFieldConstant( |
- KernelToElementMapImpl elementMap, KField field) { |
- if (_constant == null) { |
- if (node.isConst) { |
- _constant = new Constantifier(elementMap).visit(node.initializer); |
- } else { |
- throw new SpannableAssertionFailure( |
- field, |
- "Unexpected field $field in " |
- "KernelWorldBuilder._getConstructorConstant"); |
- } |
- } |
- return _constant; |
- } |
+/// [KernelToElementMap] implementation used for both world impact computation |
+/// and SSA building. |
+// TODO(johnniwinther): Remove this when [JsStrategy] is the default. |
+class KernelToElementMapImpl extends KernelToElementMapForBuildingImpl |
+ with |
+ KernelToElementMapForImpactMixin, |
+ KernelToElementMapForImpactImpl, |
+ KElementCreatorMixin |
+ implements KernelToElementMapForImpactImpl2 { |
+ KernelToElementMapImpl(DiagnosticReporter reporter, Environment environment) |
+ : super(reporter, environment); |
} |
class KernelElementEnvironment implements ElementEnvironment { |
@@ -1393,7 +1075,7 @@ class KernelElementEnvironment implements ElementEnvironment { |
@override |
Iterable<ConstantValue> getMemberMetadata(covariant KMember member) { |
- _MemberData memberData = elementMap._memberList[member.memberIndex]; |
+ MemberData memberData = elementMap._memberList[member.memberIndex]; |
return memberData.getMetadata(elementMap); |
} |
} |
@@ -1566,7 +1248,7 @@ class _EvaluationEnvironment implements EvaluationEnvironment { |
} |
class KernelResolutionWorldBuilder extends KernelResolutionWorldBuilderBase { |
- final KernelToElementMapImpl elementMap; |
+ final KernelToElementMapForImpactImpl elementMap; |
KernelResolutionWorldBuilder( |
this.elementMap, |
@@ -1620,7 +1302,7 @@ class KernelResolutionWorldBuilder extends KernelResolutionWorldBuilderBase { |
} |
class KernelClosedWorld extends ClosedWorldBase { |
- final KernelToElementMapImpl _elementMap; |
+ final KernelToElementMapForImpactImpl _elementMap; |
KernelClosedWorld(this._elementMap, |
{ElementEnvironment elementEnvironment, |
@@ -1724,12 +1406,12 @@ class KernelClosedWorld extends ClosedWorldBase { |
// Interface for testing equivalence of Kernel-based entities. |
class WorldDeconstructionForTesting { |
- final KernelToElementMapImpl elementMap; |
+ final KernelToElementMapBase elementMap; |
WorldDeconstructionForTesting(this.elementMap); |
KClass getSuperclassForClass(KClass cls) { |
- _KClassEnv env = elementMap._classEnvs[cls.classIndex]; |
+ ClassEnv env = elementMap._classEnvs[cls.classIndex]; |
ir.Supertype supertype = env.cls.supertype; |
if (supertype == null) return null; |
return elementMap.getClass(supertype.classNode); |
@@ -1740,7 +1422,7 @@ class WorldDeconstructionForTesting { |
} |
InterfaceType getMixinTypeForClass(KClass cls) { |
- _KClassEnv env = elementMap._classEnvs[cls.classIndex]; |
+ ClassEnv env = elementMap._classEnvs[cls.classIndex]; |
ir.Supertype mixedInType = env.cls.mixedInType; |
if (mixedInType == null) return null; |
return elementMap.createInterfaceType( |
@@ -1749,7 +1431,7 @@ class WorldDeconstructionForTesting { |
} |
class KernelNativeMemberResolver extends NativeMemberResolverBase { |
- final KernelToElementMapImpl elementMap; |
+ final KernelToElementMapForImpactImpl elementMap; |
final NativeBasicData nativeBasicData; |
final NativeDataBuilder nativeDataBuilder; |
@@ -1807,7 +1489,7 @@ class JsKernelToElementMap extends KernelToElementMapBase |
final JsToFrontendMap _map; |
final ElementEnvironment _elementEnvironment; |
final CommonElements _commonElements; |
- final KernelToElementMapImpl _elementMap; |
+ final KernelToElementMapForImpactImpl _elementMap; |
JsKernelToElementMap( |
DiagnosticReporter reporter, |
@@ -1820,54 +1502,56 @@ class JsKernelToElementMap extends KernelToElementMapBase |
@override |
Spannable getSpannable(MemberEntity member, ir.Node node) { |
- return _elementMap.getSpannable(_map.toFrontendMember(member), node); |
+ return _elementMap._getSpannable(_map.toFrontendMember(member), node); |
+ } |
+ |
+ Iterable<LibraryEntity> get _libraries { |
+ return _elementMap._libraries.map(_map.toBackendLibrary); |
} |
@override |
- LibraryEntity getLibrary(ir.Library node) { |
+ LibraryEntity _getLibrary(ir.Library node, [LibraryEnv env]) { |
return _map.toBackendLibrary(_elementMap.getLibrary(node)); |
} |
@override |
- Local getLocalFunction(ir.TreeNode node) { |
+ Local _getLocalFunction(ir.TreeNode node) { |
throw new UnsupportedError("JsKernelToElementMap.getLocalFunction"); |
} |
@override |
- ClassEntity getClass(ir.Class node) { |
+ ClassEntity _getClass(ir.Class node, [ClassEnv env]) { |
return _map.toBackendClass(_elementMap.getClass(node)); |
} |
@override |
- FieldEntity getField(ir.Field node) { |
- return _map.toBackendMember(_elementMap.getField(node)); |
+ TypeVariableEntity _getTypeVariable(ir.TypeParameter node) { |
+ throw new UnsupportedError("JsKernelToElementMap._getTypeVariable"); |
} |
@override |
- MemberEntity getSuperMember(ir.Member context, ir.Name name, ir.Member target, |
- {bool setter: false}) { |
- return _map.toBackendMember( |
- _elementMap.getSuperMember(context, name, target, setter: setter)); |
+ FieldEntity _getField(ir.Field node) { |
+ return _map.toBackendMember(_elementMap.getField(node)); |
} |
@override |
- FunctionEntity getMethod(ir.Procedure node) { |
+ FunctionEntity _getMethod(ir.Procedure node) { |
return _map.toBackendMember(_elementMap.getMethod(node)); |
} |
@override |
- ir.Member getMemberNode(MemberEntity member) { |
- return _elementMap.getMemberNode(_map.toFrontendMember(member)); |
+ ConstructorEntity _getConstructor(ir.Member node) { |
+ return _map.toBackendMember(_elementMap.getConstructor(node)); |
} |
@override |
- MemberEntity getMember(ir.Member node) { |
- return _map.toBackendMember(_elementMap.getMember(node)); |
+ ir.Member getMemberNode(MemberEntity member) { |
+ return _elementMap._getMemberNode(_map.toFrontendMember(member)); |
} |
@override |
- ConstructorEntity getConstructor(ir.Member node) { |
- return _map.toBackendMember(_elementMap.getConstructor(node)); |
+ ir.Class getClassNode(ClassEntity cls) { |
+ return _elementMap._getClassNode(_map.toFrontendClass(cls)); |
} |
@override |