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 return true; | 172 return true; |
173 } | 173 } |
174 | 174 |
175 void processInstantiatedClass(ClassElement cls) { | 175 void processInstantiatedClass(ClassElement cls) { |
176 cls.implementation.forEachMember(processInstantiatedClassMember); | 176 cls.implementation.forEachMember(processInstantiatedClassMember); |
177 } | 177 } |
178 | 178 |
179 /** | 179 /** |
180 * Documentation wanted -- johnniwinther | 180 * Documentation wanted -- johnniwinther |
karlklose
2013/06/19 14:37:05
I think we can remove this 'documentation'.
Johnni Winther
2013/06/21 12:19:15
Done.
| |
181 */ | 181 */ |
182 void processInstantiatedClassMember(ClassElement cls, Element member) { | 182 void processInstantiatedClassMember(ClassElement cls, Element member) { |
183 assert(invariant(member, member.isDeclaration)); | 183 assert(invariant(member, member.isDeclaration)); |
184 if (isProcessed(member)) return; | 184 if (isProcessed(member)) return; |
185 if (!member.isInstanceMember()) return; | 185 if (!member.isInstanceMember()) return; |
186 | 186 |
187 String memberName = member.name.slowToString(); | 187 String memberName = member.name.slowToString(); |
188 | 188 |
189 if (member.kind == ElementKind.FIELD) { | 189 if (member.kind == ElementKind.FIELD) { |
190 // The obvious thing to test here would be "member.isNative()", | 190 // The obvious thing to test here would be "member.isNative()", |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
224 // All field initializers must be resolved as they could | 224 // All field initializers must be resolved as they could |
225 // have an observable side-effect (and cannot be tree-shaken | 225 // have an observable side-effect (and cannot be tree-shaken |
226 // away). | 226 // away). |
227 addToWorkList(member); | 227 addToWorkList(member); |
228 return; | 228 return; |
229 } | 229 } |
230 } else if (member.kind == ElementKind.FUNCTION) { | 230 } else if (member.kind == ElementKind.FUNCTION) { |
231 if (member.name == Compiler.NO_SUCH_METHOD) { | 231 if (member.name == Compiler.NO_SUCH_METHOD) { |
232 enableNoSuchMethod(member); | 232 enableNoSuchMethod(member); |
233 } | 233 } |
234 if (member.name == Compiler.CALL_OPERATOR_NAME) { | |
235 if (!cls.typeVariables.isEmpty) { | |
karlklose
2013/06/19 14:37:05
Join the two conditions.
Johnni Winther
2013/06/21 12:19:15
Done.
| |
236 registerGenericCallMethod(member, compiler.globalDependencies); | |
237 } | |
238 } | |
234 // If there is a property access with the same name as a method we | 239 // If there is a property access with the same name as a method we |
235 // need to emit the method. | 240 // need to emit the method. |
236 if (universe.hasInvokedGetter(member, compiler)) { | 241 if (universe.hasInvokedGetter(member, compiler)) { |
237 // We will emit a closure, so make sure the bound closure class is | 242 registerClosure(member, compiler.globalDependencies); |
243 // We will emit a closure, so make sure the closure class is | |
238 // generated. | 244 // generated. |
239 registerInstantiatedClass(compiler.boundClosureClass, | 245 registerInstantiatedClass(compiler.boundClosureClass, |
240 // Precise dependency is not important here. | 246 // Precise dependency is not important here. |
241 compiler.globalDependencies); | 247 compiler.globalDependencies); |
242 return addToWorkList(member); | 248 return addToWorkList(member); |
243 } | 249 } |
244 // Store the member in [instanceFunctionsByName] to catch | 250 // Store the member in [instanceFunctionsByName] to catch |
245 // getters on the function. | 251 // getters on the function. |
246 Link<Element> members = instanceFunctionsByName.putIfAbsent( | 252 Link<Element> members = instanceFunctionsByName.putIfAbsent( |
247 memberName, () => const Link<Element>()); | 253 memberName, () => const Link<Element>()); |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
383 /// Called when [:new Symbol(...):] is seen. | 389 /// Called when [:new Symbol(...):] is seen. |
384 void registerNewSymbol(TreeElements elements) { | 390 void registerNewSymbol(TreeElements elements) { |
385 } | 391 } |
386 | 392 |
387 processLink(Map<String, Link<Element>> map, | 393 processLink(Map<String, Link<Element>> map, |
388 SourceString n, | 394 SourceString n, |
389 bool f(Element e)) { | 395 bool f(Element e)) { |
390 String memberName = n.slowToString(); | 396 String memberName = n.slowToString(); |
391 Link<Element> members = map[memberName]; | 397 Link<Element> members = map[memberName]; |
392 if (members != null) { | 398 if (members != null) { |
399 map[memberName] = const Link<Element>(); | |
393 LinkBuilder<Element> remaining = new LinkBuilder<Element>(); | 400 LinkBuilder<Element> remaining = new LinkBuilder<Element>(); |
394 for (; !members.isEmpty; members = members.tail) { | 401 for (; !members.isEmpty; members = members.tail) { |
395 if (!f(members.head)) remaining.addLast(members.head); | 402 if (!f(members.head)) remaining.addLast(members.head); |
396 } | 403 } |
397 map[memberName] = remaining.toLink(); | 404 map[memberName] = remaining.toLink(map[memberName]); |
karlklose
2013/06/19 14:37:05
Isn't the constant empty link already the default
Johnni Winther
2013/06/21 12:19:15
Comment added.
| |
398 } | 405 } |
399 } | 406 } |
400 | 407 |
401 processInstanceMembers(SourceString n, bool f(Element e)) { | 408 processInstanceMembers(SourceString n, bool f(Element e)) { |
402 processLink(instanceMembersByName, n, f); | 409 processLink(instanceMembersByName, n, f); |
403 } | 410 } |
404 | 411 |
405 processInstanceFunctions(SourceString n, bool f(Element e)) { | 412 processInstanceFunctions(SourceString n, bool f(Element e)) { |
406 processLink(instanceFunctionsByName, n, f); | 413 processLink(instanceFunctionsByName, n, f); |
407 } | 414 } |
408 | 415 |
409 void handleUnseenSelector(SourceString methodName, Selector selector) { | 416 void handleUnseenSelector(SourceString methodName, Selector selector) { |
410 processInstanceMembers(methodName, (Element member) { | 417 processInstanceMembers(methodName, (Element member) { |
411 if (selector.appliesUnnamed(member, compiler)) { | 418 if (selector.appliesUnnamed(member, compiler)) { |
419 if (member.isFunction() && selector.isGetter()) { | |
420 registerClosure(member, compiler.globalDependencies); | |
421 } | |
412 if (member.isField() && member.getEnclosingClass().isNative()) { | 422 if (member.isField() && member.getEnclosingClass().isNative()) { |
413 if (selector.isGetter() || selector.isCall()) { | 423 if (selector.isGetter() || selector.isCall()) { |
414 nativeEnqueuer.registerFieldLoad(member); | 424 nativeEnqueuer.registerFieldLoad(member); |
415 // We have to also handle storing to the field because we only get | 425 // We have to also handle storing to the field because we only get |
416 // one look at each member and there might be a store we have not | 426 // one look at each member and there might be a store we have not |
417 // seen yet. | 427 // seen yet. |
418 // TODO(sra): Process fields for storing separately. | 428 // TODO(sra): Process fields for storing separately. |
419 nativeEnqueuer.registerFieldStore(member); | 429 nativeEnqueuer.registerFieldStore(member); |
420 } else { | 430 } else { |
421 assert(selector.isSetter()); | 431 assert(selector.isSetter()); |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
512 | 522 |
513 void registerFieldGetter(Element element) { | 523 void registerFieldGetter(Element element) { |
514 universe.fieldGetters.add(element); | 524 universe.fieldGetters.add(element); |
515 } | 525 } |
516 | 526 |
517 void registerFieldSetter(Element element) { | 527 void registerFieldSetter(Element element) { |
518 universe.fieldSetters.add(element); | 528 universe.fieldSetters.add(element); |
519 } | 529 } |
520 | 530 |
521 void registerIsCheck(DartType type, TreeElements elements) { | 531 void registerIsCheck(DartType type, TreeElements elements) { |
532 type = universe.registerIsCheck(type, compiler); | |
522 // Even in checked mode, type annotations for return type and argument | 533 // Even in checked mode, type annotations for return type and argument |
523 // types do not imply type checks, so there should never be a check | 534 // types do not imply type checks, so there should never be a check |
524 // against the type variable of a typedef. | 535 // against the type variable of a typedef. |
525 assert(type.kind != TypeKind.TYPE_VARIABLE || | 536 assert(type.kind != TypeKind.TYPE_VARIABLE || |
526 !type.element.enclosingElement.isTypedef()); | 537 !type.element.enclosingElement.isTypedef()); |
527 universe.isChecks.add(type); | |
528 compiler.backend.registerIsCheck(type, this, elements); | 538 compiler.backend.registerIsCheck(type, this, elements); |
529 } | 539 } |
530 | 540 |
531 /** | 541 /** |
532 * If a factory constructor is used with type arguments, we lose track | 542 * If a factory constructor is used with type arguments, we lose track |
533 * which arguments could be used to create instances of classes that use their | 543 * which arguments could be used to create instances of classes that use their |
534 * type variables as expressions, so we have to remember if we saw such a use. | 544 * type variables as expressions, so we have to remember if we saw such a use. |
535 */ | 545 */ |
536 void registerFactoryWithTypeArguments(TreeElements elements) { | 546 void registerFactoryWithTypeArguments(TreeElements elements) { |
537 universe.usingFactoryWithTypeArguments = true; | 547 universe.usingFactoryWithTypeArguments = true; |
538 } | 548 } |
539 | 549 |
540 void registerAsCheck(DartType type, TreeElements elements) { | 550 void registerAsCheck(DartType type, TreeElements elements) { |
541 registerIsCheck(type, elements); | 551 registerIsCheck(type, elements); |
542 compiler.backend.registerAsCheck(type, elements); | 552 compiler.backend.registerAsCheck(type, elements); |
543 } | 553 } |
544 | 554 |
555 void registerGenericCallMethod(Element element, TreeElements elements) { | |
556 compiler.backend.registerGenericCallMethod(element, this, elements); | |
557 universe.genericCallMethods.add(element); | |
558 } | |
559 | |
560 void registerClosure(Element element, TreeElements elements) { | |
karlklose
2013/06/19 14:37:05
'registerClosurizedMember'?
Johnni Winther
2013/06/21 12:19:15
Done.
| |
561 if (element.computeType(compiler).containsTypeVariables) { | |
562 registerGenericClosure(element, elements); | |
563 } | |
564 universe.closurizedMembers.add(element); | |
565 } | |
566 | |
567 void registerGenericClosure(Element element, TreeElements elements) { | |
karlklose
2013/06/19 14:37:05
'registerClosurizedGenericMember'?
Johnni Winther
2013/06/21 12:19:15
Done.
| |
568 compiler.backend.registerGenericClosure(element, this, elements); | |
569 universe.closurizedGenericMembers.add(element); | |
570 } | |
571 | |
545 void forEach(f(WorkItem work)); | 572 void forEach(f(WorkItem work)); |
546 | 573 |
547 void forEachPostProcessTask(f(PostProcessTask work)) {} | 574 void forEachPostProcessTask(f(PostProcessTask work)) {} |
548 | 575 |
549 void logSummary(log(message)) { | 576 void logSummary(log(message)) { |
550 _logSpecificSummary(log); | 577 _logSpecificSummary(log); |
551 nativeEnqueuer.logSummary(log); | 578 nativeEnqueuer.logSummary(log); |
552 } | 579 } |
553 | 580 |
554 /// Log summary specific to the concrete enqueuer. | 581 /// Log summary specific to the concrete enqueuer. |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
629 } | 656 } |
630 } | 657 } |
631 | 658 |
632 if (element.isGetter() && element.name == Compiler.RUNTIME_TYPE) { | 659 if (element.isGetter() && element.name == Compiler.RUNTIME_TYPE) { |
633 // Enable runtime type support if we discover a getter called runtimeType. | 660 // Enable runtime type support if we discover a getter called runtimeType. |
634 // We have to enable runtime type before hitting the codegen, so | 661 // We have to enable runtime type before hitting the codegen, so |
635 // that constructors know whether they need to generate code for | 662 // that constructors know whether they need to generate code for |
636 // runtime type. | 663 // runtime type. |
637 compiler.enabledRuntimeType = true; | 664 compiler.enabledRuntimeType = true; |
638 // TODO(ahe): Record precise dependency here. | 665 // TODO(ahe): Record precise dependency here. |
639 compiler.backend.registerRuntimeType(compiler.globalDependencies); | 666 compiler.backend.registerRuntimeType(this, compiler.globalDependencies); |
640 } else if (element == compiler.functionApplyMethod) { | 667 } else if (element == compiler.functionApplyMethod) { |
641 compiler.enabledFunctionApply = true; | 668 compiler.enabledFunctionApply = true; |
642 } else if (element == compiler.invokeOnMethod) { | 669 } else if (element == compiler.invokeOnMethod) { |
643 compiler.enabledInvokeOn = true; | 670 compiler.enabledInvokeOn = true; |
644 } | 671 } |
645 | 672 |
646 nativeEnqueuer.registerElement(element); | 673 nativeEnqueuer.registerElement(element); |
647 } | 674 } |
648 | 675 |
649 void enableIsolateSupport(LibraryElement element) { | 676 void enableIsolateSupport(LibraryElement element) { |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
740 while(!queue.isEmpty) { | 767 while(!queue.isEmpty) { |
741 // TODO(johnniwinther): Find an optimal process order for codegen. | 768 // TODO(johnniwinther): Find an optimal process order for codegen. |
742 f(queue.removeLast()); | 769 f(queue.removeLast()); |
743 } | 770 } |
744 } | 771 } |
745 | 772 |
746 void _logSpecificSummary(log(message)) { | 773 void _logSpecificSummary(log(message)) { |
747 log('Compiled ${generatedCode.length} methods.'); | 774 log('Compiled ${generatedCode.length} methods.'); |
748 } | 775 } |
749 } | 776 } |
OLD | NEW |