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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/ir/ir_builder.dart

Issue 312793002: dart2dart: Preserve variable names throughout the IR. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Removed Definition.binding Created 6 years, 6 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 library dart2js.ir_builder; 5 library dart2js.ir_builder;
6 6
7 import 'ir_nodes.dart' as ir; 7 import 'ir_nodes.dart' as ir;
8 import '../elements/elements.dart'; 8 import '../elements/elements.dart';
9 import '../dart2jslib.dart'; 9 import '../dart2jslib.dart';
10 import '../dart_types.dart'; 10 import '../dart_types.dart';
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
184 // list of references. When the delimited subexpression is plugged into the 184 // list of references. When the delimited subexpression is plugged into the
185 // surrounding context, the free occurrences can be captured or become free 185 // surrounding context, the free occurrences can be captured or become free
186 // occurrences in the next outer delimited subexpression. 186 // occurrences in the next outer delimited subexpression.
187 // 187 //
188 // Each nested visitor maintains a list that maps indexes of variables 188 // Each nested visitor maintains a list that maps indexes of variables
189 // assigned in the delimited subexpression to their reaching definition --- 189 // assigned in the delimited subexpression to their reaching definition ---
190 // that is, the definition in effect at the hole in 'current'. These are 190 // that is, the definition in effect at the hole in 'current'. These are
191 // used to determine if a join-point continuation needs to be passed 191 // used to determine if a join-point continuation needs to be passed
192 // arguments, and what the arguments are. 192 // arguments, and what the arguments are.
193 final Map<Element, int> variableIndex; 193 final Map<Element, int> variableIndex;
194 final List<Element> index2variable;
194 final List<ir.Parameter> freeVars; 195 final List<ir.Parameter> freeVars;
195 final List<ir.Primitive> assignedVars; 196 final List<ir.Primitive> assignedVars;
196 197
197 /// Construct a top-level visitor. 198 /// Construct a top-level visitor.
198 IrBuilder(TreeElements elements, Compiler compiler, this.sourceFile) 199 IrBuilder(TreeElements elements, Compiler compiler, this.sourceFile)
199 : returnContinuation = new ir.Continuation.retrn(), 200 : returnContinuation = new ir.Continuation.retrn(),
200 parameters = <ir.Parameter>[], 201 parameters = <ir.Parameter>[],
201 variableIndex = <Element, int>{}, 202 variableIndex = <Element, int>{},
202 freeVars = null, 203 freeVars = null,
203 assignedVars = <ir.Primitive>[], 204 assignedVars = <ir.Primitive>[],
205 index2variable = <Element>[],
204 super(elements, compiler); 206 super(elements, compiler);
205 207
206 /// Construct a delimited visitor. 208 /// Construct a delimited visitor.
207 IrBuilder.delimited(IrBuilder parent) 209 IrBuilder.delimited(IrBuilder parent)
208 : sourceFile = parent.sourceFile, 210 : sourceFile = parent.sourceFile,
209 returnContinuation = parent.returnContinuation, 211 returnContinuation = parent.returnContinuation,
210 parameters = parent.parameters, 212 parameters = parent.parameters,
211 variableIndex = parent.variableIndex, 213 variableIndex = parent.variableIndex,
212 freeVars = new List<ir.Parameter>.generate( 214 freeVars = new List<ir.Parameter>.generate(
213 parent.assignedVars.length, (_) => new ir.Parameter(null), 215 parent.assignedVars.length, (_) => new ir.Parameter(null),
214 growable: false), 216 growable: false),
215 assignedVars = new List<ir.Primitive>.generate( 217 assignedVars = new List<ir.Primitive>.generate(
216 parent.assignedVars.length, (_) => null), 218 parent.assignedVars.length, (_) => null),
219 index2variable = new List<Element>.from(parent.index2variable),
217 super(parent.elements, parent.compiler); 220 super(parent.elements, parent.compiler);
218 221
219 /** 222 /**
220 * Builds the [ir.FunctionDefinition] for a function element. In case the 223 * Builds the [ir.FunctionDefinition] for a function element. In case the
221 * function uses features that cannot be expressed in the IR, this function 224 * function uses features that cannot be expressed in the IR, this function
222 * returns `null`. 225 * returns `null`.
223 */ 226 */
224 ir.FunctionDefinition buildFunction(FunctionElement functionElement) { 227 ir.FunctionDefinition buildFunction(FunctionElement functionElement) {
225 return nullIfGiveup(() => buildFunctionInternal(functionElement)); 228 return nullIfGiveup(() => buildFunctionInternal(functionElement));
226 } 229 }
227 230
228 ir.FunctionDefinition buildFunctionInternal(FunctionElement element) { 231 ir.FunctionDefinition buildFunctionInternal(FunctionElement element) {
229 assert(invariant(element, element.isImplementation)); 232 assert(invariant(element, element.isImplementation));
230 ast.FunctionExpression function = element.node; 233 ast.FunctionExpression function = element.node;
231 assert(function != null); 234 assert(function != null);
232 assert(!function.modifiers.isExternal); 235 assert(!function.modifiers.isExternal);
233 assert(elements[function] != null); 236 assert(elements[function] != null);
234 237
235 root = current = null; 238 root = current = null;
236 239
237 FunctionSignature signature = element.functionSignature; 240 FunctionSignature signature = element.functionSignature;
238 signature.orderedForEachParameter((parameterElement) { 241 signature.orderedForEachParameter((parameterElement) {
239 ir.Parameter parameter = new ir.Parameter(parameterElement); 242 ir.Parameter parameter = new ir.Parameter(parameterElement);
240 parameters.add(parameter); 243 parameters.add(parameter);
241 variableIndex[parameterElement] = assignedVars.length; 244 variableIndex[parameterElement] = assignedVars.length;
242 assignedVars.add(parameter); 245 assignedVars.add(parameter);
246 index2variable.add(parameterElement);
243 }); 247 });
244 248
245 visit(function.body); 249 visit(function.body);
246 ensureReturn(function); 250 ensureReturn(function);
247 return new ir.FunctionDefinition(returnContinuation, parameters, root); 251 return new ir.FunctionDefinition(returnContinuation, parameters, root);
248 } 252 }
249 253
250 ConstantSystem get constantSystem => compiler.backend.constantSystem; 254 ConstantSystem get constantSystem => compiler.backend.constantSystem;
251 255
252 bool get isOpen => root == null || current != null; 256 bool get isOpen => root == null || current != null;
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
338 // The last assignments, if any, reaching the end of the two subterms. 342 // The last assignments, if any, reaching the end of the two subterms.
339 ir.Primitive leftAssignment = leftBuilder.assignedVars[i]; 343 ir.Primitive leftAssignment = leftBuilder.assignedVars[i];
340 ir.Primitive rightAssignment = rightBuilder.assignedVars[i]; 344 ir.Primitive rightAssignment = rightBuilder.assignedVars[i];
341 345
342 if (leftAssignment != null || rightAssignment != null) { 346 if (leftAssignment != null || rightAssignment != null) {
343 // The corresponsing argument is the reaching definition if any, or a 347 // The corresponsing argument is the reaching definition if any, or a
344 // free occurrence. In the case that control does not reach both the 348 // free occurrence. In the case that control does not reach both the
345 // left and right subterms we will still have a join continuation with 349 // left and right subterms we will still have a join continuation with
346 // possibly arguments passed to it. Such singly-used continuations 350 // possibly arguments passed to it. Such singly-used continuations
347 // are eliminated by the shrinking conversions. 351 // are eliminated by the shrinking conversions.
348 parameters.add(new ir.Parameter(null)); 352 parameters.add(new ir.Parameter(index2variable[i]));
349 ir.Primitive reachingDefinition = 353 ir.Primitive reachingDefinition =
350 assignedVars[i] == null ? freeVars[i] : assignedVars[i]; 354 assignedVars[i] == null ? freeVars[i] : assignedVars[i];
351 leftArguments.add( 355 leftArguments.add(
352 leftAssignment == null ? reachingDefinition : leftAssignment); 356 leftAssignment == null ? reachingDefinition : leftAssignment);
353 rightArguments.add( 357 rightArguments.add(
354 rightAssignment == null ? reachingDefinition : rightAssignment); 358 rightAssignment == null ? reachingDefinition : rightAssignment);
355 } 359 }
356 } 360 }
357 return parameters; 361 return parameters;
358 } 362 }
(...skipping 29 matching lines...) Expand all
388 for (int i = 0; i < assignedVars.length; ++i) { 392 for (int i = 0; i < assignedVars.length; ++i) {
389 // Was there an assignment in the body? 393 // Was there an assignment in the body?
390 ir.Definition reachingAssignment = bodyBuilder.assignedVars[i]; 394 ir.Definition reachingAssignment = bodyBuilder.assignedVars[i];
391 // If not, was there an assignment in the condition? 395 // If not, was there an assignment in the condition?
392 if (reachingAssignment == null) { 396 if (reachingAssignment == null) {
393 reachingAssignment = condBuilder.assignedVars[i]; 397 reachingAssignment = condBuilder.assignedVars[i];
394 } 398 }
395 // If not, no value needs to be passed to the join point. 399 // If not, no value needs to be passed to the join point.
396 if (reachingAssignment == null) continue; 400 if (reachingAssignment == null) continue;
397 401
398 parameters.add(new ir.Parameter(null)); 402 parameters.add(new ir.Parameter(index2variable[i]));
399 ir.Definition entryAssignment = assignedVars[i]; 403 ir.Definition entryAssignment = assignedVars[i];
400 entryArguments.add( 404 entryArguments.add(
401 entryAssignment == null ? freeVars[i] : entryAssignment); 405 entryAssignment == null ? freeVars[i] : entryAssignment);
402 loopArguments.add(reachingAssignment); 406 loopArguments.add(reachingAssignment);
403 } 407 }
404 return parameters; 408 return parameters;
405 } 409 }
406 410
407 /// Capture free variables in the arms of a branch. 411 /// Capture free variables in the arms of a branch.
408 /// 412 ///
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after
621 ir.Primitive visitVariableDefinitions(ast.VariableDefinitions node) { 625 ir.Primitive visitVariableDefinitions(ast.VariableDefinitions node) {
622 assert(isOpen); 626 assert(isOpen);
623 for (ast.Node definition in node.definitions.nodes) { 627 for (ast.Node definition in node.definitions.nodes) {
624 Element element = elements[definition]; 628 Element element = elements[definition];
625 // Definitions are either SendSets if there is an initializer, or 629 // Definitions are either SendSets if there is an initializer, or
626 // Identifiers if there is no initializer. 630 // Identifiers if there is no initializer.
627 if (definition is ast.SendSet) { 631 if (definition is ast.SendSet) {
628 assert(!definition.arguments.isEmpty); 632 assert(!definition.arguments.isEmpty);
629 assert(definition.arguments.tail.isEmpty); 633 assert(definition.arguments.tail.isEmpty);
630 ir.Primitive initialValue = visit(definition.arguments.head); 634 ir.Primitive initialValue = visit(definition.arguments.head);
635 // If a temporary was introduced for the initializer expression,
Kevin Millikin (Google) 2014/06/10 11:33:01 Hmm, the comment says "If" but the code is uncondi
asgerf 2014/06/10 12:22:24 The 'if' I mention is inside the method (if elemen
636 // do not use a separate variable for it.
637 useElementForVariable(initialValue, element);
631 variableIndex[element] = assignedVars.length; 638 variableIndex[element] = assignedVars.length;
632 assignedVars.add(initialValue); 639 assignedVars.add(initialValue);
640 index2variable.add(element);
633 } else { 641 } else {
634 assert(definition is ast.Identifier); 642 assert(definition is ast.Identifier);
635 // The initial value is null. 643 // The initial value is null.
636 // TODO(kmillikin): Consider pooling constants. 644 // TODO(kmillikin): Consider pooling constants.
637 ir.Constant constant = new ir.Constant(constantSystem.createNull()); 645 ir.Constant constant = new ir.Constant(constantSystem.createNull());
646 useElementForVariable(constant, element);
638 add(new ir.LetPrim(constant)); 647 add(new ir.LetPrim(constant));
639 variableIndex[element] = assignedVars.length; 648 variableIndex[element] = assignedVars.length;
640 assignedVars.add(constant); 649 assignedVars.add(constant);
650 index2variable.add(element);
641 } 651 }
642 } 652 }
643 return null; 653 return null;
644 } 654 }
645 655
646 // Build(Return(e), C) = C'[InvokeContinuation(return, x)] 656 // Build(Return(e), C) = C'[InvokeContinuation(return, x)]
647 // where (C', x) = Build(e, C) 657 // where (C', x) = Build(e, C)
648 // 658 //
649 // Return without a subexpression is translated as if it were return null. 659 // Return without a subexpression is translated as if it were return null.
650 ir.Primitive visitReturn(ast.Return node) { 660 ir.Primitive visitReturn(ast.Return node) {
(...skipping 430 matching lines...) Expand 10 before | Expand all | Expand 10 after
1081 1091
1082 ir.Primitive visitSendSet(ast.SendSet node) { 1092 ir.Primitive visitSendSet(ast.SendSet node) {
1083 assert(isOpen); 1093 assert(isOpen);
1084 Element element = elements[node]; 1094 Element element = elements[node];
1085 if (node.assignmentOperator.source != '=') return giveup(); 1095 if (node.assignmentOperator.source != '=') return giveup();
1086 if (Elements.isLocal(element)) { 1096 if (Elements.isLocal(element)) {
1087 // Exactly one argument expected for a simple assignment. 1097 // Exactly one argument expected for a simple assignment.
1088 assert(!node.arguments.isEmpty); 1098 assert(!node.arguments.isEmpty);
1089 assert(node.arguments.tail.isEmpty); 1099 assert(node.arguments.tail.isEmpty);
1090 ir.Primitive result = visit(node.arguments.head); 1100 ir.Primitive result = visit(node.arguments.head);
1101 useElementForVariable(result, element);
1091 assignedVars[variableIndex[element]] = result; 1102 assignedVars[variableIndex[element]] = result;
1092 return result; 1103 return result;
1093 } else if (Elements.isStaticOrTopLevel(element)) { 1104 } else if (Elements.isStaticOrTopLevel(element)) {
1094 // TODO(asgerf): static and top-level 1105 // TODO(asgerf): static and top-level
1095 return giveup(); 1106 return giveup();
1096 } else if (node.receiver == null) { 1107 } else if (node.receiver == null) {
1097 // Nodes that fall in this case: 1108 // Nodes that fall in this case:
1098 // - Unresolved top-level 1109 // - Unresolved top-level
1099 // - Assignment to final variable (will not be resolved) 1110 // - Assignment to final variable (will not be resolved)
1100 return giveup(); 1111 return giveup();
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
1170 arguments.add(visit(part.expression)); 1181 arguments.add(visit(part.expression));
1171 arguments.add(visitLiteralString(part.string)); 1182 arguments.add(visitLiteralString(part.string));
1172 } 1183 }
1173 ir.Parameter v = new ir.Parameter(null); 1184 ir.Parameter v = new ir.Parameter(null);
1174 ir.Continuation k = new ir.Continuation([v]); 1185 ir.Continuation k = new ir.Continuation([v]);
1175 ir.ConcatenateStrings concat = new ir.ConcatenateStrings(k, arguments); 1186 ir.ConcatenateStrings concat = new ir.ConcatenateStrings(k, arguments);
1176 add(new ir.LetCont(k, concat)); 1187 add(new ir.LetCont(k, concat));
1177 return v; 1188 return v;
1178 } 1189 }
1179 1190
1191 /// Associates [primitive] with the given [element].
1192 /// This is used as a hint when choosing variables names later when
1193 /// translating out of the IR again.
1194 void useElementForVariable(ir.Primitive primitive, Element element) {
Kevin Millikin (Google) 2014/06/10 11:33:01 This works better as a method on Primitive, doesn'
asgerf 2014/06/10 12:22:24 Yes, good idea.
1195 // Use the first assigned element
1196 if (primitive.element != null) return;
1197
1198 primitive.element = element;
1199 }
1200
1180 static final String ABORT_IRNODE_BUILDER = "IrNode builder aborted"; 1201 static final String ABORT_IRNODE_BUILDER = "IrNode builder aborted";
1181 1202
1182 ir.Primitive giveup() => throw ABORT_IRNODE_BUILDER; 1203 ir.Primitive giveup() => throw ABORT_IRNODE_BUILDER;
1183 1204
1184 ir.FunctionDefinition nullIfGiveup(ir.FunctionDefinition action()) { 1205 ir.FunctionDefinition nullIfGiveup(ir.FunctionDefinition action()) {
1185 try { 1206 try {
1186 return action(); 1207 return action();
1187 } catch(e) { 1208 } catch(e) {
1188 if (e == ABORT_IRNODE_BUILDER) return null; 1209 if (e == ABORT_IRNODE_BUILDER) return null;
1189 rethrow; 1210 rethrow;
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1228 bool visitType(DartType type, Null _) => false; 1249 bool visitType(DartType type, Null _) => false;
1229 1250
1230 bool visitDynamicType(DynamicType type, Null _) => true; 1251 bool visitDynamicType(DynamicType type, Null _) => true;
1231 1252
1232 bool visitVoidType(VoidType type, Null _) => true; 1253 bool visitVoidType(VoidType type, Null _) => true;
1233 1254
1234 // Currently, InterfaceType and TypedefType are supported so long as they 1255 // Currently, InterfaceType and TypedefType are supported so long as they
1235 // do not have type parameters. They are subclasses of GenericType. 1256 // do not have type parameters. They are subclasses of GenericType.
1236 bool visitGenericType(GenericType type, Null _) => !type.isGeneric; 1257 bool visitGenericType(GenericType type, Null _) => !type.isGeneric;
1237 } 1258 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698