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