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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/cps_ir/cps_ir_builder.dart

Issue 661593004: Support local variables in analyzer2dart. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Updated cf. comments. Created 6 years, 2 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
« no previous file with comments | « pkg/analyzer2dart/test/end2end_test.dart ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 '../constants/expressions.dart'; 7 import '../constants/expressions.dart';
8 import '../constants/values.dart' show PrimitiveConstantValue; 8 import '../constants/values.dart' show PrimitiveConstantValue;
9 import '../dart_backend/dart_backend.dart' show DartBackend; 9 import '../dart_backend/dart_backend.dart' show DartBackend;
10 import '../dart_types.dart'; 10 import '../dart_types.dart';
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
158 // TODO(kmillikin): This is still kind of fishy. Refactor to not share 158 // TODO(kmillikin): This is still kind of fishy. Refactor to not share
159 // name maps or else garbage collect unneeded names. 159 // name maps or else garbage collect unneeded names.
160 assert(element == null || !variable2index.containsKey(element)); 160 assert(element == null || !variable2index.containsKey(element));
161 variable2index[element] = index2variable.length; 161 variable2index[element] = index2variable.length;
162 index2variable.add(element); 162 index2variable.add(element);
163 index2value.add(value); 163 index2value.add(value);
164 } 164 }
165 165
166 ir.Primitive lookup(Element element) { 166 ir.Primitive lookup(Element element) {
167 assert(!element.isConst); 167 assert(!element.isConst);
168 assert(invariant(element, variable2index.containsKey(element),
169 message: "Unknown variable: $element."));
168 return index2value[variable2index[element]]; 170 return index2value[variable2index[element]];
169 } 171 }
170 172
171 void update(Element element, ir.Primitive value) { 173 void update(Element element, ir.Primitive value) {
172 index2value[variable2index[element]] = value; 174 index2value[variable2index[element]] = value;
173 } 175 }
174 176
175 /// Verify that the variable2index and index2variable maps agree up to the 177 /// Verify that the variable2index and index2variable maps agree up to the
176 /// index [length] exclusive. 178 /// index [length] exclusive.
177 bool sameDomain(int length, Environment other) { 179 bool sameDomain(int length, Environment other) {
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
230 // when [IrBuilder] is a property of [IrBuilderVisitor] instead of a mixin. 232 // when [IrBuilder] is a property of [IrBuilderVisitor] instead of a mixin.
231 ConstantSystem constantSystem = DART_CONSTANT_SYSTEM; 233 ConstantSystem constantSystem = DART_CONSTANT_SYSTEM;
232 234
233 ir.Continuation returnContinuation = new ir.Continuation.retrn(); 235 ir.Continuation returnContinuation = new ir.Continuation.retrn();
234 236
235 List<ir.Parameter> _parameters = <ir.Parameter>[]; 237 List<ir.Parameter> _parameters = <ir.Parameter>[];
236 238
237 /// A map from variable indexes to their values. 239 /// A map from variable indexes to their values.
238 Environment environment = new Environment.empty(); 240 Environment environment = new Environment.empty();
239 241
242 List<ConstDeclaration> _localConstants = <ConstDeclaration>[];
243
240 // The IR builder maintains a context, which is an expression with a hole in 244 // The IR builder maintains a context, which is an expression with a hole in
241 // it. The hole represents the focus where new expressions can be added. 245 // it. The hole represents the focus where new expressions can be added.
242 // The context is implemented by 'root' which is the root of the expression 246 // The context is implemented by 'root' which is the root of the expression
243 // and 'current' which is the expression that immediately contains the hole. 247 // and 'current' which is the expression that immediately contains the hole.
244 // Not all expressions have a hole (e.g., invocations, which always occur in 248 // Not all expressions have a hole (e.g., invocations, which always occur in
245 // tail position, do not have a hole). Expressions with a hole have a plug 249 // tail position, do not have a hole). Expressions with a hole have a plug
246 // method. 250 // method.
247 // 251 //
248 // Conceptually, visiting a statement takes a context as input and returns 252 // Conceptually, visiting a statement takes a context as input and returns
249 // either a new context or else an expression without a hole if all 253 // either a new context or else an expression without a hole if all
(...skipping 23 matching lines...) Expand all
273 {bool isClosureVariable: false}) { 277 {bool isClosureVariable: false}) {
274 ir.Parameter parameter = new ir.Parameter(parameterElement); 278 ir.Parameter parameter = new ir.Parameter(parameterElement);
275 _parameters.add(parameter); 279 _parameters.add(parameter);
276 if (isClosureVariable) { 280 if (isClosureVariable) {
277 add(new ir.SetClosureVariable(parameterElement, parameter)); 281 add(new ir.SetClosureVariable(parameterElement, parameter));
278 } else { 282 } else {
279 environment.extend(parameterElement, parameter); 283 environment.extend(parameterElement, parameter);
280 } 284 }
281 } 285 }
282 286
287 void declareLocalConstant(LocalVariableElement variableElement,
288 ConstantExpression value) {
289 _localConstants.add(new ConstDeclaration(variableElement, value));
290 }
291
292 void declareLocalVariable(LocalVariableElement variableElement,
293 {ir.Primitive initialValue,
294 bool isClosureVariable: false}) {
295 assert(isOpen);
296 if (initialValue == null) {
297 // TODO(kmillikin): Consider pooling constants.
298 // The initial value is null.
299 initialValue = makePrimConst(constantSystem.createNull());
300 add(new ir.LetPrim(initialValue));
301 }
302 if (isClosureVariable) {
303 add(new ir.SetClosureVariable(variableElement,
304 initialValue,
305 isDeclaration: true));
306 } else {
307 // In case a primitive was introduced for the initializer expression,
308 // use this variable element to help derive a good name for it.
309 initialValue.useElementAsHint(variableElement);
310 environment.extend(variableElement, initialValue);
311 }
312 }
313
283 // Plug an expression into the 'hole' in the context being accumulated. The 314 // Plug an expression into the 'hole' in the context being accumulated. The
284 // empty context (just a hole) is represented by root (and current) being 315 // empty context (just a hole) is represented by root (and current) being
285 // null. Since the hole in the current context is filled by this function, 316 // null. Since the hole in the current context is filled by this function,
286 // the new hole must be in the newly added expression---which becomes the 317 // the new hole must be in the newly added expression---which becomes the
287 // new value of current. 318 // new value of current.
288 void add(ir.Expression expr) { 319 void add(ir.Expression expr) {
289 assert(isOpen); 320 assert(isOpen);
290 if (_root == null) { 321 if (_root == null) {
291 _root = _current = expr; 322 _root = _current = expr;
292 } else { 323 } else {
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
371 add(new ir.InvokeContinuation(returnContinuation, [constant])); 402 add(new ir.InvokeContinuation(returnContinuation, [constant]));
372 _current = null; 403 _current = null;
373 } 404 }
374 405
375 /// Create a [ir.FunctionDefinition] for [element] using [_root] as the body. 406 /// Create a [ir.FunctionDefinition] for [element] using [_root] as the body.
376 /// 407 ///
377 /// Parameters must be created before the construction of the body using 408 /// Parameters must be created before the construction of the body using
378 /// [createParameter]. 409 /// [createParameter].
379 ir.FunctionDefinition buildFunctionDefinition( 410 ir.FunctionDefinition buildFunctionDefinition(
380 FunctionElement element, 411 FunctionElement element,
381 List<ConstDeclaration> constants,
382 List<ConstantExpression> defaults) { 412 List<ConstantExpression> defaults) {
383 if (!element.isAbstract) { 413 if (!element.isAbstract) {
384 ensureReturn(); 414 ensureReturn();
385 return new ir.FunctionDefinition( 415 return new ir.FunctionDefinition(
386 element, returnContinuation, _parameters, _root, constants, defaults); 416 element, returnContinuation, _parameters, _root,
417 _localConstants, defaults);
387 } else { 418 } else {
388 assert(invariant(element, _root == null, 419 assert(invariant(element, _root == null,
389 message: "Non-empty body for abstract method $element: $_root")); 420 message: "Non-empty body for abstract method $element: $_root"));
390 assert(invariant(element, constants.isEmpty, 421 assert(invariant(element, _localConstants.isEmpty,
391 message: "Local constants for abstract method $element: $constants")); 422 message: "Local constants for abstract method $element: "
423 "$_localConstants"));
392 return new ir.FunctionDefinition.abstract( 424 return new ir.FunctionDefinition.abstract(
393 element, _parameters, defaults); 425 element, _parameters, defaults);
394 } 426 }
395 } 427 }
396 428
397 /// Create a static invocation of [element] with arguments structure defined 429 /// Create a static invocation of [element] with arguments structure defined
398 /// by [selector] and argument values defined by [arguments]. 430 /// by [selector] and argument values defined by [arguments].
399 ir.Primitive buildStaticInvocation(Element element, 431 ir.Primitive buildStaticInvocation(Element element,
400 Selector selector, 432 Selector selector,
401 List<ir.Definition> arguments) { 433 List<ir.Definition> arguments) {
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
446 // assigned in the delimited subexpression to their reaching definition --- 478 // assigned in the delimited subexpression to their reaching definition ---
447 // that is, the definition in effect at the hole in 'current'. These are 479 // that is, the definition in effect at the hole in 'current'. These are
448 // used to determine if a join-point continuation needs to be passed 480 // used to determine if a join-point continuation needs to be passed
449 // arguments, and what the arguments are. 481 // arguments, and what the arguments are.
450 482
451 /// A stack of collectors for breaks. 483 /// A stack of collectors for breaks.
452 final List<JumpCollector> breakCollectors; 484 final List<JumpCollector> breakCollectors;
453 /// A stack of collectors for continues. 485 /// A stack of collectors for continues.
454 final List<JumpCollector> continueCollectors; 486 final List<JumpCollector> continueCollectors;
455 487
456 final List<ConstDeclaration> localConstants;
457
458 FunctionElement currentFunction; 488 FunctionElement currentFunction;
459 final DetectClosureVariables closureLocals; 489 final DetectClosureVariables closureLocals;
460 490
461 /// Construct a top-level visitor. 491 /// Construct a top-level visitor.
462 IrBuilderVisitor(TreeElements elements, this.compiler, this.sourceFile) 492 IrBuilderVisitor(TreeElements elements, this.compiler, this.sourceFile)
463 : breakCollectors = <JumpCollector>[], 493 : breakCollectors = <JumpCollector>[],
464 continueCollectors = <JumpCollector>[], 494 continueCollectors = <JumpCollector>[],
465 localConstants = <ConstDeclaration>[],
466 closureLocals = new DetectClosureVariables(elements), 495 closureLocals = new DetectClosureVariables(elements),
467 super(elements) { 496 super(elements) {
468 constantSystem = compiler.backend.constantSystem; 497 constantSystem = compiler.backend.constantSystem;
469 } 498 }
470 499
471 /// Construct a delimited visitor for visiting a subtree. 500 /// Construct a delimited visitor for visiting a subtree.
472 /// 501 ///
473 /// The delimited visitor has its own compile-time environment mapping 502 /// The delimited visitor has its own compile-time environment mapping
474 /// local variables to their values, which is initially a copy of the parent 503 /// local variables to their values, which is initially a copy of the parent
475 /// environment. It has its own context for building an IR expression, so 504 /// environment. It has its own context for building an IR expression, so
476 /// the built expression is not plugged into the parent's context. 505 /// the built expression is not plugged into the parent's context.
477 IrBuilderVisitor.delimited(IrBuilderVisitor parent) 506 IrBuilderVisitor.delimited(IrBuilderVisitor parent)
478 : compiler = parent.compiler, 507 : compiler = parent.compiler,
479 sourceFile = parent.sourceFile, 508 sourceFile = parent.sourceFile,
480 breakCollectors = parent.breakCollectors, 509 breakCollectors = parent.breakCollectors,
481 continueCollectors = parent.continueCollectors, 510 continueCollectors = parent.continueCollectors,
482 localConstants = parent.localConstants,
483 currentFunction = parent.currentFunction, 511 currentFunction = parent.currentFunction,
484 closureLocals = parent.closureLocals, 512 closureLocals = parent.closureLocals,
485 super(parent.elements) { 513 super(parent.elements) {
486 constantSystem = parent.constantSystem; 514 constantSystem = parent.constantSystem;
487 returnContinuation = parent.returnContinuation; 515 returnContinuation = parent.returnContinuation;
516 _localConstants = parent._localConstants;
488 environment = new Environment.from(parent.environment); 517 environment = new Environment.from(parent.environment);
489 } 518 }
490 519
491 /// Construct a visitor for a recursive continuation. 520 /// Construct a visitor for a recursive continuation.
492 /// 521 ///
493 /// The recursive continuation builder has fresh parameters (i.e. SSA phis) 522 /// The recursive continuation builder has fresh parameters (i.e. SSA phis)
494 /// for all the local variables in the parent, because the invocation sites 523 /// for all the local variables in the parent, because the invocation sites
495 /// of the continuation are not all known when the builder is created. The 524 /// of the continuation are not all known when the builder is created. The
496 /// recursive invocations will be passed values for all the local variables, 525 /// recursive invocations will be passed values for all the local variables,
497 /// which may be eliminated later if they are redundant---if they take on 526 /// which may be eliminated later if they are redundant---if they take on
498 /// the same value at all invocation sites. 527 /// the same value at all invocation sites.
499 IrBuilderVisitor.recursive(IrBuilderVisitor parent) 528 IrBuilderVisitor.recursive(IrBuilderVisitor parent)
500 : compiler = parent.compiler, 529 : compiler = parent.compiler,
501 sourceFile = parent.sourceFile, 530 sourceFile = parent.sourceFile,
502 breakCollectors = parent.breakCollectors, 531 breakCollectors = parent.breakCollectors,
503 continueCollectors = parent.continueCollectors, 532 continueCollectors = parent.continueCollectors,
504 localConstants = parent.localConstants,
505 currentFunction = parent.currentFunction, 533 currentFunction = parent.currentFunction,
506 closureLocals = parent.closureLocals, 534 closureLocals = parent.closureLocals,
507 super(parent.elements) { 535 super(parent.elements) {
508 constantSystem = parent.constantSystem; 536 constantSystem = parent.constantSystem;
509 returnContinuation = parent.returnContinuation; 537 returnContinuation = parent.returnContinuation;
538 _localConstants = parent._localConstants;
510 parent.environment.index2variable.forEach(createParameter); 539 parent.environment.index2variable.forEach(createParameter);
511 } 540 }
512 541
513 /** 542 /**
514 * Builds the [ir.FunctionDefinition] for a function element. In case the 543 * Builds the [ir.FunctionDefinition] for a function element. In case the
515 * function uses features that cannot be expressed in the IR, this function 544 * function uses features that cannot be expressed in the IR, this function
516 * returns `null`. 545 * returns `null`.
517 */ 546 */
518 ir.FunctionDefinition buildFunction(FunctionElement functionElement) { 547 ir.FunctionDefinition buildFunction(FunctionElement functionElement) {
519 return nullIfGiveup(() => buildFunctionInternal(functionElement)); 548 return nullIfGiveup(() => buildFunctionInternal(functionElement));
(...skipping 16 matching lines...) Expand all
536 createParameter(parameterElement, 565 createParameter(parameterElement,
537 isClosureVariable: isClosureVariable(parameterElement)); 566 isClosureVariable: isClosureVariable(parameterElement));
538 }); 567 });
539 568
540 List<ConstantExpression> defaults = new List<ConstantExpression>(); 569 List<ConstantExpression> defaults = new List<ConstantExpression>();
541 signature.orderedOptionalParameters.forEach((ParameterElement element) { 570 signature.orderedOptionalParameters.forEach((ParameterElement element) {
542 defaults.add(getConstantForVariable(element)); 571 defaults.add(getConstantForVariable(element));
543 }); 572 });
544 573
545 visit(function.body); 574 visit(function.body);
546 return buildFunctionDefinition(element, localConstants, defaults); 575 return buildFunctionDefinition(element, defaults);
547 } 576 }
548 577
549 ir.Primitive visit(ast.Node node) => node.accept(this); 578 ir.Primitive visit(ast.Node node) => node.accept(this);
550 579
551 // ==== Statements ==== 580 // ==== Statements ====
552 // Build(Block(stamements), C) = C' 581 // Build(Block(stamements), C) = C'
553 // where C' = statements.fold(Build, C) 582 // where C' = statements.fold(Build, C)
554 ir.Primitive visitBlock(ast.Block node) { 583 ir.Primitive visitBlock(ast.Block node) {
555 assert(isOpen); 584 assert(isOpen);
556 for (ast.Node n in node.statements.nodes) { 585 for (ast.Node n in node.statements.nodes) {
(...skipping 577 matching lines...) Expand 10 before | Expand all | Expand 10 after
1134 } 1163 }
1135 1164
1136 ir.Primitive visitVariableDefinitions(ast.VariableDefinitions node) { 1165 ir.Primitive visitVariableDefinitions(ast.VariableDefinitions node) {
1137 assert(isOpen); 1166 assert(isOpen);
1138 if (node.modifiers.isConst) { 1167 if (node.modifiers.isConst) {
1139 for (ast.SendSet definition in node.definitions.nodes) { 1168 for (ast.SendSet definition in node.definitions.nodes) {
1140 assert(!definition.arguments.isEmpty); 1169 assert(!definition.arguments.isEmpty);
1141 assert(definition.arguments.tail.isEmpty); 1170 assert(definition.arguments.tail.isEmpty);
1142 VariableElement element = elements[definition]; 1171 VariableElement element = elements[definition];
1143 ConstantExpression value = getConstantForVariable(element); 1172 ConstantExpression value = getConstantForVariable(element);
1144 localConstants.add(new ConstDeclaration(element, value)); 1173 declareLocalConstant(element, value);
1145 } 1174 }
1146 } else { 1175 } else {
1147 for (ast.Node definition in node.definitions.nodes) { 1176 for (ast.Node definition in node.definitions.nodes) {
1148 Element element = elements[definition]; 1177 Element element = elements[definition];
1149 ir.Primitive initialValue; 1178 ir.Primitive initialValue;
1150 // Definitions are either SendSets if there is an initializer, or 1179 // Definitions are either SendSets if there is an initializer, or
1151 // Identifiers if there is no initializer. 1180 // Identifiers if there is no initializer.
1152 if (definition is ast.SendSet) { 1181 if (definition is ast.SendSet) {
1153 assert(!definition.arguments.isEmpty); 1182 assert(!definition.arguments.isEmpty);
1154 assert(definition.arguments.tail.isEmpty); 1183 assert(definition.arguments.tail.isEmpty);
1155 initialValue = visit(definition.arguments.head); 1184 initialValue = visit(definition.arguments.head);
1156 } else { 1185 } else {
1157 assert(definition is ast.Identifier); 1186 assert(definition is ast.Identifier);
1158 // The initial value is null.
1159 // TODO(kmillikin): Consider pooling constants.
1160 initialValue = makePrimConst(constantSystem.createNull());
1161 add(new ir.LetPrim(initialValue));
1162 } 1187 }
1163 if (isClosureVariable(element)) { 1188 declareLocalVariable(element,
1164 LocalElement local = element; 1189 initialValue: initialValue,
1165 add(new ir.SetClosureVariable(local, initialValue, 1190 isClosureVariable: isClosureVariable(element));
1166 isDeclaration: true));
1167 } else {
1168 // In case a primitive was introduced for the initializer expression,
1169 // use this variable element to help derive a good name for it.
1170 initialValue.useElementAsHint(element);
1171 environment.extend(element, initialValue);
1172 }
1173 } 1191 }
1174 } 1192 }
1175 return null; 1193 return null;
1176 } 1194 }
1177 1195
1178 // Build(Return(e), C) = C'[InvokeContinuation(return, x)] 1196 // Build(Return(e), C) = C'[InvokeContinuation(return, x)]
1179 // where (C', x) = Build(e, C) 1197 // where (C', x) = Build(e, C)
1180 // 1198 //
1181 // Return without a subexpression is translated as if it were return null. 1199 // Return without a subexpression is translated as if it were return null.
1182 ir.Primitive visitReturn(ast.Return node) { 1200 ir.Primitive visitReturn(ast.Return node) {
(...skipping 770 matching lines...) Expand 10 before | Expand all | Expand 10 after
1953 } 1971 }
1954 1972
1955 visitFunctionExpression(ast.FunctionExpression node) { 1973 visitFunctionExpression(ast.FunctionExpression node) {
1956 FunctionElement oldFunction = currentFunction; 1974 FunctionElement oldFunction = currentFunction;
1957 currentFunction = elements[node]; 1975 currentFunction = elements[node];
1958 visit(node.body); 1976 visit(node.body);
1959 currentFunction = oldFunction; 1977 currentFunction = oldFunction;
1960 } 1978 }
1961 1979
1962 } 1980 }
OLDNEW
« no previous file with comments | « pkg/analyzer2dart/test/end2end_test.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698