| 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.js.enqueue; | 5 library dart2js.js.enqueue; |
| 6 | 6 |
| 7 import 'dart:collection' show Queue; | 7 import 'dart:collection' show Queue; |
| 8 | 8 |
| 9 import '../common/backend_api.dart' show Backend; | 9 import '../common/backend_api.dart' show Backend; |
| 10 import '../common/codegen.dart' show CodegenWorkItem; | 10 import '../common/codegen.dart' show CodegenWorkItem; |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 78 } | 78 } |
| 79 | 79 |
| 80 Backend get backend => _compiler.backend; | 80 Backend get backend => _compiler.backend; |
| 81 | 81 |
| 82 CompilerOptions get options => _compiler.options; | 82 CompilerOptions get options => _compiler.options; |
| 83 | 83 |
| 84 Registry get globalDependencies => _compiler.globalDependencies; | 84 Registry get globalDependencies => _compiler.globalDependencies; |
| 85 | 85 |
| 86 Registry get mirrorDependencies => _compiler.mirrorDependencies; | 86 Registry get mirrorDependencies => _compiler.mirrorDependencies; |
| 87 | 87 |
| 88 ClassWorld get _world => _compiler.world; | 88 ClassWorld get _world => _compiler.closedWorld; |
| 89 | 89 |
| 90 bool get queueIsEmpty => queue.isEmpty; | 90 bool get queueIsEmpty => queue.isEmpty; |
| 91 | 91 |
| 92 /// Returns [:true:] if this enqueuer is the resolution enqueuer. | 92 /// Returns [:true:] if this enqueuer is the resolution enqueuer. |
| 93 bool get isResolutionQueue => false; | 93 bool get isResolutionQueue => false; |
| 94 | 94 |
| 95 QueueFilter get filter => _compiler.enqueuerFilter; | 95 QueueFilter get filter => _compiler.enqueuerFilter; |
| 96 | 96 |
| 97 DiagnosticReporter get reporter => _compiler.reporter; | 97 DiagnosticReporter get reporter => _compiler.reporter; |
| 98 | 98 |
| 99 /** | 99 /** |
| 100 * Documentation wanted -- johnniwinther | 100 * Documentation wanted -- johnniwinther |
| 101 * | 101 * |
| 102 * Invariant: [element] must be a declaration element. | 102 * Invariant: [element] must be a declaration element. |
| 103 */ | 103 */ |
| 104 void addToWorkList(Element element) { | 104 void addToWorkList(Element element) { |
| 105 assert(invariant(element, element.isDeclaration)); | 105 assert(invariant(element, element.isDeclaration)); |
| 106 // Don't generate code for foreign elements. | 106 // Don't generate code for foreign elements. |
| 107 if (backend.isForeign(element)) return; | 107 if (backend.isForeign(element)) return; |
| 108 | 108 |
| 109 // Codegen inlines field initializers. It only needs to generate | 109 // Codegen inlines field initializers. It only needs to generate |
| 110 // code for checked setters. | 110 // code for checked setters. |
| 111 if (element.isField && element.isInstanceMember) { | 111 if (element.isField && element.isInstanceMember) { |
| 112 if (!options.enableTypeAssertions || | 112 if (!options.enableTypeAssertions || element.enclosingElement.isClosure) { |
| 113 element.enclosingElement.isClosure) { | |
| 114 return; | 113 return; |
| 115 } | 114 } |
| 116 } | 115 } |
| 117 | 116 |
| 118 if (options.hasIncrementalSupport && !isProcessed(element)) { | 117 if (options.hasIncrementalSupport && !isProcessed(element)) { |
| 119 newlyEnqueuedElements.add(element); | 118 newlyEnqueuedElements.add(element); |
| 120 } | 119 } |
| 121 | 120 |
| 122 if (queueIsClosed) { | 121 if (queueIsClosed) { |
| 123 throw new SpannableAssertionFailure( | 122 throw new SpannableAssertionFailure( |
| (...skipping 14 matching lines...) Expand all Loading... |
| 138 .visitImpact(element, worldImpact, impactVisitor, impactUse); | 137 .visitImpact(element, worldImpact, impactVisitor, impactUse); |
| 139 } | 138 } |
| 140 | 139 |
| 141 void registerInstantiatedType(InterfaceType type, {bool mirrorUsage: false}) { | 140 void registerInstantiatedType(InterfaceType type, {bool mirrorUsage: false}) { |
| 142 task.measure(() { | 141 task.measure(() { |
| 143 ClassElement cls = type.element; | 142 ClassElement cls = type.element; |
| 144 bool isNative = backend.isNative(cls); | 143 bool isNative = backend.isNative(cls); |
| 145 universe.registerTypeInstantiation(type, | 144 universe.registerTypeInstantiation(type, |
| 146 isNative: isNative, | 145 isNative: isNative, |
| 147 byMirrors: mirrorUsage, onImplemented: (ClassElement cls) { | 146 byMirrors: mirrorUsage, onImplemented: (ClassElement cls) { |
| 148 backend | 147 backend.registerImplementedClass(cls, this, globalDependencies); |
| 149 .registerImplementedClass(cls, this, globalDependencies); | |
| 150 }); | 148 }); |
| 151 // TODO(johnniwinther): Share this reasoning with [Universe]. | 149 // TODO(johnniwinther): Share this reasoning with [Universe]. |
| 152 if (!cls.isAbstract || isNative || mirrorUsage) { | 150 if (!cls.isAbstract || isNative || mirrorUsage) { |
| 153 processInstantiatedClass(cls); | 151 processInstantiatedClass(cls); |
| 154 } | 152 } |
| 155 }); | 153 }); |
| 156 } | 154 } |
| 157 | 155 |
| 158 bool checkNoEnqueuedInvokedInstanceMethods() { | 156 bool checkNoEnqueuedInvokedInstanceMethods() { |
| 159 return filter.checkNoEnqueuedInvokedInstanceMethods(this); | 157 return filter.checkNoEnqueuedInvokedInstanceMethods(this); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 171 | 169 |
| 172 if (member.isField) { | 170 if (member.isField) { |
| 173 // The obvious thing to test here would be "member.isNative", | 171 // The obvious thing to test here would be "member.isNative", |
| 174 // however, that only works after metadata has been parsed/analyzed, | 172 // however, that only works after metadata has been parsed/analyzed, |
| 175 // and that may not have happened yet. | 173 // and that may not have happened yet. |
| 176 // So instead we use the enclosing class, which we know have had | 174 // So instead we use the enclosing class, which we know have had |
| 177 // its metadata parsed and analyzed. | 175 // its metadata parsed and analyzed. |
| 178 // Note: this assumes that there are no non-native fields on native | 176 // Note: this assumes that there are no non-native fields on native |
| 179 // classes, which may not be the case when a native class is subclassed. | 177 // classes, which may not be the case when a native class is subclassed. |
| 180 if (backend.isNative(cls)) { | 178 if (backend.isNative(cls)) { |
| 181 _compiler.world.registerUsedElement(member); | |
| 182 if (universe.hasInvokedGetter(member, _world) || | 179 if (universe.hasInvokedGetter(member, _world) || |
| 183 universe.hasInvocation(member, _world)) { | 180 universe.hasInvocation(member, _world)) { |
| 184 addToWorkList(member); | 181 addToWorkList(member); |
| 185 return; | 182 return; |
| 186 } | 183 } |
| 187 if (universe.hasInvokedSetter(member, _world)) { | 184 if (universe.hasInvokedSetter(member, _world)) { |
| 188 addToWorkList(member); | 185 addToWorkList(member); |
| 189 return; | 186 return; |
| 190 } | 187 } |
| 191 // Native fields need to go into instanceMembersByName as they | 188 // Native fields need to go into instanceMembersByName as they |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 264 message: "Class $superclass has not been " | 261 message: "Class $superclass has not been " |
| 265 "processed in resolution.")); | 262 "processed in resolution.")); |
| 266 */ | 263 */ |
| 267 | 264 |
| 268 _processedClasses.add(superclass); | 265 _processedClasses.add(superclass); |
| 269 recentClasses.add(superclass); | 266 recentClasses.add(superclass); |
| 270 superclass.implementation.forEachMember(processInstantiatedClassMember); | 267 superclass.implementation.forEachMember(processInstantiatedClassMember); |
| 271 // We only tell the backend once that [superclass] was instantiated, so | 268 // We only tell the backend once that [superclass] was instantiated, so |
| 272 // any additional dependencies must be treated as global | 269 // any additional dependencies must be treated as global |
| 273 // dependencies. | 270 // dependencies. |
| 274 backend.registerInstantiatedClass( | 271 backend.registerInstantiatedClass(superclass, this, globalDependencies); |
| 275 superclass, this, globalDependencies); | |
| 276 } | 272 } |
| 277 | 273 |
| 278 ClassElement superclass = cls; | 274 ClassElement superclass = cls; |
| 279 while (superclass != null) { | 275 while (superclass != null) { |
| 280 processClass(superclass); | 276 processClass(superclass); |
| 281 superclass = superclass.superclass; | 277 superclass = superclass.superclass; |
| 282 } | 278 } |
| 283 }); | 279 }); |
| 284 } | 280 } |
| 285 | 281 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 300 /// Enqeue the constructor [ctor] if it is required for reflection. | 296 /// Enqeue the constructor [ctor] if it is required for reflection. |
| 301 /// | 297 /// |
| 302 /// [enclosingWasIncluded] provides a hint whether the enclosing element was | 298 /// [enclosingWasIncluded] provides a hint whether the enclosing element was |
| 303 /// needed for reflection. | 299 /// needed for reflection. |
| 304 void enqueueReflectiveConstructor( | 300 void enqueueReflectiveConstructor( |
| 305 ConstructorElement ctor, bool enclosingWasIncluded) { | 301 ConstructorElement ctor, bool enclosingWasIncluded) { |
| 306 if (shouldIncludeElementDueToMirrors(ctor, | 302 if (shouldIncludeElementDueToMirrors(ctor, |
| 307 includedEnclosing: enclosingWasIncluded)) { | 303 includedEnclosing: enclosingWasIncluded)) { |
| 308 logEnqueueReflectiveAction(ctor); | 304 logEnqueueReflectiveAction(ctor); |
| 309 ClassElement cls = ctor.declaration.enclosingClass; | 305 ClassElement cls = ctor.declaration.enclosingClass; |
| 310 backend.registerInstantiatedType( | 306 backend.registerInstantiatedType(cls.rawType, this, mirrorDependencies, |
| 311 cls.rawType, this, mirrorDependencies, | |
| 312 mirrorUsage: true); | 307 mirrorUsage: true); |
| 313 registerStaticUse(new StaticUse.foreignUse(ctor.declaration)); | 308 registerStaticUse(new StaticUse.foreignUse(ctor.declaration)); |
| 314 } | 309 } |
| 315 } | 310 } |
| 316 | 311 |
| 317 /// Enqeue the member [element] if it is required for reflection. | 312 /// Enqeue the member [element] if it is required for reflection. |
| 318 /// | 313 /// |
| 319 /// [enclosingWasIncluded] provides a hint whether the enclosing element was | 314 /// [enclosingWasIncluded] provides a hint whether the enclosing element was |
| 320 /// needed for reflection. | 315 /// needed for reflection. |
| 321 void enqueueReflectiveMember(Element element, bool enclosingWasIncluded) { | 316 void enqueueReflectiveMember(Element element, bool enclosingWasIncluded) { |
| (...skipping 27 matching lines...) Expand all Loading... |
| 349 /// [enclosingWasIncluded] provides a hint whether the enclosing element was | 344 /// [enclosingWasIncluded] provides a hint whether the enclosing element was |
| 350 /// needed for reflection. | 345 /// needed for reflection. |
| 351 void enqueueReflectiveElementsInClass(ClassElement cls, | 346 void enqueueReflectiveElementsInClass(ClassElement cls, |
| 352 Iterable<ClassElement> recents, bool enclosingWasIncluded) { | 347 Iterable<ClassElement> recents, bool enclosingWasIncluded) { |
| 353 if (cls.library.isInternalLibrary || cls.isInjected) return; | 348 if (cls.library.isInternalLibrary || cls.isInjected) return; |
| 354 bool includeClass = shouldIncludeElementDueToMirrors(cls, | 349 bool includeClass = shouldIncludeElementDueToMirrors(cls, |
| 355 includedEnclosing: enclosingWasIncluded); | 350 includedEnclosing: enclosingWasIncluded); |
| 356 if (includeClass) { | 351 if (includeClass) { |
| 357 logEnqueueReflectiveAction(cls, "register"); | 352 logEnqueueReflectiveAction(cls, "register"); |
| 358 ClassElement decl = cls.declaration; | 353 ClassElement decl = cls.declaration; |
| 359 backend.registerInstantiatedType( | 354 backend.registerInstantiatedType(decl.rawType, this, mirrorDependencies, |
| 360 decl.rawType, this, mirrorDependencies, | |
| 361 mirrorUsage: true); | 355 mirrorUsage: true); |
| 362 } | 356 } |
| 363 // If the class is never instantiated, we know nothing of it can possibly | 357 // If the class is never instantiated, we know nothing of it can possibly |
| 364 // be reflected upon. | 358 // be reflected upon. |
| 365 // TODO(herhut): Add a warning if a mirrors annotation cannot hit. | 359 // TODO(herhut): Add a warning if a mirrors annotation cannot hit. |
| 366 if (recents.contains(cls.declaration)) { | 360 if (recents.contains(cls.declaration)) { |
| 367 logEnqueueReflectiveAction(cls, "members"); | 361 logEnqueueReflectiveAction(cls, "members"); |
| 368 cls.constructors.forEach((Element element) { | 362 cls.constructors.forEach((Element element) { |
| 369 enqueueReflectiveConstructor(element, includeClass); | 363 enqueueReflectiveConstructor(element, includeClass); |
| 370 }); | 364 }); |
| 371 cls.forEachClassMember((Member member) { | 365 cls.forEachClassMember((Member member) { |
| 372 enqueueReflectiveMember(member.element, includeClass); | 366 enqueueReflectiveMember(member.element, includeClass); |
| 373 }); | 367 }); |
| 374 } | 368 } |
| 375 } | 369 } |
| 376 | 370 |
| 377 /// Enqeue special classes that might not be visible by normal means or that | 371 /// Enqeue special classes that might not be visible by normal means or that |
| 378 /// would not normally be enqueued: | 372 /// would not normally be enqueued: |
| 379 /// | 373 /// |
| 380 /// [Closure] is treated specially as it is the superclass of all closures. | 374 /// [Closure] is treated specially as it is the superclass of all closures. |
| 381 /// Although it is in an internal library, we mark it as reflectable. Note | 375 /// Although it is in an internal library, we mark it as reflectable. Note |
| 382 /// that none of its methods are reflectable, unless reflectable by | 376 /// that none of its methods are reflectable, unless reflectable by |
| 383 /// inheritance. | 377 /// inheritance. |
| 384 void enqueueReflectiveSpecialClasses() { | 378 void enqueueReflectiveSpecialClasses() { |
| 385 Iterable<ClassElement> classes = | 379 Iterable<ClassElement> classes = backend.classesRequiredForReflection; |
| 386 backend.classesRequiredForReflection; | |
| 387 for (ClassElement cls in classes) { | 380 for (ClassElement cls in classes) { |
| 388 if (backend.referencedFromMirrorSystem(cls)) { | 381 if (backend.referencedFromMirrorSystem(cls)) { |
| 389 logEnqueueReflectiveAction(cls); | 382 logEnqueueReflectiveAction(cls); |
| 390 backend.registerInstantiatedType( | 383 backend.registerInstantiatedType(cls.rawType, this, mirrorDependencies, |
| 391 cls.rawType, this, mirrorDependencies, | |
| 392 mirrorUsage: true); | 384 mirrorUsage: true); |
| 393 } | 385 } |
| 394 } | 386 } |
| 395 } | 387 } |
| 396 | 388 |
| 397 /// Enqeue all local members of the library [lib] if they are required for | 389 /// Enqeue all local members of the library [lib] if they are required for |
| 398 /// reflection. | 390 /// reflection. |
| 399 void enqueueReflectiveElementsInLibrary( | 391 void enqueueReflectiveElementsInLibrary( |
| 400 LibraryElement lib, Iterable<ClassElement> recents) { | 392 LibraryElement lib, Iterable<ClassElement> recents) { |
| 401 bool includeLibrary = | 393 bool includeLibrary = |
| (...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 708 @override | 700 @override |
| 709 void visitStaticUse(StaticUse staticUse) { | 701 void visitStaticUse(StaticUse staticUse) { |
| 710 enqueuer.registerStaticUse(staticUse); | 702 enqueuer.registerStaticUse(staticUse); |
| 711 } | 703 } |
| 712 | 704 |
| 713 @override | 705 @override |
| 714 void visitTypeUse(TypeUse typeUse) { | 706 void visitTypeUse(TypeUse typeUse) { |
| 715 enqueuer.registerTypeUse(typeUse); | 707 enqueuer.registerTypeUse(typeUse); |
| 716 } | 708 } |
| 717 } | 709 } |
| OLD | NEW |