OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 719 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
730 last_true_block_(NULL), | 730 last_true_block_(NULL), |
731 first_false_block_(NULL), | 731 first_false_block_(NULL), |
732 split_edge_merge_block_(NULL), | 732 split_edge_merge_block_(NULL), |
733 merge_block_(NULL) { | 733 merge_block_(NULL) { |
734 continuation->Continue(&first_true_block_, | 734 continuation->Continue(&first_true_block_, |
735 &first_false_block_, | 735 &first_false_block_, |
736 &position_); | 736 &position_); |
737 } | 737 } |
738 | 738 |
739 | 739 |
740 void HGraphBuilder::IfBuilder::AddCompare(HControlInstruction* compare) { | 740 HControlInstruction* HGraphBuilder::IfBuilder::AddCompare( |
| 741 HControlInstruction* compare) { |
741 if (split_edge_merge_block_ != NULL) { | 742 if (split_edge_merge_block_ != NULL) { |
742 HEnvironment* env = first_false_block_->last_environment(); | 743 HEnvironment* env = first_false_block_->last_environment(); |
743 HBasicBlock* split_edge = | 744 HBasicBlock* split_edge = |
744 builder_->CreateBasicBlock(env->Copy()); | 745 builder_->CreateBasicBlock(env->Copy()); |
745 if (did_or_) { | 746 if (did_or_) { |
746 compare->SetSuccessorAt(0, split_edge); | 747 compare->SetSuccessorAt(0, split_edge); |
747 compare->SetSuccessorAt(1, first_false_block_); | 748 compare->SetSuccessorAt(1, first_false_block_); |
748 } else { | 749 } else { |
749 compare->SetSuccessorAt(0, first_true_block_); | 750 compare->SetSuccessorAt(0, first_true_block_); |
750 compare->SetSuccessorAt(1, split_edge); | 751 compare->SetSuccessorAt(1, split_edge); |
751 } | 752 } |
752 split_edge->GotoNoSimulate(split_edge_merge_block_); | 753 split_edge->GotoNoSimulate(split_edge_merge_block_); |
753 } else { | 754 } else { |
754 compare->SetSuccessorAt(0, first_true_block_); | 755 compare->SetSuccessorAt(0, first_true_block_); |
755 compare->SetSuccessorAt(1, first_false_block_); | 756 compare->SetSuccessorAt(1, first_false_block_); |
756 } | 757 } |
757 builder_->current_block()->Finish(compare); | 758 builder_->current_block()->Finish(compare); |
758 needs_compare_ = false; | 759 needs_compare_ = false; |
| 760 return compare; |
759 } | 761 } |
760 | 762 |
761 | 763 |
762 void HGraphBuilder::IfBuilder::Or() { | 764 void HGraphBuilder::IfBuilder::Or() { |
763 ASSERT(!did_and_); | 765 ASSERT(!did_and_); |
764 did_or_ = true; | 766 did_or_ = true; |
765 HEnvironment* env = first_false_block_->last_environment(); | 767 HEnvironment* env = first_false_block_->last_environment(); |
766 if (split_edge_merge_block_ == NULL) { | 768 if (split_edge_merge_block_ == NULL) { |
767 split_edge_merge_block_ = | 769 split_edge_merge_block_ = |
768 builder_->CreateBasicBlock(env->Copy()); | 770 builder_->CreateBasicBlock(env->Copy()); |
(...skipping 6805 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7574 return false; | 7576 return false; |
7575 } | 7577 } |
7576 return (sub->right() == sa); | 7578 return (sub->right() == sa); |
7577 } | 7579 } |
7578 | 7580 |
7579 | 7581 |
7580 // Checks if the left and the right are shift instructions with the oposite | 7582 // Checks if the left and the right are shift instructions with the oposite |
7581 // directions that can be replaced by one rotate right instruction or not. | 7583 // directions that can be replaced by one rotate right instruction or not. |
7582 // Returns the operand and the shift amount for the rotate instruction in the | 7584 // Returns the operand and the shift amount for the rotate instruction in the |
7583 // former case. | 7585 // former case. |
7584 bool HOptimizedGraphBuilder::MatchRotateRight(HValue* left, | 7586 bool HGraphBuilder::MatchRotateRight(HValue* left, |
7585 HValue* right, | 7587 HValue* right, |
7586 HValue** operand, | 7588 HValue** operand, |
7587 HValue** shift_amount) { | 7589 HValue** shift_amount) { |
7588 HShl* shl; | 7590 HShl* shl; |
7589 HShr* shr; | 7591 HShr* shr; |
7590 if (left->IsShl() && right->IsShr()) { | 7592 if (left->IsShl() && right->IsShr()) { |
7591 shl = HShl::cast(left); | 7593 shl = HShl::cast(left); |
7592 shr = HShr::cast(right); | 7594 shr = HShr::cast(right); |
7593 } else if (left->IsShr() && right->IsShl()) { | 7595 } else if (left->IsShr() && right->IsShl()) { |
7594 shl = HShl::cast(right); | 7596 shl = HShl::cast(right); |
7595 shr = HShr::cast(left); | 7597 shr = HShr::cast(left); |
7596 } else { | 7598 } else { |
7597 return false; | 7599 return false; |
(...skipping 15 matching lines...) Expand all Loading... |
7613 HConstant* right_const = HConstant::cast(right); | 7615 HConstant* right_const = HConstant::cast(right); |
7614 if (right_const->HasInteger32Value() && | 7616 if (right_const->HasInteger32Value() && |
7615 (right_const->Integer32Value() & 0x1f) != 0) { | 7617 (right_const->Integer32Value() & 0x1f) != 0) { |
7616 return false; | 7618 return false; |
7617 } | 7619 } |
7618 } | 7620 } |
7619 return true; | 7621 return true; |
7620 } | 7622 } |
7621 | 7623 |
7622 | 7624 |
| 7625 HValue* HGraphBuilder::EnforceNumberType(HValue* number, |
| 7626 Handle<Type> expected) { |
| 7627 if (expected->Is(Type::Smi())) { |
| 7628 return Add<HForceRepresentation>(number, Representation::Smi()); |
| 7629 } |
| 7630 if (expected->Is(Type::Signed32())) { |
| 7631 return Add<HForceRepresentation>(number, Representation::Integer32()); |
| 7632 } |
| 7633 return number; |
| 7634 } |
| 7635 |
| 7636 |
7623 HValue* HGraphBuilder::TruncateToNumber(HValue* value, Handle<Type>* expected) { | 7637 HValue* HGraphBuilder::TruncateToNumber(HValue* value, Handle<Type>* expected) { |
7624 if (value->IsConstant()) { | 7638 if (value->IsConstant()) { |
7625 HConstant* constant = HConstant::cast(value); | 7639 HConstant* constant = HConstant::cast(value); |
7626 Maybe<HConstant*> number = constant->CopyToTruncatedNumber(zone()); | 7640 Maybe<HConstant*> number = constant->CopyToTruncatedNumber(zone()); |
7627 if (number.has_value) { | 7641 if (number.has_value) { |
7628 *expected = handle(Type::Number(), isolate()); | 7642 *expected = handle(Type::Number(), isolate()); |
7629 return AddInstruction(number.value); | 7643 return AddInstruction(number.value); |
7630 } | 7644 } |
7631 } | 7645 } |
7632 | 7646 |
| 7647 Handle<Type> expected_type = *expected; |
| 7648 |
| 7649 // Separate the number type from the rest. |
| 7650 Handle<Type> expected_obj = handle(Type::Intersect( |
| 7651 expected_type, handle(Type::NonNumber(), isolate())), isolate()); |
| 7652 Handle<Type> expected_number = handle(Type::Intersect( |
| 7653 expected_type, handle(Type::Number(), isolate())), isolate()); |
| 7654 |
| 7655 // We expect to get a number. |
| 7656 // (We need to check first, since Type::None->Is(Type::Any()) == true. |
| 7657 if (expected_obj->Is(Type::None())) { |
| 7658 ASSERT(!expected_number->Is(Type::None())); |
| 7659 return value; |
| 7660 } |
| 7661 |
| 7662 if (expected_obj->Is(Type::Undefined())) { |
| 7663 // This is already done by HChange. |
| 7664 *expected = handle(Type::Union( |
| 7665 expected_number, handle(Type::Double(), isolate())), isolate()); |
| 7666 return value; |
| 7667 } |
| 7668 |
| 7669 if (expected_obj->Is(Type::Null())) { |
| 7670 *expected = handle(Type::Union( |
| 7671 expected_number, handle(Type::Smi(), isolate())), isolate()); |
| 7672 IfBuilder if_null(this); |
| 7673 if_null.If<HCompareObjectEqAndBranch>(value, |
| 7674 graph()->GetConstantNull()); |
| 7675 if_null.Then(); |
| 7676 Push(graph()->GetConstant0()); |
| 7677 if_null.Else(); |
| 7678 Push(value); |
| 7679 if_null.End(); |
| 7680 return Pop(); |
| 7681 } |
| 7682 |
| 7683 if (expected_obj->Is(Type::Boolean())) { |
| 7684 *expected = handle(Type::Union( |
| 7685 expected_number, handle(Type::Smi(), isolate())), isolate()); |
| 7686 IfBuilder if_true(this); |
| 7687 if_true.If<HCompareObjectEqAndBranch>(value, |
| 7688 graph()->GetConstantTrue()); |
| 7689 if_true.Then(); |
| 7690 Push(graph()->GetConstant1()); |
| 7691 if_true.Else(); |
| 7692 IfBuilder if_false(this); |
| 7693 if_false.If<HCompareObjectEqAndBranch>(value, |
| 7694 graph()->GetConstantFalse()); |
| 7695 if_false.Then(); |
| 7696 Push(graph()->GetConstant0()); |
| 7697 if_false.Else(); |
| 7698 Push(value); |
| 7699 if_false.End(); |
| 7700 if_true.End(); |
| 7701 return Pop(); |
| 7702 } |
| 7703 |
7633 return value; | 7704 return value; |
7634 } | 7705 } |
7635 | 7706 |
7636 | 7707 |
7637 HInstruction* HOptimizedGraphBuilder::BuildBinaryOperation( | 7708 HInstruction* HOptimizedGraphBuilder::BuildBinaryOperation( |
7638 BinaryOperation* expr, | 7709 BinaryOperation* expr, |
7639 HValue* left, | 7710 HValue* left, |
7640 HValue* right) { | 7711 HValue* right) { |
7641 HValue* context = environment()->context(); | 7712 HValue* context = environment()->context(); |
7642 Handle<Type> left_type = expr->left()->bounds().lower; | 7713 Handle<Type> left_type = expr->left()->bounds().lower; |
7643 Handle<Type> right_type = expr->right()->bounds().lower; | 7714 Handle<Type> right_type = expr->right()->bounds().lower; |
7644 Handle<Type> result_type = expr->bounds().lower; | 7715 Handle<Type> result_type = expr->bounds().lower; |
7645 Maybe<int> fixed_right_arg = expr->fixed_right_arg(); | 7716 Maybe<int> fixed_right_arg = expr->fixed_right_arg(); |
| 7717 |
| 7718 return HGraphBuilder::BuildBinaryOperation(expr->op(), left, right, |
| 7719 left_type, right_type, result_type, fixed_right_arg, context); |
| 7720 } |
| 7721 |
| 7722 |
| 7723 HInstruction* HGraphBuilder::BuildBinaryOperation( |
| 7724 Token::Value op, |
| 7725 HValue* left, |
| 7726 HValue* right, |
| 7727 Handle<Type> left_type, |
| 7728 Handle<Type> right_type, |
| 7729 Handle<Type> result_type, |
| 7730 Maybe<int> fixed_right_arg, |
| 7731 HValue* context) { |
| 7732 |
7646 Representation left_rep = Representation::FromType(left_type); | 7733 Representation left_rep = Representation::FromType(left_type); |
7647 Representation right_rep = Representation::FromType(right_type); | 7734 Representation right_rep = Representation::FromType(right_type); |
7648 Representation result_rep = Representation::FromType(result_type); | |
7649 | 7735 |
7650 if (expr->op() != Token::ADD || | 7736 bool maybe_string_add = op == Token::ADD && |
7651 (left->type().IsNonString() && right->type().IsNonString())) { | 7737 (left_type->Maybe(Type::String()) || |
7652 // For addition we can only truncate the arguments to number if we can | 7738 right_type->Maybe(Type::String())); |
7653 // prove that we will not end up in string concatenation mode. | |
7654 left = TruncateToNumber(left, &left_type); | |
7655 right = TruncateToNumber(right, &right_type); | |
7656 } | |
7657 | 7739 |
7658 if (left_type->Is(Type::None())) { | 7740 if (left_type->Is(Type::None())) { |
7659 Add<HDeoptimize>("Insufficient type feedback for LHS of binary operation", | 7741 Add<HDeoptimize>("Insufficient type feedback for LHS of binary operation", |
7660 Deoptimizer::SOFT); | 7742 Deoptimizer::SOFT); |
7661 // TODO(rossberg): we should be able to get rid of non-continuous defaults. | 7743 // TODO(rossberg): we should be able to get rid of non-continuous |
| 7744 // defaults. |
7662 left_type = handle(Type::Any(), isolate()); | 7745 left_type = handle(Type::Any(), isolate()); |
| 7746 } else { |
| 7747 if (!maybe_string_add) left = TruncateToNumber(left, &left_type); |
| 7748 left_rep = Representation::FromType(left_type); |
7663 } | 7749 } |
| 7750 |
7664 if (right_type->Is(Type::None())) { | 7751 if (right_type->Is(Type::None())) { |
7665 Add<HDeoptimize>("Insufficient type feedback for RHS of binary operation", | 7752 Add<HDeoptimize>("Insufficient type feedback for RHS of binary operation", |
7666 Deoptimizer::SOFT); | 7753 Deoptimizer::SOFT); |
7667 right_type = handle(Type::Any(), isolate()); | 7754 right_type = handle(Type::Any(), isolate()); |
| 7755 } else { |
| 7756 if (!maybe_string_add) right = TruncateToNumber(right, &right_type); |
| 7757 right_rep = Representation::FromType(right_type); |
7668 } | 7758 } |
| 7759 |
| 7760 Representation result_rep = Representation::FromType(result_type); |
| 7761 |
| 7762 bool is_string_add = op == Token::ADD && |
| 7763 (left_type->Is(Type::String()) || |
| 7764 right_type->Is(Type::String())); |
| 7765 |
7669 HInstruction* instr = NULL; | 7766 HInstruction* instr = NULL; |
7670 switch (expr->op()) { | 7767 switch (op) { |
7671 case Token::ADD: | 7768 case Token::ADD: |
7672 if (left_type->Is(Type::String()) && right_type->Is(Type::String())) { | 7769 if (is_string_add) { |
7673 BuildCheckHeapObject(left); | 7770 StringAddFlags flags = STRING_ADD_CHECK_BOTH; |
7674 AddInstruction(HCheckInstanceType::NewIsString(left, zone())); | 7771 if (left_type->Is(Type::String())) { |
7675 BuildCheckHeapObject(right); | 7772 BuildCheckHeapObject(left); |
7676 AddInstruction(HCheckInstanceType::NewIsString(right, zone())); | 7773 AddInstruction(HCheckInstanceType::NewIsString(left, zone())); |
7677 instr = HStringAdd::New(zone(), context, left, right); | 7774 flags = STRING_ADD_CHECK_RIGHT; |
| 7775 } |
| 7776 if (right_type->Is(Type::String())) { |
| 7777 BuildCheckHeapObject(right); |
| 7778 AddInstruction(HCheckInstanceType::NewIsString(right, zone())); |
| 7779 flags = (flags == STRING_ADD_CHECK_BOTH) |
| 7780 ? STRING_ADD_CHECK_LEFT : STRING_ADD_CHECK_NONE; |
| 7781 } |
| 7782 instr = HStringAdd::New(zone(), context, left, right, flags); |
7678 } else { | 7783 } else { |
7679 instr = HAdd::New(zone(), context, left, right); | 7784 instr = HAdd::New(zone(), context, left, right); |
7680 } | 7785 } |
7681 break; | 7786 break; |
7682 case Token::SUB: | 7787 case Token::SUB: |
7683 instr = HSub::New(zone(), context, left, right); | 7788 instr = HSub::New(zone(), context, left, right); |
7684 break; | 7789 break; |
7685 case Token::MUL: | 7790 case Token::MUL: |
7686 instr = HMul::New(zone(), context, left, right); | 7791 instr = HMul::New(zone(), context, left, right); |
7687 break; | 7792 break; |
7688 case Token::MOD: | 7793 case Token::MOD: |
7689 instr = HMod::New(zone(), context, left, right, fixed_right_arg); | 7794 instr = HMod::New(zone(), context, left, right, fixed_right_arg); |
7690 break; | 7795 break; |
7691 case Token::DIV: | 7796 case Token::DIV: |
7692 instr = HDiv::New(zone(), context, left, right); | 7797 instr = HDiv::New(zone(), context, left, right); |
7693 break; | 7798 break; |
7694 case Token::BIT_XOR: | 7799 case Token::BIT_XOR: |
7695 case Token::BIT_AND: | 7800 case Token::BIT_AND: |
7696 instr = NewUncasted<HBitwise>(expr->op(), left, right); | 7801 instr = NewUncasted<HBitwise>(op, left, right); |
7697 break; | 7802 break; |
7698 case Token::BIT_OR: { | 7803 case Token::BIT_OR: { |
7699 HValue* operand, *shift_amount; | 7804 HValue* operand, *shift_amount; |
7700 if (left_type->Is(Type::Signed32()) && | 7805 if (left_type->Is(Type::Signed32()) && |
7701 right_type->Is(Type::Signed32()) && | 7806 right_type->Is(Type::Signed32()) && |
7702 MatchRotateRight(left, right, &operand, &shift_amount)) { | 7807 MatchRotateRight(left, right, &operand, &shift_amount)) { |
7703 instr = new(zone()) HRor(context, operand, shift_amount); | 7808 instr = new(zone()) HRor(context, operand, shift_amount); |
7704 } else { | 7809 } else { |
7705 instr = NewUncasted<HBitwise>(expr->op(), left, right); | 7810 instr = NewUncasted<HBitwise>(op, left, right); |
7706 } | 7811 } |
7707 break; | 7812 break; |
7708 } | 7813 } |
7709 case Token::SAR: | 7814 case Token::SAR: |
7710 instr = HSar::New(zone(), context, left, right); | 7815 instr = HSar::New(zone(), context, left, right); |
7711 break; | 7816 break; |
7712 case Token::SHR: | 7817 case Token::SHR: |
7713 instr = HShr::New(zone(), context, left, right); | 7818 instr = HShr::New(zone(), context, left, right); |
7714 if (FLAG_opt_safe_uint32_operations && instr->IsShr() && | 7819 if (FLAG_opt_safe_uint32_operations && instr->IsShr() && |
7715 CanBeZero(right)) { | 7820 CanBeZero(right)) { |
(...skipping 1917 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9633 if (ShouldProduceTraceOutput()) { | 9738 if (ShouldProduceTraceOutput()) { |
9634 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 9739 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
9635 } | 9740 } |
9636 | 9741 |
9637 #ifdef DEBUG | 9742 #ifdef DEBUG |
9638 graph_->Verify(false); // No full verify. | 9743 graph_->Verify(false); // No full verify. |
9639 #endif | 9744 #endif |
9640 } | 9745 } |
9641 | 9746 |
9642 } } // namespace v8::internal | 9747 } } // namespace v8::internal |
OLD | NEW |