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 class Interceptors { | 5 class Interceptors { |
6 Compiler compiler; | 6 Compiler compiler; |
7 Interceptors(Compiler this.compiler); | 7 Interceptors(Compiler this.compiler); |
8 | 8 |
9 SourceString mapOperatorToMethodName(Operator op) { | 9 SourceString mapOperatorToMethodName(Operator op) { |
10 String name = op.source.stringValue; | 10 String name = op.source.stringValue; |
(...skipping 1703 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1714 } else { | 1714 } else { |
1715 assert(Elements.isLocal(element)); | 1715 assert(Elements.isLocal(element)); |
1716 closureTarget = localsHandler.readLocal(element); | 1716 closureTarget = localsHandler.readLocal(element); |
1717 } | 1717 } |
1718 var inputs = <HInstruction>[]; | 1718 var inputs = <HInstruction>[]; |
1719 inputs.add(closureTarget); | 1719 inputs.add(closureTarget); |
1720 addDynamicSendArgumentsToList(node, inputs); | 1720 addDynamicSendArgumentsToList(node, inputs); |
1721 push(new HInvokeClosure(selector, inputs)); | 1721 push(new HInvokeClosure(selector, inputs)); |
1722 } | 1722 } |
1723 | 1723 |
1724 visitForeignSend(Send node) { | 1724 void handleForeignJs(Send node) { |
1725 Identifier selector = node.selector; | 1725 Link<Node> link = node.arguments; |
1726 switch (selector.source.slowToString()) { | 1726 // If the invoke is on foreign code, don't visit the first |
1727 case "JS": | 1727 // argument, which is the type, and the second argument, |
1728 Link<Node> link = node.arguments; | 1728 // which is the foreign code. |
1729 // If the invoke is on foreign code, don't visit the first | 1729 link = link.tail.tail; |
1730 // argument, which is the type, and the second argument, | 1730 List<HInstruction> inputs = <HInstruction>[]; |
1731 // which is the foreign code. | 1731 addGenericSendArgumentsToList(link, inputs); |
1732 link = link.tail.tail; | 1732 LiteralString type = node.arguments.head; |
1733 List<HInstruction> inputs = <HInstruction>[]; | 1733 LiteralString literal = node.arguments.tail.head; |
1734 addGenericSendArgumentsToList(link, inputs); | 1734 compiler.ensure(literal is LiteralString); |
1735 LiteralString type = node.arguments.head; | 1735 compiler.ensure(type is LiteralString); |
1736 LiteralString literal = node.arguments.tail.head; | 1736 push(new HForeign(literal.dartString, type.dartString, inputs)); |
1737 compiler.ensure(literal is LiteralString); | 1737 } |
1738 compiler.ensure(type is LiteralString); | 1738 |
1739 push(new HForeign(literal.dartString, type.dartString, inputs)); | 1739 void handleForeignUnintercepted(Send node) { |
1740 break; | 1740 Link<Node> link = node.arguments; |
1741 case "UNINTERCEPTED": | 1741 if (!link.tail.isEmpty()) { |
1742 Link<Node> link = node.arguments; | 1742 compiler.cancel( |
1743 if (!link.tail.isEmpty()) { | 1743 'More than one expression in UNINTERCEPTED()', node: node); |
1744 compiler.cancel('More than one expression in UNINTERCEPTED()'); | 1744 } |
1745 } | 1745 Expression expression = link.head; |
1746 Expression expression = link.head; | 1746 disableMethodInterception(); |
1747 disableMethodInterception(); | 1747 visit(expression); |
1748 visit(expression); | 1748 enableMethodInterception(); |
1749 enableMethodInterception(); | 1749 } |
1750 break; | 1750 |
1751 case "JS_HAS_EQUALS": | 1751 void handleForeignJsHasEquals(Send node) { |
1752 List<HInstruction> inputs = <HInstruction>[]; | 1752 List<HInstruction> inputs = <HInstruction>[]; |
1753 if (!node.arguments.tail.isEmpty()) { | 1753 if (!node.arguments.tail.isEmpty()) { |
1754 compiler.cancel('More than one expression in JS_HAS_EQUALS()'); | 1754 compiler.cancel( |
1755 } | 1755 'More than one expression in JS_HAS_EQUALS()', node: node); |
1756 addGenericSendArgumentsToList(node.arguments, inputs); | 1756 } |
1757 String name = compiler.namer.instanceMethodName( | 1757 addGenericSendArgumentsToList(node.arguments, inputs); |
1758 currentLibrary, Namer.OPERATOR_EQUALS, 1); | 1758 String name = compiler.namer.instanceMethodName( |
1759 push(new HForeign(new DartString.literal('!!#.$name'), | 1759 currentLibrary, Namer.OPERATOR_EQUALS, 1); |
1760 const LiteralDartString('bool'), | 1760 push(new HForeign(new DartString.literal('!!#.$name'), |
1761 inputs)); | 1761 const LiteralDartString('bool'), |
1762 break; | 1762 inputs)); |
1763 case "native": | 1763 } |
1764 native.handleSsaNative(this, node); | 1764 |
1765 break; | 1765 void handleForeignJsCurrentIsolate(Send node) { |
1766 default: | 1766 if (!node.arguments.isEmpty()) { |
1767 throw "Unknown foreign: ${node.selector}"; | 1767 compiler.cancel( |
| 1768 'Too many arguments to JS_CURRENT_ISOLATE', node: node); |
| 1769 } |
| 1770 |
| 1771 if (!compiler.hasIsolateSupport()) { |
| 1772 // If the isolate library is not used, we just generate code |
| 1773 // to fetch the Leg's current isolate. |
| 1774 String name = compiler.namer.CURRENT_ISOLATE; |
| 1775 push(new HForeign(new DartString.literal(name), |
| 1776 const LiteralDartString('var'), |
| 1777 <HInstruction>[])); |
| 1778 } else { |
| 1779 // Call a helper method from the isolate library. The isolate |
| 1780 // library uses its own isolate structure, that encapsulates |
| 1781 // Leg's isolate. |
| 1782 Element element = compiler.isolateLibrary.find( |
| 1783 const SourceString('_currentIsolate')); |
| 1784 if (element === null) { |
| 1785 compiler.cancel( |
| 1786 'Isolate library and compiler mismatch', node: node); |
| 1787 } |
| 1788 HStatic target = new HStatic(element); |
| 1789 add(target); |
| 1790 push(new HInvokeStatic(Selector.INVOCATION_0, |
| 1791 <HInstruction>[target])); |
| 1792 } |
| 1793 } |
| 1794 |
| 1795 void handleForeignJsCallInIsolate(Send node) { |
| 1796 Link<Node> link = node.arguments; |
| 1797 if (!compiler.hasIsolateSupport()) { |
| 1798 // If the isolate library is not used, we just invoke the |
| 1799 // closure. |
| 1800 visit(link.tail.head); |
| 1801 push(new HInvokeClosure(Selector.INVOCATION_0, |
| 1802 <HInstruction>[pop()])); |
| 1803 } else { |
| 1804 // Call a helper method from the isolate library. |
| 1805 Element element = compiler.isolateLibrary.find( |
| 1806 const SourceString('_callInIsolate')); |
| 1807 if (element === null) { |
| 1808 compiler.cancel( |
| 1809 'Isolate library and compiler mismatch', node: node); |
| 1810 } |
| 1811 HStatic target = new HStatic(element); |
| 1812 add(target); |
| 1813 List<HInstruction> inputs = <HInstruction>[target]; |
| 1814 addGenericSendArgumentsToList(link, inputs); |
| 1815 push(new HInvokeStatic(Selector.INVOCATION_0, inputs)); |
| 1816 } |
| 1817 } |
| 1818 |
| 1819 handleForeignSend(Send node) { |
| 1820 Element element = elements[node]; |
| 1821 if (element === compiler.findHelper(const SourceString('JS'))) { |
| 1822 handleForeignJs(node); |
| 1823 } else if (element === compiler.findHelper( |
| 1824 const SourceString('UNINTERCEPTED'))) { |
| 1825 handleForeignUnintercepted(node); |
| 1826 } else if (element === compiler.findHelper( |
| 1827 const SourceString('JS_HAS_EQUALS'))) { |
| 1828 handleForeignJsHasEquals(node); |
| 1829 } else if (element === compiler.findHelper( |
| 1830 const SourceString('JS_CURRENT_ISOLATE'))) { |
| 1831 handleForeignJsCurrentIsolate(node); |
| 1832 } else if (element === compiler.findHelper( |
| 1833 const SourceString('JS_CALL_IN_ISOLATE'))) { |
| 1834 handleForeignJsCallInIsolate(node); |
| 1835 } else if (element === currentLibrary.find(const SourceString('native'))) { |
| 1836 native.handleSsaNative(this, node); |
| 1837 } else { |
| 1838 throw "Unknown foreign: ${node.selector}"; |
1768 } | 1839 } |
1769 } | 1840 } |
1770 | 1841 |
1771 visitSuperSend(Send node) { | 1842 visitSuperSend(Send node) { |
1772 Selector selector = elements.getSelector(node); | 1843 Selector selector = elements.getSelector(node); |
1773 Element element = elements[node]; | 1844 Element element = elements[node]; |
1774 if (element === null) { | 1845 if (element === null) { |
1775 // Example: co19/Language/10_Expressions/25_Unary_Expressions_A06_t01 | 1846 // Example: co19/Language/10_Expressions/25_Unary_Expressions_A06_t01 |
1776 compiler.unimplemented('unresolved super-send', node: node); | 1847 compiler.unimplemented('unresolved super-send', node: node); |
1777 } | 1848 } |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1832 if (element === null) { | 1903 if (element === null) { |
1833 // Example: f() with 'f' unbound. | 1904 // Example: f() with 'f' unbound. |
1834 // This can only happen inside an instance method. | 1905 // This can only happen inside an instance method. |
1835 visitDynamicSend(node); | 1906 visitDynamicSend(node); |
1836 } else if (element.kind == ElementKind.CLASS) { | 1907 } else if (element.kind == ElementKind.CLASS) { |
1837 compiler.internalError("Cannot generate code for send", node: node); | 1908 compiler.internalError("Cannot generate code for send", node: node); |
1838 } else if (element.isInstanceMember()) { | 1909 } else if (element.isInstanceMember()) { |
1839 // Example: f() with 'f' bound to instance method. | 1910 // Example: f() with 'f' bound to instance method. |
1840 visitDynamicSend(node); | 1911 visitDynamicSend(node); |
1841 } else if (element.kind === ElementKind.FOREIGN) { | 1912 } else if (element.kind === ElementKind.FOREIGN) { |
1842 visitForeignSend(node); | 1913 handleForeignSend(node); |
1843 } else if (!element.isInstanceMember()) { | 1914 } else if (!element.isInstanceMember()) { |
1844 // Example: A.f() or f() with 'f' bound to a static function. | 1915 // Example: A.f() or f() with 'f' bound to a static function. |
1845 // Also includes new A() or new A.named() which is treated like a | 1916 // Also includes new A() or new A.named() which is treated like a |
1846 // static call to a factory. | 1917 // static call to a factory. |
1847 visitStaticSend(node); | 1918 visitStaticSend(node); |
1848 } else { | 1919 } else { |
1849 compiler.internalError("Cannot generate code for send", node: node); | 1920 compiler.internalError("Cannot generate code for send", node: node); |
1850 } | 1921 } |
1851 } | 1922 } |
1852 } | 1923 } |
(...skipping 704 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2557 buildBody() { | 2628 buildBody() { |
2558 // TODO(lrn): Make sure to take continue into account. | 2629 // TODO(lrn): Make sure to take continue into account. |
2559 visit(body); | 2630 visit(body); |
2560 if (isAborted()) { | 2631 if (isAborted()) { |
2561 compiler.reportWarning(body, "aborting loop body"); | 2632 compiler.reportWarning(body, "aborting loop body"); |
2562 } | 2633 } |
2563 } | 2634 } |
2564 handleIf(buildBody, null); | 2635 handleIf(buildBody, null); |
2565 } | 2636 } |
2566 } | 2637 } |
OLD | NEW |