| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 library dart2js.ir_builder_task; | 5 library dart2js.ir_builder_task; |
| 6 | 6 |
| 7 import '../closure.dart' as closurelib; | 7 import '../closure.dart' as closurelib; |
| 8 import '../closure.dart' hide ClosureScope; | 8 import '../closure.dart' hide ClosureScope; |
| 9 import '../constants/expressions.dart'; | 9 import '../constants/expressions.dart'; |
| 10 import '../dart_types.dart'; | 10 import '../dart_types.dart'; |
| (...skipping 27 matching lines...) Expand all Loading... |
| 38 * The type inferrer works on either IR nodes or tree nodes. The IR nodes are | 38 * The type inferrer works on either IR nodes or tree nodes. The IR nodes are |
| 39 * then translated into the SSA form for optimizations and code generation. | 39 * then translated into the SSA form for optimizations and code generation. |
| 40 * Long-term, once the IR supports the full language, the backend can be | 40 * Long-term, once the IR supports the full language, the backend can be |
| 41 * re-implemented to work directly on the IR. | 41 * re-implemented to work directly on the IR. |
| 42 */ | 42 */ |
| 43 class IrBuilderTask extends CompilerTask { | 43 class IrBuilderTask extends CompilerTask { |
| 44 final Map<Element, ir.ExecutableDefinition> nodes = | 44 final Map<Element, ir.ExecutableDefinition> nodes = |
| 45 <Element, ir.ExecutableDefinition>{}; | 45 <Element, ir.ExecutableDefinition>{}; |
| 46 final bool generateSourceMap; | 46 final bool generateSourceMap; |
| 47 | 47 |
| 48 String bailoutMessage = null; |
| 49 |
| 48 IrBuilderTask(Compiler compiler, {this.generateSourceMap: true}) | 50 IrBuilderTask(Compiler compiler, {this.generateSourceMap: true}) |
| 49 : super(compiler); | 51 : super(compiler); |
| 50 | 52 |
| 51 String get name => 'IR builder'; | 53 String get name => 'IR builder'; |
| 52 | 54 |
| 53 bool hasIr(Element element) => nodes.containsKey(element.implementation); | 55 bool hasIr(Element element) => nodes.containsKey(element.implementation); |
| 54 | 56 |
| 55 ir.ExecutableDefinition getIr(ExecutableElement element) { | 57 ir.ExecutableDefinition getIr(ExecutableElement element) { |
| 56 return nodes[element.implementation]; | 58 return nodes[element.implementation]; |
| 57 } | 59 } |
| 58 | 60 |
| 59 ir.ExecutableDefinition buildNode(AstElement element) { | 61 ir.ExecutableDefinition buildNode(AstElement element) { |
| 60 if (!canBuild(element)) return null; | 62 bailoutMessage = null; |
| 63 if (!canBuild(element)) { |
| 64 bailoutMessage = 'unsupported element ${element.name}:${element.kind}'; |
| 65 return null; |
| 66 } |
| 61 | 67 |
| 62 TreeElements elementsMapping = element.resolvedAst.elements; | 68 TreeElements elementsMapping = element.resolvedAst.elements; |
| 63 element = element.implementation; | 69 element = element.implementation; |
| 64 return compiler.withCurrentElement(element, () { | 70 return compiler.withCurrentElement(element, () { |
| 65 SourceInformationBuilder sourceInformationBuilder = generateSourceMap | 71 SourceInformationBuilder sourceInformationBuilder = generateSourceMap |
| 66 ? new PositionSourceInformationBuilder(element) | 72 ? new PositionSourceInformationBuilder(element) |
| 67 : const SourceInformationBuilder(); | 73 : const SourceInformationBuilder(); |
| 68 | 74 |
| 69 IrBuilderVisitor builder = | 75 IrBuilderVisitor builder = |
| 70 compiler.backend is JavaScriptBackend | 76 compiler.backend is JavaScriptBackend |
| 71 ? new JsIrBuilderVisitor( | 77 ? new JsIrBuilderVisitor( |
| 72 elementsMapping, compiler, sourceInformationBuilder) | 78 elementsMapping, compiler, sourceInformationBuilder) |
| 73 : new DartIrBuilderVisitor( | 79 : new DartIrBuilderVisitor( |
| 74 elementsMapping, compiler, sourceInformationBuilder); | 80 elementsMapping, compiler, sourceInformationBuilder); |
| 75 ir.ExecutableDefinition definition = | 81 ir.ExecutableDefinition definition = |
| 76 builder.buildExecutable(element); | 82 builder.buildExecutable(element); |
| 77 if (definition != null) { | 83 if (definition == null) { |
| 84 bailoutMessage = builder.bailoutMessage; |
| 85 } else { |
| 78 nodes[element] = definition; | 86 nodes[element] = definition; |
| 79 } | 87 } |
| 80 return definition; | 88 return definition; |
| 81 }); | 89 }); |
| 82 } | 90 } |
| 83 | 91 |
| 84 void buildNodes() { | 92 void buildNodes() { |
| 85 measure(() { | 93 measure(() { |
| 86 Set<Element> resolved = compiler.enqueuer.resolution.resolvedElements; | 94 Set<Element> resolved = compiler.enqueuer.resolution.resolvedElements; |
| 87 resolved.forEach(buildNode); | 95 resolved.forEach(buildNode); |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 156 | 164 |
| 157 /// Construct a top-level visitor. | 165 /// Construct a top-level visitor. |
| 158 IrBuilderVisitor(TreeElements elements, | 166 IrBuilderVisitor(TreeElements elements, |
| 159 this.compiler, | 167 this.compiler, |
| 160 this.sourceInformationBuilder) | 168 this.sourceInformationBuilder) |
| 161 : super(elements); | 169 : super(elements); |
| 162 | 170 |
| 163 @override | 171 @override |
| 164 bulkHandleNode(ast.Node node, String message, _) => giveup(node, message); | 172 bulkHandleNode(ast.Node node, String message, _) => giveup(node, message); |
| 165 | 173 |
| 174 String bailoutMessage = null; |
| 175 |
| 166 @override | 176 @override |
| 167 ir.Primitive apply(ast.Node node, _) => node.accept(this); | 177 ir.Primitive apply(ast.Node node, _) => node.accept(this); |
| 168 | 178 |
| 169 @override | 179 @override |
| 170 SemanticSendVisitor get sendVisitor => this; | 180 SemanticSendVisitor get sendVisitor => this; |
| 171 | 181 |
| 172 /** | 182 /** |
| 173 * Builds the [ir.ExecutableDefinition] for an executable element. In case the | 183 * Builds the [ir.ExecutableDefinition] for an executable element. In case the |
| 174 * function uses features that cannot be expressed in the IR, this element | 184 * function uses features that cannot be expressed in the IR, this element |
| 175 * returns `null`. | 185 * returns `null`. |
| (...skipping 1578 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1754 return action(); | 1764 return action(); |
| 1755 } catch(e, tr) { | 1765 } catch(e, tr) { |
| 1756 if (e == ABORT_IRNODE_BUILDER) { | 1766 if (e == ABORT_IRNODE_BUILDER) { |
| 1757 return null; | 1767 return null; |
| 1758 } | 1768 } |
| 1759 rethrow; | 1769 rethrow; |
| 1760 } | 1770 } |
| 1761 } | 1771 } |
| 1762 | 1772 |
| 1763 void internalError(ast.Node node, String message) { | 1773 void internalError(ast.Node node, String message) { |
| 1764 giveup(node); | 1774 giveup(node, message); |
| 1765 } | 1775 } |
| 1766 | 1776 |
| 1767 @override | 1777 @override |
| 1768 visitNode(ast.Node node) { | 1778 visitNode(ast.Node node) { |
| 1769 internalError(node, "Unhandled node"); | 1779 internalError(node, "Unhandled node"); |
| 1770 } | 1780 } |
| 1781 |
| 1782 dynamic giveup(ast.Node node, [String reason]) { |
| 1783 bailoutMessage = '($node): $reason'; |
| 1784 throw ABORT_IRNODE_BUILDER; |
| 1785 } |
| 1771 } | 1786 } |
| 1772 | 1787 |
| 1773 final String ABORT_IRNODE_BUILDER = "IrNode builder aborted"; | 1788 final String ABORT_IRNODE_BUILDER = "IrNode builder aborted"; |
| 1774 | 1789 |
| 1775 dynamic giveup(ast.Node node, [String reason]) { | |
| 1776 throw ABORT_IRNODE_BUILDER; | |
| 1777 } | |
| 1778 | |
| 1779 /// Classifies local variables and local functions as captured, if they | 1790 /// Classifies local variables and local functions as captured, if they |
| 1780 /// are accessed from within a nested function. | 1791 /// are accessed from within a nested function. |
| 1781 /// | 1792 /// |
| 1782 /// This class is specific to the [DartIrBuilder], in that it gives up if it | 1793 /// This class is specific to the [DartIrBuilder], in that it gives up if it |
| 1783 /// sees a feature that is currently unsupport by that builder. In particular, | 1794 /// sees a feature that is currently unsupport by that builder. In particular, |
| 1784 /// loop variables captured in a for-loop initializer, condition, or update | 1795 /// loop variables captured in a for-loop initializer, condition, or update |
| 1785 /// expression are unsupported. | 1796 /// expression are unsupported. |
| 1786 class DartCapturedVariables extends ast.Visitor { | 1797 class DartCapturedVariables extends ast.Visitor { |
| 1787 final TreeElements elements; | 1798 final TreeElements elements; |
| 1788 DartCapturedVariables(this.elements); | 1799 DartCapturedVariables(this.elements); |
| 1789 | 1800 |
| 1790 FunctionElement currentFunction; | 1801 FunctionElement currentFunction; |
| 1791 bool insideInitializer = false; | 1802 bool insideInitializer = false; |
| 1792 Set<Local> capturedVariables = new Set<Local>(); | 1803 Set<Local> capturedVariables = new Set<Local>(); |
| 1793 | 1804 |
| 1794 Map<ast.TryStatement, TryStatementInfo> tryStatements = | 1805 Map<ast.TryStatement, TryStatementInfo> tryStatements = |
| 1795 <ast.TryStatement, TryStatementInfo>{}; | 1806 <ast.TryStatement, TryStatementInfo>{}; |
| 1796 | 1807 |
| 1797 List<TryStatementInfo> tryNestingStack = <TryStatementInfo>[]; | 1808 List<TryStatementInfo> tryNestingStack = <TryStatementInfo>[]; |
| 1798 bool get inTryStatement => tryNestingStack.isNotEmpty; | 1809 bool get inTryStatement => tryNestingStack.isNotEmpty; |
| 1799 | 1810 |
| 1811 String bailoutMessage = null; |
| 1812 |
| 1813 giveup(ast.Node node, [String reason]) { |
| 1814 bailoutMessage = '($node): $reason'; |
| 1815 throw ABORT_IRNODE_BUILDER; |
| 1816 } |
| 1817 |
| 1800 void markAsCaptured(Local local) { | 1818 void markAsCaptured(Local local) { |
| 1801 capturedVariables.add(local); | 1819 capturedVariables.add(local); |
| 1802 } | 1820 } |
| 1803 | 1821 |
| 1804 visit(ast.Node node) => node.accept(this); | 1822 visit(ast.Node node) => node.accept(this); |
| 1805 | 1823 |
| 1806 visitNode(ast.Node node) { | 1824 visitNode(ast.Node node) { |
| 1807 node.visitChildren(this); | 1825 node.visitChildren(this); |
| 1808 } | 1826 } |
| 1809 | 1827 |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1922 DartIrBuilder get irBuilder => super.irBuilder; | 1940 DartIrBuilder get irBuilder => super.irBuilder; |
| 1923 | 1941 |
| 1924 DartIrBuilderVisitor(TreeElements elements, | 1942 DartIrBuilderVisitor(TreeElements elements, |
| 1925 Compiler compiler, | 1943 Compiler compiler, |
| 1926 SourceInformationBuilder sourceInformationBuilder) | 1944 SourceInformationBuilder sourceInformationBuilder) |
| 1927 : super(elements, compiler, sourceInformationBuilder); | 1945 : super(elements, compiler, sourceInformationBuilder); |
| 1928 | 1946 |
| 1929 DartIrBuilder makeIRBuilder(ast.Node node, ExecutableElement element) { | 1947 DartIrBuilder makeIRBuilder(ast.Node node, ExecutableElement element) { |
| 1930 DartCapturedVariables closures = new DartCapturedVariables(elements); | 1948 DartCapturedVariables closures = new DartCapturedVariables(elements); |
| 1931 if (!element.isSynthesized) { | 1949 if (!element.isSynthesized) { |
| 1932 closures.visit(node); | 1950 try { |
| 1951 closures.visit(node); |
| 1952 } catch (e) { |
| 1953 bailoutMessage = closures.bailoutMessage; |
| 1954 rethrow; |
| 1955 } |
| 1933 } | 1956 } |
| 1934 return new DartIrBuilder(compiler.backend.constantSystem, | 1957 return new DartIrBuilder(compiler.backend.constantSystem, |
| 1935 element, | 1958 element, |
| 1936 closures); | 1959 closures); |
| 1937 } | 1960 } |
| 1938 | 1961 |
| 1939 /// Recursively builds the IR for the given nested function. | 1962 /// Recursively builds the IR for the given nested function. |
| 1940 ir.FunctionDefinition makeSubFunction(ast.FunctionExpression node) { | 1963 ir.FunctionDefinition makeSubFunction(ast.FunctionExpression node) { |
| 1941 FunctionElement element = elements[node]; | 1964 FunctionElement element = elements[node]; |
| 1942 assert(invariant(element, element.isImplementation)); | 1965 assert(invariant(element, element.isImplementation)); |
| (...skipping 717 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2660 SourceInformation buildCall(ast.Node node) { | 2683 SourceInformation buildCall(ast.Node node) { |
| 2661 return new PositionSourceInformation( | 2684 return new PositionSourceInformation( |
| 2662 new TokenSourceLocation(sourceFile, node.getBeginToken(), name)); | 2685 new TokenSourceLocation(sourceFile, node.getBeginToken(), name)); |
| 2663 } | 2686 } |
| 2664 | 2687 |
| 2665 @override | 2688 @override |
| 2666 SourceInformationBuilder forContext(AstElement element) { | 2689 SourceInformationBuilder forContext(AstElement element) { |
| 2667 return new PositionSourceInformationBuilder(element); | 2690 return new PositionSourceInformationBuilder(element); |
| 2668 } | 2691 } |
| 2669 } | 2692 } |
| OLD | NEW |