Chromium Code Reviews| 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..c0c5255541e02ad78e251b578a062827ea418db7 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,8 +147,8 @@ 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)); |
| } |
| @@ -172,13 +157,13 @@ class KernelToElementMapBase extends KernelToElementMapBaseMixin { |
| MemberEntity lookupClassMember(KClass cls, String name, |
|
Siggi Cherem (dart-lang)
2017/06/30 22:19:28
Switch to IndexableClass here and below?
Johnni Winther
2017/07/03 08:00:58
Yes!
|
| {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]; |
| + 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(KClass 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,62 +438,338 @@ 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)); |
| }); |
| - _ensureSupertypes(cls, env); |
| - if (env.supertype != null) { |
| - _forEachClassMember(env.supertype.element, f); |
| - } |
| + _ensureSupertypes(cls, env); |
| + if (env.supertype != null) { |
| + _forEachClassMember(env.supertype.element, f); |
| + } |
| + } |
| + |
| + 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, KClass cls) { |
|
Siggi Cherem (dart-lang)
2017/06/30 22:19:29
same thing here and below?
Johnni Winther
2017/07/03 08:00:58
Yes!
|
| + OrderedTypeSet orderedTypeSet = _getOrderedTypeSet(type.element); |
| + InterfaceType supertype = |
| + orderedTypeSet.asInstanceOf(cls, _getHierarchyDepth(cls)); |
| + if (supertype != null) { |
| + supertype = _substByContext(supertype, type); |
| + } |
| + return supertype; |
| + } |
| + |
| + OrderedTypeSet _getOrderedTypeSet(KClass cls) { |
| + ClassEnv env = _classEnvs[cls.classIndex]; |
| + _ensureSupertypes(cls, env); |
| + return env.orderedTypeSet; |
| + } |
| + |
| + int _getHierarchyDepth(KClass cls) { |
| + ClassEnv env = _classEnvs[cls.classIndex]; |
| + _ensureSupertypes(cls, env); |
| + return env.orderedTypeSet.maxDepth; |
| + } |
| + |
| + Iterable<InterfaceType> _getInterfaces(KClass 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); |
| + }); |
| } |
| - ConstantConstructor _getConstructorConstant(KConstructor constructor) { |
| - _ConstructorData data = _memberList[constructor.memberIndex]; |
| - return data.getConstructorConstant(this, constructor); |
| + 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); |
| } |
| - ConstantExpression _getFieldConstant(KField field) { |
| - _FieldData data = _memberList[field.memberIndex]; |
| - return data.getFieldConstant(this, field); |
| + 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); |
| + }); |
| } |
| } |
| -class KernelToElementMapForImpactImpl extends KernelToElementMapBase |
| - with KernelToElementMapForImpactMixin { |
| +/// 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; |
| - KernelToElementMapForImpactImpl( |
| - DiagnosticReporter reporter, Environment environment) |
| - : super(reporter, environment) { |
| - _nativeBehaviorBuilder = new KernelBehaviorBuilder(_commonElements); |
| - } |
| - |
| - @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); |
| - } |
| - |
| /// Adds libraries in [program] to the set of libraries. |
| /// |
| /// The main method of the first program is used as the main method for the |
| @@ -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 |