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 |