| 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 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 359 // Build(EmptyStatement, C) = C | 359 // Build(EmptyStatement, C) = C |
| 360 ir.Primitive visitEmptyStatement(ast.EmptyStatement node) { | 360 ir.Primitive visitEmptyStatement(ast.EmptyStatement node) { |
| 361 assert(irBuilder.isOpen); | 361 assert(irBuilder.isOpen); |
| 362 return null; | 362 return null; |
| 363 } | 363 } |
| 364 | 364 |
| 365 // Build(ExpressionStatement(e), C) = C' | 365 // Build(ExpressionStatement(e), C) = C' |
| 366 // where (C', _) = Build(e, C) | 366 // where (C', _) = Build(e, C) |
| 367 ir.Primitive visitExpressionStatement(ast.ExpressionStatement node) { | 367 ir.Primitive visitExpressionStatement(ast.ExpressionStatement node) { |
| 368 assert(irBuilder.isOpen); | 368 assert(irBuilder.isOpen); |
| 369 visit(node.expression); | 369 if (node.expression is ast.Throw) { |
| 370 // Throw expressions that occur as statements are translated differently |
| 371 // from ones that occur as subexpressions. This is achieved by peeking |
| 372 // at statement-level expressions here. |
| 373 irBuilder.buildThrow(visit(node.expression)); |
| 374 } else { |
| 375 visit(node.expression); |
| 376 } |
| 370 return null; | 377 return null; |
| 371 } | 378 } |
| 372 | 379 |
| 380 ir.Primitive visitRethrow(ast.Rethrow node) { |
| 381 assert(irBuilder.isOpen); |
| 382 irBuilder.buildRethrow(); |
| 383 return null; |
| 384 } |
| 385 |
| 373 visitFor(ast.For node) { | 386 visitFor(ast.For node) { |
| 374 List<LocalElement> loopVariables = <LocalElement>[]; | 387 List<LocalElement> loopVariables = <LocalElement>[]; |
| 375 if (node.initializer is ast.VariableDefinitions) { | 388 if (node.initializer is ast.VariableDefinitions) { |
| 376 ast.VariableDefinitions definitions = node.initializer; | 389 ast.VariableDefinitions definitions = node.initializer; |
| 377 for (ast.Node node in definitions.definitions.nodes) { | 390 for (ast.Node node in definitions.definitions.nodes) { |
| 378 LocalElement loopVariable = elements[node]; | 391 LocalElement loopVariable = elements[node]; |
| 379 loopVariables.add(loopVariable); | 392 loopVariables.add(loopVariable); |
| 380 } | 393 } |
| 381 } | 394 } |
| 382 | 395 |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 487 ir.Primitive visitReturn(ast.Return node) { | 500 ir.Primitive visitReturn(ast.Return node) { |
| 488 assert(irBuilder.isOpen); | 501 assert(irBuilder.isOpen); |
| 489 assert(invariant(node, node.beginToken.value != 'native')); | 502 assert(invariant(node, node.beginToken.value != 'native')); |
| 490 irBuilder.buildReturn(build(node.expression)); | 503 irBuilder.buildReturn(build(node.expression)); |
| 491 return null; | 504 return null; |
| 492 } | 505 } |
| 493 | 506 |
| 494 visitTryStatement(ast.TryStatement node) { | 507 visitTryStatement(ast.TryStatement node) { |
| 495 // Multiple catch blocks are not yet implemented. | 508 // Multiple catch blocks are not yet implemented. |
| 496 if (node.catchBlocks.isEmpty || | 509 if (node.catchBlocks.isEmpty || |
| 497 node.catchBlocks.nodes.tail == null) { | 510 !node.catchBlocks.nodes.tail.isEmpty) { |
| 498 return giveup(node, 'not exactly one catch block'); | 511 return giveup(node, 'not exactly one catch block'); |
| 499 } | 512 } |
| 500 // 'on T' catch blocks are not yet implemented. | 513 // 'on T' catch blocks are not yet implemented. |
| 501 if ((node.catchBlocks.nodes.head as ast.CatchBlock).onKeyword != null) { | 514 if ((node.catchBlocks.nodes.head as ast.CatchBlock).onKeyword != null) { |
| 502 return giveup(node, '"on T" catch block'); | 515 return giveup(node, '"on T" catch block'); |
| 503 } | 516 } |
| 504 // Finally blocks are not yet implemented. | 517 // Finally blocks are not yet implemented. |
| 505 if (node.finallyBlock != null) { | 518 if (node.finallyBlock != null) { |
| 506 return giveup(node, 'try/finally'); | 519 return giveup(node, 'try/finally'); |
| 507 } | 520 } |
| (...skipping 1246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1754 arguments.add(visitLiteralString(part.string)); | 1767 arguments.add(visitLiteralString(part.string)); |
| 1755 } | 1768 } |
| 1756 return irBuilder.buildStringConcatenation(arguments); | 1769 return irBuilder.buildStringConcatenation(arguments); |
| 1757 } | 1770 } |
| 1758 | 1771 |
| 1759 ir.Primitive translateConstant(ast.Node node) { | 1772 ir.Primitive translateConstant(ast.Node node) { |
| 1760 assert(irBuilder.isOpen); | 1773 assert(irBuilder.isOpen); |
| 1761 return irBuilder.buildConstantLiteral(getConstantForNode(node)); | 1774 return irBuilder.buildConstantLiteral(getConstantForNode(node)); |
| 1762 } | 1775 } |
| 1763 | 1776 |
| 1777 ir.Primitive visitThrow(ast.Throw node) { |
| 1778 assert(irBuilder.isOpen); |
| 1779 // This function is not called for throw expressions occurring as |
| 1780 // statements. |
| 1781 return irBuilder.buildNonTailThrow(visit(node.expression)); |
| 1782 } |
| 1783 |
| 1764 ir.RootNode nullIfGiveup(ir.RootNode action()) { | 1784 ir.RootNode nullIfGiveup(ir.RootNode action()) { |
| 1765 try { | 1785 try { |
| 1766 return action(); | 1786 return action(); |
| 1767 } catch(e, tr) { | 1787 } catch(e) { |
| 1768 if (e == ABORT_IRNODE_BUILDER) { | 1788 if (e == ABORT_IRNODE_BUILDER) { |
| 1769 return null; | 1789 return null; |
| 1770 } | 1790 } |
| 1771 rethrow; | 1791 rethrow; |
| 1772 } | 1792 } |
| 1773 } | 1793 } |
| 1774 | 1794 |
| 1775 void internalError(ast.Node node, String message) { | 1795 void internalError(ast.Node node, String message) { |
| 1776 giveup(node, message); | 1796 giveup(node, message); |
| 1777 } | 1797 } |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1997 LocalFunctionElement element = elements[node.function]; | 2017 LocalFunctionElement element = elements[node.function]; |
| 1998 Object inner = makeSubFunction(node.function); | 2018 Object inner = makeSubFunction(node.function); |
| 1999 irBuilder.declareLocalFunction(element, inner); | 2019 irBuilder.declareLocalFunction(element, inner); |
| 2000 } | 2020 } |
| 2001 | 2021 |
| 2002 ClosureScope getClosureScopeForNode(ast.Node node) => null; | 2022 ClosureScope getClosureScopeForNode(ast.Node node) => null; |
| 2003 ClosureEnvironment getClosureEnvironment() => null; | 2023 ClosureEnvironment getClosureEnvironment() => null; |
| 2004 | 2024 |
| 2005 ir.RootNode buildExecutable(ExecutableElement element) { | 2025 ir.RootNode buildExecutable(ExecutableElement element) { |
| 2006 return nullIfGiveup(() { | 2026 return nullIfGiveup(() { |
| 2027 ir.RootNode root; |
| 2007 if (element is FieldElement) { | 2028 if (element is FieldElement) { |
| 2008 return buildField(element); | 2029 root = buildField(element); |
| 2009 } else if (element is FunctionElement || element is ConstructorElement) { | 2030 } else if (element is FunctionElement || element is ConstructorElement) { |
| 2010 return buildFunction(element); | 2031 root = buildFunction(element); |
| 2011 } else { | 2032 } else { |
| 2012 compiler.internalError(element, "Unexpected element type $element"); | 2033 compiler.internalError(element, "Unexpected element type $element"); |
| 2013 } | 2034 } |
| 2035 new CleanupPass().visit(root); |
| 2036 return root; |
| 2014 }); | 2037 }); |
| 2015 } | 2038 } |
| 2016 | 2039 |
| 2017 /// Returns a [ir.FieldDefinition] describing the initializer of [element]. | 2040 /// Returns a [ir.FieldDefinition] describing the initializer of [element]. |
| 2018 ir.FieldDefinition buildField(FieldElement element) { | 2041 ir.FieldDefinition buildField(FieldElement element) { |
| 2019 assert(invariant(element, element.isImplementation)); | 2042 assert(invariant(element, element.isImplementation)); |
| 2020 ast.VariableDefinitions definitions = element.node; | 2043 ast.VariableDefinitions definitions = element.node; |
| 2021 ast.Node fieldDefinition = definitions.definitions.nodes.first; | 2044 ast.Node fieldDefinition = definitions.definitions.nodes.first; |
| 2022 if (definitions.modifiers.isConst) { | 2045 if (definitions.modifiers.isConst) { |
| 2023 // TODO(sigurdm): Just return const value. | 2046 // TODO(sigurdm): Just return const value. |
| (...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2217 elements); | 2240 elements); |
| 2218 closurelib.ClosureScope scope = map.capturingScopes[function.node]; | 2241 closurelib.ClosureScope scope = map.capturingScopes[function.node]; |
| 2219 if (scope == null) return null; | 2242 if (scope == null) return null; |
| 2220 return new ClosureScope(scope.boxElement, | 2243 return new ClosureScope(scope.boxElement, |
| 2221 mapValues(scope.capturedVariables, getLocation), | 2244 mapValues(scope.capturedVariables, getLocation), |
| 2222 scope.boxedLoopVariables); | 2245 scope.boxedLoopVariables); |
| 2223 } | 2246 } |
| 2224 | 2247 |
| 2225 ir.RootNode buildExecutable(ExecutableElement element) { | 2248 ir.RootNode buildExecutable(ExecutableElement element) { |
| 2226 return nullIfGiveup(() { | 2249 return nullIfGiveup(() { |
| 2250 ir.RootNode root; |
| 2227 switch (element.kind) { | 2251 switch (element.kind) { |
| 2228 case ElementKind.GENERATIVE_CONSTRUCTOR: | 2252 case ElementKind.GENERATIVE_CONSTRUCTOR: |
| 2229 return buildConstructor(element); | 2253 root = buildConstructor(element); |
| 2254 break; |
| 2230 | 2255 |
| 2231 case ElementKind.GENERATIVE_CONSTRUCTOR_BODY: | 2256 case ElementKind.GENERATIVE_CONSTRUCTOR_BODY: |
| 2232 return buildConstructorBody(element); | 2257 root = buildConstructorBody(element); |
| 2258 break; |
| 2233 | 2259 |
| 2234 case ElementKind.FUNCTION: | 2260 case ElementKind.FUNCTION: |
| 2235 case ElementKind.GETTER: | 2261 case ElementKind.GETTER: |
| 2236 case ElementKind.SETTER: | 2262 case ElementKind.SETTER: |
| 2237 return buildFunction(element); | 2263 root = buildFunction(element); |
| 2264 break; |
| 2238 | 2265 |
| 2239 default: | 2266 default: |
| 2240 compiler.internalError(element, "Unexpected element type $element"); | 2267 compiler.internalError(element, "Unexpected element type $element"); |
| 2241 } | 2268 } |
| 2269 new CleanupPass().visit(root); |
| 2270 return root; |
| 2242 }); | 2271 }); |
| 2243 } | 2272 } |
| 2244 | 2273 |
| 2245 /// Builds the IR for an [expression] taken from a different [context]. | 2274 /// Builds the IR for an [expression] taken from a different [context]. |
| 2246 /// | 2275 /// |
| 2247 /// Such expressions need to be compiled with a different [sourceFile] and | 2276 /// Such expressions need to be compiled with a different [sourceFile] and |
| 2248 /// [elements] mapping. | 2277 /// [elements] mapping. |
| 2249 ir.Primitive inlineExpression(AstElement context, ast.Expression expression) { | 2278 ir.Primitive inlineExpression(AstElement context, ast.Expression expression) { |
| 2250 JsIrBuilderVisitor visitor = new JsIrBuilderVisitor( | 2279 JsIrBuilderVisitor visitor = new JsIrBuilderVisitor( |
| 2251 context.resolvedAst.elements, | 2280 context.resolvedAst.elements, |
| (...skipping 513 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2765 SourceInformation buildCall(ast.Node node) { | 2794 SourceInformation buildCall(ast.Node node) { |
| 2766 return new PositionSourceInformation( | 2795 return new PositionSourceInformation( |
| 2767 new TokenSourceLocation(sourceFile, node.getBeginToken(), name)); | 2796 new TokenSourceLocation(sourceFile, node.getBeginToken(), name)); |
| 2768 } | 2797 } |
| 2769 | 2798 |
| 2770 @override | 2799 @override |
| 2771 SourceInformationBuilder forContext(AstElement element) { | 2800 SourceInformationBuilder forContext(AstElement element) { |
| 2772 return new PositionSourceInformationBuilder(element); | 2801 return new PositionSourceInformationBuilder(element); |
| 2773 } | 2802 } |
| 2774 } | 2803 } |
| 2804 |
| 2805 /// Perform simple post-processing on the initial CPS-translated root term. |
| 2806 /// |
| 2807 /// This pass performs backend-independent post-processing on the translated |
| 2808 /// term. It is implemented separately from the optimization passes because |
| 2809 /// it is required for correctness of the implementation. |
| 2810 /// |
| 2811 /// It performs the following translations: |
| 2812 /// - Replace [ir.LetPrim] binding a [ir.NonTailThrow] with a [ir.Throw] |
| 2813 /// expression. |
| 2814 class CleanupPass extends ir.RecursiveVisitor { |
| 2815 RemovalVisitor _remover = new RemovalVisitor(); |
| 2816 |
| 2817 ir.Expression replacementFor(ir.Expression expression) { |
| 2818 if (expression != null && expression is ir.LetPrim) { |
| 2819 ir.Primitive primitive = expression.primitive; |
| 2820 if (primitive is ir.NonTailThrow) { |
| 2821 _remover.visit(expression); |
| 2822 return new ir.Throw(primitive.value.definition); |
| 2823 } |
| 2824 } |
| 2825 return expression; |
| 2826 } |
| 2827 |
| 2828 processLetPrim(ir.LetPrim node) { |
| 2829 node.body = replacementFor(node.body); |
| 2830 } |
| 2831 |
| 2832 processLetCont(ir.LetCont node) { |
| 2833 node.body = replacementFor(node.body); |
| 2834 } |
| 2835 |
| 2836 processLetHandler(ir.LetHandler node) { |
| 2837 node.body = replacementFor(node.body); |
| 2838 } |
| 2839 |
| 2840 processLetMutable(ir.LetMutable node) { |
| 2841 node.body = replacementFor(node.body); |
| 2842 } |
| 2843 |
| 2844 processSetMutableVariable(ir.SetMutableVariable node) { |
| 2845 node.body = replacementFor(node.body); |
| 2846 } |
| 2847 |
| 2848 processDeclareFunction(ir.DeclareFunction node) { |
| 2849 node.body = replacementFor(node.body); |
| 2850 } |
| 2851 |
| 2852 processSetField(ir.SetField node) { |
| 2853 node.body = replacementFor(node.body); |
| 2854 } |
| 2855 |
| 2856 processContinuation(ir.Continuation node) { |
| 2857 node.body = replacementFor(node.body); |
| 2858 } |
| 2859 |
| 2860 processBody(ir.Body node) { |
| 2861 node.body = replacementFor(node.body); |
| 2862 } |
| 2863 } |
| 2864 |
| 2865 /// Visit a just-deleted subterm and unlink all [Reference]s in it. |
| 2866 class RemovalVisitor extends ir.RecursiveVisitor { |
| 2867 processReference(ir.Reference reference) { |
| 2868 reference.unlink(); |
| 2869 } |
| 2870 } |
| 2871 |
| OLD | NEW |