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 10977 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10988 if (right_type->Is(Type::String())) { | 10988 if (right_type->Is(Type::String())) { |
10989 right = BuildCheckString(right); | 10989 right = BuildCheckString(right); |
10990 } | 10990 } |
10991 | 10991 |
10992 // Convert left argument as necessary. | 10992 // Convert left argument as necessary. |
10993 if (left_type->Is(Type::Number())) { | 10993 if (left_type->Is(Type::Number())) { |
10994 DCHECK(right_type->Is(Type::String())); | 10994 DCHECK(right_type->Is(Type::String())); |
10995 left = BuildNumberToString(left, left_type); | 10995 left = BuildNumberToString(left, left_type); |
10996 } else if (!left_type->Is(Type::String())) { | 10996 } else if (!left_type->Is(Type::String())) { |
10997 DCHECK(right_type->Is(Type::String())); | 10997 DCHECK(right_type->Is(Type::String())); |
10998 return AddUncasted<HStringAdd>( | 10998 // TODO(bmeurer): We might want to optimize this, because we already |
10999 left, right, allocation_mode.GetPretenureMode(), | 10999 // know that the right hand side is a string. |
11000 STRING_ADD_CONVERT_LEFT, allocation_mode.feedback_site()); | 11000 Add<HPushArguments>(left, right); |
| 11001 return AddUncasted<HCallRuntime>(Runtime::FunctionForId(Runtime::kAdd), |
| 11002 2); |
11001 } | 11003 } |
11002 | 11004 |
11003 // Convert right argument as necessary. | 11005 // Convert right argument as necessary. |
11004 if (right_type->Is(Type::Number())) { | 11006 if (right_type->Is(Type::Number())) { |
11005 DCHECK(left_type->Is(Type::String())); | 11007 DCHECK(left_type->Is(Type::String())); |
11006 right = BuildNumberToString(right, right_type); | 11008 right = BuildNumberToString(right, right_type); |
11007 } else if (!right_type->Is(Type::String())) { | 11009 } else if (!right_type->Is(Type::String())) { |
11008 DCHECK(left_type->Is(Type::String())); | 11010 DCHECK(left_type->Is(Type::String())); |
11009 return AddUncasted<HStringAdd>( | 11011 // TODO(bmeurer): We might want to optimize this, because we already |
11010 left, right, allocation_mode.GetPretenureMode(), | 11012 // know that the left hand side is a string. |
11011 STRING_ADD_CONVERT_RIGHT, allocation_mode.feedback_site()); | 11013 Add<HPushArguments>(left, right); |
| 11014 return AddUncasted<HCallRuntime>(Runtime::FunctionForId(Runtime::kAdd), |
| 11015 2); |
11012 } | 11016 } |
11013 } | 11017 } |
11014 | 11018 |
11015 // Fast paths for empty constant strings. | 11019 // Fast paths for empty constant strings. |
11016 Handle<String> left_string = | 11020 Handle<String> left_string = |
11017 left->IsConstant() && HConstant::cast(left)->HasStringValue() | 11021 left->IsConstant() && HConstant::cast(left)->HasStringValue() |
11018 ? HConstant::cast(left)->StringValue() | 11022 ? HConstant::cast(left)->StringValue() |
11019 : Handle<String>(); | 11023 : Handle<String>(); |
11020 Handle<String> right_string = | 11024 Handle<String> right_string = |
11021 right->IsConstant() && HConstant::cast(right)->HasStringValue() | 11025 right->IsConstant() && HConstant::cast(right)->HasStringValue() |
11022 ? HConstant::cast(right)->StringValue() | 11026 ? HConstant::cast(right)->StringValue() |
11023 : Handle<String>(); | 11027 : Handle<String>(); |
11024 if (!left_string.is_null() && left_string->length() == 0) return right; | 11028 if (!left_string.is_null() && left_string->length() == 0) return right; |
11025 if (!right_string.is_null() && right_string->length() == 0) return left; | 11029 if (!right_string.is_null() && right_string->length() == 0) return left; |
11026 if (!left_string.is_null() && !right_string.is_null()) { | 11030 if (!left_string.is_null() && !right_string.is_null()) { |
11027 return AddUncasted<HStringAdd>( | 11031 return AddUncasted<HStringAdd>( |
11028 left, right, allocation_mode.GetPretenureMode(), | 11032 left, right, strength, allocation_mode.GetPretenureMode(), |
11029 STRING_ADD_CHECK_NONE, allocation_mode.feedback_site()); | 11033 STRING_ADD_CHECK_NONE, allocation_mode.feedback_site()); |
11030 } | 11034 } |
11031 | 11035 |
11032 // Register the dependent code with the allocation site. | 11036 // Register the dependent code with the allocation site. |
11033 if (!allocation_mode.feedback_site().is_null()) { | 11037 if (!allocation_mode.feedback_site().is_null()) { |
11034 DCHECK(!graph()->info()->IsStub()); | 11038 DCHECK(!graph()->info()->IsStub()); |
11035 Handle<AllocationSite> site(allocation_mode.feedback_site()); | 11039 Handle<AllocationSite> site(allocation_mode.feedback_site()); |
11036 top_info()->dependencies()->AssumeTenuringDecision(site); | 11040 top_info()->dependencies()->AssumeTenuringDecision(site); |
11037 } | 11041 } |
11038 | 11042 |
11039 // Inline the string addition into the stub when creating allocation | 11043 // Inline the string addition into the stub when creating allocation |
11040 // mementos to gather allocation site feedback, or if we can statically | 11044 // mementos to gather allocation site feedback, or if we can statically |
11041 // infer that we're going to create a cons string. | 11045 // infer that we're going to create a cons string. |
11042 if ((graph()->info()->IsStub() && | 11046 if ((graph()->info()->IsStub() && |
11043 allocation_mode.CreateAllocationMementos()) || | 11047 allocation_mode.CreateAllocationMementos()) || |
11044 (left->IsConstant() && | 11048 (left->IsConstant() && |
11045 HConstant::cast(left)->HasStringValue() && | 11049 HConstant::cast(left)->HasStringValue() && |
11046 HConstant::cast(left)->StringValue()->length() + 1 >= | 11050 HConstant::cast(left)->StringValue()->length() + 1 >= |
11047 ConsString::kMinLength) || | 11051 ConsString::kMinLength) || |
11048 (right->IsConstant() && | 11052 (right->IsConstant() && |
11049 HConstant::cast(right)->HasStringValue() && | 11053 HConstant::cast(right)->HasStringValue() && |
11050 HConstant::cast(right)->StringValue()->length() + 1 >= | 11054 HConstant::cast(right)->StringValue()->length() + 1 >= |
11051 ConsString::kMinLength)) { | 11055 ConsString::kMinLength)) { |
11052 return BuildStringAdd(left, right, allocation_mode); | 11056 return BuildStringAdd(left, right, allocation_mode); |
11053 } | 11057 } |
11054 | 11058 |
11055 // Fallback to using the string add stub. | 11059 // Fallback to using the string add stub. |
11056 return AddUncasted<HStringAdd>( | 11060 return AddUncasted<HStringAdd>( |
11057 left, right, allocation_mode.GetPretenureMode(), STRING_ADD_CHECK_NONE, | 11061 left, right, strength, allocation_mode.GetPretenureMode(), |
11058 allocation_mode.feedback_site()); | 11062 STRING_ADD_CHECK_NONE, allocation_mode.feedback_site()); |
11059 } | 11063 } |
11060 | 11064 |
11061 if (graph()->info()->IsStub()) { | 11065 if (graph()->info()->IsStub()) { |
11062 left = EnforceNumberType(left, left_type); | 11066 left = EnforceNumberType(left, left_type); |
11063 right = EnforceNumberType(right, right_type); | 11067 right = EnforceNumberType(right, right_type); |
11064 } | 11068 } |
11065 | 11069 |
11066 Representation result_rep = RepresentationFor(result_type); | 11070 Representation result_rep = RepresentationFor(result_type); |
11067 | 11071 |
11068 bool is_non_primitive = (left_rep.IsTagged() && !left_rep.IsSmi()) || | 11072 bool is_non_primitive = (left_rep.IsTagged() && !left_rep.IsSmi()) || |
(...skipping 1392 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12461 } | 12465 } |
12462 | 12466 |
12463 | 12467 |
12464 // Fast support for StringAdd. | 12468 // Fast support for StringAdd. |
12465 void HOptimizedGraphBuilder::GenerateStringAdd(CallRuntime* call) { | 12469 void HOptimizedGraphBuilder::GenerateStringAdd(CallRuntime* call) { |
12466 DCHECK_EQ(2, call->arguments()->length()); | 12470 DCHECK_EQ(2, call->arguments()->length()); |
12467 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 12471 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
12468 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); | 12472 CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); |
12469 HValue* right = Pop(); | 12473 HValue* right = Pop(); |
12470 HValue* left = Pop(); | 12474 HValue* left = Pop(); |
12471 HInstruction* result = NewUncasted<HStringAdd>(left, right); | 12475 HInstruction* result = |
| 12476 NewUncasted<HStringAdd>(left, right, strength(function_language_mode())); |
12472 return ast_context()->ReturnInstruction(result, call->id()); | 12477 return ast_context()->ReturnInstruction(result, call->id()); |
12473 } | 12478 } |
12474 | 12479 |
12475 | 12480 |
12476 // Fast support for SubString. | 12481 // Fast support for SubString. |
12477 void HOptimizedGraphBuilder::GenerateSubString(CallRuntime* call) { | 12482 void HOptimizedGraphBuilder::GenerateSubString(CallRuntime* call) { |
12478 DCHECK_EQ(3, call->arguments()->length()); | 12483 DCHECK_EQ(3, call->arguments()->length()); |
12479 CHECK_ALIVE(VisitExpressions(call->arguments())); | 12484 CHECK_ALIVE(VisitExpressions(call->arguments())); |
12480 PushArgumentsFromEnvironment(call->arguments()->length()); | 12485 PushArgumentsFromEnvironment(call->arguments()->length()); |
12481 HCallStub* result = New<HCallStub>(CodeStub::SubString, 3); | 12486 HCallStub* result = New<HCallStub>(CodeStub::SubString, 3); |
(...skipping 1067 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13549 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 13554 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
13550 } | 13555 } |
13551 | 13556 |
13552 #ifdef DEBUG | 13557 #ifdef DEBUG |
13553 graph_->Verify(false); // No full verify. | 13558 graph_->Verify(false); // No full verify. |
13554 #endif | 13559 #endif |
13555 } | 13560 } |
13556 | 13561 |
13557 } // namespace internal | 13562 } // namespace internal |
13558 } // namespace v8 | 13563 } // namespace v8 |
OLD | NEW |