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 class EnqueueTask extends CompilerTask { | 7 class EnqueueTask extends CompilerTask { |
8 final ResolutionEnqueuer resolution; | 8 final ResolutionEnqueuer resolution; |
9 final CodegenEnqueuer codegen; | 9 final CodegenEnqueuer codegen; |
10 | 10 |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
170 } | 170 } |
171 } | 171 } |
172 }); | 172 }); |
173 return true; | 173 return true; |
174 } | 174 } |
175 | 175 |
176 void processInstantiatedClass(ClassElement cls) { | 176 void processInstantiatedClass(ClassElement cls) { |
177 cls.implementation.forEachMember(processInstantiatedClassMember); | 177 cls.implementation.forEachMember(processInstantiatedClassMember); |
178 } | 178 } |
179 | 179 |
180 /** | |
181 * Documentation wanted -- johnniwinther | |
182 */ | |
183 void processInstantiatedClassMember(ClassElement cls, Element member) { | 180 void processInstantiatedClassMember(ClassElement cls, Element member) { |
184 assert(invariant(member, member.isDeclaration)); | 181 assert(invariant(member, member.isDeclaration)); |
185 if (isProcessed(member)) return; | 182 if (isProcessed(member)) return; |
186 if (!member.isInstanceMember()) return; | 183 if (!member.isInstanceMember()) return; |
187 | 184 |
188 String memberName = member.name.slowToString(); | 185 String memberName = member.name.slowToString(); |
189 | 186 |
190 if (member.kind == ElementKind.FIELD) { | 187 if (member.kind == ElementKind.FIELD) { |
191 // The obvious thing to test here would be "member.isNative()", | 188 // The obvious thing to test here would be "member.isNative()", |
192 // however, that only works after metadata has been parsed/analyzed, | 189 // however, that only works after metadata has been parsed/analyzed, |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
225 // All field initializers must be resolved as they could | 222 // All field initializers must be resolved as they could |
226 // have an observable side-effect (and cannot be tree-shaken | 223 // have an observable side-effect (and cannot be tree-shaken |
227 // away). | 224 // away). |
228 addToWorkList(member); | 225 addToWorkList(member); |
229 return; | 226 return; |
230 } | 227 } |
231 } else if (member.kind == ElementKind.FUNCTION) { | 228 } else if (member.kind == ElementKind.FUNCTION) { |
232 if (member.name == Compiler.NO_SUCH_METHOD) { | 229 if (member.name == Compiler.NO_SUCH_METHOD) { |
233 enableNoSuchMethod(member); | 230 enableNoSuchMethod(member); |
234 } | 231 } |
| 232 if (member.name == Compiler.CALL_OPERATOR_NAME && |
| 233 !cls.typeVariables.isEmpty) { |
| 234 registerGenericCallMethod(member, compiler.globalDependencies); |
| 235 } |
235 // If there is a property access with the same name as a method we | 236 // If there is a property access with the same name as a method we |
236 // need to emit the method. | 237 // need to emit the method. |
237 if (universe.hasInvokedGetter(member, compiler)) { | 238 if (universe.hasInvokedGetter(member, compiler)) { |
238 // We will emit a closure, so make sure the bound closure class is | 239 registerClosurizedMember(member, compiler.globalDependencies); |
| 240 // We will emit a closure, so make sure the closure class is |
239 // generated. | 241 // generated. |
240 registerInstantiatedClass(compiler.boundClosureClass, | 242 registerInstantiatedClass(compiler.boundClosureClass, |
241 // Precise dependency is not important here. | 243 // Precise dependency is not important here. |
242 compiler.globalDependencies); | 244 compiler.globalDependencies); |
243 return addToWorkList(member); | 245 return addToWorkList(member); |
244 } | 246 } |
245 // Store the member in [instanceFunctionsByName] to catch | 247 // Store the member in [instanceFunctionsByName] to catch |
246 // getters on the function. | 248 // getters on the function. |
247 Link<Element> members = instanceFunctionsByName.putIfAbsent( | 249 Link<Element> members = instanceFunctionsByName.putIfAbsent( |
248 memberName, () => const Link<Element>()); | 250 memberName, () => const Link<Element>()); |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
401 } | 403 } |
402 hasEnqueuedEverything = true; | 404 hasEnqueuedEverything = true; |
403 } | 405 } |
404 | 406 |
405 processLink(Map<String, Link<Element>> map, | 407 processLink(Map<String, Link<Element>> map, |
406 SourceString n, | 408 SourceString n, |
407 bool f(Element e)) { | 409 bool f(Element e)) { |
408 String memberName = n.slowToString(); | 410 String memberName = n.slowToString(); |
409 Link<Element> members = map[memberName]; | 411 Link<Element> members = map[memberName]; |
410 if (members != null) { | 412 if (members != null) { |
| 413 // [f] might add elements to [: map[memberName] :] during the loop below |
| 414 // so we create a new list for [: map[memberName] :] and prepend the |
| 415 // [remaining] members after the loop. |
| 416 map[memberName] = const Link<Element>(); |
411 LinkBuilder<Element> remaining = new LinkBuilder<Element>(); | 417 LinkBuilder<Element> remaining = new LinkBuilder<Element>(); |
412 for (; !members.isEmpty; members = members.tail) { | 418 for (; !members.isEmpty; members = members.tail) { |
413 if (!f(members.head)) remaining.addLast(members.head); | 419 if (!f(members.head)) remaining.addLast(members.head); |
414 } | 420 } |
415 map[memberName] = remaining.toLink(); | 421 map[memberName] = remaining.toLink(map[memberName]); |
416 } | 422 } |
417 } | 423 } |
418 | 424 |
419 processInstanceMembers(SourceString n, bool f(Element e)) { | 425 processInstanceMembers(SourceString n, bool f(Element e)) { |
420 processLink(instanceMembersByName, n, f); | 426 processLink(instanceMembersByName, n, f); |
421 } | 427 } |
422 | 428 |
423 processInstanceFunctions(SourceString n, bool f(Element e)) { | 429 processInstanceFunctions(SourceString n, bool f(Element e)) { |
424 processLink(instanceFunctionsByName, n, f); | 430 processLink(instanceFunctionsByName, n, f); |
425 } | 431 } |
426 | 432 |
427 void handleUnseenSelector(SourceString methodName, Selector selector) { | 433 void handleUnseenSelector(SourceString methodName, Selector selector) { |
428 processInstanceMembers(methodName, (Element member) { | 434 processInstanceMembers(methodName, (Element member) { |
429 if (selector.appliesUnnamed(member, compiler)) { | 435 if (selector.appliesUnnamed(member, compiler)) { |
| 436 if (member.isFunction() && selector.isGetter()) { |
| 437 registerClosurizedMember(member, compiler.globalDependencies); |
| 438 } |
430 if (member.isField() && member.getEnclosingClass().isNative()) { | 439 if (member.isField() && member.getEnclosingClass().isNative()) { |
431 if (selector.isGetter() || selector.isCall()) { | 440 if (selector.isGetter() || selector.isCall()) { |
432 nativeEnqueuer.registerFieldLoad(member); | 441 nativeEnqueuer.registerFieldLoad(member); |
433 // We have to also handle storing to the field because we only get | 442 // We have to also handle storing to the field because we only get |
434 // one look at each member and there might be a store we have not | 443 // one look at each member and there might be a store we have not |
435 // seen yet. | 444 // seen yet. |
436 // TODO(sra): Process fields for storing separately. | 445 // TODO(sra): Process fields for storing separately. |
437 nativeEnqueuer.registerFieldStore(member); | 446 nativeEnqueuer.registerFieldStore(member); |
438 } else { | 447 } else { |
439 assert(selector.isSetter()); | 448 assert(selector.isSetter()); |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
531 | 540 |
532 void registerFieldGetter(Element element) { | 541 void registerFieldGetter(Element element) { |
533 universe.fieldGetters.add(element); | 542 universe.fieldGetters.add(element); |
534 } | 543 } |
535 | 544 |
536 void registerFieldSetter(Element element) { | 545 void registerFieldSetter(Element element) { |
537 universe.fieldSetters.add(element); | 546 universe.fieldSetters.add(element); |
538 } | 547 } |
539 | 548 |
540 void registerIsCheck(DartType type, TreeElements elements) { | 549 void registerIsCheck(DartType type, TreeElements elements) { |
| 550 type = universe.registerIsCheck(type, compiler); |
541 // Even in checked mode, type annotations for return type and argument | 551 // Even in checked mode, type annotations for return type and argument |
542 // types do not imply type checks, so there should never be a check | 552 // types do not imply type checks, so there should never be a check |
543 // against the type variable of a typedef. | 553 // against the type variable of a typedef. |
544 assert(type.kind != TypeKind.TYPE_VARIABLE || | 554 assert(type.kind != TypeKind.TYPE_VARIABLE || |
545 !type.element.enclosingElement.isTypedef()); | 555 !type.element.enclosingElement.isTypedef()); |
546 universe.isChecks.add(type); | |
547 compiler.backend.registerIsCheck(type, this, elements); | 556 compiler.backend.registerIsCheck(type, this, elements); |
548 } | 557 } |
549 | 558 |
550 /** | 559 /** |
551 * If a factory constructor is used with type arguments, we lose track | 560 * If a factory constructor is used with type arguments, we lose track |
552 * which arguments could be used to create instances of classes that use their | 561 * which arguments could be used to create instances of classes that use their |
553 * type variables as expressions, so we have to remember if we saw such a use. | 562 * type variables as expressions, so we have to remember if we saw such a use. |
554 */ | 563 */ |
555 void registerFactoryWithTypeArguments(TreeElements elements) { | 564 void registerFactoryWithTypeArguments(TreeElements elements) { |
556 universe.usingFactoryWithTypeArguments = true; | 565 universe.usingFactoryWithTypeArguments = true; |
557 } | 566 } |
558 | 567 |
559 void registerAsCheck(DartType type, TreeElements elements) { | 568 void registerAsCheck(DartType type, TreeElements elements) { |
560 registerIsCheck(type, elements); | 569 registerIsCheck(type, elements); |
561 compiler.backend.registerAsCheck(type, elements); | 570 compiler.backend.registerAsCheck(type, elements); |
562 } | 571 } |
563 | 572 |
| 573 void registerGenericCallMethod(Element element, TreeElements elements) { |
| 574 compiler.backend.registerGenericCallMethod(element, this, elements); |
| 575 universe.genericCallMethods.add(element); |
| 576 } |
| 577 |
| 578 void registerClosurizedMember(Element element, TreeElements elements) { |
| 579 if (element.computeType(compiler).containsTypeVariables) { |
| 580 registerClosurizedGenericMember(element, elements); |
| 581 } |
| 582 universe.closurizedMembers.add(element); |
| 583 } |
| 584 |
| 585 void registerClosurizedGenericMember(Element element, TreeElements elements) { |
| 586 compiler.backend.registerGenericClosure(element, this, elements); |
| 587 universe.closurizedGenericMembers.add(element); |
| 588 } |
| 589 |
564 void forEach(f(WorkItem work)); | 590 void forEach(f(WorkItem work)); |
565 | 591 |
566 void forEachPostProcessTask(f(PostProcessTask work)) {} | 592 void forEachPostProcessTask(f(PostProcessTask work)) {} |
567 | 593 |
568 void logSummary(log(message)) { | 594 void logSummary(log(message)) { |
569 _logSpecificSummary(log); | 595 _logSpecificSummary(log); |
570 nativeEnqueuer.logSummary(log); | 596 nativeEnqueuer.logSummary(log); |
571 } | 597 } |
572 | 598 |
573 /// Log summary specific to the concrete enqueuer. | 599 /// Log summary specific to the concrete enqueuer. |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
648 } | 674 } |
649 } | 675 } |
650 | 676 |
651 if (element.isGetter() && element.name == Compiler.RUNTIME_TYPE) { | 677 if (element.isGetter() && element.name == Compiler.RUNTIME_TYPE) { |
652 // Enable runtime type support if we discover a getter called runtimeType. | 678 // Enable runtime type support if we discover a getter called runtimeType. |
653 // We have to enable runtime type before hitting the codegen, so | 679 // We have to enable runtime type before hitting the codegen, so |
654 // that constructors know whether they need to generate code for | 680 // that constructors know whether they need to generate code for |
655 // runtime type. | 681 // runtime type. |
656 compiler.enabledRuntimeType = true; | 682 compiler.enabledRuntimeType = true; |
657 // TODO(ahe): Record precise dependency here. | 683 // TODO(ahe): Record precise dependency here. |
658 compiler.backend.registerRuntimeType(compiler.globalDependencies); | 684 compiler.backend.registerRuntimeType(this, compiler.globalDependencies); |
659 } else if (element == compiler.functionApplyMethod) { | 685 } else if (element == compiler.functionApplyMethod) { |
660 compiler.enabledFunctionApply = true; | 686 compiler.enabledFunctionApply = true; |
661 } else if (element == compiler.invokeOnMethod) { | 687 } else if (element == compiler.invokeOnMethod) { |
662 compiler.enabledInvokeOn = true; | 688 compiler.enabledInvokeOn = true; |
663 } | 689 } |
664 | 690 |
665 nativeEnqueuer.registerElement(element); | 691 nativeEnqueuer.registerElement(element); |
666 } | 692 } |
667 | 693 |
668 void enableIsolateSupport(LibraryElement element) { | 694 void enableIsolateSupport(LibraryElement element) { |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
759 while(!queue.isEmpty) { | 785 while(!queue.isEmpty) { |
760 // TODO(johnniwinther): Find an optimal process order for codegen. | 786 // TODO(johnniwinther): Find an optimal process order for codegen. |
761 f(queue.removeLast()); | 787 f(queue.removeLast()); |
762 } | 788 } |
763 } | 789 } |
764 | 790 |
765 void _logSpecificSummary(log(message)) { | 791 void _logSpecificSummary(log(message)) { |
766 log('Compiled ${generatedCode.length} methods.'); | 792 log('Compiled ${generatedCode.length} methods.'); |
767 } | 793 } |
768 } | 794 } |
OLD | NEW |