Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(374)

Unified Diff: pkg/compiler/lib/src/universe/element_world_builder.dart

Issue 2804993002: Extract ResolutionWorldBuilderBase from ElementResolutionWorldBuilder (Closed)
Patch Set: Fix. Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: pkg/compiler/lib/src/universe/element_world_builder.dart
diff --git a/pkg/compiler/lib/src/universe/element_world_builder.dart b/pkg/compiler/lib/src/universe/element_world_builder.dart
new file mode 100644
index 0000000000000000000000000000000000000000..39ed5e5bf63d25f59e2c5270c666852cd9c676c9
--- /dev/null
+++ b/pkg/compiler/lib/src/universe/element_world_builder.dart
@@ -0,0 +1,260 @@
+// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of world_builder;
+
+/// [ResolutionEnqueuerWorldBuilder] based on the [Element] model.
+class ElementResolutionWorldBuilder extends ResolutionWorldBuilderBase {
+ /// Used for testing the new more precise computation of instantiated types
+ /// and classes.
+ static bool useInstantiationMap = false;
+
+ final JavaScriptBackend _backend;
+ final Resolution _resolution;
+
+ ElementResolutionWorldBuilder(this._backend, this._resolution,
+ SelectorConstraintsStrategy selectorConstraintsStrategy)
+ : super(_backend.compiler.elementEnvironment, _resolution.commonElements,
+ _backend.nativeBasicData, selectorConstraintsStrategy);
+
+ bool isImplemented(ClassElement cls) {
+ return super.isImplemented(cls.declaration);
+ }
+
+ void registerTypeInstantiation(
+ InterfaceType type, ClassUsedCallback classUsed,
+ {ConstructorEntity constructor,
+ bool byMirrors: false,
+ bool isRedirection: false}) {
+ ClassElement cls = type.element;
+ cls.ensureResolved(_resolution);
+ super.registerTypeInstantiation(type, classUsed,
+ constructor: constructor,
+ byMirrors: byMirrors,
+ isRedirection: isRedirection);
+ }
+
+ /// Returns the instantiation map used for computing the closed world.
+ ///
+ /// If [useInstantiationMap] is `true`, redirections are removed and
+ /// redirecting factories are converted to their effective target and type.
+ Map<ClassEntity, InstantiationInfo> getInstantiationMap() {
+ if (!useInstantiationMap) return _instantiationInfo;
+
+ Map<ClassEntity, InstantiationInfo> instantiationMap =
+ <ClassEntity, InstantiationInfo>{};
+
+ InstantiationInfo infoFor(ClassEntity cls) {
+ return instantiationMap.putIfAbsent(cls, () => new InstantiationInfo());
+ }
+
+ _instantiationInfo.forEach((cls, info) {
+ if (info.instantiationMap != null) {
+ info.instantiationMap
+ .forEach((ConstructorElement constructor, Set<Instance> set) {
+ for (Instance instance in set) {
+ if (instance.isRedirection) {
+ continue;
+ }
+ if (constructor == null || !constructor.isRedirectingFactory) {
+ infoFor(cls)
+ .addInstantiation(constructor, instance.type, instance.kind);
+ } else {
+ ConstructorElement target = constructor.effectiveTarget;
+ ResolutionInterfaceType targetType =
+ constructor.computeEffectiveTargetType(instance.type);
+ Instantiation kind = Instantiation.DIRECTLY_INSTANTIATED;
+ if (target.enclosingClass.isAbstract) {
+ // If target is a factory constructor on an abstract class.
+ kind = Instantiation.UNINSTANTIATED;
+ }
+ infoFor(targetType.element)
+ .addInstantiation(target, targetType, kind);
+ }
+ }
+ });
+ }
+ });
+ return instantiationMap;
+ }
+
+ void registerIsCheck(ResolutionDartType type) {
+ type.computeUnaliased(_resolution);
+ type = type.unaliased;
+ // Even in checked mode, type annotations for return type and argument
+ // types do not imply type checks, so there should never be a check
+ // against the type variable of a typedef.
+ assert(!type.isTypeVariable || !type.element.enclosingElement.isTypedef);
+ super.registerIsCheck(type);
+ }
+
+ void registerStaticUse(StaticUse staticUse, MemberUsedCallback memberUsed) {
+ if (staticUse.kind == StaticUseKind.CLOSURE) {
+ LocalFunctionElement localFunction = staticUse.element;
+ if (localFunction.type.containsTypeVariables) {
+ localFunctionsWithFreeTypeVariables.add(localFunction);
+ }
+ localFunctions.add(staticUse.element);
+ return;
+ }
+ MemberElement element = staticUse.element;
+ assert(invariant(element, element.isDeclaration,
+ message: "Element ${element} is not the declaration."));
+ super.registerStaticUse(staticUse, memberUsed);
+ }
+
+ _ClassUsage _createClassUsage(ClassElement cls) {
+ cls.ensureResolved(_resolution);
+ _resolution.ensureClassMembers(cls);
+ return super._createClassUsage(cls);
+ }
+
+ /// Called to add [cls] to the set of known classes.
+ ///
+ /// This ensures that class hierarchy queries can be performed on [cls] and
+ /// classes that extend or implement it.
+ void registerClass(ClassEntity cls) => _registerClass(cls);
+
+ void _registerClass(ClassEntity cls, {bool isDirectlyInstantiated: false}) {
+ _ensureClassSet(cls);
+ if (isDirectlyInstantiated) {
+ _updateClassHierarchyNodeForClass(cls, directlyInstantiated: true);
+ }
+ }
+
+ void _processInstantiatedClassMember(
+ ClassEntity cls, MemberElement member, MemberUsedCallback memberUsed) {
+ assert(invariant(member, member.isDeclaration));
+ member.computeType(_resolution);
+ super._processInstantiatedClassMember(cls, member, memberUsed);
+ }
+
+ ClassHierarchyNode _ensureClassHierarchyNode(ClassElement cls) {
+ cls = cls.declaration;
+ return _classHierarchyNodes.putIfAbsent(cls, () {
+ ClassHierarchyNode parentNode;
+ if (cls.superclass != null) {
+ parentNode = _ensureClassHierarchyNode(cls.superclass);
+ }
+ return new ClassHierarchyNode(parentNode, cls);
+ });
+ }
+
+ ClassSet _ensureClassSet(ClassElement cls) {
+ cls = cls.declaration;
+ return _classSets.putIfAbsent(cls, () {
+ ClassHierarchyNode node = _ensureClassHierarchyNode(cls);
+ ClassSet classSet = new ClassSet(node);
+
+ for (ResolutionInterfaceType type in cls.allSupertypes) {
+ // TODO(johnniwinther): Optimization: Avoid adding [cls] to
+ // superclasses.
+ ClassSet subtypeSet = _ensureClassSet(type.element);
+ subtypeSet.addSubtype(node);
+ }
+ if (cls.isMixinApplication) {
+ // TODO(johnniwinther): Store this in the [ClassSet].
+ MixinApplicationElement mixinApplication = cls;
+ if (mixinApplication.mixin != null) {
+ // If [mixinApplication] is malformed [mixin] is `null`.
+ registerMixinUse(mixinApplication, mixinApplication.mixin);
+ }
+ }
+
+ return classSet;
+ });
+ }
+
+ void _updateSuperClassHierarchyNodeForClass(ClassHierarchyNode node) {
+ // Ensure that classes implicitly implementing `Function` are in its
+ // subtype set.
+ ClassElement cls = node.cls;
+ if (cls != _commonElements.functionClass &&
+ cls.implementsFunction(_commonElements)) {
+ ClassSet subtypeSet = _ensureClassSet(_commonElements.functionClass);
+ subtypeSet.addSubtype(node);
+ }
+ if (!node.isInstantiated && node.parentNode != null) {
+ _updateSuperClassHierarchyNodeForClass(node.parentNode);
+ }
+ }
+
+ void _updateClassHierarchyNodeForClass(ClassElement cls,
+ {bool directlyInstantiated: false, bool abstractlyInstantiated: false}) {
+ ClassHierarchyNode node = _ensureClassHierarchyNode(cls);
+ _updateSuperClassHierarchyNodeForClass(node);
+ if (directlyInstantiated) {
+ node.isDirectlyInstantiated = true;
+ }
+ if (abstractlyInstantiated) {
+ node.isAbstractlyInstantiated = true;
+ }
+ }
+
+ ClosedWorld closeWorld(DiagnosticReporter reporter) {
+ Map<ClassEntity, Set<ClassEntity>> typesImplementedBySubclasses =
+ new Map<ClassEntity, Set<ClassEntity>>();
+
+ /// Updates the `isDirectlyInstantiated` and `isIndirectlyInstantiated`
+ /// properties of the [ClassHierarchyNode] for [cls].
+
+ void addSubtypes(ClassElement cls, InstantiationInfo info) {
+ if (!info.hasInstantiation) {
+ return;
+ }
+ assert(cls.isDeclaration);
+ if (!cls.isResolved) {
+ reporter.internalError(cls, 'Class "${cls.name}" is not resolved.');
+ }
+
+ _updateClassHierarchyNodeForClass(cls,
+ directlyInstantiated: info.isDirectlyInstantiated,
+ abstractlyInstantiated: info.isAbstractlyInstantiated);
+
+ // Walk through the superclasses, and record the types
+ // implemented by that type on the superclasses.
+ ClassElement superclass = cls.superclass;
+ while (superclass != null) {
+ Set<ClassEntity> typesImplementedBySubclassesOfCls =
+ typesImplementedBySubclasses.putIfAbsent(
+ superclass, () => new Set<ClassEntity>());
+ for (ResolutionInterfaceType current in cls.allSupertypes) {
+ typesImplementedBySubclassesOfCls.add(current.element);
+ }
+ superclass = superclass.superclass;
+ }
+ }
+
+ // Use the [:seenClasses:] set to include non-instantiated
+ // classes: if the superclass of these classes require RTI, then
+ // they also need RTI, so that a constructor passes the type
+ // variables to the super constructor.
+ forEachInstantiatedClass(addSubtypes);
+
+ _closed = true;
+ return _closedWorldCache = new ClosedWorldImpl(
+ backend: _backend,
+ commonElements: _commonElements,
+ resolutionWorldBuilder: this,
+ functionSetBuilder: _allFunctions,
+ allTypedefs: _allTypedefs,
+ mixinUses: _mixinUses,
+ typesImplementedBySubclasses: typesImplementedBySubclasses,
+ classHierarchyNodes: _classHierarchyNodes,
+ classSets: _classSets);
+ }
+
+ void registerUsedElement(MemberElement element) {
+ if (element.isInstanceMember && !element.isAbstract) {
+ _allFunctions.add(element);
+ }
+ }
+
+ @override
+ void registerMixinUse(
+ MixinApplicationElement mixinApplication, ClassElement mixin) {
+ assert(mixin.isDeclaration);
+ super.registerMixinUse(mixinApplication, mixin);
+ }
+}
« no previous file with comments | « pkg/compiler/lib/src/resolution/resolution.dart ('k') | pkg/compiler/lib/src/universe/resolution_world_builder.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698