Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(684)

Side by Side Diff: pkg/compiler/lib/src/cps_ir/cps_ir_builder_visitor.dart

Issue 862703002: Implement constructor bodies and initializers in CPS->JS backend. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Rename in analyzer2dart Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 part of dart2js.ir_builder; 5 part of dart2js.ir_builder;
6 6
7 /** 7 /**
8 * This task iterates through all resolved elements and builds [ir.Node]s. The 8 * This task iterates through all resolved elements and builds [ir.Node]s. The
9 * nodes are stored in the [nodes] map and accessible through [hasIr] and 9 * nodes are stored in the [nodes] map and accessible through [hasIr] and
10 * [getIr]. 10 * [getIr].
(...skipping 24 matching lines...) Expand all
35 return nodes[element.implementation]; 35 return nodes[element.implementation];
36 } 36 }
37 37
38 ir.ExecutableDefinition buildNode(AstElement element) { 38 ir.ExecutableDefinition buildNode(AstElement element) {
39 if (!canBuild(element)) return null; 39 if (!canBuild(element)) return null;
40 TreeElements elementsMapping = element.resolvedAst.elements; 40 TreeElements elementsMapping = element.resolvedAst.elements;
41 element = element.implementation; 41 element = element.implementation;
42 return compiler.withCurrentElement(element, () { 42 return compiler.withCurrentElement(element, () {
43 SourceFile sourceFile = elementSourceFile(element); 43 SourceFile sourceFile = elementSourceFile(element);
44 IrBuilderVisitor builder = 44 IrBuilderVisitor builder =
45 new IrBuilderVisitor(elementsMapping, compiler, sourceFile); 45 compiler.backend is JavaScriptBackend
46 ? new JsIrBuilderVisitor(elementsMapping, compiler, sourceFile)
47 : new DartIrBuilderVisitor(elementsMapping, compiler, sourceFile);
46 return builder.buildExecutable(element); 48 return builder.buildExecutable(element);
47 }); 49 });
48 } 50 }
49 51
50 void buildNodes() { 52 void buildNodes() {
51 measure(() { 53 measure(() {
52 Set<Element> resolved = compiler.enqueuer.resolution.resolvedElements; 54 Set<Element> resolved = compiler.enqueuer.resolution.resolvedElements;
53 resolved.forEach((AstElement element) { 55 resolved.forEach((AstElement element) {
54 ir.ExecutableDefinition definition = buildNode(element); 56 ir.ExecutableDefinition definition = buildNode(element);
55 if (definition != null) { 57 if (definition != null) {
(...skipping 19 matching lines...) Expand all
75 } 77 }
76 return compiler.backend.shouldOutput(element); 78 return compiler.backend.shouldOutput(element);
77 } 79 }
78 80
79 bool get inCheckedMode { 81 bool get inCheckedMode {
80 bool result = false; 82 bool result = false;
81 assert((result = true)); 83 assert((result = true));
82 return result; 84 return result;
83 } 85 }
84 86
85 SourceFile elementSourceFile(Element element) { 87 }
86 if (element is FunctionElement) { 88
87 FunctionElement functionElement = element; 89 SourceFile elementSourceFile(Element element) {
88 if (functionElement.patch != null) element = functionElement.patch; 90 if (element is FunctionElement) {
89 } 91 FunctionElement functionElement = element;
90 return element.compilationUnit.script.file; 92 if (functionElement.patch != null) element = functionElement.patch;
91 } 93 }
94 return element.compilationUnit.script.file;
92 } 95 }
93 96
94 class _GetterElements { 97 class _GetterElements {
95 ir.Primitive result; 98 ir.Primitive result;
96 ir.Primitive index; 99 ir.Primitive index;
97 ir.Primitive receiver; 100 ir.Primitive receiver;
98 101
99 _GetterElements({this.result, this.index, this.receiver}) ; 102 _GetterElements({this.result, this.index, this.receiver}) ;
100 } 103 }
101 104
102 /** 105 /**
103 * A tree visitor that builds [IrNodes]. The visit methods add statements using 106 * A tree visitor that builds [IrNodes]. The visit methods add statements using
104 * to the [builder] and return the last added statement for trees that represent 107 * to the [builder] and return the last added statement for trees that represent
105 * an expression. 108 * an expression.
106 */ 109 */
107 class IrBuilderVisitor extends ResolvedVisitor<ir.Primitive> 110 abstract class IrBuilderVisitor extends ResolvedVisitor<ir.Primitive>
108 with IrBuilderMixin<ast.Node> { 111 with IrBuilderMixin<ast.Node> {
109 final Compiler compiler; 112 final Compiler compiler;
110 final SourceFile sourceFile; 113 final SourceFile sourceFile;
111 ClosureClassMap closureMap;
112 114
113 // In SSA terms, join-point continuation parameters are the phis and the 115 // In SSA terms, join-point continuation parameters are the phis and the
114 // continuation invocation arguments are the corresponding phi inputs. To 116 // continuation invocation arguments are the corresponding phi inputs. To
115 // support name introduction and renaming for source level variables, we use 117 // support name introduction and renaming for source level variables, we use
116 // nested (delimited) visitors for constructing subparts of the IR that will 118 // nested (delimited) visitors for constructing subparts of the IR that will
117 // need renaming. Each source variable is assigned an index. 119 // need renaming. Each source variable is assigned an index.
118 // 120 //
119 // Each nested visitor maintains a list of free variable uses in the body. 121 // Each nested visitor maintains a list of free variable uses in the body.
120 // These are implemented as a list of parameters, each with their own use 122 // These are implemented as a list of parameters, each with their own use
121 // list of references. When the delimited subexpression is plugged into the 123 // list of references. When the delimited subexpression is plugged into the
122 // surrounding context, the free occurrences can be captured or become free 124 // surrounding context, the free occurrences can be captured or become free
123 // occurrences in the next outer delimited subexpression. 125 // occurrences in the next outer delimited subexpression.
124 // 126 //
125 // Each nested visitor maintains a list that maps indexes of variables 127 // Each nested visitor maintains a list that maps indexes of variables
126 // assigned in the delimited subexpression to their reaching definition --- 128 // assigned in the delimited subexpression to their reaching definition ---
127 // that is, the definition in effect at the hole in 'current'. These are 129 // that is, the definition in effect at the hole in 'current'. These are
128 // used to determine if a join-point continuation needs to be passed 130 // used to determine if a join-point continuation needs to be passed
129 // arguments, and what the arguments are. 131 // arguments, and what the arguments are.
130 132
131 /// Construct a top-level visitor. 133 /// Construct a top-level visitor.
132 IrBuilderVisitor(TreeElements elements, this.compiler, this.sourceFile) 134 IrBuilderVisitor(TreeElements elements, this.compiler, this.sourceFile)
133 : super(elements); 135 : super(elements);
134 136
135 /// True if using the JavaScript backend; we use this to determine how
136 /// closures should be translated.
137 bool get isJavaScriptBackend => compiler.backend is JavaScriptBackend;
138
139 /** 137 /**
140 * Builds the [ir.ExecutableDefinition] for an executable element. In case the 138 * Builds the [ir.ExecutableDefinition] for an executable element. In case the
141 * function uses features that cannot be expressed in the IR, this element 139 * function uses features that cannot be expressed in the IR, this element
142 * returns `null`. 140 * returns `null`.
143 */ 141 */
144 ir.ExecutableDefinition buildExecutable(ExecutableElement element) { 142 ir.ExecutableDefinition buildExecutable(ExecutableElement element);
145 return nullIfGiveup(() {
146 if (element is FieldElement) {
147 return buildField(element);
148 } else if (element is FunctionElement) {
149 return buildFunction(element);
150 } else {
151 compiler.internalError(element, "Unexpected element type $element");
152 }
153 });
154 }
155 143
156 Map mapValues(Map map, dynamic fn(dynamic)) { 144 ClosureScope getClosureScopeForNode(ast.Node node);
157 Map result = {}; 145 ClosureEnvironment getClosureEnvironment();
158 map.forEach((key,value) {
159 result[key] = fn(value);
160 });
161 return result;
162 }
163 146
164 // Converts closure.dart's CapturedVariable into a ClosureLocation.
165 // There is a 1:1 corresponce between these; we do this because the IR builder
166 // should not depend on synthetic elements.
167 ClosureLocation getLocation(CapturedVariable v) {
168 if (v is BoxFieldElement) {
169 return new ClosureLocation(v.box, v);
170 } else {
171 ClosureFieldElement field = v;
172 return new ClosureLocation(null, field);
173 }
174 }
175 147
176 /// If the current function is a nested function with free variables (or a
177 /// captured reference to `this`), this returns a [ClosureEnvironment]
178 /// indicating how to access these.
179 ClosureEnvironment getClosureEnvironment() {
180 if (closureMap == null) return null; // dart2dart does not use closureMap.
181 if (closureMap.closureElement == null) return null;
182 return new ClosureEnvironment(
183 closureMap.closureElement,
184 closureMap.thisLocal,
185 mapValues(closureMap.freeVariableMap, getLocation));
186 }
187
188 /// If [node] has declarations for variables that should be boxed, this
189 /// returns a [ClosureScope] naming a box to create, and enumerating the
190 /// variables that should be stored in the box.
191 ///
192 /// Also see [ClosureScope].
193 ClosureScope getClosureScope(ast.Node node) {
194 if (closureMap == null) return null; // dart2dart does not use closureMap.
195 closurelib.ClosureScope scope = closureMap.capturingScopes[node];
196 if (scope == null) return null;
197 // We translate a ClosureScope from closure.dart into IR builder's variant
198 // because the IR builder should not depend on the synthetic elements
199 // created in closure.dart.
200 return new ClosureScope(scope.boxElement,
201 mapValues(scope.capturedVariables, getLocation),
202 scope.boxedLoopVariables);
203 }
204
205 IrBuilder makeIRBuilder(ast.Node node, ExecutableElement element) {
206 if (isJavaScriptBackend) {
207 closureMap = compiler.closureToClassMapper.computeClosureToClassMapping(
208 element,
209 node,
210 elements);
211 return new JsIrBuilder(compiler.backend.constantSystem, element);
212 } else {
213 DetectClosureVariables closures = new DetectClosureVariables(elements);
214 if (!element.isSynthesized) {
215 closures.visit(node);
216 }
217 return new DartIrBuilder(compiler.backend.constantSystem,
218 element,
219 closures);
220 }
221 }
222
223 /// Returns a [ir.FieldDefinition] describing the initializer of [element].
224 ir.FieldDefinition buildField(FieldElement element) {
225 assert(invariant(element, element.isImplementation));
226 ast.VariableDefinitions definitions = element.node;
227 ast.Node fieldDefinition =
228 definitions.definitions.nodes.first;
229 if (definitions.modifiers.isConst) {
230 // TODO(sigurdm): Just return const value.
231 }
232 assert(fieldDefinition != null);
233 assert(elements[fieldDefinition] != null);
234
235 IrBuilder builder = makeIRBuilder(fieldDefinition, element);
236
237 return withBuilder(builder, () {
238 builder.buildFieldInitializerHeader(
239 closureScope: getClosureScope(fieldDefinition));
240 ir.Primitive initializer;
241 if (fieldDefinition is ast.SendSet) {
242 ast.SendSet sendSet = fieldDefinition;
243 initializer = visit(sendSet.arguments.first);
244 }
245 return builder.makeFieldDefinition(initializer);
246 });
247 }
248 148
249 ir.FunctionDefinition _makeFunctionBody(FunctionElement element, 149 ir.FunctionDefinition _makeFunctionBody(FunctionElement element,
250 ast.FunctionExpression node) { 150 ast.FunctionExpression node) {
251 FunctionSignature signature = element.functionSignature; 151 FunctionSignature signature = element.functionSignature;
252 List<ParameterElement> parameters = []; 152 List<ParameterElement> parameters = [];
253 signature.orderedForEachParameter(parameters.add); 153 signature.orderedForEachParameter(parameters.add);
254 154
255 irBuilder.buildFunctionHeader(parameters, 155 irBuilder.buildFunctionHeader(parameters,
256 closureScope: getClosureScope(node), 156 closureScope: getClosureScopeForNode(node),
257 closureEnvironment: getClosureEnvironment()); 157 env: getClosureEnvironment());
258 158
259 List<ConstantExpression> defaults = new List<ConstantExpression>(); 159 List<ConstantExpression> defaults = new List<ConstantExpression>();
260 signature.orderedOptionalParameters.forEach((ParameterElement element) { 160 signature.orderedOptionalParameters.forEach((ParameterElement element) {
261 defaults.add(getConstantForVariable(element)); 161 defaults.add(getConstantForVariable(element));
262 }); 162 });
263 163
264 List<ir.Initializer> initializers; 164 List<ir.Initializer> initializers;
265 if (element.isSynthesized) { 165 if (element.isSynthesized) {
266 assert(element is ConstructorElement); 166 assert(element is ConstructorElement);
267 return irBuilder.makeConstructorDefinition(const <ConstantExpression>[], 167 return irBuilder.makeConstructorDefinition(const <ConstantExpression>[],
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
345 "No default constructor available."); 245 "No default constructor available.");
346 } 246 }
347 result.add(irBuilder.makeSuperInitializer(target, 247 result.add(irBuilder.makeSuperInitializer(target,
348 <ir.RunnableBody>[], 248 <ir.RunnableBody>[],
349 selector)); 249 selector));
350 } 250 }
351 } 251 }
352 return result; 252 return result;
353 } 253 }
354 254
355 ir.FunctionDefinition buildFunction(FunctionElement element) {
356 assert(invariant(element, element.isImplementation));
357 ast.FunctionExpression node = element.node;
358
359 Iterable<Entity> usedFromClosure;
360 if (!element.isSynthesized) {
361 assert(node != null);
362 assert(elements[node] != null);
363 } else {
364 SynthesizedConstructorElementX constructor = element;
365 if (!constructor.isDefaultConstructor) {
366 giveup(null, 'cannot handle synthetic forwarding constructors');
367 }
368
369 usedFromClosure = <Entity>[];
370 }
371
372 IrBuilder builder = makeIRBuilder(node, element);
373
374 return withBuilder(builder, () => _makeFunctionBody(element, node));
375 }
376
377 ir.Primitive visit(ast.Node node) => node.accept(this); 255 ir.Primitive visit(ast.Node node) => node.accept(this);
378 256
379 // ==== Statements ==== 257 // ==== Statements ====
380 visitBlock(ast.Block node) { 258 visitBlock(ast.Block node) {
381 irBuilder.buildBlock(node.statements.nodes, build); 259 irBuilder.buildBlock(node.statements.nodes, build);
382 } 260 }
383 261
384 ir.Primitive visitBreakStatement(ast.BreakStatement node) { 262 ir.Primitive visitBreakStatement(ast.BreakStatement node) {
385 if (!irBuilder.buildBreak(elements.getTargetOf(node))) { 263 if (!irBuilder.buildBreak(elements.getTargetOf(node))) {
386 compiler.internalError(node, "'break' target not found"); 264 compiler.internalError(node, "'break' target not found");
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
418 loopVariables.add(loopVariable); 296 loopVariables.add(loopVariable);
419 } 297 }
420 } 298 }
421 299
422 JumpTarget target = elements.getTargetDefinition(node); 300 JumpTarget target = elements.getTargetDefinition(node);
423 irBuilder.buildFor( 301 irBuilder.buildFor(
424 buildInitializer: subbuild(node.initializer), 302 buildInitializer: subbuild(node.initializer),
425 buildCondition: subbuild(node.condition), 303 buildCondition: subbuild(node.condition),
426 buildBody: subbuild(node.body), 304 buildBody: subbuild(node.body),
427 buildUpdate: subbuildSequence(node.update), 305 buildUpdate: subbuildSequence(node.update),
428 closureScope: getClosureScope(node), 306 closureScope: getClosureScopeForNode(node),
429 loopVariables: loopVariables, 307 loopVariables: loopVariables,
430 target: target); 308 target: target);
431 } 309 }
432 310
433 visitIf(ast.If node) { 311 visitIf(ast.If node) {
434 irBuilder.buildIf( 312 irBuilder.buildIf(
435 build(node.condition), 313 build(node.condition),
436 subbuild(node.thenPart), 314 subbuild(node.thenPart),
437 subbuild(node.elsePart)); 315 subbuild(node.elsePart));
438 } 316 }
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
479 } 357 }
480 } 358 }
481 return null; 359 return null;
482 } 360 }
483 361
484 visitWhile(ast.While node) { 362 visitWhile(ast.While node) {
485 irBuilder.buildWhile( 363 irBuilder.buildWhile(
486 buildCondition: subbuild(node.condition), 364 buildCondition: subbuild(node.condition),
487 buildBody: subbuild(node.body), 365 buildBody: subbuild(node.body),
488 target: elements.getTargetDefinition(node), 366 target: elements.getTargetDefinition(node),
489 closureScope: getClosureScope(node)); 367 closureScope: getClosureScopeForNode(node));
490 } 368 }
491 369
492 visitForIn(ast.ForIn node) { 370 visitForIn(ast.ForIn node) {
493 // [node.declaredIdentifier] can be either an [ast.VariableDefinitions] 371 // [node.declaredIdentifier] can be either an [ast.VariableDefinitions]
494 // (defining a new local variable) or a send designating some existing 372 // (defining a new local variable) or a send designating some existing
495 // variable. 373 // variable.
496 ast.Node identifier = node.declaredIdentifier; 374 ast.Node identifier = node.declaredIdentifier;
497 ast.VariableDefinitions variableDeclaration = 375 ast.VariableDefinitions variableDeclaration =
498 identifier.asVariableDefinitions(); 376 identifier.asVariableDefinitions();
499 Element variableElement = elements.getForInVariable(node); 377 Element variableElement = elements.getForInVariable(node);
500 Selector selector = elements.getSelector(identifier); 378 Selector selector = elements.getSelector(identifier);
501 379
502 irBuilder.buildForIn( 380 irBuilder.buildForIn(
503 buildExpression: subbuild(node.expression), 381 buildExpression: subbuild(node.expression),
504 buildVariableDeclaration: subbuild(variableDeclaration), 382 buildVariableDeclaration: subbuild(variableDeclaration),
505 variableElement: variableElement, 383 variableElement: variableElement,
506 variableSelector: selector, 384 variableSelector: selector,
507 buildBody: subbuild(node.body), 385 buildBody: subbuild(node.body),
508 target: elements.getTargetDefinition(node), 386 target: elements.getTargetDefinition(node),
509 closureScope: getClosureScope(node)); 387 closureScope: getClosureScopeForNode(node));
510 } 388 }
511 389
512 ir.Primitive visitVariableDefinitions(ast.VariableDefinitions node) { 390 ir.Primitive visitVariableDefinitions(ast.VariableDefinitions node) {
513 assert(irBuilder.isOpen); 391 assert(irBuilder.isOpen);
514 if (node.modifiers.isConst) { 392 if (node.modifiers.isConst) {
515 for (ast.SendSet definition in node.definitions.nodes) { 393 for (ast.SendSet definition in node.definitions.nodes) {
516 assert(!definition.arguments.isEmpty); 394 assert(!definition.arguments.isEmpty);
517 assert(definition.arguments.tail.isEmpty); 395 assert(definition.arguments.tail.isEmpty);
518 VariableElement element = elements[definition]; 396 VariableElement element = elements[definition];
519 ConstantExpression value = getConstantForVariable(element); 397 ConstantExpression value = getConstantForVariable(element);
(...skipping 491 matching lines...) Expand 10 before | Expand all | Expand 10 after
1011 } 889 }
1012 890
1013 ir.Primitive translateConstant(ast.Node node, [ConstantExpression constant]) { 891 ir.Primitive translateConstant(ast.Node node, [ConstantExpression constant]) {
1014 assert(irBuilder.isOpen); 892 assert(irBuilder.isOpen);
1015 if (constant == null) { 893 if (constant == null) {
1016 constant = getConstantForNode(node); 894 constant = getConstantForNode(node);
1017 } 895 }
1018 return irBuilder.buildConstantLiteral(constant); 896 return irBuilder.buildConstantLiteral(constant);
1019 } 897 }
1020 898
1021 /// Returns the backend-specific representation of an inner function.
1022 Object makeSubFunction(ast.FunctionExpression node) {
1023 if (isJavaScriptBackend) {
1024 ClosureClassMap innerMap =
1025 compiler.closureToClassMapper.getMappingForNestedFunction(node);
1026 ClosureClassElement closureClass = innerMap.closureClassElement;
1027 return closureClass;
1028 } else {
1029 FunctionElement element = elements[node];
1030 assert(invariant(element, element.isImplementation));
1031
1032 IrBuilder builder = irBuilder.makeInnerFunctionBuilder(element);
1033
1034 return withBuilder(builder, () => _makeFunctionBody(element, node));
1035 }
1036 }
1037
1038 ir.Primitive visitFunctionExpression(ast.FunctionExpression node) {
1039 return irBuilder.buildFunctionExpression(makeSubFunction(node));
1040 }
1041
1042 visitFunctionDeclaration(ast.FunctionDeclaration node) {
1043 LocalFunctionElement element = elements[node.function];
1044 Object inner = makeSubFunction(node.function);
1045 irBuilder.declareLocalFunction(element, inner);
1046 }
1047
1048 ir.ExecutableDefinition nullIfGiveup(ir.ExecutableDefinition action()) { 899 ir.ExecutableDefinition nullIfGiveup(ir.ExecutableDefinition action()) {
1049 try { 900 try {
1050 return action(); 901 return action();
1051 } catch(e, tr) { 902 } catch(e, tr) {
1052 if (e == ABORT_IRNODE_BUILDER) { 903 if (e == ABORT_IRNODE_BUILDER) {
1053 return null; 904 return null;
1054 } 905 }
1055 rethrow; 906 rethrow;
1056 } 907 }
1057 } 908 }
1058 909
1059 void internalError(String reason, {ast.Node node}) { 910 void internalError(String reason, {ast.Node node}) {
1060 giveup(node); 911 giveup(node);
1061 } 912 }
1062 } 913 }
1063 914
1064 final String ABORT_IRNODE_BUILDER = "IrNode builder aborted"; 915 final String ABORT_IRNODE_BUILDER = "IrNode builder aborted";
1065 916
1066 dynamic giveup(ast.Node node, [String reason]) { 917 dynamic giveup(ast.Node node, [String reason]) {
1067 throw ABORT_IRNODE_BUILDER; 918 throw ABORT_IRNODE_BUILDER;
1068 } 919 }
1069 920
1070 /// Classifies local variables and local functions as captured, if they 921 /// Classifies local variables and local functions as captured, if they
1071 /// are accessed from within a nested function. 922 /// are accessed from within a nested function.
1072 /// 923 ///
1073 /// This class is specific to the [DartIrBuilder], in that it gives up if it 924 /// This class is specific to the [DartIrBuilder], in that it gives up if it
1074 /// sees a feature that is currently unsupport by that builder. In particular, 925 /// sees a feature that is currently unsupport by that builder. In particular,
1075 /// loop variables captured in a for-loop initializer, condition, or update 926 /// loop variables captured in a for-loop initializer, condition, or update
1076 /// expression are unsupported. 927 /// expression are unsupported.
1077 class DetectClosureVariables extends ast.Visitor 928 class DartCapturedVariables extends ast.Visitor
1078 implements ClosureVariableInfo { 929 implements DartCapturedVariableInfo {
1079 final TreeElements elements; 930 final TreeElements elements;
1080 DetectClosureVariables(this.elements); 931 DartCapturedVariables(this.elements);
1081 932
1082 FunctionElement currentFunction; 933 FunctionElement currentFunction;
1083 bool insideInitializer = false; 934 bool insideInitializer = false;
1084 Set<Local> capturedVariables = new Set<Local>(); 935 Set<Local> capturedVariables = new Set<Local>();
1085 936
1086 void markAsClosureVariable(Local local) { 937 void markAsCaptured(Local local) {
1087 capturedVariables.add(local); 938 capturedVariables.add(local);
1088 } 939 }
1089 940
1090 visit(ast.Node node) => node.accept(this); 941 visit(ast.Node node) => node.accept(this);
1091 942
1092 visitNode(ast.Node node) { 943 visitNode(ast.Node node) {
1093 node.visitChildren(this); 944 node.visitChildren(this);
1094 } 945 }
1095 946
1096 visitFor(ast.For node) { 947 visitFor(ast.For node) {
(...skipping 14 matching lines...) Expand all
1111 962
1112 if (node.body != null) visit(node.body); 963 if (node.body != null) visit(node.body);
1113 } 964 }
1114 965
1115 void handleSend(ast.Send node) { 966 void handleSend(ast.Send node) {
1116 Element element = elements[node]; 967 Element element = elements[node];
1117 if (Elements.isLocal(element) && 968 if (Elements.isLocal(element) &&
1118 !element.isConst && 969 !element.isConst &&
1119 element.enclosingElement != currentFunction) { 970 element.enclosingElement != currentFunction) {
1120 LocalElement local = element; 971 LocalElement local = element;
1121 markAsClosureVariable(local); 972 markAsCaptured(local);
1122 } 973 }
1123 } 974 }
1124 975
1125 visitSend(ast.Send node) { 976 visitSend(ast.Send node) {
1126 handleSend(node); 977 handleSend(node);
1127 node.visitChildren(this); 978 node.visitChildren(this);
1128 } 979 }
1129 980
1130 visitSendSet(ast.SendSet node) { 981 visitSendSet(ast.SendSet node) {
1131 handleSend(node); 982 handleSend(node);
1132 Element element = elements[node]; 983 Element element = elements[node];
1133 // Initializers in an initializer-list can communicate via parameters. 984 // Initializers in an initializer-list can communicate via parameters.
1134 // If a parameter is stored in an initializer list we box it. 985 // If a parameter is stored in an initializer list we box it.
1135 if (insideInitializer && 986 if (insideInitializer &&
1136 Elements.isLocal(element) && 987 Elements.isLocal(element) &&
1137 element.isParameter) { 988 element.isParameter) {
1138 LocalElement local = element; 989 LocalElement local = element;
1139 // TODO(sigurdm): Fix this. 990 // TODO(sigurdm): Fix this.
1140 // Though these variables do not outlive the activation of the function, 991 // Though these variables do not outlive the activation of the function,
1141 // they still need to be boxed. As a simplification, we treat them as if 992 // they still need to be boxed. As a simplification, we treat them as if
1142 // they are captured by a closure (i.e., they do outlive the activation of 993 // they are captured by a closure (i.e., they do outlive the activation of
1143 // the function). 994 // the function).
1144 markAsClosureVariable(local); 995 markAsCaptured(local);
1145 } 996 }
1146 node.visitChildren(this); 997 node.visitChildren(this);
1147 } 998 }
1148 999
1149 visitFunctionExpression(ast.FunctionExpression node) { 1000 visitFunctionExpression(ast.FunctionExpression node) {
1150 FunctionElement oldFunction = currentFunction; 1001 FunctionElement oldFunction = currentFunction;
1151 currentFunction = elements[node]; 1002 currentFunction = elements[node];
1152 if (node.initializers != null) { 1003 if (node.initializers != null) {
1153 insideInitializer = true; 1004 insideInitializer = true;
1154 visit(node.initializers); 1005 visit(node.initializers);
1155 insideInitializer = false; 1006 insideInitializer = false;
1156 } 1007 }
1157 visit(node.body); 1008 visit(node.body);
1158 currentFunction = oldFunction; 1009 currentFunction = oldFunction;
1159 } 1010 }
1160 } 1011 }
1012
1013 /// IR builder specific to the Dart backend, coupled to the [DartIrBuilder].
1014 class DartIrBuilderVisitor extends IrBuilderVisitor {
1015 /// Promote the type of [irBuilder] to [DartIrBuilder].
1016 DartIrBuilder get irBuilder => super.irBuilder;
1017
1018 DartIrBuilderVisitor(TreeElements elements,
1019 Compiler compiler,
1020 SourceFile sourceFile)
1021 : super(elements, compiler, sourceFile);
1022
1023 DartIrBuilder makeIRBuilder(ast.Node node, ExecutableElement element) {
1024 DartCapturedVariables closures = new DartCapturedVariables(elements);
1025 if (!element.isSynthesized) {
1026 closures.visit(node);
1027 }
1028 return new DartIrBuilder(compiler.backend.constantSystem,
1029 element,
1030 closures);
1031 }
1032
1033 /// Recursively builds the IR for the given nested function.
1034 ir.FunctionDefinition makeSubFunction(ast.FunctionExpression node) {
1035 FunctionElement element = elements[node];
1036 assert(invariant(element, element.isImplementation));
1037
1038 IrBuilder builder = irBuilder.makeInnerFunctionBuilder(element);
1039
1040 return withBuilder(builder, () => _makeFunctionBody(element, node));
1041 }
1042
1043 ir.Primitive visitFunctionExpression(ast.FunctionExpression node) {
1044 return irBuilder.buildFunctionExpression(makeSubFunction(node));
1045 }
1046
1047 visitFunctionDeclaration(ast.FunctionDeclaration node) {
1048 LocalFunctionElement element = elements[node.function];
1049 Object inner = makeSubFunction(node.function);
1050 irBuilder.declareLocalFunction(element, inner);
1051 }
1052
1053 ClosureScope getClosureScopeForNode(ast.Node node) => null;
1054 ClosureEnvironment getClosureEnvironment() => null;
1055
1056 ir.ExecutableDefinition buildExecutable(ExecutableElement element) {
1057 return nullIfGiveup(() {
1058 if (element is FieldElement) {
1059 return buildField(element);
1060 } else if (element is FunctionElement) {
1061 return buildFunction(element);
1062 } else {
1063 compiler.internalError(element, "Unexpected element type $element");
1064 }
1065 });
1066 }
1067
1068 /// Returns a [ir.FieldDefinition] describing the initializer of [element].
1069 ir.FieldDefinition buildField(FieldElement element) {
1070 assert(invariant(element, element.isImplementation));
1071 ast.VariableDefinitions definitions = element.node;
1072 ast.Node fieldDefinition = definitions.definitions.nodes.first;
1073 if (definitions.modifiers.isConst) {
1074 // TODO(sigurdm): Just return const value.
1075 }
1076 assert(fieldDefinition != null);
1077 assert(elements[fieldDefinition] != null);
1078
1079 IrBuilder builder = makeIRBuilder(fieldDefinition, element);
1080
1081 return withBuilder(builder, () {
1082 builder.buildFieldInitializerHeader(
1083 closureScope: getClosureScopeForNode(fieldDefinition));
1084 ir.Primitive initializer;
1085 if (fieldDefinition is ast.SendSet) {
1086 ast.SendSet sendSet = fieldDefinition;
1087 initializer = visit(sendSet.arguments.first);
1088 }
1089 return builder.makeFieldDefinition(initializer);
1090 });
1091 }
1092
1093 ir.FunctionDefinition buildFunction(FunctionElement element) {
1094 assert(invariant(element, element.isImplementation));
1095 ast.FunctionExpression node = element.node;
1096
1097 if (!element.isSynthesized) {
1098 assert(node != null);
1099 assert(elements[node] != null);
1100 } else {
1101 SynthesizedConstructorElementX constructor = element;
1102 if (!constructor.isDefaultConstructor) {
1103 giveup(null, 'cannot handle synthetic forwarding constructors');
1104 }
1105 }
1106
1107 IrBuilder builder = makeIRBuilder(node, element);
1108
1109 return withBuilder(builder, () => _makeFunctionBody(element, node));
1110 }
1111 }
1112
1113 /// IR builder specific to the JavaScript backend, coupled to the [JsIrBuilder].
1114 class JsIrBuilderVisitor extends IrBuilderVisitor {
1115 /// Promote the type of [irBuilder] to [JsIrBuilder].
1116 JsIrBuilder get irBuilder => super.irBuilder;
1117 ClosureClassMap closureMap;
floitsch 2015/01/22 10:36:01 Add a small comment what this is and where it come
asgerf 2015/01/22 10:58:29 Done.
1118
1119 /// During construction of a constructor factory, [fieldValues] maps fields
1120 /// to the primitive containing their initial value.
1121 Map<FieldElement, ir.Primitive> fieldValues = <FieldElement, ir.Primitive>{};
1122
1123 JsIrBuilderVisitor(TreeElements elements,
1124 Compiler compiler,
1125 SourceFile sourceFile)
1126 : super(elements, compiler, sourceFile);
1127
1128 /// Builds the IR for creating an instance of the closure class corresponding
1129 /// to the given nested function.
1130 ClosureClassElement makeSubFunction(ast.FunctionExpression node) {
1131 ClosureClassMap innerMap =
1132 compiler.closureToClassMapper.getMappingForNestedFunction(node);
1133 ClosureClassElement closureClass = innerMap.closureClassElement;
1134 return closureClass;
1135 }
1136
1137 ir.Primitive visitFunctionExpression(ast.FunctionExpression node) {
1138 return irBuilder.buildFunctionExpression(makeSubFunction(node));
1139 }
1140
1141 visitFunctionDeclaration(ast.FunctionDeclaration node) {
1142 LocalFunctionElement element = elements[node.function];
1143 Object inner = makeSubFunction(node.function);
1144 irBuilder.declareLocalFunction(element, inner);
1145 }
1146
1147 Map mapValues(Map map, dynamic fn(dynamic)) {
1148 Map result = {};
1149 map.forEach((key, value) {
1150 result[key] = fn(value);
1151 });
1152 return result;
1153 }
1154
1155 /// Converts closure.dart's CapturedVariable into a ClosureLocation.
1156 /// There is a 1:1 corresponce between these; we do this because the
1157 /// IR builder should not depend on synthetic elements.
1158 ClosureLocation getLocation(CapturedVariable v) {
1159 if (v is BoxFieldElement) {
1160 return new ClosureLocation(v.box, v);
1161 } else {
1162 ClosureFieldElement field = v;
1163 return new ClosureLocation(null, field);
1164 }
1165 }
1166
1167 /// If the current function is a nested function with free variables (or a
1168 /// captured reference to `this`), returns a [ClosureEnvironment]
1169 /// indicating how to access these.
1170 ClosureEnvironment getClosureEnvironment() {
1171 if (closureMap.closureElement == null) return null;
1172 return new ClosureEnvironment(
1173 closureMap.closureElement,
1174 closureMap.thisLocal,
1175 mapValues(closureMap.freeVariableMap, getLocation));
1176 }
1177
1178 /// If [node] has declarations for variables that should be boxed,
1179 /// returns a [ClosureScope] naming a box to create, and enumerating the
1180 /// variables that should be stored in the box.
1181 ///
1182 /// Also see [ClosureScope].
1183 ClosureScope getClosureScopeForNode(ast.Node node) {
1184 closurelib.ClosureScope scope = closureMap.capturingScopes[node];
1185 if (scope == null) return null;
1186 // We translate a ClosureScope from closure.dart into IR builder's variant
1187 // because the IR builder should not depend on the synthetic elements
1188 // created in closure.dart.
1189 return new ClosureScope(scope.boxElement,
1190 mapValues(scope.capturedVariables, getLocation),
1191 scope.boxedLoopVariables);
1192 }
1193
1194 /// Returns the [ClosureScope] for any function, possibly different from the
1195 /// one currently being built.
1196 ClosureScope getClosureScopeForFunction(FunctionElement function) {
1197 ClosureClassMap map =
1198 compiler.closureToClassMapper.computeClosureToClassMapping(
1199 function,
1200 function.node,
1201 elements);
1202 closurelib.ClosureScope scope = map.capturingScopes[function.node];
1203 if (scope == null) return null;
1204 return new ClosureScope(scope.boxElement,
1205 mapValues(scope.capturedVariables, getLocation),
1206 scope.boxedLoopVariables);
1207 }
1208
1209 ir.ExecutableDefinition buildExecutable(ExecutableElement element) {
1210 return nullIfGiveup(() {
1211 switch (element.kind) {
1212 case ElementKind.GENERATIVE_CONSTRUCTOR:
1213 return buildConstructor(element);
1214
1215 case ElementKind.GENERATIVE_CONSTRUCTOR_BODY:
1216 return buildConstructorBody(element);
1217
1218 case ElementKind.FUNCTION:
1219 case ElementKind.GETTER:
1220 case ElementKind.SETTER:
1221 return buildFunction(element);
1222
1223 default:
1224 compiler.internalError(element, "Unexpected element type $element");
1225 }
1226 });
1227 }
1228
1229 /// Builds the IR for an [expression] taken from a different [context].
1230 ///
1231 /// Such expressions need to be compiled with a different [sourceFile] and
1232 /// [elements] mapping.
1233 ir.Primitive inlineExpression(AstElement context, ast.Expression expression) {
1234 JsIrBuilderVisitor visitor = new JsIrBuilderVisitor(
1235 context.resolvedAst.elements,
1236 compiler,
1237 elementSourceFile(context));
1238 return visitor.withBuilder(irBuilder, () => visitor.visit(expression));
1239 }
1240
1241 /// Builds the IR for a given constructor.
1242 ///
1243 /// 1. Evaluates all own or inherited field initializers.
1244 /// 2. Creates the object and assigns its fields.
1245 /// 3. Calls constructor body and super constructor bodies.
1246 /// 4. Returns the created object.
1247 ir.FunctionDefinition buildConstructor(ConstructorElement constructor) {
1248 constructor = constructor.implementation;
1249 ClassElement classElement = constructor.enclosingClass.implementation;
1250
1251 JsIrBuilder builder =
1252 new JsIrBuilder(compiler.backend.constantSystem, constructor);
1253
1254 return withBuilder(builder, () {
1255 // Setup parameters and create a box if anything is captured.
1256 List<ParameterElement> parameters = [];
1257 constructor.functionSignature.orderedForEachParameter(parameters.add);
1258 builder.buildFunctionHeader(parameters,
1259 closureScope: getClosureScopeForFunction(constructor));
1260
1261 // -- Step 1: evaluate field initializers ---
1262 // Evaluate field initializers in constructor and super constructors.
1263 List<ConstructorElement> constructorList = <ConstructorElement>[];
1264 evaluateConstructorFieldInitializers(constructor, constructorList);
1265
1266 // All parameters in all constructors are now bound in the environment.
1267 // BoxLocals for captured parameters are also in the environment.
1268 // The initial value of all fields are now bound in [fieldValues].
1269
1270 // --- Step 2: create the object ---
1271 // Get the initial field values in the canonical order.
1272 List<ir.Primitive> instanceArguments = <ir.Primitive>[];
1273 classElement.forEachInstanceField((ClassElement c, FieldElement field) {
1274 ir.Primitive value = fieldValues[field];
1275 if (value != null) {
1276 instanceArguments.add(fieldValues[field]);
1277 } else {
1278 assert(Elements.isNativeOrExtendsNative(c));
1279 // Native fields are initialized elsewhere.
1280 }
1281 }, includeSuperAndInjectedMembers: true);
1282 ir.Primitive instance =
1283 new ir.CreateInstance(classElement, instanceArguments);
1284 irBuilder.add(new ir.LetPrim(instance));
1285
1286 // --- Step 3: call constructor bodies ---
1287 for (ConstructorElement target in constructorList) {
1288 ConstructorBodyElement bodyElement = getConstructorBody(target);
1289 if (bodyElement == null) continue; // Skip if constructor has no body.
1290 List<ir.Primitive> bodyArguments = <ir.Primitive>[];
1291 for (Local param in getConstructorBodyParameters(bodyElement)) {
1292 bodyArguments.add(irBuilder.environment.lookup(param));
1293 }
1294 irBuilder.buildInvokeDirectly(bodyElement, instance, bodyArguments);
1295 }
1296
1297 // --- step 4: return the created object ----
1298 irBuilder.buildReturn(instance);
1299
1300 return irBuilder.makeFunctionDefinition([]);
1301 });
1302 }
1303
1304 /// Evaluates all field initializers on [constructor] and all constructors
1305 /// invoked through `this()` or `super()` ("superconstructors").
1306 ///
1307 /// The resulting field values will be available in [fieldValues]. The values
1308 /// are not stored in any fields.
1309 ///
1310 /// This procedure assumes that the parameters to [constructor] are available
1311 /// in the IR builder's environment.
1312 ///
1313 /// The parameters to superconstructors are, however, assumed *not* to be in
1314 /// the environment, but will be put there by this procedure.
1315 ///
1316 /// All constructors will be added to [supers], with superconstructors first.
1317 void evaluateConstructorFieldInitializers(ConstructorElement constructor,
1318 List<ConstructorElement> supers) {
1319 // Evaluate declaration-site field initializers.
1320 ClassElement enclosingClass = constructor.enclosingClass.implementation;
1321 enclosingClass.forEachInstanceField((ClassElement _, FieldElement field) {
1322 if (field.initializer != null) {
1323 fieldValues[field] = inlineExpression(field, field.initializer);
1324 } else {
1325 if (Elements.isNativeOrExtendsNative(enclosingClass)) {
1326 // Native field is initialized elsewhere.
1327 } else {
1328 // Fields without an initializer default to null.
1329 // This value will be overwritten below if an initializer is found.
1330 fieldValues[field] = irBuilder.buildNullLiteral();
1331 }
1332 }
1333 });
1334 // Evaluate initializing parameters, e.g. `Foo(this.x)`.
1335 constructor.functionSignature.orderedForEachParameter(
1336 (ParameterElement parameter) {
1337 if (parameter.isInitializingFormal) {
1338 InitializingFormalElement fieldParameter = parameter;
1339 fieldValues[fieldParameter.fieldElement] =
1340 irBuilder.buildLocalGet(parameter);
1341 }
1342 });
1343 // Evaluate constructor initializers, e.g. `Foo() : x = 50`.
1344 ast.FunctionExpression node = constructor.node;
1345 bool hasConstructorCall = false; // Has this() or super() initializer?
1346 if (node != null && node.initializers != null) {
1347 for(ast.Node initializer in node.initializers) {
1348 if (initializer is ast.SendSet) {
1349 // Field initializer.
1350 FieldElement field = elements[initializer];
1351 fieldValues[field] =
1352 inlineExpression(constructor, initializer.arguments.head);
1353 } else if (initializer is ast.Send) {
1354 // Super or this initializer.
1355 ConstructorElement target = elements[initializer].implementation;
1356 Selector selector = elements.getSelector(initializer);
1357 List<ir.Primitive> arguments = initializer.arguments.mapToList(visit);
1358 loadArguments(target, selector, arguments);
1359 evaluateConstructorFieldInitializers(target, supers);
1360 hasConstructorCall = true;
1361 } else {
1362 compiler.internalError(initializer,
1363 "Unexpected initializer type $initializer");
1364 }
1365 }
1366 }
1367 // If no super() or this() was found, also call default superconstructor.
1368 if (!hasConstructorCall && !enclosingClass.isObject) {
1369 ClassElement superClass = enclosingClass.superclass;
1370 Selector selector =
1371 new Selector.callDefaultConstructor(enclosingClass.library);
1372 FunctionElement target = superClass.lookupConstructor(selector);
1373 if (target == null) {
1374 compiler.internalError(superClass, "No default constructor available.");
1375 }
1376 evaluateConstructorFieldInitializers(target, supers);
1377 }
1378 // Add this constructor after the superconstructors.
1379 supers.add(constructor);
1380 }
1381
1382 /// In preparation of inlining (part of) [target], the [arguments] are moved
1383 /// into the environment bindings for the corresponding parameters.
1384 ///
1385 /// Defaults for optional arguments are evaluated in order to ensure
1386 /// all parameters are available in the environment.
1387 void loadArguments(FunctionElement target,
1388 Selector selector,
1389 List<ir.Primitive> arguments) {
1390 target = target.implementation;
1391 FunctionSignature signature = target.functionSignature;
1392
1393 // Establish a scope in case parameters are captured.
1394 ClosureScope scope = getClosureScopeForFunction(target);
1395 irBuilder._enterScope(scope);
1396
1397 // Load required parameters
1398 int index = 0;
1399 signature.forEachRequiredParameter((ParameterElement param) {
1400 irBuilder.declareLocalVariable(param, initialValue: arguments[index]);
1401 index++;
1402 });
1403
1404 // Load optional parameters, evaluating default values for omitted ones.
1405 signature.forEachOptionalParameter((ParameterElement param) {
1406 ir.Primitive value;
1407 // Load argument if provided.
1408 if (signature.optionalParametersAreNamed) {
1409 int translatedIndex = selector.namedArguments.indexOf(param.name);
1410 if (translatedIndex != -1) {
1411 value = arguments[translatedIndex];
1412 }
1413 } else if (index < arguments.length) {
1414 value = arguments[index];
1415 }
1416 // Load default if argument was not provided.
1417 if (value == null) {
1418 if (param.initializer != null) {
1419 value = visit(param.initializer);
1420 } else {
1421 value = irBuilder.buildNullLiteral();
1422 }
1423 }
1424 irBuilder.declareLocalVariable(param, initialValue: value);
1425 index++;
1426 });
1427 }
1428
1429 /**
1430 * Returns the constructor body associated with the given constructor or
1431 * creates a new constructor body, if none can be found.
1432 *
1433 * Returns `null` if the constructor does not have a body.
1434 */
1435 ConstructorBodyElement getConstructorBody(FunctionElement constructor) {
1436 // TODO(asgerf): This is largely inherited from the SSA builder.
1437 // The ConstructorBodyElement has an invalid function signature, but we
1438 // cannot add a BoxLocal as parameter, because BoxLocal is not an element.
1439 // Instead of forging ParameterElements to forge a FunctionSignature, we
1440 // need a way to create backend methods without creating more fake elements.
1441
1442 assert(constructor.isGenerativeConstructor);
1443 assert(invariant(constructor, constructor.isImplementation));
1444 if (constructor.isSynthesized) return null;
1445 ast.FunctionExpression node = constructor.node;
1446 // If we know the body doesn't have any code, we don't generate it.
1447 if (!node.hasBody()) return null;
1448 if (node.hasEmptyBody()) return null;
1449 ClassElement classElement = constructor.enclosingClass;
1450 ConstructorBodyElement bodyElement;
1451 classElement.forEachBackendMember((Element backendMember) {
1452 if (backendMember.isGenerativeConstructorBody) {
1453 ConstructorBodyElement body = backendMember;
1454 if (body.constructor == constructor) {
1455 bodyElement = backendMember;
1456 }
1457 }
1458 });
1459 if (bodyElement == null) {
1460 bodyElement = new ConstructorBodyElementX(constructor);
1461 classElement.addBackendMember(bodyElement);
1462
1463 if (constructor.isPatch) {
1464 // Create origin body element for patched constructors.
1465 ConstructorBodyElementX patch = bodyElement;
1466 ConstructorBodyElementX origin =
1467 new ConstructorBodyElementX(constructor.origin);
1468 origin.applyPatch(patch);
1469 classElement.origin.addBackendMember(bodyElement.origin);
1470 }
1471 }
1472 assert(bodyElement.isGenerativeConstructorBody);
1473 return bodyElement;
1474 }
1475
1476 /// The list of parameters to send from the generative constructor
1477 /// to the generative constructor body.
1478 ///
1479 /// Boxed parameters are not in the list, instead, a [BoxLocal] is passed
1480 /// containing the boxed parameters.
1481 ///
1482 /// For example, given the following constructor,
1483 ///
1484 /// Foo(x, y) : field = (() => ++x) { print(x + y) }
1485 ///
1486 /// the argument `x` would be replaced by a [BoxLocal]:
1487 ///
1488 /// Foo_body(box0, y) { print(box0.x + y) }
1489 ///
1490 List<Local> getConstructorBodyParameters(ConstructorBodyElement body) {
1491 List<Local> parameters = <Local>[];
1492 ClosureScope scope = getClosureScopeForFunction(body.constructor);
1493 if (scope != null) {
1494 parameters.add(scope.box);
1495 }
1496 body.functionSignature.orderedForEachParameter((ParameterElement param) {
1497 if (scope != null && scope.capturedVariables.containsKey(param)) {
1498 // Do not pass this parameter; the box will carry its value.
1499 } else {
1500 parameters.add(param);
1501 }
1502 });
1503 return parameters;
1504 }
1505
1506 /// Builds the IR for the body of a constructor.
1507 ///
1508 /// This function is invoked from one or more "factory" constructors built by
1509 /// [buildConstructor].
1510 ir.FunctionDefinition buildConstructorBody(ConstructorBodyElement body) {
1511 ConstructorElement constructor = body.constructor;
1512 ast.FunctionExpression node = constructor.node;
1513 closureMap = compiler.closureToClassMapper.computeClosureToClassMapping(
1514 constructor,
1515 node,
1516 elements);
1517
1518 JsIrBuilder builder =
1519 new JsIrBuilder(compiler.backend.constantSystem, body);
1520
1521 return withBuilder(builder, () {
1522 irBuilder.buildConstructorBodyHeader(getConstructorBodyParameters(body),
1523 getClosureScopeForNode(node));
1524 visit(node.body);
1525 return irBuilder.makeFunctionDefinition([]);
1526 });
1527 }
1528
1529 ir.FunctionDefinition buildFunction(FunctionElement element) {
1530 assert(invariant(element, element.isImplementation));
1531 ast.FunctionExpression node = element.node;
1532
1533 assert(!element.isSynthesized);
1534 assert(node != null);
1535 assert(elements[node] != null);
1536
1537 closureMap = compiler.closureToClassMapper.computeClosureToClassMapping(
1538 element,
1539 node,
1540 elements);
1541 IrBuilder builder =
1542 new JsIrBuilder(compiler.backend.constantSystem, element);
1543 return withBuilder(builder, () => _makeFunctionBody(element, node));
1544 }
1545
1546 }
1547
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart ('k') | pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698