| 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; | 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 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 299 | 299 |
| 300 /// Add the constant [variableElement] to the environment with [value] as its | 300 /// Add the constant [variableElement] to the environment with [value] as its |
| 301 /// constant value. | 301 /// constant value. |
| 302 void declareLocalConstant(LocalVariableElement variableElement, | 302 void declareLocalConstant(LocalVariableElement variableElement, |
| 303 ConstantExpression value) { | 303 ConstantExpression value) { |
| 304 state.localConstants.add(new ConstDeclaration(variableElement, value)); | 304 state.localConstants.add(new ConstDeclaration(variableElement, value)); |
| 305 } | 305 } |
| 306 | 306 |
| 307 /// Add [variableElement] to the environment with [initialValue] as its | 307 /// Add [variableElement] to the environment with [initialValue] as its |
| 308 /// initial value. | 308 /// initial value. |
| 309 /// | |
| 310 /// [isClosureVariable] marks whether [variableElement] is accessed from an | |
| 311 /// inner function. | |
| 312 void declareLocalVariable(LocalVariableElement variableElement, | 309 void declareLocalVariable(LocalVariableElement variableElement, |
| 313 {ir.Primitive initialValue}) { | 310 {ir.Primitive initialValue}) { |
| 314 assert(isOpen); | 311 assert(isOpen); |
| 315 if (initialValue == null) { | 312 if (initialValue == null) { |
| 316 // TODO(kmillikin): Consider pooling constants. | 313 // TODO(kmillikin): Consider pooling constants. |
| 317 // The initial value is null. | 314 // The initial value is null. |
| 318 initialValue = buildNullLiteral(); | 315 initialValue = buildNullLiteral(); |
| 319 } | 316 } |
| 320 if (isClosureVariable(variableElement)) { | 317 if (isClosureVariable(variableElement)) { |
| 321 add(new ir.SetClosureVariable(variableElement, | 318 add(new ir.SetClosureVariable(variableElement, |
| 322 initialValue, | 319 initialValue, |
| 323 isDeclaration: true)); | 320 isDeclaration: true)); |
| 324 } else { | 321 } else { |
| 325 // In case a primitive was introduced for the initializer expression, | 322 // In case a primitive was introduced for the initializer expression, |
| 326 // use this variable element to help derive a good name for it. | 323 // use this variable element to help derive a good name for it. |
| 327 initialValue.useElementAsHint(variableElement); | 324 initialValue.useElementAsHint(variableElement); |
| 328 environment.extend(variableElement, initialValue); | 325 environment.extend(variableElement, initialValue); |
| 329 } | 326 } |
| 330 } | 327 } |
| 331 | 328 |
| 329 /// Add [functionElement] to the environment with provided [definition]. |
| 330 void declareLocalFunction(LocalFunctionElement functionElement, |
| 331 ir.FunctionDefinition definition) { |
| 332 assert(isOpen); |
| 333 if (isClosureVariable(functionElement)) { |
| 334 add(new ir.DeclareFunction(functionElement, definition)); |
| 335 } else { |
| 336 ir.CreateFunction prim = new ir.CreateFunction(definition); |
| 337 add(new ir.LetPrim(prim)); |
| 338 environment.extend(functionElement, prim); |
| 339 prim.useElementAsHint(functionElement); |
| 340 } |
| 341 } |
| 342 |
| 332 // Plug an expression into the 'hole' in the context being accumulated. The | 343 // Plug an expression into the 'hole' in the context being accumulated. The |
| 333 // empty context (just a hole) is represented by root (and current) being | 344 // empty context (just a hole) is represented by root (and current) being |
| 334 // null. Since the hole in the current context is filled by this function, | 345 // null. Since the hole in the current context is filled by this function, |
| 335 // the new hole must be in the newly added expression---which becomes the | 346 // the new hole must be in the newly added expression---which becomes the |
| 336 // new value of current. | 347 // new value of current. |
| 337 void add(ir.Expression expr) { | 348 void add(ir.Expression expr) { |
| 338 assert(isOpen); | 349 assert(isOpen); |
| 339 if (_root == null) { | 350 if (_root == null) { |
| 340 _root = _current = expr; | 351 _root = _current = expr; |
| 341 } else { | 352 } else { |
| (...skipping 25 matching lines...) Expand all Loading... |
| 367 } | 378 } |
| 368 | 379 |
| 369 ir.Primitive _buildInvokeDynamic(ir.Primitive receiver, | 380 ir.Primitive _buildInvokeDynamic(ir.Primitive receiver, |
| 370 Selector selector, | 381 Selector selector, |
| 371 List<ir.Definition> arguments) { | 382 List<ir.Definition> arguments) { |
| 372 assert(isOpen); | 383 assert(isOpen); |
| 373 return _continueWithExpression( | 384 return _continueWithExpression( |
| 374 (k) => new ir.InvokeMethod(receiver, selector, k, arguments)); | 385 (k) => new ir.InvokeMethod(receiver, selector, k, arguments)); |
| 375 } | 386 } |
| 376 | 387 |
| 388 ir.Primitive _buildInvokeCall(ir.Primitive target, |
| 389 Selector selector, |
| 390 List<ir.Definition> arguments) { |
| 391 Selector callSelector = new Selector.callClosure( |
| 392 selector.argumentCount, |
| 393 selector.namedArguments); |
| 394 return _buildInvokeDynamic(target, callSelector, arguments); |
| 395 } |
| 396 |
| 377 | 397 |
| 378 /// Create a constant literal from [constant]. | 398 /// Create a constant literal from [constant]. |
| 379 ir.Constant buildConstantLiteral(ConstantExpression constant) { | 399 ir.Constant buildConstantLiteral(ConstantExpression constant) { |
| 380 assert(isOpen); | 400 assert(isOpen); |
| 381 ir.Constant prim = new ir.Constant(constant); | 401 ir.Constant prim = new ir.Constant(constant); |
| 382 add(new ir.LetPrim(prim)); | 402 add(new ir.LetPrim(prim)); |
| 383 return prim; | 403 return prim; |
| 384 } | 404 } |
| 385 | 405 |
| 386 // Helper for building primitive literals. | 406 // Helper for building primitive literals. |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 487 new ir.LetCont(elseContinuation, | 507 new ir.LetCont(elseContinuation, |
| 488 new ir.Branch(new ir.IsTrue(condition), | 508 new ir.Branch(new ir.IsTrue(condition), |
| 489 thenContinuation, | 509 thenContinuation, |
| 490 elseContinuation))))); | 510 elseContinuation))))); |
| 491 return (thenValue == elseValue) | 511 return (thenValue == elseValue) |
| 492 ? thenValue | 512 ? thenValue |
| 493 : joinContinuation.parameters.last; | 513 : joinContinuation.parameters.last; |
| 494 | 514 |
| 495 } | 515 } |
| 496 | 516 |
| 517 /// Create a function expression from [definition]. |
| 518 ir.Primitive buildFunctionExpression(ir.FunctionDefinition definition) { |
| 519 ir.CreateFunction prim = new ir.CreateFunction(definition); |
| 520 add(new ir.LetPrim(prim)); |
| 521 return prim; |
| 522 } |
| 523 |
| 497 /** | 524 /** |
| 498 * Add an explicit `return null` for functions that don't have a return | 525 * Add an explicit `return null` for functions that don't have a return |
| 499 * statement on each branch. This includes functions with an empty body, | 526 * statement on each branch. This includes functions with an empty body, |
| 500 * such as `foo(){ }`. | 527 * such as `foo(){ }`. |
| 501 */ | 528 */ |
| 502 void _ensureReturn() { | 529 void _ensureReturn() { |
| 503 if (!isOpen) return; | 530 if (!isOpen) return; |
| 504 ir.Constant constant = buildNullLiteral(); | 531 ir.Constant constant = buildNullLiteral(); |
| 505 add(new ir.InvokeContinuation(state.returnContinuation, [constant])); | 532 add(new ir.InvokeContinuation(state.returnContinuation, [constant])); |
| 506 _current = null; | 533 _current = null; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 522 assert(invariant(element, _root == null, | 549 assert(invariant(element, _root == null, |
| 523 message: "Non-empty body for abstract method $element: $_root")); | 550 message: "Non-empty body for abstract method $element: $_root")); |
| 524 assert(invariant(element, state.localConstants.isEmpty, | 551 assert(invariant(element, state.localConstants.isEmpty, |
| 525 message: "Local constants for abstract method $element: " | 552 message: "Local constants for abstract method $element: " |
| 526 "${state.localConstants}")); | 553 "${state.localConstants}")); |
| 527 return new ir.FunctionDefinition.abstract( | 554 return new ir.FunctionDefinition.abstract( |
| 528 element, _parameters, defaults); | 555 element, _parameters, defaults); |
| 529 } | 556 } |
| 530 } | 557 } |
| 531 | 558 |
| 532 | |
| 533 /// Create a super invocation where the method name and the argument structure | 559 /// Create a super invocation where the method name and the argument structure |
| 534 /// are defined by [selector] and the argument values are defined by | 560 /// are defined by [selector] and the argument values are defined by |
| 535 /// [arguments]. | 561 /// [arguments]. |
| 536 ir.Primitive buildSuperInvocation(Selector selector, | 562 ir.Primitive buildSuperInvocation(Selector selector, |
| 537 List<ir.Definition> arguments) { | 563 List<ir.Definition> arguments) { |
| 538 return _buildInvokeSuper(selector, arguments); | 564 return _buildInvokeSuper(selector, arguments); |
| 539 } | 565 } |
| 540 | 566 |
| 541 /// Create a getter invocation on the super class where the getter name is | 567 /// Create a getter invocation on the super class where the getter name is |
| 542 /// defined by [selector]. | 568 /// defined by [selector]. |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 658 assert(isOpen); | 684 assert(isOpen); |
| 659 if (isClosureVariable(local)) { | 685 if (isClosureVariable(local)) { |
| 660 add(new ir.SetClosureVariable(local, value)); | 686 add(new ir.SetClosureVariable(local, value)); |
| 661 } else { | 687 } else { |
| 662 value.useElementAsHint(local); | 688 value.useElementAsHint(local); |
| 663 environment.update(local, value); | 689 environment.update(local, value); |
| 664 } | 690 } |
| 665 return value; | 691 return value; |
| 666 } | 692 } |
| 667 | 693 |
| 694 /// Create an invocation of [local] where the argument structure is defined |
| 695 /// by [selector] and the argument values are defined by [arguments]. |
| 696 ir.Primitive buildLocalInvocation(LocalElement local, |
| 697 Selector selector, |
| 698 List<ir.Definition> arguments) { |
| 699 ir.Primitive receiver; |
| 700 if (isClosureVariable(local)) { |
| 701 receiver = new ir.GetClosureVariable(local); |
| 702 add(new ir.LetPrim(receiver)); |
| 703 } else { |
| 704 receiver = environment.lookup(local); |
| 705 } |
| 706 return _buildInvokeCall(receiver, selector, arguments); |
| 707 } |
| 708 |
| 709 /// Create an invocation of the [functionExpression] where the argument |
| 710 /// structure are defined by [selector] and the argument values are defined by |
| 711 /// [arguments]. |
| 712 ir.Primitive buildFunctionExpressionInvocation( |
| 713 ir.Primitive functionExpression, |
| 714 Selector selector, |
| 715 List<ir.Definition> arguments) { |
| 716 return _buildInvokeCall(functionExpression, selector, arguments); |
| 717 } |
| 718 |
| 668 /// Creates an if-then-else statement with the provided [condition] where the | 719 /// Creates an if-then-else statement with the provided [condition] where the |
| 669 /// then and else branches are created through the [buildThenPart] and | 720 /// then and else branches are created through the [buildThenPart] and |
| 670 /// [buildElsePart] functions, respectively. | 721 /// [buildElsePart] functions, respectively. |
| 671 /// | 722 /// |
| 672 /// An if-then statement is created if [buildElsePart] is a no-op. | 723 /// An if-then statement is created if [buildElsePart] is a no-op. |
| 673 // TODO(johnniwinther): Unify implementation with [buildConditional] and | 724 // TODO(johnniwinther): Unify implementation with [buildConditional] and |
| 674 // [_buildLogicalOperator]. | 725 // [_buildLogicalOperator]. |
| 675 void buildIf(ir.Primitive condition, | 726 void buildIf(ir.Primitive condition, |
| 676 void buildThenPart(IrBuilder builder), | 727 void buildThenPart(IrBuilder builder), |
| 677 void buildElsePart(IrBuilder builder)) { | 728 void buildElsePart(IrBuilder builder)) { |
| (...skipping 725 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1403 index = 0; | 1454 index = 0; |
| 1404 for (int i = 0; i < environment.length; ++i) { | 1455 for (int i = 0; i < environment.length; ++i) { |
| 1405 if (common[i] == null) { | 1456 if (common[i] == null) { |
| 1406 environment.index2value[i] = parameters[index++]; | 1457 environment.index2value[i] = parameters[index++]; |
| 1407 } | 1458 } |
| 1408 } | 1459 } |
| 1409 | 1460 |
| 1410 return join; | 1461 return join; |
| 1411 } | 1462 } |
| 1412 } | 1463 } |
| OLD | NEW |