| 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
|
|
|