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 js_backend; | 5 part of js_backend; |
6 | 6 |
7 typedef void Recompile(Element element); | 7 typedef void Recompile(Element element); |
8 | 8 |
9 class ReturnInfo { | 9 class ReturnInfo { |
10 HType returnType; | 10 HType returnType; |
(...skipping 628 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
639 : types = new HTypeMap(), | 639 : types = new HTypeMap(), |
640 boundsChecked = new Set<HInstruction>(); | 640 boundsChecked = new Set<HInstruction>(); |
641 } | 641 } |
642 | 642 |
643 class JavaScriptBackend extends Backend { | 643 class JavaScriptBackend extends Backend { |
644 SsaBuilderTask builder; | 644 SsaBuilderTask builder; |
645 SsaOptimizerTask optimizer; | 645 SsaOptimizerTask optimizer; |
646 SsaCodeGeneratorTask generator; | 646 SsaCodeGeneratorTask generator; |
647 CodeEmitterTask emitter; | 647 CodeEmitterTask emitter; |
648 | 648 |
| 649 ClassElement jsStringClass; |
| 650 ClassElement objectInterceptorClass; |
| 651 Element getInterceptorMethod; |
| 652 |
649 final Namer namer; | 653 final Namer namer; |
650 | 654 |
651 /** | 655 /** |
652 * Interface used to determine if an object has the JavaScript | 656 * Interface used to determine if an object has the JavaScript |
653 * indexing behavior. The interface is only visible to specific | 657 * indexing behavior. The interface is only visible to specific |
654 * libraries. | 658 * libraries. |
655 */ | 659 */ |
656 ClassElement jsIndexingBehaviorInterface; | 660 ClassElement jsIndexingBehaviorInterface; |
657 | 661 |
658 final Map<Element, ReturnInfo> returnInfo; | 662 final Map<Element, ReturnInfo> returnInfo; |
659 | 663 |
660 /** | 664 /** |
661 * Documentation wanted -- johnniwinther | 665 * Documentation wanted -- johnniwinther |
662 * | 666 * |
663 * Invariant: Elements must be declaration elements. | 667 * Invariant: Elements must be declaration elements. |
664 */ | 668 */ |
665 final List<Element> invalidateAfterCodegen; | 669 final List<Element> invalidateAfterCodegen; |
666 ArgumentTypesRegistry argumentTypes; | 670 ArgumentTypesRegistry argumentTypes; |
667 FieldTypesRegistry fieldTypes; | 671 FieldTypesRegistry fieldTypes; |
668 | 672 |
669 final Interceptors interceptors; | 673 final Interceptors interceptors; |
670 | 674 |
| 675 /** |
| 676 * A collection of selectors of intercepted method calls. The |
| 677 * emitter uses this set to generate the [:ObjectInterceptor:] class |
| 678 * whose members just forward the call to the intercepted receiver. |
| 679 */ |
| 680 final Set<Selector> usedInterceptors; |
| 681 |
| 682 /** |
| 683 * The members of instantiated interceptor classes: maps a member |
| 684 * name to the list of members that have that name. This map is used |
| 685 * by the codegen to know whether a send must be intercepted or not. |
| 686 */ |
| 687 final Map<SourceString, List<Element>> interceptedElements; |
| 688 |
671 List<CompilerTask> get tasks { | 689 List<CompilerTask> get tasks { |
672 return <CompilerTask>[builder, optimizer, generator, emitter]; | 690 return <CompilerTask>[builder, optimizer, generator, emitter]; |
673 } | 691 } |
674 | 692 |
675 JavaScriptBackend(Compiler compiler, | 693 JavaScriptBackend(Compiler compiler, |
676 bool generateSourceMap, | 694 bool generateSourceMap, |
677 bool disableEval) | 695 bool disableEval) |
678 : namer = new Namer(compiler), | 696 : namer = new Namer(compiler), |
679 returnInfo = new Map<Element, ReturnInfo>(), | 697 returnInfo = new Map<Element, ReturnInfo>(), |
680 invalidateAfterCodegen = new List<Element>(), | 698 invalidateAfterCodegen = new List<Element>(), |
681 interceptors = new Interceptors(compiler), | 699 interceptors = new Interceptors(compiler), |
| 700 usedInterceptors = new Set<Selector>(), |
| 701 interceptedElements = new Map<SourceString, List<Element>>(), |
682 super(compiler, JAVA_SCRIPT_CONSTANT_SYSTEM) { | 702 super(compiler, JAVA_SCRIPT_CONSTANT_SYSTEM) { |
683 emitter = disableEval | 703 emitter = disableEval |
684 ? new CodeEmitterNoEvalTask(compiler, namer, generateSourceMap) | 704 ? new CodeEmitterNoEvalTask(compiler, namer, generateSourceMap) |
685 : new CodeEmitterTask(compiler, namer, generateSourceMap); | 705 : new CodeEmitterTask(compiler, namer, generateSourceMap); |
686 builder = new SsaBuilderTask(this); | 706 builder = new SsaBuilderTask(this); |
687 optimizer = new SsaOptimizerTask(this); | 707 optimizer = new SsaOptimizerTask(this); |
688 generator = new SsaCodeGeneratorTask(this); | 708 generator = new SsaCodeGeneratorTask(this); |
689 argumentTypes = new ArgumentTypesRegistry(this); | 709 argumentTypes = new ArgumentTypesRegistry(this); |
690 fieldTypes = new FieldTypesRegistry(this); | 710 fieldTypes = new FieldTypesRegistry(this); |
691 } | 711 } |
692 | 712 |
| 713 bool isInterceptorClass(Element element) { |
| 714 return element == jsStringClass; |
| 715 } |
| 716 |
| 717 void addInterceptedSelector(Selector selector) { |
| 718 usedInterceptors.add(selector); |
| 719 } |
| 720 |
| 721 bool shouldInterceptSelector(Selector selector) { |
| 722 List<Element> intercepted = interceptedElements[selector.name]; |
| 723 if (intercepted == null) return false; |
| 724 for (Element element in intercepted) { |
| 725 if (selector.applies(element, compiler)) return true; |
| 726 } |
| 727 return false; |
| 728 } |
| 729 |
| 730 |
| 731 void registerInstantiatedClass(ClassElement cls, Enqueuer enqueuer) { |
| 732 ClassElement result = null; |
| 733 if (cls == compiler.stringClass) { |
| 734 if (jsStringClass == null) { |
| 735 jsStringClass = |
| 736 compiler.findInterceptor(const SourceString('JSString')); |
| 737 objectInterceptorClass = |
| 738 compiler.findInterceptor(const SourceString('ObjectInterceptor')); |
| 739 getInterceptorMethod = |
| 740 compiler.findInterceptor(const SourceString('getInterceptor')); |
| 741 } |
| 742 result = jsStringClass; |
| 743 } |
| 744 |
| 745 if (result == null) return; |
| 746 |
| 747 result.forEachMember((_, Element member) { |
| 748 List<Element> list = interceptedElements.putIfAbsent( |
| 749 member.name, () => new List<Element>()); |
| 750 list.add(member); |
| 751 }); |
| 752 |
| 753 enqueuer.registerInstantiatedClass(result); |
| 754 } |
| 755 |
693 Element get cyclicThrowHelper { | 756 Element get cyclicThrowHelper { |
694 return compiler.findHelper(const SourceString("throwCyclicInit")); | 757 return compiler.findHelper(const SourceString("throwCyclicInit")); |
695 } | 758 } |
696 | 759 |
697 JavaScriptItemCompilationContext createItemCompilationContext() { | 760 JavaScriptItemCompilationContext createItemCompilationContext() { |
698 return new JavaScriptItemCompilationContext(); | 761 return new JavaScriptItemCompilationContext(); |
699 } | 762 } |
700 | 763 |
701 Element getInterceptor(Selector selector) { | 764 Element getInterceptor(Selector selector) { |
702 return interceptors.getStaticInterceptor(selector); | 765 return interceptors.getStaticInterceptor(selector); |
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
952 print("Inferred return types:"); | 1015 print("Inferred return types:"); |
953 print("----------------------"); | 1016 print("----------------------"); |
954 dumpReturnTypes(); | 1017 dumpReturnTypes(); |
955 print(""); | 1018 print(""); |
956 print("Inferred field types:"); | 1019 print("Inferred field types:"); |
957 print("------------------------"); | 1020 print("------------------------"); |
958 fieldTypes.dump(); | 1021 fieldTypes.dump(); |
959 print(""); | 1022 print(""); |
960 } | 1023 } |
961 } | 1024 } |
OLD | NEW |