OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/hydrogen.h" | 5 #include "src/hydrogen.h" |
6 | 6 |
7 #include <sstream> | 7 #include <sstream> |
8 | 8 |
9 #include "src/v8.h" | 9 #include "src/v8.h" |
10 | 10 |
(...skipping 10271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10282 } | 10282 } |
10283 Push(number_input); | 10283 Push(number_input); |
10284 } | 10284 } |
10285 | 10285 |
10286 // The addition has no side effects, so we do not need | 10286 // The addition has no side effects, so we do not need |
10287 // to simulate the expression stack after this instruction. | 10287 // to simulate the expression stack after this instruction. |
10288 // Any later failures deopt to the load of the input or earlier. | 10288 // Any later failures deopt to the load of the input or earlier. |
10289 HConstant* delta = (expr->op() == Token::INC) | 10289 HConstant* delta = (expr->op() == Token::INC) |
10290 ? graph()->GetConstant1() | 10290 ? graph()->GetConstant1() |
10291 : graph()->GetConstantMinus1(); | 10291 : graph()->GetConstantMinus1(); |
10292 HInstruction* instr = AddUncasted<HAdd>(Top(), delta); | 10292 HInstruction* instr = AddUncasted<HAdd>(Top(), delta, |
| 10293 function_language_mode()); |
10293 if (instr->IsAdd()) { | 10294 if (instr->IsAdd()) { |
10294 HAdd* add = HAdd::cast(instr); | 10295 HAdd* add = HAdd::cast(instr); |
10295 add->set_observed_input_representation(1, rep); | 10296 add->set_observed_input_representation(1, rep); |
10296 add->set_observed_input_representation(2, Representation::Smi()); | 10297 add->set_observed_input_representation(2, Representation::Smi()); |
10297 } | 10298 } |
10298 instr->SetFlag(HInstruction::kCannotBeTagged); | 10299 instr->SetFlag(HInstruction::kCannotBeTagged); |
10299 instr->ClearAllSideEffects(); | 10300 instr->ClearAllSideEffects(); |
10300 return instr; | 10301 return instr; |
10301 } | 10302 } |
10302 | 10303 |
(...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10630 right_type->Maybe(Type::String()) || | 10631 right_type->Maybe(Type::String()) || |
10631 right_type->Maybe(Type::Receiver())); | 10632 right_type->Maybe(Type::Receiver())); |
10632 } | 10633 } |
10633 | 10634 |
10634 Representation left_rep = RepresentationFor(left_type); | 10635 Representation left_rep = RepresentationFor(left_type); |
10635 Representation right_rep = RepresentationFor(right_type); | 10636 Representation right_rep = RepresentationFor(right_type); |
10636 | 10637 |
10637 if (!left_type->IsInhabited()) { | 10638 if (!left_type->IsInhabited()) { |
10638 Add<HDeoptimize>( | 10639 Add<HDeoptimize>( |
10639 Deoptimizer::kInsufficientTypeFeedbackForLHSOfBinaryOperation, | 10640 Deoptimizer::kInsufficientTypeFeedbackForLHSOfBinaryOperation, |
10640 is_strong(language_mode) ? Deoptimizer::EAGER : Deoptimizer::SOFT); | 10641 Deoptimizer::SOFT); |
10641 left_type = Type::Any(zone()); | 10642 left_type = Type::Any(zone()); |
10642 left_rep = RepresentationFor(left_type); | 10643 left_rep = RepresentationFor(left_type); |
10643 maybe_string_add = op == Token::ADD; | 10644 maybe_string_add = op == Token::ADD; |
10644 } | 10645 } |
10645 | 10646 |
10646 if (!right_type->IsInhabited()) { | 10647 if (!right_type->IsInhabited()) { |
10647 Add<HDeoptimize>( | 10648 Add<HDeoptimize>( |
10648 Deoptimizer::kInsufficientTypeFeedbackForRHSOfBinaryOperation, | 10649 Deoptimizer::kInsufficientTypeFeedbackForRHSOfBinaryOperation, |
10649 is_strong(language_mode) ? Deoptimizer::EAGER : Deoptimizer::SOFT); | 10650 Deoptimizer::SOFT); |
10650 right_type = Type::Any(zone()); | 10651 right_type = Type::Any(zone()); |
10651 right_rep = RepresentationFor(right_type); | 10652 right_rep = RepresentationFor(right_type); |
10652 maybe_string_add = op == Token::ADD; | 10653 maybe_string_add = op == Token::ADD; |
10653 } | 10654 } |
10654 | 10655 |
10655 if (!maybe_string_add) { | 10656 if (!maybe_string_add) { |
10656 left = TruncateToNumber(left, &left_type); | 10657 left = TruncateToNumber(left, &left_type); |
10657 right = TruncateToNumber(right, &right_type); | 10658 right = TruncateToNumber(right, &right_type); |
10658 } | 10659 } |
10659 | 10660 |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10702 ? HConstant::cast(left)->StringValue() | 10703 ? HConstant::cast(left)->StringValue() |
10703 : Handle<String>(); | 10704 : Handle<String>(); |
10704 Handle<String> right_string = | 10705 Handle<String> right_string = |
10705 right->IsConstant() && HConstant::cast(right)->HasStringValue() | 10706 right->IsConstant() && HConstant::cast(right)->HasStringValue() |
10706 ? HConstant::cast(right)->StringValue() | 10707 ? HConstant::cast(right)->StringValue() |
10707 : Handle<String>(); | 10708 : Handle<String>(); |
10708 if (!left_string.is_null() && left_string->length() == 0) return right; | 10709 if (!left_string.is_null() && left_string->length() == 0) return right; |
10709 if (!right_string.is_null() && right_string->length() == 0) return left; | 10710 if (!right_string.is_null() && right_string->length() == 0) return left; |
10710 if (!left_string.is_null() && !right_string.is_null()) { | 10711 if (!left_string.is_null() && !right_string.is_null()) { |
10711 return AddUncasted<HStringAdd>( | 10712 return AddUncasted<HStringAdd>( |
10712 left, right, allocation_mode.GetPretenureMode(), | 10713 left, right, language_mode, allocation_mode.GetPretenureMode(), |
10713 STRING_ADD_CHECK_NONE, allocation_mode.feedback_site()); | 10714 STRING_ADD_CHECK_NONE, allocation_mode.feedback_site()); |
10714 } | 10715 } |
10715 | 10716 |
10716 // Register the dependent code with the allocation site. | 10717 // Register the dependent code with the allocation site. |
10717 if (!allocation_mode.feedback_site().is_null()) { | 10718 if (!allocation_mode.feedback_site().is_null()) { |
10718 DCHECK(!graph()->info()->IsStub()); | 10719 DCHECK(!graph()->info()->IsStub()); |
10719 Handle<AllocationSite> site(allocation_mode.feedback_site()); | 10720 Handle<AllocationSite> site(allocation_mode.feedback_site()); |
10720 top_info()->dependencies()->AssumeTenuringDecision(site); | 10721 top_info()->dependencies()->AssumeTenuringDecision(site); |
10721 } | 10722 } |
10722 | 10723 |
10723 // Inline the string addition into the stub when creating allocation | 10724 // Inline the string addition into the stub when creating allocation |
10724 // mementos to gather allocation site feedback, or if we can statically | 10725 // mementos to gather allocation site feedback, or if we can statically |
10725 // infer that we're going to create a cons string. | 10726 // infer that we're going to create a cons string. |
10726 if ((graph()->info()->IsStub() && | 10727 if ((graph()->info()->IsStub() && |
10727 allocation_mode.CreateAllocationMementos()) || | 10728 allocation_mode.CreateAllocationMementos()) || |
10728 (left->IsConstant() && | 10729 (left->IsConstant() && |
10729 HConstant::cast(left)->HasStringValue() && | 10730 HConstant::cast(left)->HasStringValue() && |
10730 HConstant::cast(left)->StringValue()->length() + 1 >= | 10731 HConstant::cast(left)->StringValue()->length() + 1 >= |
10731 ConsString::kMinLength) || | 10732 ConsString::kMinLength) || |
10732 (right->IsConstant() && | 10733 (right->IsConstant() && |
10733 HConstant::cast(right)->HasStringValue() && | 10734 HConstant::cast(right)->HasStringValue() && |
10734 HConstant::cast(right)->StringValue()->length() + 1 >= | 10735 HConstant::cast(right)->StringValue()->length() + 1 >= |
10735 ConsString::kMinLength)) { | 10736 ConsString::kMinLength)) { |
10736 return BuildStringAdd(left, right, allocation_mode); | 10737 return BuildStringAdd(left, right, allocation_mode); |
10737 } | 10738 } |
10738 | 10739 |
10739 // Fallback to using the string add stub. | 10740 // Fallback to using the string add stub. |
10740 return AddUncasted<HStringAdd>( | 10741 return AddUncasted<HStringAdd>( |
10741 left, right, allocation_mode.GetPretenureMode(), | 10742 left, right, language_mode, allocation_mode.GetPretenureMode(), |
10742 STRING_ADD_CHECK_NONE, allocation_mode.feedback_site()); | 10743 STRING_ADD_CHECK_NONE, allocation_mode.feedback_site()); |
10743 } | 10744 } |
10744 | 10745 |
10745 if (graph()->info()->IsStub()) { | 10746 if (graph()->info()->IsStub()) { |
10746 left = EnforceNumberType(left, left_type); | 10747 left = EnforceNumberType(left, left_type); |
10747 right = EnforceNumberType(right, right_type); | 10748 right = EnforceNumberType(right, right_type); |
10748 } | 10749 } |
10749 | 10750 |
10750 Representation result_rep = RepresentationFor(result_type); | 10751 Representation result_rep = RepresentationFor(result_type); |
10751 | 10752 |
10752 bool is_non_primitive = (left_rep.IsTagged() && !left_rep.IsSmi()) || | 10753 bool is_non_primitive = (left_rep.IsTagged() && !left_rep.IsSmi()) || |
10753 (right_rep.IsTagged() && !right_rep.IsSmi()); | 10754 (right_rep.IsTagged() && !right_rep.IsSmi()); |
10754 | 10755 |
10755 HInstruction* instr = NULL; | 10756 HInstruction* instr = NULL; |
10756 // Only the stub is allowed to call into the runtime, since otherwise we would | 10757 // Only the stub is allowed to call into the runtime, since otherwise we would |
10757 // inline several instructions (including the two pushes) for every tagged | 10758 // inline several instructions (including the two pushes) for every tagged |
10758 // operation in optimized code, which is more expensive, than a stub call. | 10759 // operation in optimized code, which is more expensive, than a stub call. |
10759 if (graph()->info()->IsStub() && is_non_primitive) { | 10760 if (graph()->info()->IsStub() && is_non_primitive) { |
10760 HValue* function = AddLoadJSBuiltin( | 10761 HValue* function = AddLoadJSBuiltin( |
10761 BinaryOpIC::TokenToJSBuiltin(op, language_mode)); | 10762 BinaryOpIC::TokenToJSBuiltin(op, language_mode)); |
10762 Add<HPushArguments>(left, right); | 10763 Add<HPushArguments>(left, right); |
10763 instr = AddUncasted<HInvokeFunction>(function, 2); | 10764 instr = AddUncasted<HInvokeFunction>(function, 2); |
10764 } else { | 10765 } else { |
10765 switch (op) { | 10766 switch (op) { |
10766 case Token::ADD: | 10767 case Token::ADD: |
10767 instr = AddUncasted<HAdd>(left, right); | 10768 instr = AddUncasted<HAdd>(left, right, language_mode); |
10768 break; | 10769 break; |
10769 case Token::SUB: | 10770 case Token::SUB: |
10770 instr = AddUncasted<HSub>(left, right); | 10771 instr = AddUncasted<HSub>(left, right, language_mode); |
10771 break; | 10772 break; |
10772 case Token::MUL: | 10773 case Token::MUL: |
10773 instr = AddUncasted<HMul>(left, right); | 10774 instr = AddUncasted<HMul>(left, right, language_mode); |
10774 break; | 10775 break; |
10775 case Token::MOD: { | 10776 case Token::MOD: { |
10776 if (fixed_right_arg.IsJust() && | 10777 if (fixed_right_arg.IsJust() && |
10777 !right->EqualsInteger32Constant(fixed_right_arg.FromJust())) { | 10778 !right->EqualsInteger32Constant(fixed_right_arg.FromJust())) { |
10778 HConstant* fixed_right = | 10779 HConstant* fixed_right = |
10779 Add<HConstant>(static_cast<int>(fixed_right_arg.FromJust())); | 10780 Add<HConstant>(static_cast<int>(fixed_right_arg.FromJust())); |
10780 IfBuilder if_same(this); | 10781 IfBuilder if_same(this); |
10781 if_same.If<HCompareNumericAndBranch>(right, fixed_right, Token::EQ); | 10782 if_same.If<HCompareNumericAndBranch>(right, fixed_right, Token::EQ); |
10782 if_same.Then(); | 10783 if_same.Then(); |
10783 if_same.ElseDeopt(Deoptimizer::kUnexpectedRHSOfBinaryOperation); | 10784 if_same.ElseDeopt(Deoptimizer::kUnexpectedRHSOfBinaryOperation); |
10784 right = fixed_right; | 10785 right = fixed_right; |
10785 } | 10786 } |
10786 instr = AddUncasted<HMod>(left, right); | 10787 instr = AddUncasted<HMod>(left, right, language_mode); |
10787 break; | 10788 break; |
10788 } | 10789 } |
10789 case Token::DIV: | 10790 case Token::DIV: |
10790 instr = AddUncasted<HDiv>(left, right); | 10791 instr = AddUncasted<HDiv>(left, right, language_mode); |
10791 break; | 10792 break; |
10792 case Token::BIT_XOR: | 10793 case Token::BIT_XOR: |
10793 case Token::BIT_AND: | 10794 case Token::BIT_AND: |
10794 instr = AddUncasted<HBitwise>(op, left, right); | 10795 instr = AddUncasted<HBitwise>(op, left, right, language_mode); |
10795 break; | 10796 break; |
10796 case Token::BIT_OR: { | 10797 case Token::BIT_OR: { |
10797 HValue* operand, *shift_amount; | 10798 HValue* operand, *shift_amount; |
10798 if (left_type->Is(Type::Signed32()) && | 10799 if (left_type->Is(Type::Signed32()) && |
10799 right_type->Is(Type::Signed32()) && | 10800 right_type->Is(Type::Signed32()) && |
10800 MatchRotateRight(left, right, &operand, &shift_amount)) { | 10801 MatchRotateRight(left, right, &operand, &shift_amount)) { |
10801 instr = AddUncasted<HRor>(operand, shift_amount); | 10802 instr = AddUncasted<HRor>(operand, shift_amount, language_mode); |
10802 } else { | 10803 } else { |
10803 instr = AddUncasted<HBitwise>(op, left, right); | 10804 instr = AddUncasted<HBitwise>(op, left, right, language_mode); |
10804 } | 10805 } |
10805 break; | 10806 break; |
10806 } | 10807 } |
10807 case Token::SAR: | 10808 case Token::SAR: |
10808 instr = AddUncasted<HSar>(left, right); | 10809 instr = AddUncasted<HSar>(left, right, language_mode); |
10809 break; | 10810 break; |
10810 case Token::SHR: | 10811 case Token::SHR: |
10811 instr = AddUncasted<HShr>(left, right); | 10812 instr = AddUncasted<HShr>(left, right, language_mode); |
10812 if (instr->IsShr() && CanBeZero(right)) { | 10813 if (instr->IsShr() && CanBeZero(right)) { |
10813 graph()->RecordUint32Instruction(instr); | 10814 graph()->RecordUint32Instruction(instr); |
10814 } | 10815 } |
10815 break; | 10816 break; |
10816 case Token::SHL: | 10817 case Token::SHL: |
10817 instr = AddUncasted<HShl>(left, right); | 10818 instr = AddUncasted<HShl>(left, right, language_mode); |
10818 break; | 10819 break; |
10819 default: | 10820 default: |
10820 UNREACHABLE(); | 10821 UNREACHABLE(); |
10821 } | 10822 } |
10822 } | 10823 } |
10823 | 10824 |
10824 if (instr->IsBinaryOperation()) { | 10825 if (instr->IsBinaryOperation()) { |
10825 HBinaryOperation* binop = HBinaryOperation::cast(instr); | 10826 HBinaryOperation* binop = HBinaryOperation::cast(instr); |
10826 binop->set_observed_input_representation(1, left_rep); | 10827 binop->set_observed_input_representation(1, left_rep); |
10827 binop->set_observed_input_representation(2, right_rep); | 10828 binop->set_observed_input_representation(2, right_rep); |
(...skipping 1219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12047 } | 12048 } |
12048 | 12049 |
12049 | 12050 |
12050 // Fast support for StringAdd. | 12051 // Fast support for StringAdd. |
12051 void HOptimizedGraphBuilder::GenerateStringAdd(CallRuntime* call) { | 12052 void HOptimizedGraphBuilder::GenerateStringAdd(CallRuntime* call) { |
12052 DCHECK_EQ(2, call->arguments()->length()); | 12053 DCHECK_EQ(2, call->arguments()->length()); |
12053 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 12054 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
12054 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | 12055 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
12055 HValue* right = Pop(); | 12056 HValue* right = Pop(); |
12056 HValue* left = Pop(); | 12057 HValue* left = Pop(); |
12057 HInstruction* result = NewUncasted<HStringAdd>(left, right); | 12058 HInstruction* result = NewUncasted<HStringAdd>(left, right, |
| 12059 function_language_mode()); |
12058 return ast_context()->ReturnInstruction(result, call->id()); | 12060 return ast_context()->ReturnInstruction(result, call->id()); |
12059 } | 12061 } |
12060 | 12062 |
12061 | 12063 |
12062 // Fast support for SubString. | 12064 // Fast support for SubString. |
12063 void HOptimizedGraphBuilder::GenerateSubString(CallRuntime* call) { | 12065 void HOptimizedGraphBuilder::GenerateSubString(CallRuntime* call) { |
12064 DCHECK_EQ(3, call->arguments()->length()); | 12066 DCHECK_EQ(3, call->arguments()->length()); |
12065 CHECK_ALIVE(VisitExpressions(call->arguments())); | 12067 CHECK_ALIVE(VisitExpressions(call->arguments())); |
12066 PushArgumentsFromEnvironment(call->arguments()->length()); | 12068 PushArgumentsFromEnvironment(call->arguments()->length()); |
12067 HCallStub* result = New<HCallStub>(CodeStub::SubString, 3); | 12069 HCallStub* result = New<HCallStub>(CodeStub::SubString, 3); |
(...skipping 1076 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13144 if (ShouldProduceTraceOutput()) { | 13146 if (ShouldProduceTraceOutput()) { |
13145 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 13147 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
13146 } | 13148 } |
13147 | 13149 |
13148 #ifdef DEBUG | 13150 #ifdef DEBUG |
13149 graph_->Verify(false); // No full verify. | 13151 graph_->Verify(false); // No full verify. |
13150 #endif | 13152 #endif |
13151 } | 13153 } |
13152 | 13154 |
13153 } } // namespace v8::internal | 13155 } } // namespace v8::internal |
OLD | NEW |