| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 #include "vm/flow_graph_optimizer.h" | 5 #include "vm/flow_graph_optimizer.h" |
| 6 | 6 |
| 7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
| 8 #include "vm/cha.h" | 8 #include "vm/cha.h" |
| 9 #include "vm/flow_graph_builder.h" | 9 #include "vm/flow_graph_builder.h" |
| 10 #include "vm/flow_graph_compiler.h" |
| 10 #include "vm/hash_map.h" | 11 #include "vm/hash_map.h" |
| 11 #include "vm/il_printer.h" | 12 #include "vm/il_printer.h" |
| 12 #include "vm/intermediate_language.h" | 13 #include "vm/intermediate_language.h" |
| 13 #include "vm/object_store.h" | 14 #include "vm/object_store.h" |
| 14 #include "vm/parser.h" | 15 #include "vm/parser.h" |
| 15 #include "vm/scopes.h" | 16 #include "vm/scopes.h" |
| 16 #include "vm/symbols.h" | 17 #include "vm/symbols.h" |
| 17 | 18 |
| 18 namespace dart { | 19 namespace dart { |
| 19 | 20 |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 76 } | 77 } |
| 77 } | 78 } |
| 78 } | 79 } |
| 79 } | 80 } |
| 80 | 81 |
| 81 | 82 |
| 82 static Definition* CreateConversion(Representation from, | 83 static Definition* CreateConversion(Representation from, |
| 83 Representation to, | 84 Representation to, |
| 84 Definition* def, | 85 Definition* def, |
| 85 Instruction* deopt_target) { | 86 Instruction* deopt_target) { |
| 86 if ((from == kUnboxedDouble) && (to == kTagged)) { | 87 if ((from == kTagged) && (to == kUnboxedInteger)) { |
| 88 const intptr_t deopt_id = (deopt_target != NULL) ? |
| 89 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; |
| 90 ASSERT((deopt_target != NULL) || (def->GetPropagatedCid() == kDoubleCid)); |
| 91 return new UnboxIntegerInstr(new Value(def), deopt_id); |
| 92 } else if ((from == kUnboxedInteger) && (to == kTagged)) { |
| 93 return new BoxIntegerInstr(new Value(def)); |
| 94 } else if ((from == kUnboxedDouble) && (to == kTagged)) { |
| 87 return new BoxDoubleInstr(new Value(def), NULL); | 95 return new BoxDoubleInstr(new Value(def), NULL); |
| 88 } else if ((from == kTagged) && (to == kUnboxedDouble)) { | 96 } else if ((from == kTagged) && (to == kUnboxedDouble)) { |
| 89 const intptr_t deopt_id = (deopt_target != NULL) ? | 97 const intptr_t deopt_id = (deopt_target != NULL) ? |
| 90 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; | 98 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; |
| 91 ASSERT((deopt_target != NULL) || (def->GetPropagatedCid() == kDoubleCid)); | 99 ASSERT((deopt_target != NULL) || (def->GetPropagatedCid() == kDoubleCid)); |
| 92 return new UnboxDoubleInstr(new Value(def), deopt_id); | 100 return new UnboxDoubleInstr(new Value(def), deopt_id); |
| 93 } else { | 101 } else { |
| 94 UNREACHABLE(); | 102 UNREACHABLE(); |
| 95 return NULL; | 103 return NULL; |
| 96 } | 104 } |
| (...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 464 if (ShouldSpecializeForDouble(ic_data)) { | 472 if (ShouldSpecializeForDouble(ic_data)) { |
| 465 operands_type = kDoubleCid; | 473 operands_type = kDoubleCid; |
| 466 } else { | 474 } else { |
| 467 return false; | 475 return false; |
| 468 } | 476 } |
| 469 break; | 477 break; |
| 470 case Token::kMOD: | 478 case Token::kMOD: |
| 471 // TODO(vegorov): implement fast path code for modulo. | 479 // TODO(vegorov): implement fast path code for modulo. |
| 472 return false; | 480 return false; |
| 473 case Token::kBIT_AND: | 481 case Token::kBIT_AND: |
| 482 case Token::kBIT_OR: |
| 483 case Token::kBIT_XOR: |
| 474 if (HasOnlyTwoSmi(ic_data)) { | 484 if (HasOnlyTwoSmi(ic_data)) { |
| 475 operands_type = kSmiCid; | 485 operands_type = kSmiCid; |
| 476 } else if (HasTwoMintOrSmi(ic_data)) { | 486 } else if (HasTwoMintOrSmi(ic_data) && |
| 487 FlowGraphCompiler::SupportsUnboxedMints()) { |
| 477 operands_type = kMintCid; | 488 operands_type = kMintCid; |
| 478 } else { | 489 } else { |
| 479 return false; | 490 return false; |
| 480 } | 491 } |
| 481 break; | 492 break; |
| 482 case Token::kBIT_OR: | |
| 483 case Token::kBIT_XOR: | |
| 484 case Token::kTRUNCDIV: | 493 case Token::kTRUNCDIV: |
| 485 case Token::kSHR: | 494 case Token::kSHR: |
| 486 case Token::kSHL: | 495 case Token::kSHL: |
| 487 if (HasOnlyTwoSmi(ic_data)) { | 496 if (HasOnlyTwoSmi(ic_data)) { |
| 488 operands_type = kSmiCid; | 497 operands_type = kSmiCid; |
| 489 } else { | 498 } else { |
| 490 return false; | 499 return false; |
| 491 } | 500 } |
| 492 break; | 501 break; |
| 493 default: | 502 default: |
| (...skipping 17 matching lines...) Expand all Loading... |
| 511 UnboxedDoubleBinaryOpInstr* double_bin_op = | 520 UnboxedDoubleBinaryOpInstr* double_bin_op = |
| 512 new UnboxedDoubleBinaryOpInstr(op_kind, | 521 new UnboxedDoubleBinaryOpInstr(op_kind, |
| 513 left->Copy(), | 522 left->Copy(), |
| 514 right->Copy(), | 523 right->Copy(), |
| 515 call); | 524 call); |
| 516 call->ReplaceWith(double_bin_op, current_iterator()); | 525 call->ReplaceWith(double_bin_op, current_iterator()); |
| 517 RemovePushArguments(call); | 526 RemovePushArguments(call); |
| 518 } else if (operands_type == kMintCid) { | 527 } else if (operands_type == kMintCid) { |
| 519 Value* left = call->ArgumentAt(0)->value(); | 528 Value* left = call->ArgumentAt(0)->value(); |
| 520 Value* right = call->ArgumentAt(1)->value(); | 529 Value* right = call->ArgumentAt(1)->value(); |
| 521 BinaryMintOpInstr* bin_op = new BinaryMintOpInstr(op_kind, | 530 UnboxedMintBinaryOpInstr* bin_op = |
| 522 call, | 531 new UnboxedMintBinaryOpInstr(op_kind, left, right, call); |
| 523 left, | |
| 524 right); | |
| 525 call->ReplaceWith(bin_op, current_iterator()); | 532 call->ReplaceWith(bin_op, current_iterator()); |
| 526 RemovePushArguments(call); | 533 RemovePushArguments(call); |
| 527 } else { | 534 } else { |
| 528 ASSERT(operands_type == kSmiCid); | 535 ASSERT(operands_type == kSmiCid); |
| 529 Value* left = call->ArgumentAt(0)->value(); | 536 Value* left = call->ArgumentAt(0)->value(); |
| 530 Value* right = call->ArgumentAt(1)->value(); | 537 Value* right = call->ArgumentAt(1)->value(); |
| 531 // Insert two smi checks and attach a copy of the original | 538 // Insert two smi checks and attach a copy of the original |
| 532 // environment because the smi operation can still deoptimize. | 539 // environment because the smi operation can still deoptimize. |
| 533 InsertBefore(call, | 540 InsertBefore(call, |
| 534 new CheckSmiInstr(left->Copy(), call->deopt_id()), | 541 new CheckSmiInstr(left->Copy(), call->deopt_id()), |
| (...skipping 429 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 964 new StrictCompareInstr(strict_kind, comp->left(), comp->right()); | 971 new StrictCompareInstr(strict_kind, comp->left(), comp->right()); |
| 965 instr->ReplaceWith(strict_comp, iterator); | 972 instr->ReplaceWith(strict_comp, iterator); |
| 966 return; | 973 return; |
| 967 } | 974 } |
| 968 if (!comp->HasICData() || (comp->ic_data()->NumberOfChecks() == 0)) return; | 975 if (!comp->HasICData() || (comp->ic_data()->NumberOfChecks() == 0)) return; |
| 969 if (comp->ic_data()->NumberOfChecks() == 1) { | 976 if (comp->ic_data()->NumberOfChecks() == 1) { |
| 970 ASSERT(comp->ic_data()->num_args_tested() == 2); | 977 ASSERT(comp->ic_data()->num_args_tested() == 2); |
| 971 GrowableArray<intptr_t> class_ids; | 978 GrowableArray<intptr_t> class_ids; |
| 972 Function& target = Function::Handle(); | 979 Function& target = Function::Handle(); |
| 973 comp->ic_data()->GetCheckAt(0, &class_ids, &target); | 980 comp->ic_data()->GetCheckAt(0, &class_ids, &target); |
| 974 // TODO(srdjan): allow for mixed mode comparison. | 981 // TODO(srdjan): allow for mixed mode int/double comparison. |
| 982 |
| 975 if ((class_ids[0] == kSmiCid) && (class_ids[1] == kSmiCid)) { | 983 if ((class_ids[0] == kSmiCid) && (class_ids[1] == kSmiCid)) { |
| 976 optimizer->InsertBefore( | 984 optimizer->InsertBefore( |
| 977 instr, | 985 instr, |
| 978 new CheckSmiInstr(comp->left()->Copy(), comp->deopt_id()), | 986 new CheckSmiInstr(comp->left()->Copy(), comp->deopt_id()), |
| 979 instr->env(), | 987 instr->env(), |
| 980 Definition::kEffect); | 988 Definition::kEffect); |
| 981 optimizer->InsertBefore( | 989 optimizer->InsertBefore( |
| 982 instr, | 990 instr, |
| 983 new CheckSmiInstr(comp->right()->Copy(), comp->deopt_id()), | 991 new CheckSmiInstr(comp->right()->Copy(), comp->deopt_id()), |
| 984 instr->env(), | 992 instr->env(), |
| 985 Definition::kEffect); | 993 Definition::kEffect); |
| 986 comp->set_receiver_class_id(kSmiCid); | 994 comp->set_receiver_class_id(kSmiCid); |
| 987 } else if ((class_ids[0] == kDoubleCid) && (class_ids[1] == kDoubleCid)) { | 995 } else if ((class_ids[0] == kDoubleCid) && (class_ids[1] == kDoubleCid)) { |
| 988 comp->set_receiver_class_id(kDoubleCid); | 996 comp->set_receiver_class_id(kDoubleCid); |
| 997 } else if (HasTwoMintOrSmi(*comp->ic_data()) && |
| 998 FlowGraphCompiler::SupportsUnboxedMints()) { |
| 999 comp->set_receiver_class_id(kMintCid); |
| 989 } else { | 1000 } else { |
| 990 ASSERT(comp->receiver_class_id() == kIllegalCid); | 1001 ASSERT(comp->receiver_class_id() == kIllegalCid); |
| 991 } | 1002 } |
| 1003 } else if (HasTwoMintOrSmi(*comp->ic_data())) { |
| 1004 comp->set_receiver_class_id(kMintCid); |
| 992 } else if (comp->ic_data()->AllReceiversAreNumbers()) { | 1005 } else if (comp->ic_data()->AllReceiversAreNumbers()) { |
| 993 comp->set_receiver_class_id(kNumberCid); | 1006 comp->set_receiver_class_id(kNumberCid); |
| 994 } | 1007 } |
| 995 } | 1008 } |
| 996 | 1009 |
| 997 | 1010 |
| 998 void FlowGraphOptimizer::VisitEqualityCompare(EqualityCompareInstr* instr) { | 1011 void FlowGraphOptimizer::VisitEqualityCompare(EqualityCompareInstr* instr) { |
| 999 HandleEqualityCompare(this, instr, instr, current_iterator()); | 1012 HandleEqualityCompare(this, instr, instr, current_iterator()); |
| 1000 } | 1013 } |
| 1001 | 1014 |
| (...skipping 1774 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2776 SetValue(instr, non_constant_); | 2789 SetValue(instr, non_constant_); |
| 2777 } | 2790 } |
| 2778 } else { | 2791 } else { |
| 2779 // TODO(kmillikin): support other types. | 2792 // TODO(kmillikin): support other types. |
| 2780 SetValue(instr, non_constant_); | 2793 SetValue(instr, non_constant_); |
| 2781 } | 2794 } |
| 2782 } | 2795 } |
| 2783 } | 2796 } |
| 2784 | 2797 |
| 2785 | 2798 |
| 2799 void ConstantPropagator::VisitBoxInteger(BoxIntegerInstr* instr) { |
| 2800 // TODO(kmillikin): Handle box operation. |
| 2801 SetValue(instr, non_constant_); |
| 2802 } |
| 2803 |
| 2804 |
| 2805 void ConstantPropagator::VisitUnboxInteger(UnboxIntegerInstr* instr) { |
| 2806 // TODO(kmillikin): Handle unbox operation. |
| 2807 SetValue(instr, non_constant_); |
| 2808 } |
| 2809 |
| 2810 |
| 2811 void ConstantPropagator::VisitUnboxedMintBinaryOp( |
| 2812 UnboxedMintBinaryOpInstr* instr) { |
| 2813 // TODO(kmillikin): Handle binary operations. |
| 2814 SetValue(instr, non_constant_); |
| 2815 } |
| 2816 |
| 2817 |
| 2786 void ConstantPropagator::VisitBinaryMintOp(BinaryMintOpInstr* instr) { | 2818 void ConstantPropagator::VisitBinaryMintOp(BinaryMintOpInstr* instr) { |
| 2787 const Object& left = instr->left()->definition()->constant_value(); | 2819 const Object& left = instr->left()->definition()->constant_value(); |
| 2788 const Object& right = instr->right()->definition()->constant_value(); | 2820 const Object& right = instr->right()->definition()->constant_value(); |
| 2789 if (IsNonConstant(left) || IsNonConstant(right)) { | 2821 if (IsNonConstant(left) || IsNonConstant(right)) { |
| 2790 SetValue(instr, non_constant_); | 2822 SetValue(instr, non_constant_); |
| 2791 } else if (IsConstant(left) && IsConstant(right)) { | 2823 } else if (IsConstant(left) && IsConstant(right)) { |
| 2792 // TODO(kmillikin): Handle binary operations. | 2824 // TODO(kmillikin): Handle binary operations. |
| 2793 SetValue(instr, non_constant_); | 2825 SetValue(instr, non_constant_); |
| 2794 } | 2826 } |
| 2795 } | 2827 } |
| (...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3031 | 3063 |
| 3032 if (FLAG_trace_constant_propagation) { | 3064 if (FLAG_trace_constant_propagation) { |
| 3033 OS::Print("\n==== After constant propagation ====\n"); | 3065 OS::Print("\n==== After constant propagation ====\n"); |
| 3034 FlowGraphPrinter printer(*graph_); | 3066 FlowGraphPrinter printer(*graph_); |
| 3035 printer.PrintBlocks(); | 3067 printer.PrintBlocks(); |
| 3036 } | 3068 } |
| 3037 } | 3069 } |
| 3038 | 3070 |
| 3039 | 3071 |
| 3040 } // namespace dart | 3072 } // namespace dart |
| OLD | NEW |