Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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.optimizers; | 5 part of dart2js.optimizers; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * Propagates constants throughout the IR, and replaces branches with fixed | 8 * Propagates constants throughout the IR, and replaces branches with fixed |
| 9 * jumps as well as side-effect free expressions with known constant results. | 9 * jumps as well as side-effect free expressions with known constant results. |
| 10 * Should be followed by the [ShrinkingReducer] pass. | 10 * Should be followed by the [ShrinkingReducer] pass. |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 70 void unlink()) { | 70 void unlink()) { |
| 71 _ConstnessLattice cell = node2value[node]; | 71 _ConstnessLattice cell = node2value[node]; |
| 72 if (cell == null || !cell.isConstant) { | 72 if (cell == null || !cell.isConstant) { |
| 73 return null; | 73 return null; |
| 74 } | 74 } |
| 75 | 75 |
| 76 assert(continuation.parameters.length == 1); | 76 assert(continuation.parameters.length == 1); |
| 77 | 77 |
| 78 // Set up the replacement structure. | 78 // Set up the replacement structure. |
| 79 | 79 |
| 80 values.PrimitiveConstant primitiveConstant = cell.constant; | 80 PrimitiveConstantValue primitiveConstant = cell.constant; |
| 81 ConstExp constExp = new PrimitiveConstExp(primitiveConstant); | 81 ConstantExpression constExp = new PrimitiveConstantExpression(primitiveConst ant); |
|
sigurdm
2014/10/01 07:46:47
Long line
Johnni Winther
2014/10/01 08:21:23
Done.
| |
| 82 Constant constant = new Constant(constExp); | 82 Constant constant = new Constant(constExp); |
| 83 LetPrim letPrim = new LetPrim(constant); | 83 LetPrim letPrim = new LetPrim(constant); |
| 84 InvokeContinuation invoke = | 84 InvokeContinuation invoke = |
| 85 new InvokeContinuation(continuation, <Definition>[constant]); | 85 new InvokeContinuation(continuation, <Definition>[constant]); |
| 86 | 86 |
| 87 invoke.parent = constant.parent = letPrim; | 87 invoke.parent = constant.parent = letPrim; |
| 88 letPrim.body = invoke; | 88 letPrim.body = invoke; |
| 89 | 89 |
| 90 // Replace the method invocation. | 90 // Replace the method invocation. |
| 91 | 91 |
| (...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 361 } else if (lhs.isNonConst) { | 361 } else if (lhs.isNonConst) { |
| 362 setValues(_ConstnessLattice.NonConst); | 362 setValues(_ConstnessLattice.NonConst); |
| 363 return; | 363 return; |
| 364 } else if (!node.selector.isOperator) { | 364 } else if (!node.selector.isOperator) { |
| 365 // TODO(jgruber): Handle known methods on constants such as String.length. | 365 // TODO(jgruber): Handle known methods on constants such as String.length. |
| 366 setValues(_ConstnessLattice.NonConst); | 366 setValues(_ConstnessLattice.NonConst); |
| 367 return; | 367 return; |
| 368 } | 368 } |
| 369 | 369 |
| 370 // Calculate the resulting constant if possible. | 370 // Calculate the resulting constant if possible. |
| 371 values.Constant result; | 371 ConstantValue result; |
| 372 String opname = node.selector.name; | 372 String opname = node.selector.name; |
| 373 if (node.selector.argumentCount == 0) { | 373 if (node.selector.argumentCount == 0) { |
| 374 // Unary operator. | 374 // Unary operator. |
| 375 | 375 |
| 376 if (opname == "unary-") { | 376 if (opname == "unary-") { |
| 377 opname = "-"; | 377 opname = "-"; |
| 378 } | 378 } |
| 379 dart2js.UnaryOperation operation = constantSystem.lookupUnary(opname); | 379 dart2js.UnaryOperation operation = constantSystem.lookupUnary(opname); |
| 380 if (operation != null) { | 380 if (operation != null) { |
| 381 result = operation.fold(lhs.constant); | 381 result = operation.fold(lhs.constant); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 438 } | 438 } |
| 439 Constant constant = ref.definition; | 439 Constant constant = ref.definition; |
| 440 return constant != null && constant.value.isString; | 440 return constant != null && constant.value.isString; |
| 441 }); | 441 }); |
| 442 | 442 |
| 443 assert(cont.parameters.length == 1); | 443 assert(cont.parameters.length == 1); |
| 444 if (allStringConstants) { | 444 if (allStringConstants) { |
| 445 // All constant, we can concatenate ourselves. | 445 // All constant, we can concatenate ourselves. |
| 446 Iterable<String> allStrings = node.arguments.map((Reference ref) { | 446 Iterable<String> allStrings = node.arguments.map((Reference ref) { |
| 447 Constant constant = ref.definition; | 447 Constant constant = ref.definition; |
| 448 values.StringConstant stringConstant = constant.value; | 448 StringConstantValue stringConstant = constant.value; |
| 449 return stringConstant.value.slowToString(); | 449 return stringConstant.primitiveValue.slowToString(); |
| 450 }); | 450 }); |
| 451 LiteralDartString dartString = new LiteralDartString(allStrings.join()); | 451 LiteralDartString dartString = new LiteralDartString(allStrings.join()); |
| 452 values.Constant constant = new values.StringConstant(dartString); | 452 ConstantValue constant = new StringConstantValue(dartString); |
| 453 setValues(new _ConstnessLattice(constant)); | 453 setValues(new _ConstnessLattice(constant)); |
| 454 } else { | 454 } else { |
| 455 setValues(_ConstnessLattice.NonConst); | 455 setValues(_ConstnessLattice.NonConst); |
| 456 } | 456 } |
| 457 } | 457 } |
| 458 | 458 |
| 459 void visitBranch(Branch node) { | 459 void visitBranch(Branch node) { |
| 460 IsTrue isTrue = node.condition; | 460 IsTrue isTrue = node.condition; |
| 461 _ConstnessLattice conditionCell = getValue(isTrue.value.definition); | 461 _ConstnessLattice conditionCell = getValue(isTrue.value.definition); |
| 462 | 462 |
| 463 if (conditionCell.isUnknown) { | 463 if (conditionCell.isUnknown) { |
| 464 return; // And come back later. | 464 return; // And come back later. |
| 465 } else if (conditionCell.isNonConst) { | 465 } else if (conditionCell.isNonConst) { |
| 466 setReachable(node.trueContinuation.definition); | 466 setReachable(node.trueContinuation.definition); |
| 467 setReachable(node.falseContinuation.definition); | 467 setReachable(node.falseContinuation.definition); |
| 468 } else if (conditionCell.isConstant && | 468 } else if (conditionCell.isConstant && |
| 469 !(conditionCell.constant.isBool)) { | 469 !(conditionCell.constant.isBool)) { |
| 470 // Treat non-bool constants in condition as non-const since they result | 470 // Treat non-bool constants in condition as non-const since they result |
| 471 // in type errors in checked mode. | 471 // in type errors in checked mode. |
| 472 // TODO(jgruber): Default to false in unchecked mode. | 472 // TODO(jgruber): Default to false in unchecked mode. |
| 473 setReachable(node.trueContinuation.definition); | 473 setReachable(node.trueContinuation.definition); |
| 474 setReachable(node.falseContinuation.definition); | 474 setReachable(node.falseContinuation.definition); |
| 475 setValue(isTrue.value.definition, _ConstnessLattice.NonConst); | 475 setValue(isTrue.value.definition, _ConstnessLattice.NonConst); |
| 476 } else if (conditionCell.isConstant && | 476 } else if (conditionCell.isConstant && |
| 477 conditionCell.constant.isBool) { | 477 conditionCell.constant.isBool) { |
| 478 values.BoolConstant boolConstant = conditionCell.constant; | 478 BoolConstantValue boolConstant = conditionCell.constant; |
| 479 setReachable((boolConstant.isTrue) ? | 479 setReachable((boolConstant.isTrue) ? |
| 480 node.trueContinuation.definition : node.falseContinuation.definition); | 480 node.trueContinuation.definition : node.falseContinuation.definition); |
| 481 } | 481 } |
| 482 } | 482 } |
| 483 | 483 |
| 484 void visitTypeOperator(TypeOperator node) { | 484 void visitTypeOperator(TypeOperator node) { |
| 485 Continuation cont = node.continuation.definition; | 485 Continuation cont = node.continuation.definition; |
| 486 setReachable(cont); | 486 setReachable(cont); |
| 487 | 487 |
| 488 void setValues(_ConstnessLattice updateValue) { | 488 void setValues(_ConstnessLattice updateValue) { |
| 489 setValue(node, updateValue); | 489 setValue(node, updateValue); |
| 490 Parameter returnValue = cont.parameters[0]; | 490 Parameter returnValue = cont.parameters[0]; |
| 491 setValue(returnValue, updateValue); | 491 setValue(returnValue, updateValue); |
| 492 } | 492 } |
| 493 | 493 |
| 494 if (node.operator != "is") { | 494 if (node.operator != "is") { |
| 495 // TODO(jgruber): Add support for `as` casts. | 495 // TODO(jgruber): Add support for `as` casts. |
| 496 setValues(_ConstnessLattice.NonConst); | 496 setValues(_ConstnessLattice.NonConst); |
| 497 } | 497 } |
| 498 | 498 |
| 499 _ConstnessLattice cell = getValue(node.receiver.definition); | 499 _ConstnessLattice cell = getValue(node.receiver.definition); |
| 500 if (cell.isUnknown) { | 500 if (cell.isUnknown) { |
| 501 return; // And come back later. | 501 return; // And come back later. |
| 502 } else if (cell.isNonConst) { | 502 } else if (cell.isNonConst) { |
| 503 setValues(_ConstnessLattice.NonConst); | 503 setValues(_ConstnessLattice.NonConst); |
| 504 } else if (node.type.kind == types.TypeKind.INTERFACE) { | 504 } else if (node.type.kind == types.TypeKind.INTERFACE) { |
| 505 // Receiver is a constant, perform is-checks at compile-time. | 505 // Receiver is a constant, perform is-checks at compile-time. |
| 506 | 506 |
| 507 types.InterfaceType checkedType = node.type; | 507 types.InterfaceType checkedType = node.type; |
| 508 values.Constant constant = cell.constant; | 508 ConstantValue constant = cell.constant; |
| 509 types.DartType constantType = constant.computeType(compiler); | 509 types.DartType constantType = constant.computeType(compiler); |
| 510 | 510 |
| 511 _ConstnessLattice result = _ConstnessLattice.NonConst; | 511 _ConstnessLattice result = _ConstnessLattice.NonConst; |
| 512 if (constant.isNull && | 512 if (constant.isNull && |
| 513 checkedType.element != compiler.nullClass && | 513 checkedType.element != compiler.nullClass && |
| 514 checkedType.element != compiler.objectClass) { | 514 checkedType.element != compiler.objectClass) { |
| 515 // `(null is Type)` is true iff Type is in { Null, Object }. | 515 // `(null is Type)` is true iff Type is in { Null, Object }. |
| 516 result = new _ConstnessLattice(new values.FalseConstant()); | 516 result = new _ConstnessLattice(new FalseConstantValue()); |
| 517 } else { | 517 } else { |
| 518 // Otherwise, perform a standard subtype check. | 518 // Otherwise, perform a standard subtype check. |
| 519 result = new _ConstnessLattice( | 519 result = new _ConstnessLattice( |
| 520 constantSystem.isSubtype(compiler, constantType, checkedType) | 520 constantSystem.isSubtype(compiler, constantType, checkedType) |
| 521 ? new values.TrueConstant() | 521 ? new TrueConstantValue() |
| 522 : new values.FalseConstant()); | 522 : new FalseConstantValue()); |
| 523 } | 523 } |
| 524 | 524 |
| 525 setValues(result); | 525 setValues(result); |
| 526 } | 526 } |
| 527 } | 527 } |
| 528 | 528 |
| 529 void visitSetClosureVariable(SetClosureVariable node) { | 529 void visitSetClosureVariable(SetClosureVariable node) { |
| 530 setReachable(node.body); | 530 setReachable(node.body); |
| 531 } | 531 } |
| 532 | 532 |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 555 void visitThis(This node) { | 555 void visitThis(This node) { |
| 556 setValue(node, _ConstnessLattice.NonConst); | 556 setValue(node, _ConstnessLattice.NonConst); |
| 557 } | 557 } |
| 558 | 558 |
| 559 void visitReifyTypeVar(ReifyTypeVar node) { | 559 void visitReifyTypeVar(ReifyTypeVar node) { |
| 560 setValue(node, _ConstnessLattice.NonConst); | 560 setValue(node, _ConstnessLattice.NonConst); |
| 561 } | 561 } |
| 562 | 562 |
| 563 void visitCreateFunction(CreateFunction node) { | 563 void visitCreateFunction(CreateFunction node) { |
| 564 setReachable(node.definition); | 564 setReachable(node.definition); |
| 565 values.Constant constant = | 565 ConstantValue constant = |
| 566 new values.FunctionConstant(node.definition.element); | 566 new FunctionConstantValue(node.definition.element); |
| 567 setValue(node, new _ConstnessLattice(constant)); | 567 setValue(node, new _ConstnessLattice(constant)); |
| 568 } | 568 } |
| 569 | 569 |
| 570 void visitGetClosureVariable(GetClosureVariable node) { | 570 void visitGetClosureVariable(GetClosureVariable node) { |
| 571 setValue(node, _ConstnessLattice.NonConst); | 571 setValue(node, _ConstnessLattice.NonConst); |
| 572 } | 572 } |
| 573 | 573 |
| 574 void visitParameter(Parameter node) { | 574 void visitParameter(Parameter node) { |
| 575 if (node.parent is FunctionDefinition) { | 575 if (node.parent is FunctionDefinition) { |
| 576 // Functions may escape and thus their parameters must be initialized to | 576 // Functions may escape and thus their parameters must be initialized to |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 607 /// Represents the constant-state of a variable at some point in the program. | 607 /// Represents the constant-state of a variable at some point in the program. |
| 608 /// UNKNOWN: may be some as yet undetermined constant. | 608 /// UNKNOWN: may be some as yet undetermined constant. |
| 609 /// CONSTANT: is a constant as stored in the local field. | 609 /// CONSTANT: is a constant as stored in the local field. |
| 610 /// NONCONST: not a constant. | 610 /// NONCONST: not a constant. |
| 611 class _ConstnessLattice { | 611 class _ConstnessLattice { |
| 612 static const int UNKNOWN = 0; | 612 static const int UNKNOWN = 0; |
| 613 static const int CONSTANT = 1; | 613 static const int CONSTANT = 1; |
| 614 static const int NONCONST = 2; | 614 static const int NONCONST = 2; |
| 615 | 615 |
| 616 final int kind; | 616 final int kind; |
| 617 final values.Constant constant; | 617 final ConstantValue constant; |
| 618 | 618 |
| 619 static final _ConstnessLattice Unknown = | 619 static final _ConstnessLattice Unknown = |
| 620 new _ConstnessLattice._internal(UNKNOWN, null); | 620 new _ConstnessLattice._internal(UNKNOWN, null); |
| 621 static final _ConstnessLattice NonConst = | 621 static final _ConstnessLattice NonConst = |
| 622 new _ConstnessLattice._internal(NONCONST, null); | 622 new _ConstnessLattice._internal(NONCONST, null); |
| 623 | 623 |
| 624 _ConstnessLattice._internal(this.kind, this.constant); | 624 _ConstnessLattice._internal(this.kind, this.constant); |
| 625 _ConstnessLattice(this.constant) : kind = CONSTANT { | 625 _ConstnessLattice(this.constant) : kind = CONSTANT { |
| 626 assert(this.constant != null); | 626 assert(this.constant != null); |
| 627 } | 627 } |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 656 return that; | 656 return that; |
| 657 } | 657 } |
| 658 | 658 |
| 659 if (this.constant == that.constant) { | 659 if (this.constant == that.constant) { |
| 660 return this; | 660 return this; |
| 661 } | 661 } |
| 662 | 662 |
| 663 return NonConst; | 663 return NonConst; |
| 664 } | 664 } |
| 665 } | 665 } |
| OLD | NEW |