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 |