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/allocation-site-scopes.h" | 9 #include "src/allocation-site-scopes.h" |
10 #include "src/ast-numbering.h" | 10 #include "src/ast-numbering.h" |
(...skipping 10996 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11007 if (right_type->Is(Type::String())) { | 11007 if (right_type->Is(Type::String())) { |
11008 right = BuildCheckString(right); | 11008 right = BuildCheckString(right); |
11009 } | 11009 } |
11010 | 11010 |
11011 // Convert left argument as necessary. | 11011 // Convert left argument as necessary. |
11012 if (left_type->Is(Type::Number())) { | 11012 if (left_type->Is(Type::Number())) { |
11013 DCHECK(right_type->Is(Type::String())); | 11013 DCHECK(right_type->Is(Type::String())); |
11014 left = BuildNumberToString(left, left_type); | 11014 left = BuildNumberToString(left, left_type); |
11015 } else if (!left_type->Is(Type::String())) { | 11015 } else if (!left_type->Is(Type::String())) { |
11016 DCHECK(right_type->Is(Type::String())); | 11016 DCHECK(right_type->Is(Type::String())); |
11017 // TODO(bmeurer): We might want to optimize this, because we already | 11017 return AddUncasted<HStringAdd>( |
11018 // know that the right hand side is a string. | 11018 left, right, allocation_mode.GetPretenureMode(), |
11019 Add<HPushArguments>(left, right); | 11019 STRING_ADD_CONVERT_LEFT, allocation_mode.feedback_site()); |
11020 return AddUncasted<HCallRuntime>(Runtime::FunctionForId(Runtime::kAdd), | |
11021 2); | |
11022 } | 11020 } |
11023 | 11021 |
11024 // Convert right argument as necessary. | 11022 // Convert right argument as necessary. |
11025 if (right_type->Is(Type::Number())) { | 11023 if (right_type->Is(Type::Number())) { |
11026 DCHECK(left_type->Is(Type::String())); | 11024 DCHECK(left_type->Is(Type::String())); |
11027 right = BuildNumberToString(right, right_type); | 11025 right = BuildNumberToString(right, right_type); |
11028 } else if (!right_type->Is(Type::String())) { | 11026 } else if (!right_type->Is(Type::String())) { |
11029 DCHECK(left_type->Is(Type::String())); | 11027 DCHECK(left_type->Is(Type::String())); |
11030 // TODO(bmeurer): We might want to optimize this, because we already | 11028 return AddUncasted<HStringAdd>( |
11031 // know that the left hand side is a string. | 11029 left, right, allocation_mode.GetPretenureMode(), |
11032 Add<HPushArguments>(left, right); | 11030 STRING_ADD_CONVERT_RIGHT, allocation_mode.feedback_site()); |
11033 return AddUncasted<HCallRuntime>(Runtime::FunctionForId(Runtime::kAdd), | |
11034 2); | |
11035 } | 11031 } |
11036 } | 11032 } |
11037 | 11033 |
11038 // Fast paths for empty constant strings. | 11034 // Fast paths for empty constant strings. |
11039 Handle<String> left_string = | 11035 Handle<String> left_string = |
11040 left->IsConstant() && HConstant::cast(left)->HasStringValue() | 11036 left->IsConstant() && HConstant::cast(left)->HasStringValue() |
11041 ? HConstant::cast(left)->StringValue() | 11037 ? HConstant::cast(left)->StringValue() |
11042 : Handle<String>(); | 11038 : Handle<String>(); |
11043 Handle<String> right_string = | 11039 Handle<String> right_string = |
11044 right->IsConstant() && HConstant::cast(right)->HasStringValue() | 11040 right->IsConstant() && HConstant::cast(right)->HasStringValue() |
11045 ? HConstant::cast(right)->StringValue() | 11041 ? HConstant::cast(right)->StringValue() |
11046 : Handle<String>(); | 11042 : Handle<String>(); |
11047 if (!left_string.is_null() && left_string->length() == 0) return right; | 11043 if (!left_string.is_null() && left_string->length() == 0) return right; |
11048 if (!right_string.is_null() && right_string->length() == 0) return left; | 11044 if (!right_string.is_null() && right_string->length() == 0) return left; |
11049 if (!left_string.is_null() && !right_string.is_null()) { | 11045 if (!left_string.is_null() && !right_string.is_null()) { |
11050 return AddUncasted<HStringAdd>( | 11046 return AddUncasted<HStringAdd>( |
11051 left, right, strength, allocation_mode.GetPretenureMode(), | 11047 left, right, allocation_mode.GetPretenureMode(), |
11052 STRING_ADD_CHECK_NONE, allocation_mode.feedback_site()); | 11048 STRING_ADD_CHECK_NONE, allocation_mode.feedback_site()); |
11053 } | 11049 } |
11054 | 11050 |
11055 // Register the dependent code with the allocation site. | 11051 // Register the dependent code with the allocation site. |
11056 if (!allocation_mode.feedback_site().is_null()) { | 11052 if (!allocation_mode.feedback_site().is_null()) { |
11057 DCHECK(!graph()->info()->IsStub()); | 11053 DCHECK(!graph()->info()->IsStub()); |
11058 Handle<AllocationSite> site(allocation_mode.feedback_site()); | 11054 Handle<AllocationSite> site(allocation_mode.feedback_site()); |
11059 top_info()->dependencies()->AssumeTenuringDecision(site); | 11055 top_info()->dependencies()->AssumeTenuringDecision(site); |
11060 } | 11056 } |
11061 | 11057 |
11062 // Inline the string addition into the stub when creating allocation | 11058 // Inline the string addition into the stub when creating allocation |
11063 // mementos to gather allocation site feedback, or if we can statically | 11059 // mementos to gather allocation site feedback, or if we can statically |
11064 // infer that we're going to create a cons string. | 11060 // infer that we're going to create a cons string. |
11065 if ((graph()->info()->IsStub() && | 11061 if ((graph()->info()->IsStub() && |
11066 allocation_mode.CreateAllocationMementos()) || | 11062 allocation_mode.CreateAllocationMementos()) || |
11067 (left->IsConstant() && | 11063 (left->IsConstant() && |
11068 HConstant::cast(left)->HasStringValue() && | 11064 HConstant::cast(left)->HasStringValue() && |
11069 HConstant::cast(left)->StringValue()->length() + 1 >= | 11065 HConstant::cast(left)->StringValue()->length() + 1 >= |
11070 ConsString::kMinLength) || | 11066 ConsString::kMinLength) || |
11071 (right->IsConstant() && | 11067 (right->IsConstant() && |
11072 HConstant::cast(right)->HasStringValue() && | 11068 HConstant::cast(right)->HasStringValue() && |
11073 HConstant::cast(right)->StringValue()->length() + 1 >= | 11069 HConstant::cast(right)->StringValue()->length() + 1 >= |
11074 ConsString::kMinLength)) { | 11070 ConsString::kMinLength)) { |
11075 return BuildStringAdd(left, right, allocation_mode); | 11071 return BuildStringAdd(left, right, allocation_mode); |
11076 } | 11072 } |
11077 | 11073 |
11078 // Fallback to using the string add stub. | 11074 // Fallback to using the string add stub. |
11079 return AddUncasted<HStringAdd>( | 11075 return AddUncasted<HStringAdd>( |
11080 left, right, strength, allocation_mode.GetPretenureMode(), | 11076 left, right, allocation_mode.GetPretenureMode(), STRING_ADD_CHECK_NONE, |
11081 STRING_ADD_CHECK_NONE, allocation_mode.feedback_site()); | 11077 allocation_mode.feedback_site()); |
11082 } | 11078 } |
11083 | 11079 |
11084 if (graph()->info()->IsStub()) { | 11080 if (graph()->info()->IsStub()) { |
11085 left = EnforceNumberType(left, left_type); | 11081 left = EnforceNumberType(left, left_type); |
11086 right = EnforceNumberType(right, right_type); | 11082 right = EnforceNumberType(right, right_type); |
11087 } | 11083 } |
11088 | 11084 |
11089 Representation result_rep = RepresentationFor(result_type); | 11085 Representation result_rep = RepresentationFor(result_type); |
11090 | 11086 |
11091 bool is_non_primitive = (left_rep.IsTagged() && !left_rep.IsSmi()) || | 11087 bool is_non_primitive = (left_rep.IsTagged() && !left_rep.IsSmi()) || |
(...skipping 1437 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12529 } | 12525 } |
12530 | 12526 |
12531 | 12527 |
12532 // Fast support for StringAdd. | 12528 // Fast support for StringAdd. |
12533 void HOptimizedGraphBuilder::GenerateStringAdd(CallRuntime* call) { | 12529 void HOptimizedGraphBuilder::GenerateStringAdd(CallRuntime* call) { |
12534 DCHECK_EQ(2, call->arguments()->length()); | 12530 DCHECK_EQ(2, call->arguments()->length()); |
12535 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 12531 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
12536 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | 12532 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
12537 HValue* right = Pop(); | 12533 HValue* right = Pop(); |
12538 HValue* left = Pop(); | 12534 HValue* left = Pop(); |
12539 HInstruction* result = | 12535 HInstruction* result = NewUncasted<HStringAdd>(left, right); |
12540 NewUncasted<HStringAdd>(left, right, strength(function_language_mode())); | |
12541 return ast_context()->ReturnInstruction(result, call->id()); | 12536 return ast_context()->ReturnInstruction(result, call->id()); |
12542 } | 12537 } |
12543 | 12538 |
12544 | 12539 |
12545 // Fast support for SubString. | 12540 // Fast support for SubString. |
12546 void HOptimizedGraphBuilder::GenerateSubString(CallRuntime* call) { | 12541 void HOptimizedGraphBuilder::GenerateSubString(CallRuntime* call) { |
12547 DCHECK_EQ(3, call->arguments()->length()); | 12542 DCHECK_EQ(3, call->arguments()->length()); |
12548 CHECK_ALIVE(VisitExpressions(call->arguments())); | 12543 CHECK_ALIVE(VisitExpressions(call->arguments())); |
12549 PushArgumentsFromEnvironment(call->arguments()->length()); | 12544 PushArgumentsFromEnvironment(call->arguments()->length()); |
12550 HCallStub* result = New<HCallStub>(CodeStub::SubString, 3); | 12545 HCallStub* result = New<HCallStub>(CodeStub::SubString, 3); |
(...skipping 1057 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13608 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 13603 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
13609 } | 13604 } |
13610 | 13605 |
13611 #ifdef DEBUG | 13606 #ifdef DEBUG |
13612 graph_->Verify(false); // No full verify. | 13607 graph_->Verify(false); // No full verify. |
13613 #endif | 13608 #endif |
13614 } | 13609 } |
13615 | 13610 |
13616 } // namespace internal | 13611 } // namespace internal |
13617 } // namespace v8 | 13612 } // namespace v8 |
OLD | NEW |