Chromium Code Reviews| 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 10282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 10293 | 10293 |
| 10294 HInstruction* HOptimizedGraphBuilder::BuildIncrement( | 10294 HInstruction* HOptimizedGraphBuilder::BuildIncrement( |
| 10295 bool returns_original_input, | 10295 bool returns_original_input, |
| 10296 CountOperation* expr) { | 10296 CountOperation* expr) { |
| 10297 // The input to the count operation is on top of the expression stack. | 10297 // The input to the count operation is on top of the expression stack. |
| 10298 Representation rep = RepresentationFor(expr->type()); | 10298 Representation rep = RepresentationFor(expr->type()); |
| 10299 if (rep.IsNone() || rep.IsTagged()) { | 10299 if (rep.IsNone() || rep.IsTagged()) { |
| 10300 rep = Representation::Smi(); | 10300 rep = Representation::Smi(); |
| 10301 } | 10301 } |
| 10302 | 10302 |
| 10303 if (returns_original_input) { | 10303 if (returns_original_input && !is_strong(function_language_mode())) { |
| 10304 // We need an explicit HValue representing ToNumber(input). The | 10304 // We need an explicit HValue representing ToNumber(input). The |
| 10305 // actual HChange instruction we need is (sometimes) added in a later | 10305 // actual HChange instruction we need is (sometimes) added in a later |
| 10306 // phase, so it is not available now to be used as an input to HAdd and | 10306 // phase, so it is not available now to be used as an input to HAdd and |
| 10307 // as the return value. | 10307 // as the return value. |
| 10308 HInstruction* number_input = AddUncasted<HForceRepresentation>(Pop(), rep); | 10308 HInstruction* number_input = AddUncasted<HForceRepresentation>(Pop(), rep); |
| 10309 if (!rep.IsDouble()) { | 10309 if (!rep.IsDouble()) { |
| 10310 number_input->SetFlag(HInstruction::kFlexibleRepresentation); | 10310 number_input->SetFlag(HInstruction::kFlexibleRepresentation); |
| 10311 number_input->SetFlag(HInstruction::kCannotBeTagged); | 10311 number_input->SetFlag(HInstruction::kCannotBeTagged); |
| 10312 } | 10312 } |
| 10313 Push(number_input); | 10313 Push(number_input); |
| 10314 } | 10314 } |
| 10315 | 10315 |
| 10316 // The addition has no side effects, so we do not need | 10316 // The addition has no side effects, so we do not need |
| 10317 // to simulate the expression stack after this instruction. | 10317 // to simulate the expression stack after this instruction. |
| 10318 // Any later failures deopt to the load of the input or earlier. | 10318 // Any later failures deopt to the load of the input or earlier. |
| 10319 HConstant* delta = (expr->op() == Token::INC) | 10319 HConstant* delta = (expr->op() == Token::INC) |
| 10320 ? graph()->GetConstant1() | 10320 ? graph()->GetConstant1() |
| 10321 : graph()->GetConstantMinus1(); | 10321 : graph()->GetConstantMinus1(); |
| 10322 HInstruction* instr = | 10322 HInstruction* instr = |
| 10323 AddUncasted<HAdd>(Top(), delta, strength(function_language_mode())); | 10323 AddUncasted<HAdd>(Top(), delta, strength(function_language_mode())); |
| 10324 if (instr->IsAdd()) { | 10324 if (instr->IsAdd()) { |
| 10325 HAdd* add = HAdd::cast(instr); | 10325 HAdd* add = HAdd::cast(instr); |
| 10326 add->set_observed_input_representation(1, rep); | 10326 if (!is_strong(function_language_mode())) { |
|
rossberg
2015/06/30 12:53:52
Hm, why no recording in strong mode? Can you add a
conradw
2015/06/30 14:01:10
Urk, this was something I added while misunderstan
| |
| 10327 add->set_observed_input_representation(1, rep); | |
| 10328 } | |
| 10327 add->set_observed_input_representation(2, Representation::Smi()); | 10329 add->set_observed_input_representation(2, Representation::Smi()); |
| 10328 } | 10330 } |
| 10331 if (!is_strong(function_language_mode())) { | |
| 10332 instr->ClearAllSideEffects(); | |
| 10333 } else { | |
| 10334 Add<HSimulate>(expr->ToNumberId(), REMOVABLE_SIMULATE); | |
| 10335 } | |
| 10329 instr->SetFlag(HInstruction::kCannotBeTagged); | 10336 instr->SetFlag(HInstruction::kCannotBeTagged); |
| 10330 instr->ClearAllSideEffects(); | |
| 10331 return instr; | 10337 return instr; |
| 10332 } | 10338 } |
| 10333 | 10339 |
| 10334 | 10340 |
| 10335 void HOptimizedGraphBuilder::BuildStoreForEffect(Expression* expr, | 10341 void HOptimizedGraphBuilder::BuildStoreForEffect(Expression* expr, |
| 10336 Property* prop, | 10342 Property* prop, |
| 10337 BailoutId ast_id, | 10343 BailoutId ast_id, |
| 10338 BailoutId return_id, | 10344 BailoutId return_id, |
| 10339 HValue* object, | 10345 HValue* object, |
| 10340 HValue* key, | 10346 HValue* key, |
| (...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 10604 Type* left_type = expr->left()->bounds().lower; | 10610 Type* left_type = expr->left()->bounds().lower; |
| 10605 Type* right_type = expr->right()->bounds().lower; | 10611 Type* right_type = expr->right()->bounds().lower; |
| 10606 Type* result_type = expr->bounds().lower; | 10612 Type* result_type = expr->bounds().lower; |
| 10607 Maybe<int> fixed_right_arg = expr->fixed_right_arg(); | 10613 Maybe<int> fixed_right_arg = expr->fixed_right_arg(); |
| 10608 Handle<AllocationSite> allocation_site = expr->allocation_site(); | 10614 Handle<AllocationSite> allocation_site = expr->allocation_site(); |
| 10609 | 10615 |
| 10610 HAllocationMode allocation_mode; | 10616 HAllocationMode allocation_mode; |
| 10611 if (FLAG_allocation_site_pretenuring && !allocation_site.is_null()) { | 10617 if (FLAG_allocation_site_pretenuring && !allocation_site.is_null()) { |
| 10612 allocation_mode = HAllocationMode(allocation_site); | 10618 allocation_mode = HAllocationMode(allocation_site); |
| 10613 } | 10619 } |
| 10614 | |
| 10615 HValue* result = HGraphBuilder::BuildBinaryOperation( | 10620 HValue* result = HGraphBuilder::BuildBinaryOperation( |
| 10616 expr->op(), left, right, left_type, right_type, result_type, | 10621 expr->op(), left, right, left_type, right_type, result_type, |
| 10617 fixed_right_arg, allocation_mode, strength(function_language_mode())); | 10622 fixed_right_arg, allocation_mode, strength(function_language_mode()), |
| 10623 expr->id()); | |
| 10618 // Add a simulate after instructions with observable side effects, and | 10624 // Add a simulate after instructions with observable side effects, and |
| 10619 // after phis, which are the result of BuildBinaryOperation when we | 10625 // after phis, which are the result of BuildBinaryOperation when we |
| 10620 // inlined some complex subgraph. | 10626 // inlined some complex subgraph. |
| 10621 if (result->HasObservableSideEffects() || result->IsPhi()) { | 10627 if (result->HasObservableSideEffects() || result->IsPhi()) { |
| 10622 if (push_sim_result == PUSH_BEFORE_SIMULATE) { | 10628 if (push_sim_result == PUSH_BEFORE_SIMULATE) { |
| 10623 Push(result); | 10629 Push(result); |
| 10624 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); | 10630 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); |
| 10625 Drop(1); | 10631 Drop(1); |
| 10626 } else { | 10632 } else { |
| 10627 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); | 10633 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); |
| 10628 } | 10634 } |
| 10629 } | 10635 } |
| 10630 return result; | 10636 return result; |
| 10631 } | 10637 } |
| 10632 | 10638 |
| 10633 | 10639 |
| 10634 HValue* HGraphBuilder::BuildBinaryOperation(Token::Value op, HValue* left, | 10640 HValue* HGraphBuilder::BuildBinaryOperation( |
| 10635 HValue* right, Type* left_type, | 10641 Token::Value op, HValue* left, HValue* right, Type* left_type, |
| 10636 Type* right_type, Type* result_type, | 10642 Type* right_type, Type* result_type, Maybe<int> fixed_right_arg, |
| 10637 Maybe<int> fixed_right_arg, | 10643 HAllocationMode allocation_mode, Strength strength, BailoutId opt_id) { |
| 10638 HAllocationMode allocation_mode, | |
| 10639 Strength strength) { | |
| 10640 bool maybe_string_add = false; | 10644 bool maybe_string_add = false; |
| 10641 if (op == Token::ADD) { | 10645 if (op == Token::ADD) { |
| 10642 // If we are adding constant string with something for which we don't have | 10646 // If we are adding constant string with something for which we don't have |
| 10643 // a feedback yet, assume that it's also going to be a string and don't | 10647 // a feedback yet, assume that it's also going to be a string and don't |
| 10644 // generate deopt instructions. | 10648 // generate deopt instructions. |
| 10645 if (!left_type->IsInhabited() && right->IsConstant() && | 10649 if (!left_type->IsInhabited() && right->IsConstant() && |
| 10646 HConstant::cast(right)->HasStringValue()) { | 10650 HConstant::cast(right)->HasStringValue()) { |
| 10647 left_type = Type::String(); | 10651 left_type = Type::String(); |
| 10648 } | 10652 } |
| 10649 | 10653 |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 10672 | 10676 |
| 10673 if (!right_type->IsInhabited()) { | 10677 if (!right_type->IsInhabited()) { |
| 10674 Add<HDeoptimize>( | 10678 Add<HDeoptimize>( |
| 10675 Deoptimizer::kInsufficientTypeFeedbackForRHSOfBinaryOperation, | 10679 Deoptimizer::kInsufficientTypeFeedbackForRHSOfBinaryOperation, |
| 10676 Deoptimizer::SOFT); | 10680 Deoptimizer::SOFT); |
| 10677 right_type = Type::Any(zone()); | 10681 right_type = Type::Any(zone()); |
| 10678 right_rep = RepresentationFor(right_type); | 10682 right_rep = RepresentationFor(right_type); |
| 10679 maybe_string_add = op == Token::ADD; | 10683 maybe_string_add = op == Token::ADD; |
| 10680 } | 10684 } |
| 10681 | 10685 |
| 10682 if (!maybe_string_add) { | 10686 if (!maybe_string_add && !is_strong(strength)) { |
| 10683 left = TruncateToNumber(left, &left_type); | 10687 left = TruncateToNumber(left, &left_type); |
| 10684 right = TruncateToNumber(right, &right_type); | 10688 right = TruncateToNumber(right, &right_type); |
| 10685 } | 10689 } |
| 10686 | 10690 |
| 10687 // Special case for string addition here. | 10691 // Special case for string addition here. |
| 10688 if (op == Token::ADD && | 10692 if (op == Token::ADD && |
| 10689 (left_type->Is(Type::String()) || right_type->Is(Type::String()))) { | 10693 (left_type->Is(Type::String()) || right_type->Is(Type::String()))) { |
| 10690 // Validate type feedback for left argument. | 10694 // Validate type feedback for left argument. |
| 10691 if (left_type->Is(Type::String())) { | 10695 if (left_type->Is(Type::String())) { |
| 10692 left = BuildCheckString(left); | 10696 left = BuildCheckString(left); |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 10782 HInstruction* instr = NULL; | 10786 HInstruction* instr = NULL; |
| 10783 // Only the stub is allowed to call into the runtime, since otherwise we would | 10787 // Only the stub is allowed to call into the runtime, since otherwise we would |
| 10784 // inline several instructions (including the two pushes) for every tagged | 10788 // inline several instructions (including the two pushes) for every tagged |
| 10785 // operation in optimized code, which is more expensive, than a stub call. | 10789 // operation in optimized code, which is more expensive, than a stub call. |
| 10786 if (graph()->info()->IsStub() && is_non_primitive) { | 10790 if (graph()->info()->IsStub() && is_non_primitive) { |
| 10787 HValue* function = | 10791 HValue* function = |
| 10788 AddLoadJSBuiltin(BinaryOpIC::TokenToJSBuiltin(op, strength)); | 10792 AddLoadJSBuiltin(BinaryOpIC::TokenToJSBuiltin(op, strength)); |
| 10789 Add<HPushArguments>(left, right); | 10793 Add<HPushArguments>(left, right); |
| 10790 instr = AddUncasted<HInvokeFunction>(function, 2); | 10794 instr = AddUncasted<HInvokeFunction>(function, 2); |
| 10791 } else { | 10795 } else { |
| 10796 if (is_strong(strength) && Token::IsBitOp(op)) { | |
| 10797 IfBuilder if_builder(this); | |
| 10798 if_builder.If<HHasInstanceTypeAndBranch>(left, ODDBALL_TYPE); | |
| 10799 if_builder.OrIf<HHasInstanceTypeAndBranch>(right, ODDBALL_TYPE); | |
| 10800 if_builder.Then(); | |
| 10801 Add<HCallRuntime>( | |
| 10802 isolate()->factory()->empty_string(), | |
| 10803 Runtime::FunctionForId(Runtime::kThrowStrongModeImplicitConversion), | |
| 10804 0); | |
| 10805 if (!graph()->info()->IsStub()) { | |
| 10806 Add<HSimulate>(opt_id, REMOVABLE_SIMULATE); | |
| 10807 } | |
| 10808 if_builder.End(); | |
| 10809 } | |
| 10792 switch (op) { | 10810 switch (op) { |
| 10793 case Token::ADD: | 10811 case Token::ADD: |
| 10794 instr = AddUncasted<HAdd>(left, right, strength); | 10812 instr = AddUncasted<HAdd>(left, right, strength); |
| 10795 break; | 10813 break; |
| 10796 case Token::SUB: | 10814 case Token::SUB: |
| 10797 instr = AddUncasted<HSub>(left, right, strength); | 10815 instr = AddUncasted<HSub>(left, right, strength); |
| 10798 break; | 10816 break; |
| 10799 case Token::MUL: | 10817 case Token::MUL: |
| 10800 instr = AddUncasted<HMul>(left, right, strength); | 10818 instr = AddUncasted<HMul>(left, right, strength); |
| 10801 break; | 10819 break; |
| (...skipping 437 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 11239 AddSimulate(bailout_id, REMOVABLE_SIMULATE); | 11257 AddSimulate(bailout_id, REMOVABLE_SIMULATE); |
| 11240 Drop(1); | 11258 Drop(1); |
| 11241 } else { | 11259 } else { |
| 11242 AddSimulate(bailout_id, REMOVABLE_SIMULATE); | 11260 AddSimulate(bailout_id, REMOVABLE_SIMULATE); |
| 11243 } | 11261 } |
| 11244 } | 11262 } |
| 11245 // TODO(jkummerow): Can we make this more efficient? | 11263 // TODO(jkummerow): Can we make this more efficient? |
| 11246 HBranch* branch = New<HBranch>(result); | 11264 HBranch* branch = New<HBranch>(result); |
| 11247 return branch; | 11265 return branch; |
| 11248 } else { | 11266 } else { |
| 11267 if (is_strong(function_language_mode()) && | |
| 11268 Token::IsOrderedRelationalCompareOp(op)) { | |
| 11269 IfBuilder if_builder(this); | |
| 11270 if_builder.If<HHasInstanceTypeAndBranch>(left, ODDBALL_TYPE); | |
| 11271 if_builder.OrIf<HHasInstanceTypeAndBranch>(right, ODDBALL_TYPE); | |
| 11272 if_builder.Then(); | |
| 11273 Add<HCallRuntime>( | |
| 11274 isolate()->factory()->empty_string(), | |
| 11275 Runtime::FunctionForId(Runtime::kThrowStrongModeImplicitConversion), | |
| 11276 0); | |
| 11277 Add<HSimulate>(bailout_id, REMOVABLE_SIMULATE); | |
| 11278 if_builder.End(); | |
| 11279 } | |
| 11249 HCompareNumericAndBranch* result = | 11280 HCompareNumericAndBranch* result = |
| 11250 New<HCompareNumericAndBranch>(left, right, op); | 11281 New<HCompareNumericAndBranch>(left, right, op); |
| 11251 result->set_observed_input_representation(left_rep, right_rep); | 11282 result->set_observed_input_representation(left_rep, right_rep); |
| 11252 if (top_info()->is_tracking_positions()) { | 11283 if (top_info()->is_tracking_positions()) { |
| 11253 result->SetOperandPositions(zone(), left_position, right_position); | 11284 result->SetOperandPositions(zone(), left_position, right_position); |
| 11254 } | 11285 } |
| 11255 return result; | 11286 return result; |
| 11256 } | 11287 } |
| 11257 } | 11288 } |
| 11258 } | 11289 } |
| (...skipping 1945 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 13204 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 13235 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
| 13205 } | 13236 } |
| 13206 | 13237 |
| 13207 #ifdef DEBUG | 13238 #ifdef DEBUG |
| 13208 graph_->Verify(false); // No full verify. | 13239 graph_->Verify(false); // No full verify. |
| 13209 #endif | 13240 #endif |
| 13210 } | 13241 } |
| 13211 | 13242 |
| 13212 } // namespace internal | 13243 } // namespace internal |
| 13213 } // namespace v8 | 13244 } // namespace v8 |
| OLD | NEW |