| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library dart2js.enqueue; | 5 library dart2js.enqueue; |
| 6 | 6 |
| 7 import 'dart:collection' show Queue; | 7 import 'dart:collection' show Queue; |
| 8 | 8 |
| 9 import 'cache_strategy.dart'; | 9 import 'cache_strategy.dart'; |
| 10 import 'common/backend_api.dart' show Backend; | 10 import 'common/backend_api.dart' show Backend; |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 136 final CompilerTask task; | 136 final CompilerTask task; |
| 137 final String name; | 137 final String name; |
| 138 final Resolution _resolution; | 138 final Resolution _resolution; |
| 139 final CompilerOptions _options; | 139 final CompilerOptions _options; |
| 140 final Backend backend; | 140 final Backend backend; |
| 141 final GlobalDependencyRegistry _globalDependencies; | 141 final GlobalDependencyRegistry _globalDependencies; |
| 142 final CommonElements _commonElements; | 142 final CommonElements _commonElements; |
| 143 final native.NativeEnqueuer nativeEnqueuer; | 143 final native.NativeEnqueuer nativeEnqueuer; |
| 144 | 144 |
| 145 final EnqueuerStrategy strategy; | 145 final EnqueuerStrategy strategy; |
| 146 final Set<ClassElement> _processedClasses = new Set<ClassElement>(); | |
| 147 Set<ClassElement> _recentClasses = new Setlet<ClassElement>(); | 146 Set<ClassElement> _recentClasses = new Setlet<ClassElement>(); |
| 148 final ResolutionWorldBuilderImpl _universe; | 147 final ResolutionWorldBuilderImpl _universe; |
| 149 | 148 |
| 150 bool queueIsClosed = false; | 149 bool queueIsClosed = false; |
| 151 | 150 |
| 152 WorldImpactVisitor _impactVisitor; | 151 WorldImpactVisitor _impactVisitor; |
| 153 | 152 |
| 154 /// All declaration elements that have been processed by the resolver. | 153 /// All declaration elements that have been processed by the resolver. |
| 155 final Set<AstElement> processedElements = new Set<AstElement>(); | 154 final Set<AstElement> processedElements = new Set<AstElement>(); |
| 156 | 155 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 179 } | 178 } |
| 180 | 179 |
| 181 ResolutionWorldBuilder get universe => _universe; | 180 ResolutionWorldBuilder get universe => _universe; |
| 182 | 181 |
| 183 OpenWorld get _openWorld => universe.openWorld; | 182 OpenWorld get _openWorld => universe.openWorld; |
| 184 | 183 |
| 185 bool get queueIsEmpty => _queue.isEmpty; | 184 bool get queueIsEmpty => _queue.isEmpty; |
| 186 | 185 |
| 187 DiagnosticReporter get _reporter => _resolution.reporter; | 186 DiagnosticReporter get _reporter => _resolution.reporter; |
| 188 | 187 |
| 189 Iterable<ClassElement> get processedClasses => _processedClasses; | 188 Iterable<ClassElement> get processedClasses => _universe.processedClasses; |
| 190 | 189 |
| 191 void applyImpact(WorldImpact worldImpact, {Element impactSource}) { | 190 void applyImpact(WorldImpact worldImpact, {Element impactSource}) { |
| 192 if (worldImpact.isEmpty) return; | 191 if (worldImpact.isEmpty) return; |
| 193 impactStrategy.visitImpact( | 192 impactStrategy.visitImpact( |
| 194 impactSource, worldImpact, _impactVisitor, impactUse); | 193 impactSource, worldImpact, _impactVisitor, impactUse); |
| 195 } | 194 } |
| 196 | 195 |
| 197 void _registerInstantiatedType(InterfaceType type, | 196 void _registerInstantiatedType(InterfaceType type, |
| 198 {ConstructorElement constructor, | 197 {ConstructorElement constructor, |
| 199 bool mirrorUsage: false, | 198 bool mirrorUsage: false, |
| 200 bool nativeUsage: false, | 199 bool nativeUsage: false, |
| 201 bool globalDependency: false, | 200 bool globalDependency: false, |
| 202 bool isRedirection: false}) { | 201 bool isRedirection: false}) { |
| 203 task.measure(() { | 202 task.measure(() { |
| 204 ClassElement cls = type.element; | 203 _universe.registerTypeInstantiation(type, _applyClassUse, |
| 205 cls.ensureResolved(_resolution); | |
| 206 bool isNative = backend.isNative(cls); | |
| 207 _universe.registerTypeInstantiation(type, | |
| 208 constructor: constructor, | 204 constructor: constructor, |
| 209 isNative: isNative, | |
| 210 byMirrors: mirrorUsage, | 205 byMirrors: mirrorUsage, |
| 211 isRedirection: isRedirection, onImplemented: (ClassElement cls) { | 206 isRedirection: isRedirection); |
| 212 applyImpact(backend.registerImplementedClass(cls, forResolution: true)); | |
| 213 }); | |
| 214 if (globalDependency && !mirrorUsage) { | 207 if (globalDependency && !mirrorUsage) { |
| 215 _globalDependencies.registerDependency(type.element); | 208 _globalDependencies.registerDependency(type.element); |
| 216 } | 209 } |
| 217 if (nativeUsage) { | 210 if (nativeUsage) { |
| 218 nativeEnqueuer.onInstantiatedType(type); | 211 nativeEnqueuer.onInstantiatedType(type); |
| 219 } | 212 } |
| 220 backend.registerInstantiatedType(type); | 213 backend.registerInstantiatedType(type); |
| 221 // TODO(johnniwinther): Share this reasoning with [Universe]. | |
| 222 if (!cls.isAbstract || isNative || mirrorUsage) { | |
| 223 _processInstantiatedClass(cls); | |
| 224 } | |
| 225 }); | 214 }); |
| 226 } | 215 } |
| 227 | 216 |
| 228 bool checkNoEnqueuedInvokedInstanceMethods() { | 217 bool checkNoEnqueuedInvokedInstanceMethods() { |
| 229 return strategy.checkEnqueuerConsistency(this); | 218 return strategy.checkEnqueuerConsistency(this); |
| 230 } | 219 } |
| 231 | 220 |
| 232 void checkClass(ClassElement cls) { | 221 void checkClass(ClassElement cls) { |
| 233 _processClassMembers(cls, | 222 _universe.processClassMembers(cls, |
| 234 (MemberElement member, EnumSet<MemberUse> useSet) { | 223 (MemberElement member, EnumSet<MemberUse> useSet) { |
| 235 if (useSet.isNotEmpty) { | 224 if (useSet.isNotEmpty) { |
| 236 _reporter.internalError(member, | 225 _reporter.internalError(member, |
| 237 'Unenqueued use of $member: ${useSet.iterable(MemberUse.values)}'); | 226 'Unenqueued use of $member: ${useSet.iterable(MemberUse.values)}'); |
| 238 } | 227 } |
| 239 }); | 228 }); |
| 240 } | 229 } |
| 241 | 230 |
| 242 /// Callback for applying the first seen use of a [member]. | 231 /// Callback for applying the first seen use of a [member]. |
| 243 void _applyFirstUse(MemberElement member, EnumSet<MemberUse> useSet) { | 232 void _applyFirstMemberUse(MemberElement member, EnumSet<MemberUse> useSet) { |
| 244 ClassElement cls = member.enclosingClass; | 233 ClassElement cls = member.enclosingClass; |
| 245 if (member.isFunction) { | 234 if (member.isFunction) { |
| 246 MemberElement function = member; | 235 MemberElement function = member; |
| 247 if (function.name == Identifiers.noSuchMethod_) { | 236 if (function.name == Identifiers.noSuchMethod_) { |
| 248 _registerNoSuchMethod(function); | 237 _registerNoSuchMethod(function); |
| 249 } | 238 } |
| 250 if (function.name == Identifiers.call && !cls.typeVariables.isEmpty) { | 239 if (function.name == Identifiers.call && !cls.typeVariables.isEmpty) { |
| 251 _registerCallMethodWithFreeTypeVariables(function); | 240 _registerCallMethodWithFreeTypeVariables(function); |
| 252 } | 241 } |
| 253 } | 242 } |
| 254 _applyUse(member, useSet); | 243 _applyMemberUse(member, useSet); |
| 255 } | 244 } |
| 256 | 245 |
| 257 /// Callback for applying the use of a [member]. | 246 /// Callback for applying the use of a [member]. |
| 258 void _applyUse(Entity member, EnumSet<MemberUse> useSet) { | 247 void _applyMemberUse(Entity member, EnumSet<MemberUse> useSet) { |
| 259 if (useSet.contains(MemberUse.NORMAL)) { | 248 if (useSet.contains(MemberUse.NORMAL)) { |
| 260 _addToWorkList(member); | 249 _addToWorkList(member); |
| 261 } | 250 } |
| 262 if (useSet.contains(MemberUse.CLOSURIZE)) { | 251 if (useSet.contains(MemberUse.CLOSURIZE)) { |
| 263 _registerClosurizedMember(member); | 252 _registerClosurizedMember(member); |
| 264 } | 253 } |
| 265 } | 254 } |
| 266 | 255 |
| 267 /// TODO(johnniwinther): Move this to [ResolutionWorldBuilderImpl]. | 256 /// Callback for applying the use of a [cls]. |
| 268 void _processInstantiatedClass(ClassElement cls) { | 257 void _applyClassUse(ClassEntity cls, EnumSet<ClassUse> useSet) { |
| 269 task.measure(() { | 258 if (useSet.contains(ClassUse.INSTANTIATED)) { |
| 270 if (_processedClasses.contains(cls)) return; | 259 _recentClasses.add(cls); |
| 271 // The class must be resolved to compute the set of all | 260 _universe.processClassMembers(cls, _applyFirstMemberUse); |
| 272 // supertypes. | 261 // We only tell the backend once that [cls] was instantiated, so |
| 273 cls.ensureResolved(_resolution); | 262 // any additional dependencies must be treated as global |
| 274 | 263 // dependencies. |
| 275 void processClass(ClassElement superclass) { | 264 applyImpact(backend.registerInstantiatedClass(cls, forResolution: true)); |
| 276 if (_processedClasses.contains(superclass)) return; | 265 } |
| 277 | 266 if (useSet.contains(ClassUse.IMPLEMENTED)) { |
| 278 _processedClasses.add(superclass); | 267 applyImpact(backend.registerImplementedClass(cls, forResolution: true)); |
| 279 _recentClasses.add(superclass); | 268 } |
| 280 superclass.ensureResolved(_resolution); | |
| 281 _processClassMembers(superclass, _applyFirstUse); | |
| 282 _resolution.ensureClassMembers(superclass); | |
| 283 // We only tell the backend once that [superclass] was instantiated, so | |
| 284 // any additional dependencies must be treated as global | |
| 285 // dependencies. | |
| 286 applyImpact( | |
| 287 backend.registerInstantiatedClass(superclass, forResolution: true)); | |
| 288 } | |
| 289 | |
| 290 ClassElement superclass = cls; | |
| 291 while (superclass != null) { | |
| 292 processClass(superclass); | |
| 293 superclass = superclass.superclass; | |
| 294 } | |
| 295 }); | |
| 296 } | |
| 297 | |
| 298 /// TODO(johnniwinther): Move this to [ResolutionWorldBuilderImpl]. | |
| 299 void _processClassMembers(ClassElement cls, MemberUsed memberUsed) { | |
| 300 cls.implementation.forEachMember((ClassElement cls, MemberElement member) { | |
| 301 _universe.processInstantiatedClassMember(cls, member, memberUsed); | |
| 302 }); | |
| 303 } | 269 } |
| 304 | 270 |
| 305 void processDynamicUse(DynamicUse dynamicUse) { | 271 void processDynamicUse(DynamicUse dynamicUse) { |
| 306 task.measure(() { | 272 task.measure(() { |
| 307 _universe.registerDynamicUse(dynamicUse, _applyUse); | 273 _universe.registerDynamicUse(dynamicUse, _applyMemberUse); |
| 308 }); | 274 }); |
| 309 } | 275 } |
| 310 | 276 |
| 311 void processStaticUse(StaticUse staticUse) { | 277 void processStaticUse(StaticUse staticUse) { |
| 312 Element element = staticUse.element; | 278 Element element = staticUse.element; |
| 313 assert(invariant(element, element.isDeclaration, | 279 assert(invariant(element, element.isDeclaration, |
| 314 message: "Element ${element} is not the declaration.")); | 280 message: "Element ${element} is not the declaration.")); |
| 315 _universe.registerStaticUse(staticUse); | 281 _universe.registerStaticUse(staticUse); |
| 316 applyImpact(backend.registerStaticUse(element, forResolution: true)); | 282 applyImpact(backend.registerStaticUse(element, forResolution: true)); |
| 317 bool addElement = true; | 283 bool addElement = true; |
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 550 | 516 |
| 551 void _emptyDeferredQueue() { | 517 void _emptyDeferredQueue() { |
| 552 while (!_deferredQueue.isEmpty) { | 518 while (!_deferredQueue.isEmpty) { |
| 553 _DeferredAction task = _deferredQueue.removeFirst(); | 519 _DeferredAction task = _deferredQueue.removeFirst(); |
| 554 _reporter.withCurrentElement(task.element, task.action); | 520 _reporter.withCurrentElement(task.element, task.action); |
| 555 } | 521 } |
| 556 } | 522 } |
| 557 | 523 |
| 558 void forgetElement(Element element, Compiler compiler) { | 524 void forgetElement(Element element, Compiler compiler) { |
| 559 _universe.forgetElement(element, compiler); | 525 _universe.forgetElement(element, compiler); |
| 560 _processedClasses.remove(element); | |
| 561 processedElements.remove(element); | 526 processedElements.remove(element); |
| 562 } | 527 } |
| 563 } | 528 } |
| 564 | 529 |
| 565 void removeFromSet(Map<String, Set<Element>> map, Element element) { | 530 void removeFromSet(Map<String, Set<Element>> map, Element element) { |
| 566 Set<Element> set = map[element.name]; | 531 Set<Element> set = map[element.name]; |
| 567 if (set == null) return; | 532 if (set == null) return; |
| 568 set.remove(element); | 533 set.remove(element); |
| 569 } | 534 } |
| 570 | 535 |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 658 } | 623 } |
| 659 | 624 |
| 660 typedef void _DeferredActionFunction(); | 625 typedef void _DeferredActionFunction(); |
| 661 | 626 |
| 662 class _DeferredAction { | 627 class _DeferredAction { |
| 663 final Element element; | 628 final Element element; |
| 664 final _DeferredActionFunction action; | 629 final _DeferredActionFunction action; |
| 665 | 630 |
| 666 _DeferredAction(this.element, this.action); | 631 _DeferredAction(this.element, this.action); |
| 667 } | 632 } |
| OLD | NEW |