| 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/crankshaft/hydrogen.h" | 5 #include "src/crankshaft/hydrogen.h" |
| 6 | 6 |
| 7 #include <sstream> | 7 #include <sstream> |
| 8 | 8 |
| 9 #include "src/allocation-site-scopes.h" | 9 #include "src/allocation-site-scopes.h" |
| 10 #include "src/ast/ast-numbering.h" | 10 #include "src/ast/ast-numbering.h" |
| (...skipping 10888 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10899 return number; | 10899 return number; |
| 10900 } | 10900 } |
| 10901 | 10901 |
| 10902 | 10902 |
| 10903 HValue* HGraphBuilder::TruncateToNumber(HValue* value, Type** expected) { | 10903 HValue* HGraphBuilder::TruncateToNumber(HValue* value, Type** expected) { |
| 10904 if (value->IsConstant()) { | 10904 if (value->IsConstant()) { |
| 10905 HConstant* constant = HConstant::cast(value); | 10905 HConstant* constant = HConstant::cast(value); |
| 10906 Maybe<HConstant*> number = | 10906 Maybe<HConstant*> number = |
| 10907 constant->CopyToTruncatedNumber(isolate(), zone()); | 10907 constant->CopyToTruncatedNumber(isolate(), zone()); |
| 10908 if (number.IsJust()) { | 10908 if (number.IsJust()) { |
| 10909 *expected = Type::Number(zone()); | 10909 *expected = Type::Number(); |
| 10910 return AddInstruction(number.FromJust()); | 10910 return AddInstruction(number.FromJust()); |
| 10911 } | 10911 } |
| 10912 } | 10912 } |
| 10913 | 10913 |
| 10914 // We put temporary values on the stack, which don't correspond to anything | 10914 // We put temporary values on the stack, which don't correspond to anything |
| 10915 // in baseline code. Since nothing is observable we avoid recording those | 10915 // in baseline code. Since nothing is observable we avoid recording those |
| 10916 // pushes with a NoObservableSideEffectsScope. | 10916 // pushes with a NoObservableSideEffectsScope. |
| 10917 NoObservableSideEffectsScope no_effects(this); | 10917 NoObservableSideEffectsScope no_effects(this); |
| 10918 | 10918 |
| 10919 Type* expected_type = *expected; | 10919 Type* expected_type = *expected; |
| 10920 | 10920 |
| 10921 // Separate the number type from the rest. | 10921 // Separate the number type from the rest. |
| 10922 Type* expected_obj = | 10922 Type* expected_obj = |
| 10923 Type::Intersect(expected_type, Type::NonNumber(zone()), zone()); | 10923 Type::Intersect(expected_type, Type::NonNumber(), zone()); |
| 10924 Type* expected_number = | 10924 Type* expected_number = |
| 10925 Type::Intersect(expected_type, Type::Number(zone()), zone()); | 10925 Type::Intersect(expected_type, Type::Number(), zone()); |
| 10926 | 10926 |
| 10927 // We expect to get a number. | 10927 // We expect to get a number. |
| 10928 // (We need to check first, since Type::None->Is(Type::Any()) == true. | 10928 // (We need to check first, since Type::None->Is(Type::Any()) == true. |
| 10929 if (expected_obj->Is(Type::None())) { | 10929 if (expected_obj->Is(Type::None())) { |
| 10930 DCHECK(!expected_number->Is(Type::None(zone()))); | 10930 DCHECK(!expected_number->Is(Type::None())); |
| 10931 return value; | 10931 return value; |
| 10932 } | 10932 } |
| 10933 | 10933 |
| 10934 if (expected_obj->Is(Type::Undefined(zone()))) { | 10934 if (expected_obj->Is(Type::Undefined())) { |
| 10935 // This is already done by HChange. | 10935 // This is already done by HChange. |
| 10936 *expected = Type::Union(expected_number, Type::Number(zone()), zone()); | 10936 *expected = Type::Union(expected_number, Type::Number(), zone()); |
| 10937 return value; | 10937 return value; |
| 10938 } | 10938 } |
| 10939 | 10939 |
| 10940 return value; | 10940 return value; |
| 10941 } | 10941 } |
| 10942 | 10942 |
| 10943 | 10943 |
| 10944 HValue* HOptimizedGraphBuilder::BuildBinaryOperation( | 10944 HValue* HOptimizedGraphBuilder::BuildBinaryOperation( |
| 10945 BinaryOperation* expr, | 10945 BinaryOperation* expr, |
| 10946 HValue* left, | 10946 HValue* left, |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11001 right_type->Maybe(Type::Receiver())); | 11001 right_type->Maybe(Type::Receiver())); |
| 11002 } | 11002 } |
| 11003 | 11003 |
| 11004 Representation left_rep = RepresentationFor(left_type); | 11004 Representation left_rep = RepresentationFor(left_type); |
| 11005 Representation right_rep = RepresentationFor(right_type); | 11005 Representation right_rep = RepresentationFor(right_type); |
| 11006 | 11006 |
| 11007 if (!left_type->IsInhabited()) { | 11007 if (!left_type->IsInhabited()) { |
| 11008 Add<HDeoptimize>( | 11008 Add<HDeoptimize>( |
| 11009 Deoptimizer::kInsufficientTypeFeedbackForLHSOfBinaryOperation, | 11009 Deoptimizer::kInsufficientTypeFeedbackForLHSOfBinaryOperation, |
| 11010 Deoptimizer::SOFT); | 11010 Deoptimizer::SOFT); |
| 11011 left_type = Type::Any(zone()); | 11011 left_type = Type::Any(); |
| 11012 left_rep = RepresentationFor(left_type); | 11012 left_rep = RepresentationFor(left_type); |
| 11013 maybe_string_add = op == Token::ADD; | 11013 maybe_string_add = op == Token::ADD; |
| 11014 } | 11014 } |
| 11015 | 11015 |
| 11016 if (!right_type->IsInhabited()) { | 11016 if (!right_type->IsInhabited()) { |
| 11017 Add<HDeoptimize>( | 11017 Add<HDeoptimize>( |
| 11018 Deoptimizer::kInsufficientTypeFeedbackForRHSOfBinaryOperation, | 11018 Deoptimizer::kInsufficientTypeFeedbackForRHSOfBinaryOperation, |
| 11019 Deoptimizer::SOFT); | 11019 Deoptimizer::SOFT); |
| 11020 right_type = Type::Any(zone()); | 11020 right_type = Type::Any(); |
| 11021 right_rep = RepresentationFor(right_type); | 11021 right_rep = RepresentationFor(right_type); |
| 11022 maybe_string_add = op == Token::ADD; | 11022 maybe_string_add = op == Token::ADD; |
| 11023 } | 11023 } |
| 11024 | 11024 |
| 11025 if (!maybe_string_add && !is_strong(strength)) { | 11025 if (!maybe_string_add && !is_strong(strength)) { |
| 11026 left = TruncateToNumber(left, &left_type); | 11026 left = TruncateToNumber(left, &left_type); |
| 11027 right = TruncateToNumber(right, &right_type); | 11027 right = TruncateToNumber(right, &right_type); |
| 11028 } | 11028 } |
| 11029 | 11029 |
| 11030 // Special case for string addition here. | 11030 // Special case for string addition here. |
| (...skipping 533 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11564 Token::Value op, HValue* left, HValue* right, Type* left_type, | 11564 Token::Value op, HValue* left, HValue* right, Type* left_type, |
| 11565 Type* right_type, Type* combined_type, SourcePosition left_position, | 11565 Type* right_type, Type* combined_type, SourcePosition left_position, |
| 11566 SourcePosition right_position, PushBeforeSimulateBehavior push_sim_result, | 11566 SourcePosition right_position, PushBeforeSimulateBehavior push_sim_result, |
| 11567 BailoutId bailout_id) { | 11567 BailoutId bailout_id) { |
| 11568 // Cases handled below depend on collected type feedback. They should | 11568 // Cases handled below depend on collected type feedback. They should |
| 11569 // soft deoptimize when there is no type feedback. | 11569 // soft deoptimize when there is no type feedback. |
| 11570 if (!combined_type->IsInhabited()) { | 11570 if (!combined_type->IsInhabited()) { |
| 11571 Add<HDeoptimize>( | 11571 Add<HDeoptimize>( |
| 11572 Deoptimizer::kInsufficientTypeFeedbackForCombinedTypeOfBinaryOperation, | 11572 Deoptimizer::kInsufficientTypeFeedbackForCombinedTypeOfBinaryOperation, |
| 11573 Deoptimizer::SOFT); | 11573 Deoptimizer::SOFT); |
| 11574 combined_type = left_type = right_type = Type::Any(zone()); | 11574 combined_type = left_type = right_type = Type::Any(); |
| 11575 } | 11575 } |
| 11576 | 11576 |
| 11577 Representation left_rep = RepresentationFor(left_type); | 11577 Representation left_rep = RepresentationFor(left_type); |
| 11578 Representation right_rep = RepresentationFor(right_type); | 11578 Representation right_rep = RepresentationFor(right_type); |
| 11579 Representation combined_rep = RepresentationFor(combined_type); | 11579 Representation combined_rep = RepresentationFor(combined_type); |
| 11580 | 11580 |
| 11581 if (combined_type->Is(Type::Receiver())) { | 11581 if (combined_type->Is(Type::Receiver())) { |
| 11582 if (Token::IsEqualityOp(op)) { | 11582 if (Token::IsEqualityOp(op)) { |
| 11583 // HCompareObjectEqAndBranch can only deal with object, so | 11583 // HCompareObjectEqAndBranch can only deal with object, so |
| 11584 // exclude numbers. | 11584 // exclude numbers. |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11750 if (expr->op() == Token::EQ_STRICT) { | 11750 if (expr->op() == Token::EQ_STRICT) { |
| 11751 HConstant* nil_constant = nil == kNullValue | 11751 HConstant* nil_constant = nil == kNullValue |
| 11752 ? graph()->GetConstantNull() | 11752 ? graph()->GetConstantNull() |
| 11753 : graph()->GetConstantUndefined(); | 11753 : graph()->GetConstantUndefined(); |
| 11754 HCompareObjectEqAndBranch* instr = | 11754 HCompareObjectEqAndBranch* instr = |
| 11755 New<HCompareObjectEqAndBranch>(value, nil_constant); | 11755 New<HCompareObjectEqAndBranch>(value, nil_constant); |
| 11756 return ast_context()->ReturnControl(instr, expr->id()); | 11756 return ast_context()->ReturnControl(instr, expr->id()); |
| 11757 } else { | 11757 } else { |
| 11758 DCHECK_EQ(Token::EQ, expr->op()); | 11758 DCHECK_EQ(Token::EQ, expr->op()); |
| 11759 Type* type = expr->combined_type()->Is(Type::None()) | 11759 Type* type = expr->combined_type()->Is(Type::None()) |
| 11760 ? Type::Any(zone()) : expr->combined_type(); | 11760 ? Type::Any() |
| 11761 : expr->combined_type(); |
| 11761 HIfContinuation continuation; | 11762 HIfContinuation continuation; |
| 11762 BuildCompareNil(value, type, &continuation); | 11763 BuildCompareNil(value, type, &continuation); |
| 11763 return ast_context()->ReturnContinuation(&continuation, expr->id()); | 11764 return ast_context()->ReturnContinuation(&continuation, expr->id()); |
| 11764 } | 11765 } |
| 11765 } | 11766 } |
| 11766 | 11767 |
| 11767 | 11768 |
| 11768 void HOptimizedGraphBuilder::VisitSpread(Spread* expr) { UNREACHABLE(); } | 11769 void HOptimizedGraphBuilder::VisitSpread(Spread* expr) { UNREACHABLE(); } |
| 11769 | 11770 |
| 11770 | 11771 |
| (...skipping 542 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12313 return ast_context()->ReturnValue(Pop()); | 12314 return ast_context()->ReturnValue(Pop()); |
| 12314 } | 12315 } |
| 12315 } | 12316 } |
| 12316 | 12317 |
| 12317 | 12318 |
| 12318 void HOptimizedGraphBuilder::GenerateToName(CallRuntime* call) { | 12319 void HOptimizedGraphBuilder::GenerateToName(CallRuntime* call) { |
| 12319 DCHECK_EQ(1, call->arguments()->length()); | 12320 DCHECK_EQ(1, call->arguments()->length()); |
| 12320 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 12321 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 12321 HValue* input = Pop(); | 12322 HValue* input = Pop(); |
| 12322 if (input->type().IsSmi()) { | 12323 if (input->type().IsSmi()) { |
| 12323 HValue* result = BuildNumberToString(input, Type::SignedSmall(zone())); | 12324 HValue* result = BuildNumberToString(input, Type::SignedSmall()); |
| 12324 return ast_context()->ReturnValue(result); | 12325 return ast_context()->ReturnValue(result); |
| 12325 } else if (input->type().IsTaggedNumber()) { | 12326 } else if (input->type().IsTaggedNumber()) { |
| 12326 HValue* result = BuildNumberToString(input, Type::Number(zone())); | 12327 HValue* result = BuildNumberToString(input, Type::Number()); |
| 12327 return ast_context()->ReturnValue(result); | 12328 return ast_context()->ReturnValue(result); |
| 12328 } else if (input->type().IsString()) { | 12329 } else if (input->type().IsString()) { |
| 12329 return ast_context()->ReturnValue(input); | 12330 return ast_context()->ReturnValue(input); |
| 12330 } else { | 12331 } else { |
| 12331 Callable callable = CodeFactory::ToName(isolate()); | 12332 Callable callable = CodeFactory::ToName(isolate()); |
| 12332 HValue* stub = Add<HConstant>(callable.code()); | 12333 HValue* stub = Add<HConstant>(callable.code()); |
| 12333 HValue* values[] = {context(), input}; | 12334 HValue* values[] = {context(), input}; |
| 12334 HInstruction* result = | 12335 HInstruction* result = |
| 12335 New<HCallWithDescriptor>(stub, 0, callable.descriptor(), | 12336 New<HCallWithDescriptor>(stub, 0, callable.descriptor(), |
| 12336 Vector<HValue*>(values, arraysize(values))); | 12337 Vector<HValue*>(values, arraysize(values))); |
| (...skipping 400 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12737 HValue* result = BuildRegExpConstructResult(length, index, input); | 12738 HValue* result = BuildRegExpConstructResult(length, index, input); |
| 12738 return ast_context()->ReturnValue(result); | 12739 return ast_context()->ReturnValue(result); |
| 12739 } | 12740 } |
| 12740 | 12741 |
| 12741 | 12742 |
| 12742 // Fast support for number to string. | 12743 // Fast support for number to string. |
| 12743 void HOptimizedGraphBuilder::GenerateNumberToString(CallRuntime* call) { | 12744 void HOptimizedGraphBuilder::GenerateNumberToString(CallRuntime* call) { |
| 12744 DCHECK_EQ(1, call->arguments()->length()); | 12745 DCHECK_EQ(1, call->arguments()->length()); |
| 12745 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 12746 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 12746 HValue* number = Pop(); | 12747 HValue* number = Pop(); |
| 12747 HValue* result = BuildNumberToString(number, Type::Any(zone())); | 12748 HValue* result = BuildNumberToString(number, Type::Any()); |
| 12748 return ast_context()->ReturnValue(result); | 12749 return ast_context()->ReturnValue(result); |
| 12749 } | 12750 } |
| 12750 | 12751 |
| 12751 | 12752 |
| 12752 // Fast support for calls. | 12753 // Fast support for calls. |
| 12753 void HOptimizedGraphBuilder::GenerateCall(CallRuntime* call) { | 12754 void HOptimizedGraphBuilder::GenerateCall(CallRuntime* call) { |
| 12754 DCHECK_LE(2, call->arguments()->length()); | 12755 DCHECK_LE(2, call->arguments()->length()); |
| 12755 CHECK_ALIVE(VisitExpressions(call->arguments())); | 12756 CHECK_ALIVE(VisitExpressions(call->arguments())); |
| 12756 CallTrampolineDescriptor descriptor(isolate()); | 12757 CallTrampolineDescriptor descriptor(isolate()); |
| 12757 PushArgumentsFromEnvironment(call->arguments()->length() - 1); | 12758 PushArgumentsFromEnvironment(call->arguments()->length() - 1); |
| (...skipping 906 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 13664 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 13665 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
| 13665 } | 13666 } |
| 13666 | 13667 |
| 13667 #ifdef DEBUG | 13668 #ifdef DEBUG |
| 13668 graph_->Verify(false); // No full verify. | 13669 graph_->Verify(false); // No full verify. |
| 13669 #endif | 13670 #endif |
| 13670 } | 13671 } |
| 13671 | 13672 |
| 13672 } // namespace internal | 13673 } // namespace internal |
| 13673 } // namespace v8 | 13674 } // namespace v8 |
| OLD | NEW |