| 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 |