| 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 22 matching lines...) Expand all Loading... |
| 33 * used in the rest of the compilation. This is ensured by setting the element's | 33 * used in the rest of the compilation. This is ensured by setting the element's |
| 34 * cached tree to `null` and also breaking the token stream to crash future | 34 * cached tree to `null` and also breaking the token stream to crash future |
| 35 * attempts to parse. | 35 * attempts to parse. |
| 36 * | 36 * |
| 37 * The type inferrer works on either IR nodes or tree nodes. The IR nodes are | 37 * The type inferrer works on either IR nodes or tree nodes. The IR nodes are |
| 38 * then translated into the SSA form for optimizations and code generation. | 38 * then translated into the SSA form for optimizations and code generation. |
| 39 * Long-term, once the IR supports the full language, the backend can be | 39 * Long-term, once the IR supports the full language, the backend can be |
| 40 * re-implemented to work directly on the IR. | 40 * re-implemented to work directly on the IR. |
| 41 */ | 41 */ |
| 42 class IrBuilderTask extends CompilerTask { | 42 class IrBuilderTask extends CompilerTask { |
| 43 final Map<Element, ir.RootNode> nodes = <Element, ir.RootNode>{}; | 43 final Map<Element, ir.FunctionDefinition> nodes = |
| 44 <Element, ir.FunctionDefinition>{}; |
| 44 final SourceInformationFactory sourceInformationFactory; | 45 final SourceInformationFactory sourceInformationFactory; |
| 45 | 46 |
| 46 String bailoutMessage = null; | 47 String bailoutMessage = null; |
| 47 | 48 |
| 48 IrBuilderTask(Compiler compiler, this.sourceInformationFactory) | 49 IrBuilderTask(Compiler compiler, this.sourceInformationFactory) |
| 49 : super(compiler); | 50 : super(compiler); |
| 50 | 51 |
| 51 String get name => 'IR builder'; | 52 String get name => 'IR builder'; |
| 52 | 53 |
| 53 bool hasIr(Element element) => nodes.containsKey(element.implementation); | 54 bool hasIr(Element element) => nodes.containsKey(element.implementation); |
| 54 | 55 |
| 55 ir.RootNode getIr(ExecutableElement element) { | 56 ir.FunctionDefinition getIr(ExecutableElement element) { |
| 56 return nodes[element.implementation]; | 57 return nodes[element.implementation]; |
| 57 } | 58 } |
| 58 | 59 |
| 59 ir.RootNode buildNode(AstElement element) { | 60 ir.FunctionDefinition buildNode(AstElement element) { |
| 60 return measure(() => _buildNode(element)); | 61 return measure(() => _buildNode(element)); |
| 61 } | 62 } |
| 62 | 63 |
| 63 ir.RootNode _buildNode(AstElement element) { | 64 ir.FunctionDefinition _buildNode(AstElement element) { |
| 64 bailoutMessage = null; | 65 bailoutMessage = null; |
| 65 if (!canBuild(element)) { | |
| 66 bailoutMessage = 'unsupported element ${element.name}:${element.kind}'; | |
| 67 return null; | |
| 68 } | |
| 69 | 66 |
| 70 TreeElements elementsMapping = element.resolvedAst.elements; | 67 TreeElements elementsMapping = element.resolvedAst.elements; |
| 71 element = element.implementation; | 68 element = element.implementation; |
| 72 return compiler.withCurrentElement(element, () { | 69 return compiler.withCurrentElement(element, () { |
| 73 SourceInformationBuilder sourceInformationBuilder = | 70 SourceInformationBuilder sourceInformationBuilder = |
| 74 sourceInformationFactory.forContext(element); | 71 sourceInformationFactory.forContext(element); |
| 75 | 72 |
| 76 IrBuilderVisitor builder = | 73 IrBuilderVisitor builder = |
| 77 compiler.backend is JavaScriptBackend | 74 new JsIrBuilderVisitor( |
| 78 ? new JsIrBuilderVisitor( | |
| 79 elementsMapping, compiler, sourceInformationBuilder) | |
| 80 : new DartIrBuilderVisitor( | |
| 81 elementsMapping, compiler, sourceInformationBuilder); | 75 elementsMapping, compiler, sourceInformationBuilder); |
| 82 ir.RootNode irNode = builder.buildExecutable(element); | 76 ir.FunctionDefinition irNode = builder.buildExecutable(element); |
| 83 if (irNode == null) { | 77 if (irNode == null) { |
| 84 bailoutMessage = builder.bailoutMessage; | 78 bailoutMessage = builder.bailoutMessage; |
| 85 } else { | 79 } else { |
| 86 nodes[element] = irNode; | 80 nodes[element] = irNode; |
| 87 } | 81 } |
| 88 return irNode; | 82 return irNode; |
| 89 }); | 83 }); |
| 90 } | 84 } |
| 91 | 85 |
| 92 void buildNodes() { | 86 void buildNodes() { |
| 93 measure(() { | 87 measure(() { |
| 94 Set<Element> resolved = compiler.enqueuer.resolution.resolvedElements; | 88 Set<Element> resolved = compiler.enqueuer.resolution.resolvedElements; |
| 95 resolved.forEach(buildNode); | 89 resolved.forEach(buildNode); |
| 96 }); | 90 }); |
| 97 } | 91 } |
| 98 | 92 |
| 99 bool canBuild(Element element) { | |
| 100 // If using JavaScript backend, don't try to bail out early. | |
| 101 if (compiler.backend is JavaScriptBackend) return true; | |
| 102 | |
| 103 if (element is TypedefElement) return false; | |
| 104 if (element is FunctionElement) { | |
| 105 // TODO(sigurdm): Support native functions for dart2js. | |
| 106 assert(invariant(element, !element.isNative)); | |
| 107 | |
| 108 if (element is ConstructorElement) { | |
| 109 if (!element.isGenerativeConstructor) { | |
| 110 // TODO(kmillikin,sigurdm): Support constructors. | |
| 111 return false; | |
| 112 } | |
| 113 if (element.isSynthesized) { | |
| 114 // Do generate CPS for synthetic constructors. | |
| 115 return true; | |
| 116 } | |
| 117 } | |
| 118 } else if (element is! FieldElement) { | |
| 119 compiler.internalError(element, "Unexpected element type $element"); | |
| 120 } | |
| 121 return compiler.backend.shouldOutput(element); | |
| 122 } | |
| 123 | |
| 124 bool get inCheckedMode { | 93 bool get inCheckedMode { |
| 125 bool result = false; | 94 bool result = false; |
| 126 assert((result = true)); | 95 assert((result = true)); |
| 127 return result; | 96 return result; |
| 128 } | 97 } |
| 129 | 98 |
| 130 } | 99 } |
| 131 | 100 |
| 132 /** | 101 /** |
| 133 * A tree visitor that builds [IrNodes]. The visit methods add statements using | 102 * A tree visitor that builds [IrNodes]. The visit methods add statements using |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 184 | 153 |
| 185 String bailoutMessage = null; | 154 String bailoutMessage = null; |
| 186 | 155 |
| 187 @override | 156 @override |
| 188 ir.Primitive apply(ast.Node node, _) => node.accept(this); | 157 ir.Primitive apply(ast.Node node, _) => node.accept(this); |
| 189 | 158 |
| 190 @override | 159 @override |
| 191 SemanticSendVisitor get sendVisitor => this; | 160 SemanticSendVisitor get sendVisitor => this; |
| 192 | 161 |
| 193 /** | 162 /** |
| 194 * Builds the [ir.RootNode] for an executable element. In case the | 163 * Builds the [ir.FunctionDefinition] for an executable element. In case the |
| 195 * function uses features that cannot be expressed in the IR, this element | 164 * function uses features that cannot be expressed in the IR, this element |
| 196 * returns `null`. | 165 * returns `null`. |
| 197 */ | 166 */ |
| 198 ir.RootNode buildExecutable(ExecutableElement element); | 167 ir.FunctionDefinition buildExecutable(ExecutableElement element); |
| 199 | 168 |
| 200 ClosureClassMap get closureClassMap; | 169 ClosureClassMap get closureClassMap; |
| 201 ClosureScope getClosureScopeForNode(ast.Node node); | 170 ClosureScope getClosureScopeForNode(ast.Node node); |
| 202 ClosureEnvironment getClosureEnvironment(); | 171 ClosureEnvironment getClosureEnvironment(); |
| 203 | 172 |
| 204 /// Normalizes the argument list to a static invocation (i.e. where the target | 173 /// Normalizes the argument list to a static invocation (i.e. where the target |
| 205 /// element is known). | 174 /// element is known). |
| 206 /// | 175 /// |
| 207 /// For the JS backend, inserts default arguments and normalizes order of | 176 /// For the JS backend, inserts default arguments and normalizes order of |
| 208 /// named arguments. | 177 /// named arguments. |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 241 return newSelector; | 210 return newSelector; |
| 242 } | 211 } |
| 243 } | 212 } |
| 244 | 213 |
| 245 /// Like [useSelectorType], except the original typed selector is obtained | 214 /// Like [useSelectorType], except the original typed selector is obtained |
| 246 /// from the [node]. | 215 /// from the [node]. |
| 247 Selector useSelectorTypeOfNode(Selector newSelector, ast.Send node) { | 216 Selector useSelectorTypeOfNode(Selector newSelector, ast.Send node) { |
| 248 return useSelectorType(newSelector, elements.getSelector(node)); | 217 return useSelectorType(newSelector, elements.getSelector(node)); |
| 249 } | 218 } |
| 250 | 219 |
| 251 ir.RootNode _makeFunctionBody(FunctionElement element, | 220 ir.FunctionDefinition _makeFunctionBody(FunctionElement element, |
| 252 ast.FunctionExpression node) { | 221 ast.FunctionExpression node) { |
| 253 FunctionSignature signature = element.functionSignature; | 222 FunctionSignature signature = element.functionSignature; |
| 254 List<ParameterElement> parameters = []; | 223 List<ParameterElement> parameters = []; |
| 255 signature.orderedForEachParameter(parameters.add); | 224 signature.orderedForEachParameter(parameters.add); |
| 256 | 225 |
| 257 irBuilder.buildFunctionHeader(parameters, | 226 irBuilder.buildFunctionHeader(parameters, |
| 258 closureScope: getClosureScopeForNode(node), | 227 closureScope: getClosureScopeForNode(node), |
| 259 env: getClosureEnvironment()); | 228 env: getClosureEnvironment()); |
| 260 | 229 |
| 261 List<ConstantExpression> defaults = new List<ConstantExpression>(); | 230 visit(node.body); |
| 262 signature.orderedOptionalParameters.forEach((ParameterElement element) { | 231 return irBuilder.makeFunctionDefinition(); |
| 263 defaults.add(getConstantForVariable(element)); | |
| 264 }); | |
| 265 | |
| 266 List<ir.Initializer> initializers; | |
| 267 if (element.isSynthesized) { | |
| 268 assert(element is ConstructorElement); | |
| 269 return irBuilder.makeConstructorDefinition(const <ConstantExpression>[], | |
| 270 const <ir.Initializer>[]); | |
| 271 } else if (element.isGenerativeConstructor) { | |
| 272 if (element.isExternal) { | |
| 273 return irBuilder.makeAbstractConstructorDefinition(defaults); | |
| 274 } else { | |
| 275 initializers = buildConstructorInitializers(node, element); | |
| 276 visit(node.body); | |
| 277 return irBuilder.makeConstructorDefinition(defaults, initializers); | |
| 278 } | |
| 279 } else { | |
| 280 visit(node.body); | |
| 281 return irBuilder.makeFunctionDefinition(defaults); | |
| 282 } | |
| 283 } | |
| 284 | |
| 285 List<ir.Initializer> buildConstructorInitializers( | |
| 286 ast.FunctionExpression function, ConstructorElement element) { | |
| 287 List<ir.Initializer> result = <ir.Initializer>[]; | |
| 288 FunctionSignature signature = element.functionSignature; | |
| 289 | |
| 290 void tryAddInitializingFormal(ParameterElement parameterElement) { | |
| 291 if (parameterElement.isInitializingFormal) { | |
| 292 InitializingFormalElement initializingFormal = parameterElement; | |
| 293 withBuilder(irBuilder.makeInitializerBuilder(), () { | |
| 294 ir.Primitive value = | |
| 295 irBuilder.buildLocalVariableGet(parameterElement); | |
| 296 result.add(irBuilder.makeFieldInitializer( | |
| 297 initializingFormal.fieldElement, | |
| 298 irBuilder.makeBody(value))); | |
| 299 }); | |
| 300 } | |
| 301 } | |
| 302 | |
| 303 // TODO(sigurdm): Preserve initializing formals as initializing formals. | |
| 304 signature.orderedForEachParameter(tryAddInitializingFormal); | |
| 305 | |
| 306 if (function.initializers == null) return result; | |
| 307 bool explicitSuperInitializer = false; | |
| 308 for(ast.Node initializer in function.initializers) { | |
| 309 if (initializer is ast.SendSet) { | |
| 310 // Field initializer. | |
| 311 FieldElement field = elements[initializer]; | |
| 312 withBuilder(irBuilder.makeInitializerBuilder(), () { | |
| 313 ir.Primitive value = visit(initializer.arguments.head); | |
| 314 ir.Body body = irBuilder.makeBody(value); | |
| 315 result.add(irBuilder.makeFieldInitializer(field, body)); | |
| 316 }); | |
| 317 } else if (initializer is ast.Send) { | |
| 318 // Super or this initializer. | |
| 319 if (ast.Initializers.isConstructorRedirect(initializer)) { | |
| 320 giveup(initializer, "constructor redirect (this) initializer"); | |
| 321 } | |
| 322 ConstructorElement constructor = elements[initializer].implementation; | |
| 323 Selector selector = elements.getSelector(initializer); | |
| 324 List<ir.Body> arguments = | |
| 325 initializer.arguments.mapToList((ast.Node argument) { | |
| 326 return withBuilder(irBuilder.makeInitializerBuilder(), () { | |
| 327 ir.Primitive value = visit(argument); | |
| 328 return irBuilder.makeBody(value); | |
| 329 }); | |
| 330 }); | |
| 331 result.add(irBuilder.makeSuperInitializer(constructor, | |
| 332 arguments, | |
| 333 selector)); | |
| 334 explicitSuperInitializer = true; | |
| 335 } else { | |
| 336 compiler.internalError(initializer, | |
| 337 "Unexpected initializer type $initializer"); | |
| 338 } | |
| 339 | |
| 340 } | |
| 341 if (!explicitSuperInitializer) { | |
| 342 // No super initializer found. Try to find the default constructor if | |
| 343 // the class is not Object. | |
| 344 ClassElement enclosingClass = element.enclosingClass; | |
| 345 if (!enclosingClass.isObject) { | |
| 346 ClassElement superClass = enclosingClass.superclass; | |
| 347 FunctionElement target = superClass.lookupDefaultConstructor(); | |
| 348 if (target == null) { | |
| 349 compiler.internalError(superClass, | |
| 350 "No default constructor available."); | |
| 351 } | |
| 352 Selector selector = new Selector.callDefaultConstructor(); | |
| 353 result.add(irBuilder.makeSuperInitializer(target, | |
| 354 <ir.Body>[], | |
| 355 selector)); | |
| 356 } | |
| 357 } | |
| 358 return result; | |
| 359 } | 232 } |
| 360 | 233 |
| 361 ir.Primitive visit(ast.Node node) => node.accept(this); | 234 ir.Primitive visit(ast.Node node) => node.accept(this); |
| 362 | 235 |
| 363 // ## Statements ## | 236 // ## Statements ## |
| 364 visitBlock(ast.Block node) { | 237 visitBlock(ast.Block node) { |
| 365 irBuilder.buildBlock(node.statements.nodes, build); | 238 irBuilder.buildBlock(node.statements.nodes, build); |
| 366 } | 239 } |
| 367 | 240 |
| 368 ir.Primitive visitBreakStatement(ast.BreakStatement node) { | 241 ir.Primitive visitBreakStatement(ast.BreakStatement node) { |
| (...skipping 1547 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1916 CallStructure callStructure, _) { | 1789 CallStructure callStructure, _) { |
| 1917 List<ir.Primitive> args = | 1790 List<ir.Primitive> args = |
| 1918 translateDynamicArguments(arguments, callStructure); | 1791 translateDynamicArguments(arguments, callStructure); |
| 1919 Name name = new Name(setter.name, setter.library); | 1792 Name name = new Name(setter.name, setter.library); |
| 1920 Selector selector = useSelectorTypeOfNode( | 1793 Selector selector = useSelectorTypeOfNode( |
| 1921 new Selector(SelectorKind.CALL, name, callStructure), | 1794 new Selector(SelectorKind.CALL, name, callStructure), |
| 1922 node); | 1795 node); |
| 1923 return buildInstanceNoSuchMethod(selector, args); | 1796 return buildInstanceNoSuchMethod(selector, args); |
| 1924 } | 1797 } |
| 1925 | 1798 |
| 1926 ir.RootNode nullIfGiveup(ir.RootNode action()) { | 1799 ir.FunctionDefinition nullIfGiveup(ir.FunctionDefinition action()) { |
| 1927 try { | 1800 try { |
| 1928 return action(); | 1801 return action(); |
| 1929 } catch(e) { | 1802 } catch(e) { |
| 1930 if (e == ABORT_IRNODE_BUILDER) { | 1803 if (e == ABORT_IRNODE_BUILDER) { |
| 1931 return null; | 1804 return null; |
| 1932 } | 1805 } |
| 1933 rethrow; | 1806 rethrow; |
| 1934 } | 1807 } |
| 1935 } | 1808 } |
| 1936 | 1809 |
| (...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2103 // In the closure conversion pass we check for isInitializingFormal, | 1976 // In the closure conversion pass we check for isInitializingFormal, |
| 2104 // but I'm not sure it can arise. | 1977 // but I'm not sure it can arise. |
| 2105 assert(!local.isInitializingFormal); | 1978 assert(!local.isInitializingFormal); |
| 2106 tryNestingStack.last.declared.add(local); | 1979 tryNestingStack.last.declared.add(local); |
| 2107 } | 1980 } |
| 2108 } | 1981 } |
| 2109 node.visitChildren(this); | 1982 node.visitChildren(this); |
| 2110 } | 1983 } |
| 2111 } | 1984 } |
| 2112 | 1985 |
| 2113 /// IR builder specific to the Dart backend, coupled to the [DartIrBuilder]. | |
| 2114 class DartIrBuilderVisitor extends IrBuilderVisitor { | |
| 2115 /// Promote the type of [irBuilder] to [DartIrBuilder]. | |
| 2116 DartIrBuilder get irBuilder => super.irBuilder; | |
| 2117 | |
| 2118 DartIrBuilderVisitor(TreeElements elements, | |
| 2119 Compiler compiler, | |
| 2120 SourceInformationBuilder sourceInformationBuilder) | |
| 2121 : super(elements, compiler, sourceInformationBuilder); | |
| 2122 | |
| 2123 DartIrBuilder makeIRBuilder(ExecutableElement element, | |
| 2124 Set<Local> capturedVariables) { | |
| 2125 return new DartIrBuilder(compiler.backend.constantSystem, | |
| 2126 element, | |
| 2127 capturedVariables); | |
| 2128 } | |
| 2129 | |
| 2130 DartCapturedVariables _analyzeCapturedVariables(ExecutableElement element, | |
| 2131 ast.Node node) { | |
| 2132 DartCapturedVariables variables = new DartCapturedVariables(elements); | |
| 2133 if (!element.isSynthesized) { | |
| 2134 try { | |
| 2135 variables.analyze(node); | |
| 2136 } catch (e) { | |
| 2137 bailoutMessage = variables.bailoutMessage; | |
| 2138 rethrow; | |
| 2139 } | |
| 2140 } | |
| 2141 return variables; | |
| 2142 } | |
| 2143 | |
| 2144 /// Recursively builds the IR for the given nested function. | |
| 2145 ir.FunctionDefinition makeSubFunction(ast.FunctionExpression node) { | |
| 2146 FunctionElement element = elements[node]; | |
| 2147 assert(invariant(element, element.isImplementation)); | |
| 2148 | |
| 2149 IrBuilder builder = irBuilder.makeInnerFunctionBuilder(element); | |
| 2150 | |
| 2151 return withBuilder(builder, () => _makeFunctionBody(element, node)); | |
| 2152 } | |
| 2153 | |
| 2154 ir.Primitive visitFunctionExpression(ast.FunctionExpression node) { | |
| 2155 return irBuilder.buildFunctionExpression(makeSubFunction(node)); | |
| 2156 } | |
| 2157 | |
| 2158 visitFunctionDeclaration(ast.FunctionDeclaration node) { | |
| 2159 LocalFunctionElement element = elements[node.function]; | |
| 2160 Object inner = makeSubFunction(node.function); | |
| 2161 irBuilder.declareLocalFunction(element, inner); | |
| 2162 } | |
| 2163 | |
| 2164 ClosureClassMap get closureClassMap => null; | |
| 2165 ClosureScope getClosureScopeForNode(ast.Node node) => null; | |
| 2166 ClosureEnvironment getClosureEnvironment() => null; | |
| 2167 | |
| 2168 ir.RootNode buildExecutable(ExecutableElement element) { | |
| 2169 return nullIfGiveup(() { | |
| 2170 ir.RootNode root; | |
| 2171 if (element is FieldElement) { | |
| 2172 root = buildField(element); | |
| 2173 } else if (element is FunctionElement || element is ConstructorElement) { | |
| 2174 root = buildFunction(element); | |
| 2175 } else { | |
| 2176 compiler.internalError(element, "Unexpected element type $element"); | |
| 2177 } | |
| 2178 new CleanupPass().visit(root); | |
| 2179 return root; | |
| 2180 }); | |
| 2181 } | |
| 2182 | |
| 2183 /// Returns a [ir.FieldDefinition] describing the initializer of [element]. | |
| 2184 ir.FieldDefinition buildField(FieldElement element) { | |
| 2185 assert(invariant(element, element.isImplementation)); | |
| 2186 ast.VariableDefinitions definitions = element.node; | |
| 2187 ast.Node fieldDefinition = definitions.definitions.nodes.first; | |
| 2188 if (definitions.modifiers.isConst) { | |
| 2189 // TODO(sigurdm): Just return const value. | |
| 2190 } | |
| 2191 assert(fieldDefinition != null); | |
| 2192 assert(elements[fieldDefinition] != null); | |
| 2193 | |
| 2194 DartCapturedVariables variables = | |
| 2195 _analyzeCapturedVariables(element, fieldDefinition); | |
| 2196 tryStatements = variables.tryStatements; | |
| 2197 IrBuilder builder = makeIRBuilder(element, variables.capturedVariables); | |
| 2198 | |
| 2199 return withBuilder(builder, () { | |
| 2200 builder.buildFieldInitializerHeader( | |
| 2201 closureScope: getClosureScopeForNode(fieldDefinition)); | |
| 2202 ir.Primitive initializer; | |
| 2203 if (fieldDefinition is ast.SendSet) { | |
| 2204 ast.SendSet sendSet = fieldDefinition; | |
| 2205 initializer = visit(sendSet.arguments.first); | |
| 2206 } | |
| 2207 return builder.makeFieldDefinition(initializer); | |
| 2208 }); | |
| 2209 } | |
| 2210 | |
| 2211 ir.RootNode buildFunction(FunctionElement element) { | |
| 2212 assert(invariant(element, element.isImplementation)); | |
| 2213 ast.FunctionExpression node = element.node; | |
| 2214 if (element.asyncMarker != AsyncMarker.SYNC) { | |
| 2215 giveup(null, 'cannot handle async-await'); | |
| 2216 } | |
| 2217 | |
| 2218 if (!element.isSynthesized) { | |
| 2219 assert(node != null); | |
| 2220 assert(elements[node] != null); | |
| 2221 } else { | |
| 2222 SynthesizedConstructorElementX constructor = element; | |
| 2223 if (!constructor.isDefaultConstructor) { | |
| 2224 giveup(null, 'cannot handle synthetic forwarding constructors'); | |
| 2225 } | |
| 2226 } | |
| 2227 | |
| 2228 DartCapturedVariables variables = | |
| 2229 _analyzeCapturedVariables(element, node); | |
| 2230 tryStatements = variables.tryStatements; | |
| 2231 IrBuilder builder = makeIRBuilder(element, variables.capturedVariables); | |
| 2232 | |
| 2233 return withBuilder(builder, () => _makeFunctionBody(element, node)); | |
| 2234 } | |
| 2235 | |
| 2236 List<ir.Primitive> normalizeStaticArguments( | |
| 2237 CallStructure callStructure, | |
| 2238 FunctionElement target, | |
| 2239 List<ir.Primitive> arguments) { | |
| 2240 return arguments; | |
| 2241 } | |
| 2242 | |
| 2243 List<ir.Primitive> normalizeDynamicArguments( | |
| 2244 CallStructure callStructure, | |
| 2245 List<ir.Primitive> arguments) { | |
| 2246 return arguments; | |
| 2247 } | |
| 2248 | |
| 2249 @override | |
| 2250 ir.Primitive handleConstructorInvoke( | |
| 2251 ast.NewExpression node, | |
| 2252 ConstructorElement constructor, | |
| 2253 DartType type, | |
| 2254 ast.NodeList arguments, | |
| 2255 CallStructure callStructure, _) { | |
| 2256 List<ir.Primitive> arguments = | |
| 2257 node.send.arguments.mapToList(visit, growable:false); | |
| 2258 return irBuilder.buildConstructorInvocation( | |
| 2259 constructor, | |
| 2260 callStructure, | |
| 2261 type, | |
| 2262 arguments); | |
| 2263 } | |
| 2264 | |
| 2265 @override | |
| 2266 ir.Primitive buildStaticNoSuchMethod(Selector selector, | |
| 2267 List<ir.Primitive> arguments) { | |
| 2268 return giveup(null, 'Static noSuchMethod'); | |
| 2269 } | |
| 2270 | |
| 2271 @override | |
| 2272 ir.Primitive buildInstanceNoSuchMethod(Selector selector, | |
| 2273 List<ir.Primitive> arguments) { | |
| 2274 return giveup(null, 'Instance noSuchMethod'); | |
| 2275 } | |
| 2276 | |
| 2277 @override | |
| 2278 ir.Primitive buildRuntimeError(String message) { | |
| 2279 return giveup(null, 'Build runtime error: $message'); | |
| 2280 } | |
| 2281 | |
| 2282 @override | |
| 2283 ir.Primitive buildAbstractClassInstantiationError(ClassElement element) { | |
| 2284 return giveup(null, 'Abstract class instantiation: ${element.name}'); | |
| 2285 } | |
| 2286 | |
| 2287 ir.Primitive buildStaticFieldGet(FieldElement field, SourceInformation src) { | |
| 2288 return irBuilder.buildStaticFieldLazyGet(field, src); | |
| 2289 } | |
| 2290 } | |
| 2291 | |
| 2292 /// The [IrBuilder]s view on the information about the program that has been | 1986 /// The [IrBuilder]s view on the information about the program that has been |
| 2293 /// computed in resolution and and type interence. | 1987 /// computed in resolution and and type interence. |
| 2294 class GlobalProgramInformation { | 1988 class GlobalProgramInformation { |
| 2295 final Compiler _compiler; | 1989 final Compiler _compiler; |
| 2296 JavaScriptBackend get _backend => _compiler.backend; | 1990 JavaScriptBackend get _backend => _compiler.backend; |
| 2297 | 1991 |
| 2298 GlobalProgramInformation(this._compiler); | 1992 GlobalProgramInformation(this._compiler); |
| 2299 | 1993 |
| 2300 /// Returns [true], if the analysis could not determine that the type | 1994 /// Returns [true], if the analysis could not determine that the type |
| 2301 /// arguments for the class [cls] are never used in the program. | 1995 /// arguments for the class [cls] are never used in the program. |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2403 function, | 2097 function, |
| 2404 function.node, | 2098 function.node, |
| 2405 elements); | 2099 elements); |
| 2406 closurelib.ClosureScope scope = map.capturingScopes[function.node]; | 2100 closurelib.ClosureScope scope = map.capturingScopes[function.node]; |
| 2407 if (scope == null) return null; | 2101 if (scope == null) return null; |
| 2408 return new ClosureScope(scope.boxElement, | 2102 return new ClosureScope(scope.boxElement, |
| 2409 mapValues(scope.capturedVariables, getLocation), | 2103 mapValues(scope.capturedVariables, getLocation), |
| 2410 scope.boxedLoopVariables); | 2104 scope.boxedLoopVariables); |
| 2411 } | 2105 } |
| 2412 | 2106 |
| 2413 ir.RootNode buildExecutable(ExecutableElement element) { | 2107 ir.FunctionDefinition buildExecutable(ExecutableElement element) { |
| 2414 return nullIfGiveup(() { | 2108 return nullIfGiveup(() { |
| 2415 ir.RootNode root; | 2109 ir.FunctionDefinition root; |
| 2416 switch (element.kind) { | 2110 switch (element.kind) { |
| 2417 case ElementKind.GENERATIVE_CONSTRUCTOR: | 2111 case ElementKind.GENERATIVE_CONSTRUCTOR: |
| 2418 root = buildConstructor(element); | 2112 root = buildConstructor(element); |
| 2419 break; | 2113 break; |
| 2420 | 2114 |
| 2421 case ElementKind.GENERATIVE_CONSTRUCTOR_BODY: | 2115 case ElementKind.GENERATIVE_CONSTRUCTOR_BODY: |
| 2422 root = buildConstructorBody(element); | 2116 root = buildConstructorBody(element); |
| 2423 break; | 2117 break; |
| 2424 | 2118 |
| 2425 case ElementKind.FUNCTION: | 2119 case ElementKind.FUNCTION: |
| (...skipping 25 matching lines...) Expand all Loading... |
| 2451 if (!backend.constants.lazyStatics.contains(element)) { | 2145 if (!backend.constants.lazyStatics.contains(element)) { |
| 2452 return null; // Nothing to do. | 2146 return null; // Nothing to do. |
| 2453 } | 2147 } |
| 2454 closureClassMap = | 2148 closureClassMap = |
| 2455 compiler.closureToClassMapper.computeClosureToClassMapping( | 2149 compiler.closureToClassMapper.computeClosureToClassMapping( |
| 2456 element, | 2150 element, |
| 2457 element.node, | 2151 element.node, |
| 2458 elements); | 2152 elements); |
| 2459 IrBuilder builder = getBuilderFor(element); | 2153 IrBuilder builder = getBuilderFor(element); |
| 2460 return withBuilder(builder, () { | 2154 return withBuilder(builder, () { |
| 2155 irBuilder.buildFunctionHeader(<Local>[]); |
| 2461 ir.Primitive initialValue = visit(element.initializer); | 2156 ir.Primitive initialValue = visit(element.initializer); |
| 2462 irBuilder.buildReturn(initialValue); | 2157 irBuilder.buildReturn(initialValue); |
| 2463 return irBuilder.makeLazyFieldInitializer(); | 2158 return irBuilder.makeFunctionDefinition(); |
| 2464 }); | 2159 }); |
| 2465 } | 2160 } |
| 2466 | 2161 |
| 2467 /// Builds the IR for an [expression] taken from a different [context]. | 2162 /// Builds the IR for an [expression] taken from a different [context]. |
| 2468 /// | 2163 /// |
| 2469 /// Such expressions need to be compiled with a different [sourceFile] and | 2164 /// Such expressions need to be compiled with a different [sourceFile] and |
| 2470 /// [elements] mapping. | 2165 /// [elements] mapping. |
| 2471 ir.Primitive inlineExpression(AstElement context, ast.Expression expression) { | 2166 ir.Primitive inlineExpression(AstElement context, ast.Expression expression) { |
| 2472 JsIrBuilderVisitor visitor = new JsIrBuilderVisitor( | 2167 JsIrBuilderVisitor visitor = new JsIrBuilderVisitor( |
| 2473 context.resolvedAst.elements, | 2168 context.resolvedAst.elements, |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2589 List<ir.Primitive> bodyArguments = <ir.Primitive>[]; | 2284 List<ir.Primitive> bodyArguments = <ir.Primitive>[]; |
| 2590 for (Local param in getConstructorBodyParameters(bodyElement)) { | 2285 for (Local param in getConstructorBodyParameters(bodyElement)) { |
| 2591 bodyArguments.add(irBuilder.environment.lookup(param)); | 2286 bodyArguments.add(irBuilder.environment.lookup(param)); |
| 2592 } | 2287 } |
| 2593 irBuilder.buildInvokeDirectly(bodyElement, instance, bodyArguments); | 2288 irBuilder.buildInvokeDirectly(bodyElement, instance, bodyArguments); |
| 2594 } | 2289 } |
| 2595 | 2290 |
| 2596 // --- step 4: return the created object ---- | 2291 // --- step 4: return the created object ---- |
| 2597 irBuilder.buildReturn(instance); | 2292 irBuilder.buildReturn(instance); |
| 2598 | 2293 |
| 2599 return irBuilder.makeFunctionDefinition([]); | 2294 return irBuilder.makeFunctionDefinition(); |
| 2600 }); | 2295 }); |
| 2601 } | 2296 } |
| 2602 | 2297 |
| 2603 /// Evaluates all field initializers on [constructor] and all constructors | 2298 /// Evaluates all field initializers on [constructor] and all constructors |
| 2604 /// invoked through `this()` or `super()` ("superconstructors"). | 2299 /// invoked through `this()` or `super()` ("superconstructors"). |
| 2605 /// | 2300 /// |
| 2606 /// The resulting field values will be available in [fieldValues]. The values | 2301 /// The resulting field values will be available in [fieldValues]. The values |
| 2607 /// are not stored in any fields. | 2302 /// are not stored in any fields. |
| 2608 /// | 2303 /// |
| 2609 /// This procedure assumes that the parameters to [constructor] are available | 2304 /// This procedure assumes that the parameters to [constructor] are available |
| (...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2873 // TODO(kmillikin): We should combine closure conversion and try/catch | 2568 // TODO(kmillikin): We should combine closure conversion and try/catch |
| 2874 // variable analysis in some way. | 2569 // variable analysis in some way. |
| 2875 DartCapturedVariables variables = _analyzeCapturedVariables(node); | 2570 DartCapturedVariables variables = _analyzeCapturedVariables(node); |
| 2876 tryStatements = variables.tryStatements; | 2571 tryStatements = variables.tryStatements; |
| 2877 JsIrBuilder builder = getBuilderFor(body); | 2572 JsIrBuilder builder = getBuilderFor(body); |
| 2878 | 2573 |
| 2879 return withBuilder(builder, () { | 2574 return withBuilder(builder, () { |
| 2880 irBuilder.buildConstructorBodyHeader(getConstructorBodyParameters(body), | 2575 irBuilder.buildConstructorBodyHeader(getConstructorBodyParameters(body), |
| 2881 getClosureScopeForNode(node)); | 2576 getClosureScopeForNode(node)); |
| 2882 visit(node.body); | 2577 visit(node.body); |
| 2883 return irBuilder.makeFunctionDefinition([]); | 2578 return irBuilder.makeFunctionDefinition(); |
| 2884 }); | 2579 }); |
| 2885 } | 2580 } |
| 2886 | 2581 |
| 2887 ir.FunctionDefinition buildFunction(FunctionElement element) { | 2582 ir.FunctionDefinition buildFunction(FunctionElement element) { |
| 2888 assert(invariant(element, element.isImplementation)); | 2583 assert(invariant(element, element.isImplementation)); |
| 2889 ast.FunctionExpression node = element.node; | 2584 ast.FunctionExpression node = element.node; |
| 2890 | 2585 |
| 2891 assert(!element.isSynthesized); | 2586 assert(!element.isSynthesized); |
| 2892 assert(node != null); | 2587 assert(node != null); |
| 2893 assert(elements[node] != null); | 2588 assert(elements[node] != null); |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2970 for (int i=0; i < callStructure.positionalArgumentCount; i++) { | 2665 for (int i=0; i < callStructure.positionalArgumentCount; i++) { |
| 2971 result.add(arguments[i]); | 2666 result.add(arguments[i]); |
| 2972 } | 2667 } |
| 2973 for (String argName in callStructure.getOrderedNamedArguments()) { | 2668 for (String argName in callStructure.getOrderedNamedArguments()) { |
| 2974 int nameIndex = callStructure.namedArguments.indexOf(argName); | 2669 int nameIndex = callStructure.namedArguments.indexOf(argName); |
| 2975 int translatedIndex = callStructure.positionalArgumentCount + nameIndex; | 2670 int translatedIndex = callStructure.positionalArgumentCount + nameIndex; |
| 2976 result.add(arguments[translatedIndex]); | 2671 result.add(arguments[translatedIndex]); |
| 2977 } | 2672 } |
| 2978 return result; | 2673 return result; |
| 2979 } | 2674 } |
| 2675 |
| 2980 @override | 2676 @override |
| 2981 ir.Primitive handleConstructorInvoke( | 2677 ir.Primitive handleConstructorInvoke( |
| 2982 ast.NewExpression node, | 2678 ast.NewExpression node, |
| 2983 ConstructorElement constructor, | 2679 ConstructorElement constructor, |
| 2984 DartType type, | 2680 DartType type, |
| 2985 ast.NodeList arguments, | 2681 ast.NodeList arguments, |
| 2986 CallStructure callStructure, | 2682 CallStructure callStructure, |
| 2987 _) { | 2683 _) { |
| 2988 List<ir.Primitive> arguments = | 2684 List<ir.Primitive> arguments = |
| 2989 node.send.arguments.mapToList(visit, growable:false); | 2685 node.send.arguments.mapToList(visit, growable:false); |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3071 if (expression != null && expression is ir.LetPrim) { | 2767 if (expression != null && expression is ir.LetPrim) { |
| 3072 ir.Primitive primitive = expression.primitive; | 2768 ir.Primitive primitive = expression.primitive; |
| 3073 if (primitive is ir.NonTailThrow) { | 2769 if (primitive is ir.NonTailThrow) { |
| 3074 _remover.visit(expression); | 2770 _remover.visit(expression); |
| 3075 return new ir.Throw(primitive.value.definition); | 2771 return new ir.Throw(primitive.value.definition); |
| 3076 } | 2772 } |
| 3077 } | 2773 } |
| 3078 return expression; | 2774 return expression; |
| 3079 } | 2775 } |
| 3080 | 2776 |
| 2777 processFunctionDefinition(ir.FunctionDefinition node) { |
| 2778 node.body = replacementFor(node.body); |
| 2779 } |
| 2780 |
| 3081 processLetPrim(ir.LetPrim node) { | 2781 processLetPrim(ir.LetPrim node) { |
| 3082 node.body = replacementFor(node.body); | 2782 node.body = replacementFor(node.body); |
| 3083 } | 2783 } |
| 3084 | 2784 |
| 3085 processLetCont(ir.LetCont node) { | 2785 processLetCont(ir.LetCont node) { |
| 3086 node.body = replacementFor(node.body); | 2786 node.body = replacementFor(node.body); |
| 3087 } | 2787 } |
| 3088 | 2788 |
| 3089 processLetHandler(ir.LetHandler node) { | 2789 processLetHandler(ir.LetHandler node) { |
| 3090 node.body = replacementFor(node.body); | 2790 node.body = replacementFor(node.body); |
| 3091 } | 2791 } |
| 3092 | 2792 |
| 3093 processLetMutable(ir.LetMutable node) { | 2793 processLetMutable(ir.LetMutable node) { |
| 3094 node.body = replacementFor(node.body); | 2794 node.body = replacementFor(node.body); |
| 3095 } | 2795 } |
| 3096 | 2796 |
| 3097 processSetMutableVariable(ir.SetMutableVariable node) { | 2797 processSetMutableVariable(ir.SetMutableVariable node) { |
| 3098 node.body = replacementFor(node.body); | 2798 node.body = replacementFor(node.body); |
| 3099 } | 2799 } |
| 3100 | 2800 |
| 3101 processDeclareFunction(ir.DeclareFunction node) { | |
| 3102 node.body = replacementFor(node.body); | |
| 3103 } | |
| 3104 | |
| 3105 processSetField(ir.SetField node) { | 2801 processSetField(ir.SetField node) { |
| 3106 node.body = replacementFor(node.body); | 2802 node.body = replacementFor(node.body); |
| 3107 } | 2803 } |
| 3108 | 2804 |
| 3109 processSetStatic(ir.SetStatic node) { | 2805 processSetStatic(ir.SetStatic node) { |
| 3110 node.body = replacementFor(node.body); | 2806 node.body = replacementFor(node.body); |
| 3111 } | 2807 } |
| 3112 | 2808 |
| 3113 processContinuation(ir.Continuation node) { | 2809 processContinuation(ir.Continuation node) { |
| 3114 node.body = replacementFor(node.body); | 2810 node.body = replacementFor(node.body); |
| 3115 } | 2811 } |
| 3116 | |
| 3117 processBody(ir.Body node) { | |
| 3118 node.body = replacementFor(node.body); | |
| 3119 } | |
| 3120 } | 2812 } |
| 3121 | 2813 |
| 3122 /// Visit a just-deleted subterm and unlink all [Reference]s in it. | 2814 /// Visit a just-deleted subterm and unlink all [Reference]s in it. |
| 3123 class RemovalVisitor extends ir.RecursiveVisitor { | 2815 class RemovalVisitor extends ir.RecursiveVisitor { |
| 3124 processReference(ir.Reference reference) { | 2816 processReference(ir.Reference reference) { |
| 3125 reference.unlink(); | 2817 reference.unlink(); |
| 3126 } | 2818 } |
| 3127 } | 2819 } |
| OLD | NEW |