| 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 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 73 } | 74 } |
| 74 } | 75 } |
| 75 } | 76 } |
| 76 } | 77 } |
| 77 | 78 |
| 78 | 79 |
| 79 static Definition* CreateConversion(Representation from, | 80 static Definition* CreateConversion(Representation from, |
| 80 Representation to, | 81 Representation to, |
| 81 Definition* def, | 82 Definition* def, |
| 82 Instruction* deopt_target) { | 83 Instruction* deopt_target) { |
| 83 if ((from == kUnboxedDouble) && (to == kTagged)) { | 84 if (from == kTagged && to == kUnboxedInteger) { |
| 85 const intptr_t deopt_id = (deopt_target != NULL) ? |
| 86 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; |
| 87 ASSERT((deopt_target != NULL) || (def->GetPropagatedCid() == kDoubleCid)); |
| 88 return new UnboxIntegerInstr(new Value(def), deopt_id); |
| 89 } else if (from == kUnboxedInteger && to == kTagged) { |
| 90 return new BoxIntegerInstr(new Value(def)); |
| 91 } else if ((from == kUnboxedDouble) && (to == kTagged)) { |
| 84 return new BoxDoubleInstr(new Value(def), NULL); | 92 return new BoxDoubleInstr(new Value(def), NULL); |
| 85 } else if ((from == kTagged) && (to == kUnboxedDouble)) { | 93 } else if ((from == kTagged) && (to == kUnboxedDouble)) { |
| 86 const intptr_t deopt_id = (deopt_target != NULL) ? | 94 const intptr_t deopt_id = (deopt_target != NULL) ? |
| 87 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; | 95 deopt_target->DeoptimizationTarget() : Isolate::kNoDeoptId; |
| 88 ASSERT((deopt_target != NULL) || (def->GetPropagatedCid() == kDoubleCid)); | 96 ASSERT((deopt_target != NULL) || (def->GetPropagatedCid() == kDoubleCid)); |
| 89 return new UnboxDoubleInstr(new Value(def), deopt_id); | 97 return new UnboxDoubleInstr(new Value(def), deopt_id); |
| 90 } else { | 98 } else { |
| 91 UNREACHABLE(); | 99 UNREACHABLE(); |
| 92 return NULL; | 100 return NULL; |
| 93 } | 101 } |
| (...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 477 if (ShouldSpecializeForDouble(ic_data)) { | 485 if (ShouldSpecializeForDouble(ic_data)) { |
| 478 operands_type = kDoubleCid; | 486 operands_type = kDoubleCid; |
| 479 } else { | 487 } else { |
| 480 return false; | 488 return false; |
| 481 } | 489 } |
| 482 break; | 490 break; |
| 483 case Token::kMOD: | 491 case Token::kMOD: |
| 484 // TODO(vegorov): implement fast path code for modulo. | 492 // TODO(vegorov): implement fast path code for modulo. |
| 485 return false; | 493 return false; |
| 486 case Token::kBIT_AND: | 494 case Token::kBIT_AND: |
| 495 case Token::kBIT_OR: |
| 496 case Token::kBIT_XOR: |
| 487 if (HasOnlyTwoSmi(ic_data)) { | 497 if (HasOnlyTwoSmi(ic_data)) { |
| 488 operands_type = kSmiCid; | 498 operands_type = kSmiCid; |
| 489 } else if (HasTwoMintOrSmi(ic_data)) { | 499 } else if (HasTwoMintOrSmi(ic_data) && |
| 500 FlowGraphCompiler::SupportsUnboxedMints()) { |
| 490 operands_type = kMintCid; | 501 operands_type = kMintCid; |
| 491 } else { | 502 } else { |
| 492 return false; | 503 return false; |
| 493 } | 504 } |
| 494 break; | 505 break; |
| 495 case Token::kBIT_OR: | |
| 496 case Token::kBIT_XOR: | |
| 497 case Token::kTRUNCDIV: | 506 case Token::kTRUNCDIV: |
| 507 case Token::kSHL: |
| 498 case Token::kSHR: | 508 case Token::kSHR: |
| 499 case Token::kSHL: | |
| 500 if (HasOnlyTwoSmi(ic_data)) { | 509 if (HasOnlyTwoSmi(ic_data)) { |
| 501 operands_type = kSmiCid; | 510 operands_type = kSmiCid; |
| 502 } else { | 511 } else { |
| 503 return false; | 512 return false; |
| 504 } | 513 } |
| 505 break; | 514 break; |
| 506 default: | 515 default: |
| 507 UNREACHABLE(); | 516 UNREACHABLE(); |
| 508 }; | 517 }; |
| 509 | 518 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 524 UnboxedDoubleBinaryOpInstr* double_bin_op = | 533 UnboxedDoubleBinaryOpInstr* double_bin_op = |
| 525 new UnboxedDoubleBinaryOpInstr(op_kind, | 534 new UnboxedDoubleBinaryOpInstr(op_kind, |
| 526 left->Copy(), | 535 left->Copy(), |
| 527 right->Copy(), | 536 right->Copy(), |
| 528 call); | 537 call); |
| 529 call->ReplaceWith(double_bin_op, current_iterator()); | 538 call->ReplaceWith(double_bin_op, current_iterator()); |
| 530 RemovePushArguments(call); | 539 RemovePushArguments(call); |
| 531 } else if (operands_type == kMintCid) { | 540 } else if (operands_type == kMintCid) { |
| 532 Value* left = call->ArgumentAt(0)->value(); | 541 Value* left = call->ArgumentAt(0)->value(); |
| 533 Value* right = call->ArgumentAt(1)->value(); | 542 Value* right = call->ArgumentAt(1)->value(); |
| 534 BinaryMintOpInstr* bin_op = new BinaryMintOpInstr(op_kind, | 543 UnboxedMintBinaryOpInstr* bin_op = |
| 535 call, | 544 new UnboxedMintBinaryOpInstr(op_kind, left, right, call); |
| 536 left, | |
| 537 right); | |
| 538 call->ReplaceWith(bin_op, current_iterator()); | 545 call->ReplaceWith(bin_op, current_iterator()); |
| 539 RemovePushArguments(call); | 546 RemovePushArguments(call); |
| 540 } else { | 547 } else { |
| 541 ASSERT(operands_type == kSmiCid); | 548 ASSERT(operands_type == kSmiCid); |
| 542 Value* left = call->ArgumentAt(0)->value(); | 549 Value* left = call->ArgumentAt(0)->value(); |
| 543 Value* right = call->ArgumentAt(1)->value(); | 550 Value* right = call->ArgumentAt(1)->value(); |
| 544 // Insert two smi checks and attach a copy of the original | 551 // Insert two smi checks and attach a copy of the original |
| 545 // environment because the smi operation can still deoptimize. | 552 // environment because the smi operation can still deoptimize. |
| 546 InsertBefore(call, | 553 InsertBefore(call, |
| 547 new CheckSmiInstr(left->Copy(), call->deopt_id()), | 554 new CheckSmiInstr(left->Copy(), call->deopt_id()), |
| (...skipping 429 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 977 new StrictCompareInstr(strict_kind, comp->left(), comp->right()); | 984 new StrictCompareInstr(strict_kind, comp->left(), comp->right()); |
| 978 instr->ReplaceWith(strict_comp, iterator); | 985 instr->ReplaceWith(strict_comp, iterator); |
| 979 return; | 986 return; |
| 980 } | 987 } |
| 981 if (!comp->HasICData() || (comp->ic_data()->NumberOfChecks() == 0)) return; | 988 if (!comp->HasICData() || (comp->ic_data()->NumberOfChecks() == 0)) return; |
| 982 if (comp->ic_data()->NumberOfChecks() == 1) { | 989 if (comp->ic_data()->NumberOfChecks() == 1) { |
| 983 ASSERT(comp->ic_data()->num_args_tested() == 2); | 990 ASSERT(comp->ic_data()->num_args_tested() == 2); |
| 984 GrowableArray<intptr_t> class_ids; | 991 GrowableArray<intptr_t> class_ids; |
| 985 Function& target = Function::Handle(); | 992 Function& target = Function::Handle(); |
| 986 comp->ic_data()->GetCheckAt(0, &class_ids, &target); | 993 comp->ic_data()->GetCheckAt(0, &class_ids, &target); |
| 987 // TODO(srdjan): allow for mixed mode comparison. | 994 // TODO(srdjan): allow for mixed mode int/double comparison. |
| 995 |
| 988 if ((class_ids[0] == kSmiCid) && (class_ids[1] == kSmiCid)) { | 996 if ((class_ids[0] == kSmiCid) && (class_ids[1] == kSmiCid)) { |
| 989 optimizer->InsertBefore( | 997 optimizer->InsertBefore( |
| 990 instr, | 998 instr, |
| 991 new CheckSmiInstr(comp->left()->Copy(), comp->deopt_id()), | 999 new CheckSmiInstr(comp->left()->Copy(), comp->deopt_id()), |
| 992 instr->env(), | 1000 instr->env(), |
| 993 Definition::kEffect); | 1001 Definition::kEffect); |
| 994 optimizer->InsertBefore( | 1002 optimizer->InsertBefore( |
| 995 instr, | 1003 instr, |
| 996 new CheckSmiInstr(comp->right()->Copy(), comp->deopt_id()), | 1004 new CheckSmiInstr(comp->right()->Copy(), comp->deopt_id()), |
| 997 instr->env(), | 1005 instr->env(), |
| 998 Definition::kEffect); | 1006 Definition::kEffect); |
| 999 comp->set_receiver_class_id(kSmiCid); | 1007 comp->set_receiver_class_id(kSmiCid); |
| 1000 } else if ((class_ids[0] == kDoubleCid) && (class_ids[1] == kDoubleCid)) { | 1008 } else if ((class_ids[0] == kDoubleCid) && (class_ids[1] == kDoubleCid)) { |
| 1001 comp->set_receiver_class_id(kDoubleCid); | 1009 comp->set_receiver_class_id(kDoubleCid); |
| 1010 } else if (HasTwoMintOrSmi(*comp->ic_data()) && |
| 1011 FlowGraphCompiler::SupportsUnboxedMints()) { |
| 1012 comp->set_receiver_class_id(kMintCid); |
| 1002 } else { | 1013 } else { |
| 1003 ASSERT(comp->receiver_class_id() == kIllegalCid); | 1014 ASSERT(comp->receiver_class_id() == kIllegalCid); |
| 1004 } | 1015 } |
| 1016 } else if (HasTwoMintOrSmi(*comp->ic_data())) { |
| 1017 comp->set_receiver_class_id(kMintCid); |
| 1005 } else if (comp->ic_data()->AllReceiversAreNumbers()) { | 1018 } else if (comp->ic_data()->AllReceiversAreNumbers()) { |
| 1006 comp->set_receiver_class_id(kNumberCid); | 1019 comp->set_receiver_class_id(kNumberCid); |
| 1007 } | 1020 } |
| 1008 } | 1021 } |
| 1009 | 1022 |
| 1010 | 1023 |
| 1011 void FlowGraphOptimizer::VisitEqualityCompare(EqualityCompareInstr* instr) { | 1024 void FlowGraphOptimizer::VisitEqualityCompare(EqualityCompareInstr* instr) { |
| 1012 HandleEqualityCompare(this, instr, instr, current_iterator()); | 1025 HandleEqualityCompare(this, instr, instr, current_iterator()); |
| 1013 } | 1026 } |
| 1014 | 1027 |
| (...skipping 1692 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2707 SetValue(instr, non_constant_); | 2720 SetValue(instr, non_constant_); |
| 2708 } | 2721 } |
| 2709 } else { | 2722 } else { |
| 2710 // TODO(kmillikin): support other types. | 2723 // TODO(kmillikin): support other types. |
| 2711 SetValue(instr, non_constant_); | 2724 SetValue(instr, non_constant_); |
| 2712 } | 2725 } |
| 2713 } | 2726 } |
| 2714 } | 2727 } |
| 2715 | 2728 |
| 2716 | 2729 |
| 2717 void ConstantPropagator::VisitBinaryMintOp(BinaryMintOpInstr* instr) { | 2730 void ConstantPropagator::VisitBoxInteger(BoxIntegerInstr* instr) { |
| 2718 const Object& left = instr->left()->definition()->constant_value(); | 2731 // TODO(kmillikin): Handle box operation. |
| 2719 const Object& right = instr->right()->definition()->constant_value(); | 2732 SetValue(instr, non_constant_); |
| 2720 if (IsNonConstant(left) || IsNonConstant(right)) { | |
| 2721 SetValue(instr, non_constant_); | |
| 2722 } else if (IsConstant(left) && IsConstant(right)) { | |
| 2723 // TODO(kmillikin): Handle binary operations. | |
| 2724 SetValue(instr, non_constant_); | |
| 2725 } | |
| 2726 } | 2733 } |
| 2727 | 2734 |
| 2728 | 2735 |
| 2736 void ConstantPropagator::VisitUnboxInteger(UnboxIntegerInstr* instr) { |
| 2737 // TODO(kmillikin): Handle unbox operation. |
| 2738 SetValue(instr, non_constant_); |
| 2739 } |
| 2740 |
| 2741 |
| 2742 void ConstantPropagator::VisitUnboxedMintBinaryOp( |
| 2743 UnboxedMintBinaryOpInstr* instr) { |
| 2744 // TODO(kmillikin): Handle binary operations. |
| 2745 SetValue(instr, non_constant_); |
| 2746 } |
| 2747 |
| 2729 void ConstantPropagator::VisitUnarySmiOp(UnarySmiOpInstr* instr) { | 2748 void ConstantPropagator::VisitUnarySmiOp(UnarySmiOpInstr* instr) { |
| 2730 const Object& value = instr->value()->definition()->constant_value(); | 2749 const Object& value = instr->value()->definition()->constant_value(); |
| 2731 if (IsNonConstant(value)) { | 2750 if (IsNonConstant(value)) { |
| 2732 SetValue(instr, non_constant_); | 2751 SetValue(instr, non_constant_); |
| 2733 } else if (IsConstant(value)) { | 2752 } else if (IsConstant(value)) { |
| 2734 // TODO(kmillikin): Handle unary operations. | 2753 // TODO(kmillikin): Handle unary operations. |
| 2735 SetValue(instr, non_constant_); | 2754 SetValue(instr, non_constant_); |
| 2736 } | 2755 } |
| 2737 } | 2756 } |
| 2738 | 2757 |
| (...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2968 } | 2987 } |
| 2969 | 2988 |
| 2970 graph_->DiscoverBlocks(); | 2989 graph_->DiscoverBlocks(); |
| 2971 GrowableArray<BitVector*> dominance_frontier; | 2990 GrowableArray<BitVector*> dominance_frontier; |
| 2972 graph_->ComputeDominators(&dominance_frontier); | 2991 graph_->ComputeDominators(&dominance_frontier); |
| 2973 graph_->ComputeUseLists(); | 2992 graph_->ComputeUseLists(); |
| 2974 } | 2993 } |
| 2975 | 2994 |
| 2976 | 2995 |
| 2977 } // namespace dart | 2996 } // namespace dart |
| OLD | NEW |