| 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 |