| 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 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 135 BaseImplementationOfLocalsMixin<ir.Primitive, dynamic>, | 135 BaseImplementationOfLocalsMixin<ir.Primitive, dynamic>, |
| 136 BaseImplementationOfDynamicsMixin<ir.Primitive, dynamic>, | 136 BaseImplementationOfDynamicsMixin<ir.Primitive, dynamic>, |
| 137 BaseImplementationOfConstantsMixin<ir.Primitive, dynamic>, | 137 BaseImplementationOfConstantsMixin<ir.Primitive, dynamic>, |
| 138 BaseImplementationOfSuperIncDecsMixin<ir.Primitive, dynamic>, | 138 BaseImplementationOfSuperIncDecsMixin<ir.Primitive, dynamic>, |
| 139 BaseImplementationOfNewMixin<ir.Primitive, dynamic>, | 139 BaseImplementationOfNewMixin<ir.Primitive, dynamic>, |
| 140 ErrorBulkMixin<ir.Primitive, dynamic> | 140 ErrorBulkMixin<ir.Primitive, dynamic> |
| 141 implements SemanticSendVisitor<ir.Primitive, dynamic> { | 141 implements SemanticSendVisitor<ir.Primitive, dynamic> { |
| 142 final Compiler compiler; | 142 final Compiler compiler; |
| 143 final SourceInformationBuilder sourceInformationBuilder; | 143 final SourceInformationBuilder sourceInformationBuilder; |
| 144 | 144 |
| 145 /// A map from try statements in the source to analysis information about |
| 146 /// them. |
| 147 /// |
| 148 /// The analysis information includes the set of variables that must be |
| 149 /// copied into [ir.MutableVariable]s on entry to the try and copied out on |
| 150 /// exit. |
| 151 Map<ast.TryStatement, TryStatementInfo> tryStatements = null; |
| 152 |
| 145 // In SSA terms, join-point continuation parameters are the phis and the | 153 // In SSA terms, join-point continuation parameters are the phis and the |
| 146 // continuation invocation arguments are the corresponding phi inputs. To | 154 // continuation invocation arguments are the corresponding phi inputs. To |
| 147 // support name introduction and renaming for source level variables, we use | 155 // support name introduction and renaming for source level variables, we use |
| 148 // nested (delimited) visitors for constructing subparts of the IR that will | 156 // nested (delimited) visitors for constructing subparts of the IR that will |
| 149 // need renaming. Each source variable is assigned an index. | 157 // need renaming. Each source variable is assigned an index. |
| 150 // | 158 // |
| 151 // Each nested visitor maintains a list of free variable uses in the body. | 159 // Each nested visitor maintains a list of free variable uses in the body. |
| 152 // These are implemented as a list of parameters, each with their own use | 160 // These are implemented as a list of parameters, each with their own use |
| 153 // list of references. When the delimited subexpression is plugged into the | 161 // list of references. When the delimited subexpression is plugged into the |
| 154 // surrounding context, the free occurrences can be captured or become free | 162 // surrounding context, the free occurrences can be captured or become free |
| (...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 464 // Return without a subexpression is translated as if it were return null. | 472 // Return without a subexpression is translated as if it were return null. |
| 465 ir.Primitive visitReturn(ast.Return node) { | 473 ir.Primitive visitReturn(ast.Return node) { |
| 466 assert(irBuilder.isOpen); | 474 assert(irBuilder.isOpen); |
| 467 assert(invariant(node, node.beginToken.value != 'native')); | 475 assert(invariant(node, node.beginToken.value != 'native')); |
| 468 irBuilder.buildReturn(build(node.expression)); | 476 irBuilder.buildReturn(build(node.expression)); |
| 469 return null; | 477 return null; |
| 470 } | 478 } |
| 471 | 479 |
| 472 visitTryStatement(ast.TryStatement node) { | 480 visitTryStatement(ast.TryStatement node) { |
| 473 // Try/catch is not yet implemented in the JS backend. | 481 // Try/catch is not yet implemented in the JS backend. |
| 474 if (this.irBuilder.tryStatements == null) { | 482 if (tryStatements == null) { |
| 475 return giveup(node, 'try/catch in the JS backend'); | 483 return giveup(node, 'try/catch in the JS backend'); |
| 476 } | 484 } |
| 477 // Multiple catch blocks are not yet implemented. | 485 // Multiple catch blocks are not yet implemented. |
| 478 if (node.catchBlocks.isEmpty || | 486 if (node.catchBlocks.isEmpty || |
| 479 node.catchBlocks.nodes.tail == null) { | 487 node.catchBlocks.nodes.tail == null) { |
| 480 return giveup(node, 'not exactly one catch block'); | 488 return giveup(node, 'not exactly one catch block'); |
| 481 } | 489 } |
| 482 // 'on T' catch blocks are not yet implemented. | 490 // 'on T' catch blocks are not yet implemented. |
| 483 if ((node.catchBlocks.nodes.head as ast.CatchBlock).onKeyword != null) { | 491 if ((node.catchBlocks.nodes.head as ast.CatchBlock).onKeyword != null) { |
| 484 return giveup(node, '"on T" catch block'); | 492 return giveup(node, '"on T" catch block'); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 496 if (catchClause.trace != null) { | 504 if (catchClause.trace != null) { |
| 497 stackTraceVariable = elements[catchClause.trace]; | 505 stackTraceVariable = elements[catchClause.trace]; |
| 498 } | 506 } |
| 499 catchClauseInfos.add(new CatchClauseInfo( | 507 catchClauseInfos.add(new CatchClauseInfo( |
| 500 exceptionVariable: exceptionVariable, | 508 exceptionVariable: exceptionVariable, |
| 501 stackTraceVariable: stackTraceVariable, | 509 stackTraceVariable: stackTraceVariable, |
| 502 buildCatchBlock: subbuild(catchClause.block))); | 510 buildCatchBlock: subbuild(catchClause.block))); |
| 503 } | 511 } |
| 504 | 512 |
| 505 irBuilder.buildTry( | 513 irBuilder.buildTry( |
| 506 tryStatementInfo: irBuilder.tryStatements[node], | 514 tryStatementInfo: tryStatements[node], |
| 507 buildTryBlock: subbuild(node.tryBlock), | 515 buildTryBlock: subbuild(node.tryBlock), |
| 508 catchClauseInfos: catchClauseInfos); | 516 catchClauseInfos: catchClauseInfos); |
| 509 } | 517 } |
| 510 | 518 |
| 511 // ## Expressions ## | 519 // ## Expressions ## |
| 512 ir.Primitive visitConditional(ast.Conditional node) { | 520 ir.Primitive visitConditional(ast.Conditional node) { |
| 513 return irBuilder.buildConditional( | 521 return irBuilder.buildConditional( |
| 514 build(node.condition), | 522 build(node.condition), |
| 515 subbuild(node.thenExpression), | 523 subbuild(node.thenExpression), |
| 516 subbuild(node.elseExpression)); | 524 subbuild(node.elseExpression)); |
| (...skipping 1293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1810 | 1818 |
| 1811 giveup(ast.Node node, [String reason]) { | 1819 giveup(ast.Node node, [String reason]) { |
| 1812 bailoutMessage = '($node): $reason'; | 1820 bailoutMessage = '($node): $reason'; |
| 1813 throw ABORT_IRNODE_BUILDER; | 1821 throw ABORT_IRNODE_BUILDER; |
| 1814 } | 1822 } |
| 1815 | 1823 |
| 1816 void markAsCaptured(Local local) { | 1824 void markAsCaptured(Local local) { |
| 1817 capturedVariables.add(local); | 1825 capturedVariables.add(local); |
| 1818 } | 1826 } |
| 1819 | 1827 |
| 1828 analyze(ast.Node node) { |
| 1829 visit(node); |
| 1830 // Variables that are captured by a closure are boxed for their entire |
| 1831 // lifetime, so they never need to be boxed on entry to a try block. |
| 1832 // They are not filtered out before this because we cannot identify all |
| 1833 // of them in the same pass (they may be captured by a closure after the |
| 1834 // try statement). |
| 1835 for (TryStatementInfo info in tryStatements.values) { |
| 1836 info.boxedOnEntry.removeAll(capturedVariables); |
| 1837 } |
| 1838 } |
| 1839 |
| 1820 visit(ast.Node node) => node.accept(this); | 1840 visit(ast.Node node) => node.accept(this); |
| 1821 | 1841 |
| 1822 visitNode(ast.Node node) { | 1842 visitNode(ast.Node node) { |
| 1823 node.visitChildren(this); | 1843 node.visitChildren(this); |
| 1824 } | 1844 } |
| 1825 | 1845 |
| 1826 visitFor(ast.For node) { | 1846 visitFor(ast.For node) { |
| 1827 if (node.initializer != null) visit(node.initializer); | 1847 if (node.initializer != null) visit(node.initializer); |
| 1828 if (node.condition != null) visit(node.condition); | 1848 if (node.condition != null) visit(node.condition); |
| 1829 if (node.update != null) visit(node.update); | 1849 if (node.update != null) visit(node.update); |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1935 /// IR builder specific to the Dart backend, coupled to the [DartIrBuilder]. | 1955 /// IR builder specific to the Dart backend, coupled to the [DartIrBuilder]. |
| 1936 class DartIrBuilderVisitor extends IrBuilderVisitor { | 1956 class DartIrBuilderVisitor extends IrBuilderVisitor { |
| 1937 /// Promote the type of [irBuilder] to [DartIrBuilder]. | 1957 /// Promote the type of [irBuilder] to [DartIrBuilder]. |
| 1938 DartIrBuilder get irBuilder => super.irBuilder; | 1958 DartIrBuilder get irBuilder => super.irBuilder; |
| 1939 | 1959 |
| 1940 DartIrBuilderVisitor(TreeElements elements, | 1960 DartIrBuilderVisitor(TreeElements elements, |
| 1941 Compiler compiler, | 1961 Compiler compiler, |
| 1942 SourceInformationBuilder sourceInformationBuilder) | 1962 SourceInformationBuilder sourceInformationBuilder) |
| 1943 : super(elements, compiler, sourceInformationBuilder); | 1963 : super(elements, compiler, sourceInformationBuilder); |
| 1944 | 1964 |
| 1945 DartIrBuilder makeIRBuilder(ast.Node node, ExecutableElement element) { | 1965 DartIrBuilder makeIRBuilder(ExecutableElement element, |
| 1946 DartCapturedVariables closures = new DartCapturedVariables(elements); | 1966 Set<Local> capturedVariables) { |
| 1967 return new DartIrBuilder(compiler.backend.constantSystem, |
| 1968 element, |
| 1969 capturedVariables); |
| 1970 } |
| 1971 |
| 1972 DartCapturedVariables _analyzeCapturedVariables(ExecutableElement element, |
| 1973 ast.Node node) { |
| 1974 DartCapturedVariables variables = new DartCapturedVariables(elements); |
| 1947 if (!element.isSynthesized) { | 1975 if (!element.isSynthesized) { |
| 1948 try { | 1976 try { |
| 1949 closures.visit(node); | 1977 variables.analyze(node); |
| 1950 } catch (e) { | 1978 } catch (e) { |
| 1951 bailoutMessage = closures.bailoutMessage; | 1979 bailoutMessage = variables.bailoutMessage; |
| 1952 rethrow; | 1980 rethrow; |
| 1953 } | 1981 } |
| 1954 } | 1982 } |
| 1955 return new DartIrBuilder(compiler.backend.constantSystem, | 1983 return variables; |
| 1956 element, | |
| 1957 closures); | |
| 1958 } | 1984 } |
| 1959 | 1985 |
| 1960 /// Recursively builds the IR for the given nested function. | 1986 /// Recursively builds the IR for the given nested function. |
| 1961 ir.FunctionDefinition makeSubFunction(ast.FunctionExpression node) { | 1987 ir.FunctionDefinition makeSubFunction(ast.FunctionExpression node) { |
| 1962 FunctionElement element = elements[node]; | 1988 FunctionElement element = elements[node]; |
| 1963 assert(invariant(element, element.isImplementation)); | 1989 assert(invariant(element, element.isImplementation)); |
| 1964 | 1990 |
| 1965 IrBuilder builder = irBuilder.makeInnerFunctionBuilder(element); | 1991 IrBuilder builder = irBuilder.makeInnerFunctionBuilder(element); |
| 1966 | 1992 |
| 1967 return withBuilder(builder, () => _makeFunctionBody(element, node)); | 1993 return withBuilder(builder, () => _makeFunctionBody(element, node)); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1996 ir.FieldDefinition buildField(FieldElement element) { | 2022 ir.FieldDefinition buildField(FieldElement element) { |
| 1997 assert(invariant(element, element.isImplementation)); | 2023 assert(invariant(element, element.isImplementation)); |
| 1998 ast.VariableDefinitions definitions = element.node; | 2024 ast.VariableDefinitions definitions = element.node; |
| 1999 ast.Node fieldDefinition = definitions.definitions.nodes.first; | 2025 ast.Node fieldDefinition = definitions.definitions.nodes.first; |
| 2000 if (definitions.modifiers.isConst) { | 2026 if (definitions.modifiers.isConst) { |
| 2001 // TODO(sigurdm): Just return const value. | 2027 // TODO(sigurdm): Just return const value. |
| 2002 } | 2028 } |
| 2003 assert(fieldDefinition != null); | 2029 assert(fieldDefinition != null); |
| 2004 assert(elements[fieldDefinition] != null); | 2030 assert(elements[fieldDefinition] != null); |
| 2005 | 2031 |
| 2006 IrBuilder builder = makeIRBuilder(fieldDefinition, element); | 2032 DartCapturedVariables variables = |
| 2033 _analyzeCapturedVariables(element, fieldDefinition); |
| 2034 tryStatements = variables.tryStatements; |
| 2035 IrBuilder builder = makeIRBuilder(element, variables.capturedVariables); |
| 2007 | 2036 |
| 2008 return withBuilder(builder, () { | 2037 return withBuilder(builder, () { |
| 2009 builder.buildFieldInitializerHeader( | 2038 builder.buildFieldInitializerHeader( |
| 2010 closureScope: getClosureScopeForNode(fieldDefinition)); | 2039 closureScope: getClosureScopeForNode(fieldDefinition)); |
| 2011 ir.Primitive initializer; | 2040 ir.Primitive initializer; |
| 2012 if (fieldDefinition is ast.SendSet) { | 2041 if (fieldDefinition is ast.SendSet) { |
| 2013 ast.SendSet sendSet = fieldDefinition; | 2042 ast.SendSet sendSet = fieldDefinition; |
| 2014 initializer = visit(sendSet.arguments.first); | 2043 initializer = visit(sendSet.arguments.first); |
| 2015 } | 2044 } |
| 2016 return builder.makeFieldDefinition(initializer); | 2045 return builder.makeFieldDefinition(initializer); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 2027 if (!element.isSynthesized) { | 2056 if (!element.isSynthesized) { |
| 2028 assert(node != null); | 2057 assert(node != null); |
| 2029 assert(elements[node] != null); | 2058 assert(elements[node] != null); |
| 2030 } else { | 2059 } else { |
| 2031 SynthesizedConstructorElementX constructor = element; | 2060 SynthesizedConstructorElementX constructor = element; |
| 2032 if (!constructor.isDefaultConstructor) { | 2061 if (!constructor.isDefaultConstructor) { |
| 2033 giveup(null, 'cannot handle synthetic forwarding constructors'); | 2062 giveup(null, 'cannot handle synthetic forwarding constructors'); |
| 2034 } | 2063 } |
| 2035 } | 2064 } |
| 2036 | 2065 |
| 2037 IrBuilder builder = makeIRBuilder(node, element); | 2066 DartCapturedVariables variables = |
| 2067 _analyzeCapturedVariables(element, node); |
| 2068 tryStatements = variables.tryStatements; |
| 2069 IrBuilder builder = makeIRBuilder(element, variables.capturedVariables); |
| 2038 | 2070 |
| 2039 return withBuilder(builder, () => _makeFunctionBody(element, node)); | 2071 return withBuilder(builder, () => _makeFunctionBody(element, node)); |
| 2040 } | 2072 } |
| 2041 | 2073 |
| 2042 List<ir.Primitive> normalizeStaticArguments( | 2074 List<ir.Primitive> normalizeStaticArguments( |
| 2043 CallStructure callStructure, | 2075 CallStructure callStructure, |
| 2044 FunctionElement target, | 2076 FunctionElement target, |
| 2045 List<ir.Primitive> arguments) { | 2077 List<ir.Primitive> arguments) { |
| 2046 return arguments; | 2078 return arguments; |
| 2047 } | 2079 } |
| (...skipping 633 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2681 SourceInformation buildCall(ast.Node node) { | 2713 SourceInformation buildCall(ast.Node node) { |
| 2682 return new PositionSourceInformation( | 2714 return new PositionSourceInformation( |
| 2683 new TokenSourceLocation(sourceFile, node.getBeginToken(), name)); | 2715 new TokenSourceLocation(sourceFile, node.getBeginToken(), name)); |
| 2684 } | 2716 } |
| 2685 | 2717 |
| 2686 @override | 2718 @override |
| 2687 SourceInformationBuilder forContext(AstElement element) { | 2719 SourceInformationBuilder forContext(AstElement element) { |
| 2688 return new PositionSourceInformationBuilder(element); | 2720 return new PositionSourceInformationBuilder(element); |
| 2689 } | 2721 } |
| 2690 } | 2722 } |
| OLD | NEW |