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