| 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 part of dart2js; | 5 part of dart2js; |
| 6 | 6 |
| 7 typedef ItemCompilationContext ItemCompilationContextCreator(); | 7 typedef ItemCompilationContext ItemCompilationContextCreator(); |
| 8 | 8 |
| 9 class EnqueueTask extends CompilerTask { | 9 class EnqueueTask extends CompilerTask { |
| 10 final ResolutionEnqueuer resolution; | 10 final ResolutionEnqueuer resolution; |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 75 final Set<ClassElement> seenClasses = new Set<ClassElement>(); | 75 final Set<ClassElement> seenClasses = new Set<ClassElement>(); |
| 76 final Universe universe = new Universe(); | 76 final Universe universe = new Universe(); |
| 77 | 77 |
| 78 bool queueIsClosed = false; | 78 bool queueIsClosed = false; |
| 79 EnqueueTask task; | 79 EnqueueTask task; |
| 80 native.NativeEnqueuer nativeEnqueuer; // Set by EnqueueTask | 80 native.NativeEnqueuer nativeEnqueuer; // Set by EnqueueTask |
| 81 | 81 |
| 82 bool hasEnqueuedEverything = false; | 82 bool hasEnqueuedEverything = false; |
| 83 bool hasEnqueuedReflectiveStaticFields = false; | 83 bool hasEnqueuedReflectiveStaticFields = false; |
| 84 | 84 |
| 85 Relations get dependencies; |
| 86 |
| 85 Enqueuer(this.name, this.compiler, this.itemCompilationContextCreator); | 87 Enqueuer(this.name, this.compiler, this.itemCompilationContextCreator); |
| 86 | 88 |
| 87 Queue<WorkItem> get queue; | 89 Queue<WorkItem> get queue; |
| 88 | 90 |
| 89 /// Returns [:true:] if this enqueuer is the resolution enqueuer. | 91 /// Returns [:true:] if this enqueuer is the resolution enqueuer. |
| 90 bool get isResolutionQueue => false; | 92 bool get isResolutionQueue => false; |
| 91 | 93 |
| 92 /// Returns [:true:] if [member] has been processed by this enqueuer. | 94 /// Returns [:true:] if [member] has been processed by this enqueuer. |
| 93 bool isProcessed(Element member); | 95 bool isProcessed(Element member); |
| 94 | 96 |
| 95 /** | 97 /** |
| 96 * Documentation wanted -- johnniwinther | 98 * Documentation wanted -- johnniwinther |
| 97 * | 99 * |
| 98 * Invariant: [element] must be a declaration element. | 100 * Invariant: [element] must be a declaration element. |
| 99 */ | 101 */ |
| 100 void addToWorkList(Element element) { | 102 void addToWorkList(Element element) { |
| 101 assert(invariant(element, element.isDeclaration)); | 103 assert(invariant(element, element.isDeclaration)); |
| 102 internalAddToWorkList(element); | 104 if (internalAddToWorkList(element)) { |
| 105 dependencies.put('addsToWorklist', compiler.currentElement, element); |
| 106 } |
| 103 } | 107 } |
| 104 | 108 |
| 105 /** | 109 /** |
| 106 * Adds [element] to the work list if it has not already been processed. | 110 * Adds [element] to the work list if it has not already been processed. |
| 111 * |
| 112 * Returns [true] if the element was actually added to the queue. |
| 107 */ | 113 */ |
| 108 void internalAddToWorkList(Element element); | 114 bool internalAddToWorkList(Element element); |
| 109 | 115 |
| 110 void registerInstantiatedType(InterfaceType type, Registry registry) { | 116 void registerInstantiatedType(InterfaceType type, Registry registry) { |
| 111 task.measure(() { | 117 task.measure(() { |
| 112 ClassElement cls = type.element; | 118 ClassElement cls = type.element; |
| 113 registry.registerDependency(cls); | 119 registry.registerDependency(cls); |
| 114 cls.ensureResolved(compiler); | 120 cls.ensureResolved(compiler); |
| 115 universe.instantiatedTypes.add(type); | 121 universe.instantiatedTypes.add(type); |
| 116 if (!cls.isAbstract | 122 if (!cls.isAbstract |
| 117 // We can't use the closed-world assumption with native abstract | 123 // We can't use the closed-world assumption with native abstract |
| 118 // classes; a native abstract class may have non-abstract subclasses | 124 // classes; a native abstract class may have non-abstract subclasses |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 210 registerClosurizedMember(member, compiler.globalDependencies); | 216 registerClosurizedMember(member, compiler.globalDependencies); |
| 211 addToWorkList(member); | 217 addToWorkList(member); |
| 212 return; | 218 return; |
| 213 } | 219 } |
| 214 // Store the member in [instanceFunctionsByName] to catch | 220 // Store the member in [instanceFunctionsByName] to catch |
| 215 // getters on the function. | 221 // getters on the function. |
| 216 Link<Element> members = instanceFunctionsByName.putIfAbsent( | 222 Link<Element> members = instanceFunctionsByName.putIfAbsent( |
| 217 memberName, () => const Link<Element>()); | 223 memberName, () => const Link<Element>()); |
| 218 instanceFunctionsByName[memberName] = members.prepend(member); | 224 instanceFunctionsByName[memberName] = members.prepend(member); |
| 219 if (universe.hasInvocation(member, compiler)) { | 225 if (universe.hasInvocation(member, compiler)) { |
| 226 for (Selector selector in |
| 227 universe.getMatchingSelectors(member, compiler)) { |
| 228 dependencies.enqueues(getContext(), member); |
| 229 } |
| 220 addToWorkList(member); | 230 addToWorkList(member); |
| 221 return; | 231 return; |
| 222 } | 232 } |
| 223 } else if (member.kind == ElementKind.GETTER) { | 233 } else if (member.kind == ElementKind.GETTER) { |
| 224 if (universe.hasInvokedGetter(member, compiler)) { | 234 if (universe.hasInvokedGetter(member, compiler)) { |
| 225 addToWorkList(member); | 235 addToWorkList(member); |
| 226 return; | 236 return; |
| 227 } | 237 } |
| 228 // We don't know what selectors the returned closure accepts. If | 238 // We don't know what selectors the returned closure accepts. If |
| 229 // the set contains any selector we have to assume that it matches. | 239 // the set contains any selector we have to assume that it matches. |
| 230 if (universe.hasInvocation(member, compiler)) { | 240 if (universe.hasInvocation(member, compiler)) { |
| 231 addToWorkList(member); | 241 addToWorkList(member); |
| 232 return; | 242 return; |
| 233 } | 243 } |
| 234 } else if (member.kind == ElementKind.SETTER) { | 244 } else if (member.kind == ElementKind.SETTER) { |
| 235 if (universe.hasInvokedSetter(member, compiler)) { | 245 if (universe.hasInvokedSetter(member, compiler)) { |
| 236 addToWorkList(member); | 246 addToWorkList(member); |
| 237 return; | 247 return; |
| 238 } | 248 } |
| 239 } | 249 } |
| 240 | 250 |
| 241 // The element is not yet used. Add it to the list of instance | 251 // The element is not yet used. Add it to the list of instance |
| 242 // members to still be processed. | 252 // members to still be processed. |
| 243 Link<Element> members = instanceMembersByName.putIfAbsent( | 253 Link<Element> members = instanceMembersByName.putIfAbsent( |
| 244 memberName, () => const Link<Element>()); | 254 memberName, () => const Link<Element>()); |
| 245 instanceMembersByName[memberName] = members.prepend(member); | 255 instanceMembersByName[memberName] = members.prepend(member); |
| 246 } | 256 } |
| 247 | 257 |
| 258 // TODO(karlklose): get the context. |
| 259 getContext() => compiler.currentElement; |
| 260 |
| 248 void enableNoSuchMethod(Element element) {} | 261 void enableNoSuchMethod(Element element) {} |
| 249 void enableIsolateSupport(LibraryElement element) {} | 262 void enableIsolateSupport(LibraryElement element) {} |
| 250 | 263 |
| 251 void onRegisterInstantiatedClass(ClassElement cls) { | 264 void onRegisterInstantiatedClass(ClassElement cls) { |
| 252 task.measure(() { | 265 task.measure(() { |
| 253 if (seenClasses.contains(cls)) return; | 266 if (seenClasses.contains(cls)) return; |
| 254 // The class must be resolved to compute the set of all | 267 // The class must be resolved to compute the set of all |
| 255 // supertypes. | 268 // supertypes. |
| 256 cls.ensureResolved(compiler); | 269 cls.ensureResolved(compiler); |
| 257 | 270 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 271 cls, this, compiler.globalDependencies); | 284 cls, this, compiler.globalDependencies); |
| 272 } | 285 } |
| 273 processClass(cls); | 286 processClass(cls); |
| 274 for (Link<DartType> supertypes = cls.allSupertypes; | 287 for (Link<DartType> supertypes = cls.allSupertypes; |
| 275 !supertypes.isEmpty; supertypes = supertypes.tail) { | 288 !supertypes.isEmpty; supertypes = supertypes.tail) { |
| 276 processClass(supertypes.head.element); | 289 processClass(supertypes.head.element); |
| 277 } | 290 } |
| 278 }); | 291 }); |
| 279 } | 292 } |
| 280 | 293 |
| 281 void registerNewSelector(Selector selector, | 294 void registerNewSelector(Element context, |
| 295 Selector selector, |
| 282 Map<String, Set<Selector>> selectorsMap) { | 296 Map<String, Set<Selector>> selectorsMap) { |
| 283 String name = selector.name; | 297 String name = selector.name; |
| 284 Set<Selector> selectors = | 298 Set<Selector> selectors = |
| 285 selectorsMap.putIfAbsent(name, () => new Setlet<Selector>()); | 299 selectorsMap.putIfAbsent(name, () => new Setlet<Selector>()); |
| 286 if (!selectors.contains(selector)) { | 300 if (!selectors.contains(selector)) { |
| 287 selectors.add(selector); | 301 selectors.add(selector); |
| 288 handleUnseenSelector(name, selector); | 302 handleUnseenSelector(getContext(), name, selector); |
| 289 } | 303 } |
| 290 } | 304 } |
| 291 | 305 |
| 292 void registerInvocation(Selector selector) { | 306 void registerInvocation(Element context, Selector selector) { |
| 293 task.measure(() { | 307 task.measure(() { |
| 294 registerNewSelector(selector, universe.invokedNames); | 308 registerNewSelector(context, selector, universe.invokedNames); |
| 295 }); | 309 }); |
| 296 } | 310 } |
| 297 | 311 |
| 298 void registerInvokedGetter(Selector selector) { | 312 void registerInvokedGetter(Element context, Selector selector) { |
| 299 task.measure(() { | 313 task.measure(() { |
| 300 registerNewSelector(selector, universe.invokedGetters); | 314 registerNewSelector(context, selector, universe.invokedGetters); |
| 301 }); | 315 }); |
| 302 } | 316 } |
| 303 | 317 |
| 304 void registerInvokedSetter(Selector selector) { | 318 void registerInvokedSetter(Element context, Selector selector) { |
| 305 task.measure(() { | 319 task.measure(() { |
| 306 registerNewSelector(selector, universe.invokedSetters); | 320 registerNewSelector(context, selector, universe.invokedSetters); |
| 307 }); | 321 }); |
| 308 } | 322 } |
| 309 | 323 |
| 310 void pretendElementWasUsed(Element element, Registry registry) { | 324 void pretendElementWasUsed(Element element, Registry registry) { |
| 311 if (!compiler.backend.isNeededForReflection(element)) return; | 325 if (!compiler.backend.isNeededForReflection(element)) return; |
| 312 if (Elements.isUnresolved(element)) { | 326 if (Elements.isUnresolved(element)) { |
| 313 // Ignore. | 327 // Ignore. |
| 314 } else if (element.isSynthesized | 328 } else if (element.isSynthesized |
| 315 && element.library.isPlatformLibrary) { | 329 && element.library.isPlatformLibrary) { |
| 316 // TODO(ahe): Work-around for http://dartbug.com/11205. | 330 // TODO(ahe): Work-around for http://dartbug.com/11205. |
| 317 } else if (element.isConstructor) { | 331 } else if (element.isConstructor) { |
| 318 ClassElement cls = element.declaration.enclosingClass; | 332 ClassElement cls = element.declaration.enclosingClass; |
| 319 registerInstantiatedType(cls.rawType, registry); | 333 registerInstantiatedType(cls.rawType, registry); |
| 320 registerStaticUse(element.declaration); | 334 registerStaticUse(element.declaration); |
| 321 } else if (element.isClass) { | 335 } else if (element.isClass) { |
| 322 ClassElement cls = element.declaration; | 336 ClassElement cls = element.declaration; |
| 323 registerInstantiatedClass(cls, registry); | 337 registerInstantiatedClass(cls, registry); |
| 324 // Make sure that even abstract classes are considered instantiated. | 338 // Make sure that even abstract classes are considered instantiated. |
| 325 universe.instantiatedClasses.add(cls); | 339 universe.instantiatedClasses.add(cls); |
| 326 } else if (element.impliesType) { | 340 } else if (element.impliesType) { |
| 327 // Don't enqueue typedefs, and type variables. | 341 // Don't enqueue typedefs, and type variables. |
| 328 } else if (Elements.isStaticOrTopLevel(element)) { | 342 } else if (Elements.isStaticOrTopLevel(element)) { |
| 329 registerStaticUse(element.declaration); | 343 registerStaticUse(element.declaration); |
| 330 } else if (element.isInstanceMember) { | 344 } else if (element.isInstanceMember) { |
| 331 Selector selector = new Selector.fromElement(element, compiler); | 345 Selector selector = new Selector.fromElement(element, compiler); |
| 332 registerSelectorUse(selector); | 346 registerSelectorUse(element, selector); |
| 333 if (element.isField) { | 347 if (element.isField) { |
| 334 Selector selector = | 348 Selector selector = |
| 335 new Selector.setter(element.name, element.library); | 349 new Selector.setter(element.name, element.library); |
| 336 registerInvokedSetter(selector); | 350 registerInvokedSetter(element, selector); |
| 337 } | 351 } |
| 338 } | 352 } |
| 339 } | 353 } |
| 340 | 354 |
| 341 void enqueueEverything() { | 355 void enqueueEverything() { |
| 342 if (hasEnqueuedEverything) return; | 356 if (hasEnqueuedEverything) return; |
| 343 compiler.log('Enqueuing everything'); | 357 compiler.log('Enqueuing everything'); |
| 344 task.ensureAllElementsByName(); | 358 task.ensureAllElementsByName(); |
| 345 for (Link link in task.allElementsByName.values) { | 359 for (Link link in task.allElementsByName.values) { |
| 346 for (Element element in link) { | 360 for (Element element in link) { |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 379 } | 393 } |
| 380 | 394 |
| 381 processInstanceMembers(String n, bool f(Element e)) { | 395 processInstanceMembers(String n, bool f(Element e)) { |
| 382 processLink(instanceMembersByName, n, f); | 396 processLink(instanceMembersByName, n, f); |
| 383 } | 397 } |
| 384 | 398 |
| 385 processInstanceFunctions(String n, bool f(Element e)) { | 399 processInstanceFunctions(String n, bool f(Element e)) { |
| 386 processLink(instanceFunctionsByName, n, f); | 400 processLink(instanceFunctionsByName, n, f); |
| 387 } | 401 } |
| 388 | 402 |
| 389 void handleUnseenSelector(String methodName, Selector selector) { | 403 void handleUnseenSelector(Element context, |
| 404 String methodName, |
| 405 Selector selector) { |
| 390 processInstanceMembers(methodName, (Element member) { | 406 processInstanceMembers(methodName, (Element member) { |
| 407 dependencies.enqueues(context, member); |
| 391 if (selector.appliesUnnamed(member, compiler)) { | 408 if (selector.appliesUnnamed(member, compiler)) { |
| 392 if (member.isFunction && selector.isGetter) { | 409 if (member.isFunction && selector.isGetter) { |
| 393 registerClosurizedMember(member, compiler.globalDependencies); | 410 registerClosurizedMember(member, compiler.globalDependencies); |
| 394 } | 411 } |
| 395 if (member.isField && member.enclosingClass.isNative) { | 412 if (member.isField && member.enclosingClass.isNative) { |
| 396 if (selector.isGetter || selector.isCall) { | 413 if (selector.isGetter || selector.isCall) { |
| 397 nativeEnqueuer.registerFieldLoad(member); | 414 nativeEnqueuer.registerFieldLoad(member); |
| 398 // We have to also handle storing to the field because we only get | 415 // We have to also handle storing to the field because we only get |
| 399 // one look at each member and there might be a store we have not | 416 // one look at each member and there might be a store we have not |
| 400 // seen yet. | 417 // seen yet. |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 438 compiler.backend.registerStaticUse(element, this); | 455 compiler.backend.registerStaticUse(element, this); |
| 439 } | 456 } |
| 440 | 457 |
| 441 void registerGetOfStaticFunction(FunctionElement element) { | 458 void registerGetOfStaticFunction(FunctionElement element) { |
| 442 registerStaticUse(element); | 459 registerStaticUse(element); |
| 443 registerInstantiatedClass(compiler.closureClass, | 460 registerInstantiatedClass(compiler.closureClass, |
| 444 compiler.globalDependencies); | 461 compiler.globalDependencies); |
| 445 universe.staticFunctionsNeedingGetter.add(element); | 462 universe.staticFunctionsNeedingGetter.add(element); |
| 446 } | 463 } |
| 447 | 464 |
| 448 void registerDynamicInvocation(Selector selector) { | 465 void registerDynamicInvocation(Element context, Selector selector) { |
| 449 assert(selector != null); | 466 assert(selector != null); |
| 450 registerInvocation(selector); | 467 registerInvocation(context, selector); |
| 451 } | 468 } |
| 452 | 469 |
| 453 void registerSelectorUse(Selector selector) { | 470 void registerSelectorUse(Element context, Selector selector) { |
| 454 if (selector.isGetter) { | 471 if (selector.isGetter) { |
| 455 registerInvokedGetter(selector); | 472 registerInvokedGetter(context, selector); |
| 456 } else if (selector.isSetter) { | 473 } else if (selector.isSetter) { |
| 457 registerInvokedSetter(selector); | 474 registerInvokedSetter(context, selector); |
| 458 } else { | 475 } else { |
| 459 registerInvocation(selector); | 476 registerInvocation(context, selector); |
| 460 } | 477 } |
| 461 } | 478 } |
| 462 | 479 |
| 463 void registerDynamicGetter(Selector selector) { | 480 void registerDynamicGetter(Element context, Selector selector) { |
| 464 registerInvokedGetter(selector); | 481 registerInvokedGetter(context, selector); |
| 465 } | 482 } |
| 466 | 483 |
| 467 void registerDynamicSetter(Selector selector) { | 484 void registerDynamicSetter(Element context, Selector selector) { |
| 468 registerInvokedSetter(selector); | 485 registerInvokedSetter(context, selector); |
| 469 } | 486 } |
| 470 | 487 |
| 471 void registerGetterForSuperMethod(Element element) { | 488 void registerGetterForSuperMethod(Element element) { |
| 472 universe.methodsNeedingSuperGetter.add(element); | 489 universe.methodsNeedingSuperGetter.add(element); |
| 473 } | 490 } |
| 474 | 491 |
| 475 void registerFieldGetter(Element element) { | 492 void registerFieldGetter(Element element) { |
| 476 universe.fieldGetters.add(element); | 493 universe.fieldGetters.add(element); |
| 477 } | 494 } |
| 478 | 495 |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 564 final Map<Element, TreeElements> resolvedElements; | 581 final Map<Element, TreeElements> resolvedElements; |
| 565 | 582 |
| 566 final Queue<ResolutionWorkItem> queue; | 583 final Queue<ResolutionWorkItem> queue; |
| 567 | 584 |
| 568 /** | 585 /** |
| 569 * A deferred task queue for the resolution phase which is processed | 586 * A deferred task queue for the resolution phase which is processed |
| 570 * when the resolution queue has been emptied. | 587 * when the resolution queue has been emptied. |
| 571 */ | 588 */ |
| 572 final Queue<DeferredTask> deferredTaskQueue; | 589 final Queue<DeferredTask> deferredTaskQueue; |
| 573 | 590 |
| 591 Relations dependencies; |
| 592 |
| 574 ResolutionEnqueuer(Compiler compiler, | 593 ResolutionEnqueuer(Compiler compiler, |
| 575 ItemCompilationContext itemCompilationContextCreator()) | 594 ItemCompilationContext itemCompilationContextCreator()) |
| 576 : super('resolution enqueuer', compiler, itemCompilationContextCreator), | 595 : super('resolution enqueuer', compiler, itemCompilationContextCreator), |
| 577 resolvedElements = new Map<Element, TreeElements>(), | 596 resolvedElements = new Map<Element, TreeElements>(), |
| 578 queue = new Queue<ResolutionWorkItem>(), | 597 queue = new Queue<ResolutionWorkItem>(), |
| 579 deferredTaskQueue = new Queue<DeferredTask>(); | 598 deferredTaskQueue = new Queue<DeferredTask>() { |
| 599 dependencies = new Relations(this); |
| 600 } |
| 580 | 601 |
| 581 bool get isResolutionQueue => true; | 602 bool get isResolutionQueue => true; |
| 582 | 603 |
| 583 bool isProcessed(Element member) => resolvedElements.containsKey(member); | 604 bool isProcessed(Element member) => resolvedElements.containsKey(member); |
| 584 | 605 |
| 585 /// Returns [:true:] if [element] has actually been used. | 606 /// Returns [:true:] if [element] has actually been used. |
| 586 bool isLive(Element element) { | 607 bool isLive(Element element) { |
| 587 if (seenClasses.contains(element)) return true; | 608 if (seenClasses.contains(element)) return true; |
| 588 if (getCachedElements(element) != null) return true; | 609 if (getCachedElements(element) != null) return true; |
| 589 return false; | 610 return false; |
| 590 } | 611 } |
| 591 | 612 |
| 592 TreeElements getCachedElements(Element element) { | 613 TreeElements getCachedElements(Element element) { |
| 593 // TODO(ngeoffray): Get rid of this check. | 614 // TODO(ngeoffray): Get rid of this check. |
| 594 if (element.enclosingElement.isClosure) { | 615 if (element.enclosingElement.isClosure) { |
| 595 closureMapping.ClosureClassElement cls = element.enclosingElement; | 616 closureMapping.ClosureClassElement cls = element.enclosingElement; |
| 596 element = cls.methodElement; | 617 element = cls.methodElement; |
| 597 } else if (element.isGenerativeConstructorBody) { | 618 } else if (element.isGenerativeConstructorBody) { |
| 598 ConstructorBodyElement body = element; | 619 ConstructorBodyElement body = element; |
| 599 element = body.constructor; | 620 element = body.constructor; |
| 600 } | 621 } |
| 601 Element owner = element.outermostEnclosingMemberOrTopLevel; | 622 Element owner = element.outermostEnclosingMemberOrTopLevel; |
| 602 if (owner == null) { | 623 if (owner == null) { |
| 603 owner = element; | 624 owner = element; |
| 604 } | 625 } |
| 605 return resolvedElements[owner.declaration]; | 626 return resolvedElements[owner.declaration]; |
| 606 } | 627 } |
| 607 | 628 |
| 608 void internalAddToWorkList(Element element) { | 629 bool internalAddToWorkList(Element element) { |
| 609 assert(invariant(element, element is AnalyzableElement, | 630 assert(invariant(element, element is AnalyzableElement, |
| 610 message: 'Element $element is not analyzable.')); | 631 message: 'Element $element is not analyzable.')); |
| 611 if (getCachedElements(element) != null) return; | 632 if (getCachedElements(element) != null) return false; |
| 612 if (queueIsClosed) { | 633 if (queueIsClosed) { |
| 613 throw new SpannableAssertionFailure(element, | 634 throw new SpannableAssertionFailure(element, |
| 614 "Resolution work list is closed. Trying to add $element."); | 635 "Resolution work list is closed. Trying to add $element."); |
| 615 } | 636 } |
| 616 | 637 |
| 617 compiler.world.registerUsedElement(element); | 638 compiler.world.registerUsedElement(element); |
| 618 | 639 |
| 619 queue.add(new ResolutionWorkItem(element, itemCompilationContextCreator())); | 640 queue.add(new ResolutionWorkItem(element, itemCompilationContextCreator())); |
| 620 | 641 |
| 621 // Enable isolate support if we start using something from the isolate | 642 // Enable isolate support if we start using something from the isolate |
| (...skipping 23 matching lines...) Expand all Loading... |
| 645 compiler.enabledRuntimeType = true; | 666 compiler.enabledRuntimeType = true; |
| 646 // TODO(ahe): Record precise dependency here. | 667 // TODO(ahe): Record precise dependency here. |
| 647 compiler.backend.registerRuntimeType(this, compiler.globalDependencies); | 668 compiler.backend.registerRuntimeType(this, compiler.globalDependencies); |
| 648 } else if (element == compiler.functionApplyMethod) { | 669 } else if (element == compiler.functionApplyMethod) { |
| 649 compiler.enabledFunctionApply = true; | 670 compiler.enabledFunctionApply = true; |
| 650 } else if (element == compiler.invokeOnMethod) { | 671 } else if (element == compiler.invokeOnMethod) { |
| 651 compiler.enabledInvokeOn = true; | 672 compiler.enabledInvokeOn = true; |
| 652 } | 673 } |
| 653 | 674 |
| 654 nativeEnqueuer.registerElement(element); | 675 nativeEnqueuer.registerElement(element); |
| 676 return true; |
| 655 } | 677 } |
| 656 | 678 |
| 657 void enableIsolateSupport(LibraryElement element) { | 679 void enableIsolateSupport(LibraryElement element) { |
| 658 compiler.isolateLibrary = element.patch; | 680 compiler.isolateLibrary = element.patch; |
| 659 for (String name in const [Compiler.START_ROOT_ISOLATE, | 681 for (String name in const [Compiler.START_ROOT_ISOLATE, |
| 660 '_currentIsolate', | 682 '_currentIsolate', |
| 661 '_callInIsolate']) { | 683 '_callInIsolate']) { |
| 662 Element element = compiler.isolateHelperLibrary.find(name); | 684 Element element = compiler.isolateHelperLibrary.find(name); |
| 663 addToWorkList(element); | 685 addToWorkList(element); |
| 664 compiler.globalDependencies.registerDependency(element); | 686 compiler.globalDependencies.registerDependency(element); |
| 665 } | 687 } |
| 666 } | 688 } |
| 667 | 689 |
| 668 void enableNoSuchMethod(Element element) { | 690 void enableNoSuchMethod(Element element) { |
| 669 if (compiler.enabledNoSuchMethod) return; | 691 if (compiler.enabledNoSuchMethod) return; |
| 670 if (compiler.backend.isDefaultNoSuchMethodImplementation(element)) return; | 692 if (compiler.backend.isDefaultNoSuchMethodImplementation(element)) return; |
| 671 | 693 |
| 672 Selector selector = compiler.noSuchMethodSelector; | 694 Selector selector = compiler.noSuchMethodSelector; |
| 673 compiler.enabledNoSuchMethod = true; | 695 compiler.enabledNoSuchMethod = true; |
| 674 compiler.backend.enableNoSuchMethod(this); | 696 compiler.backend.enableNoSuchMethod(element, this); |
| 675 } | 697 } |
| 676 | 698 |
| 677 /** | 699 /** |
| 678 * Adds an action to the deferred task queue. | 700 * Adds an action to the deferred task queue. |
| 679 * | 701 * |
| 680 * The action is performed the next time the resolution queue has been | 702 * The action is performed the next time the resolution queue has been |
| 681 * emptied. | 703 * emptied. |
| 682 * | 704 * |
| 683 * The queue is processed in FIFO order. | 705 * The queue is processed in FIFO order. |
| 684 */ | 706 */ |
| (...skipping 26 matching lines...) Expand all Loading... |
| 711 log('Resolved ${resolvedElements.length} elements.'); | 733 log('Resolved ${resolvedElements.length} elements.'); |
| 712 } | 734 } |
| 713 } | 735 } |
| 714 | 736 |
| 715 /// [Enqueuer] which is specific to code generation. | 737 /// [Enqueuer] which is specific to code generation. |
| 716 class CodegenEnqueuer extends Enqueuer { | 738 class CodegenEnqueuer extends Enqueuer { |
| 717 final Queue<CodegenWorkItem> queue; | 739 final Queue<CodegenWorkItem> queue; |
| 718 final Map<Element, js.Expression> generatedCode = | 740 final Map<Element, js.Expression> generatedCode = |
| 719 new Map<Element, js.Expression>(); | 741 new Map<Element, js.Expression>(); |
| 720 | 742 |
| 743 Relations dependencies; |
| 744 |
| 721 CodegenEnqueuer(Compiler compiler, | 745 CodegenEnqueuer(Compiler compiler, |
| 722 ItemCompilationContext itemCompilationContextCreator()) | 746 ItemCompilationContext itemCompilationContextCreator()) |
| 723 : super('codegen enqueuer', compiler, itemCompilationContextCreator), | 747 : super('codegen enqueuer', compiler, itemCompilationContextCreator), |
| 724 queue = new Queue<CodegenWorkItem>(); | 748 queue = new Queue<CodegenWorkItem>() { |
| 749 dependencies = new Relations(this); |
| 750 } |
| 725 | 751 |
| 726 bool isProcessed(Element member) => | 752 bool isProcessed(Element member) => |
| 727 member.isAbstract || generatedCode.containsKey(member); | 753 member.isAbstract || generatedCode.containsKey(member); |
| 728 | 754 |
| 729 void internalAddToWorkList(Element element) { | 755 bool internalAddToWorkList(Element element) { |
| 730 // Don't generate code for foreign elements. | 756 // Don't generate code for foreign elements. |
| 731 if (element.isForeign(compiler)) return; | 757 if (element.isForeign(compiler)) return false; |
| 732 | 758 |
| 733 // Codegen inlines field initializers. It only needs to generate | 759 // Codegen inlines field initializers. It only needs to generate |
| 734 // code for checked setters. | 760 // code for checked setters. |
| 735 if (element.isField && element.isInstanceMember) { | 761 if (element.isField && element.isInstanceMember) { |
| 736 if (!compiler.enableTypeAssertions | 762 if (!compiler.enableTypeAssertions |
| 737 || element.enclosingElement.isClosure) { | 763 || element.enclosingElement.isClosure) { |
| 738 return; | 764 return false; |
| 739 } | 765 } |
| 740 } | 766 } |
| 741 | 767 |
| 742 if (queueIsClosed) { | 768 if (queueIsClosed) { |
| 743 throw new SpannableAssertionFailure(element, | 769 throw new SpannableAssertionFailure(element, |
| 744 "Codegen work list is closed. Trying to add $element"); | 770 "Codegen work list is closed. Trying to add $element"); |
| 745 } | 771 } |
| 746 CodegenWorkItem workItem = new CodegenWorkItem( | 772 CodegenWorkItem workItem = new CodegenWorkItem( |
| 747 element, itemCompilationContextCreator()); | 773 element, itemCompilationContextCreator()); |
| 748 queue.add(workItem); | 774 queue.add(workItem); |
| 775 return true; |
| 749 } | 776 } |
| 750 | 777 |
| 751 void _logSpecificSummary(log(message)) { | 778 void _logSpecificSummary(log(message)) { |
| 752 log('Compiled ${generatedCode.length} methods.'); | 779 log('Compiled ${generatedCode.length} methods.'); |
| 753 } | 780 } |
| 754 } | 781 } |
| OLD | NEW |