OLD | NEW |
1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 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 #include "src/code-stub-assembler.h" | 4 #include "src/code-stub-assembler.h" |
5 #include "src/code-factory.h" | 5 #include "src/code-factory.h" |
6 #include "src/frames-inl.h" | 6 #include "src/frames-inl.h" |
7 #include "src/frames.h" | 7 #include "src/frames.h" |
8 | 8 |
9 namespace v8 { | 9 namespace v8 { |
10 namespace internal { | 10 namespace internal { |
(...skipping 3530 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3541 a->Goto(&end); | 3541 a->Goto(&end); |
3542 } | 3542 } |
3543 | 3543 |
3544 a->BIND(&end); | 3544 a->BIND(&end); |
3545 return var_result.value(); | 3545 return var_result.value(); |
3546 } | 3546 } |
3547 | 3547 |
3548 } // namespace | 3548 } // namespace |
3549 | 3549 |
3550 Node* CodeStubAssembler::SubString(Node* context, Node* string, Node* from, | 3550 Node* CodeStubAssembler::SubString(Node* context, Node* string, Node* from, |
3551 Node* to) { | 3551 Node* to, SubStringFlags flags) { |
| 3552 DCHECK(flags == SubStringFlags::NONE || |
| 3553 flags == SubStringFlags::FROM_TO_ARE_BOUNDED); |
3552 VARIABLE(var_result, MachineRepresentation::kTagged); | 3554 VARIABLE(var_result, MachineRepresentation::kTagged); |
3553 ToDirectStringAssembler to_direct(state(), string); | 3555 ToDirectStringAssembler to_direct(state(), string); |
3554 Label end(this), runtime(this); | 3556 Label end(this), runtime(this); |
3555 | 3557 |
3556 // Make sure first argument is a string. | 3558 // Make sure first argument is a string. |
3557 CSA_ASSERT(this, TaggedIsNotSmi(string)); | 3559 CSA_ASSERT(this, TaggedIsNotSmi(string)); |
3558 CSA_ASSERT(this, IsString(string)); | 3560 CSA_ASSERT(this, IsString(string)); |
3559 | 3561 |
3560 // Make sure that both from and to are non-negative smis. | 3562 // Make sure that both from and to are non-negative smis. |
3561 | 3563 |
3562 GotoIfNot(TaggedIsPositiveSmi(from), &runtime); | 3564 if (flags == SubStringFlags::NONE) { |
3563 GotoIfNot(TaggedIsPositiveSmi(to), &runtime); | 3565 GotoIfNot(TaggedIsPositiveSmi(from), &runtime); |
| 3566 GotoIfNot(TaggedIsPositiveSmi(to), &runtime); |
| 3567 } else { |
| 3568 CSA_ASSERT(this, TaggedIsPositiveSmi(from)); |
| 3569 CSA_ASSERT(this, TaggedIsPositiveSmi(to)); |
| 3570 } |
3564 | 3571 |
3565 Node* const substr_length = SmiSub(to, from); | 3572 Node* const substr_length = SmiSub(to, from); |
3566 Node* const string_length = LoadStringLength(string); | 3573 Node* const string_length = LoadStringLength(string); |
3567 | 3574 |
3568 // Begin dispatching based on substring length. | 3575 // Begin dispatching based on substring length. |
3569 | 3576 |
3570 Label original_string_or_invalid_length(this); | 3577 Label original_string_or_invalid_length(this); |
3571 GotoIf(SmiAboveOrEqual(substr_length, string_length), | 3578 GotoIf(SmiAboveOrEqual(substr_length, string_length), |
3572 &original_string_or_invalid_length); | 3579 &original_string_or_invalid_length); |
3573 | 3580 |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3654 // Substrings of length 1 are generated through CharCodeAt and FromCharCode. | 3661 // Substrings of length 1 are generated through CharCodeAt and FromCharCode. |
3655 BIND(&single_char); | 3662 BIND(&single_char); |
3656 { | 3663 { |
3657 Node* char_code = StringCharCodeAt(string, from); | 3664 Node* char_code = StringCharCodeAt(string, from); |
3658 var_result.Bind(StringFromCharCode(char_code)); | 3665 var_result.Bind(StringFromCharCode(char_code)); |
3659 Goto(&end); | 3666 Goto(&end); |
3660 } | 3667 } |
3661 | 3668 |
3662 BIND(&original_string_or_invalid_length); | 3669 BIND(&original_string_or_invalid_length); |
3663 { | 3670 { |
3664 // Longer than original string's length or negative: unsafe arguments. | 3671 if (flags == SubStringFlags::NONE) { |
3665 GotoIf(SmiAbove(substr_length, string_length), &runtime); | 3672 // Longer than original string's length or negative: unsafe arguments. |
| 3673 GotoIf(SmiAbove(substr_length, string_length), &runtime); |
| 3674 } else { |
| 3675 // with flag SubStringFlags::FROM_TO_ARE_BOUNDED, the only way we can |
| 3676 // get here is if substr_length is equal to string_length. |
| 3677 CSA_ASSERT(this, SmiEqual(substr_length, string_length)); |
| 3678 } |
3666 | 3679 |
3667 // Equal length - check if {from, to} == {0, str.length}. | 3680 // Equal length - check if {from, to} == {0, str.length}. |
3668 GotoIf(SmiAbove(from, SmiConstant(Smi::kZero)), &runtime); | 3681 GotoIf(SmiAbove(from, SmiConstant(Smi::kZero)), &runtime); |
3669 | 3682 |
3670 // Return the original string (substr_length == string_length). | 3683 // Return the original string (substr_length == string_length). |
3671 | 3684 |
3672 Counters* counters = isolate()->counters(); | 3685 Counters* counters = isolate()->counters(); |
3673 IncrementCounter(counters->sub_string_native(), 1); | 3686 IncrementCounter(counters->sub_string_native(), 1); |
3674 | 3687 |
3675 var_result.Bind(string); | 3688 var_result.Bind(string); |
(...skipping 5404 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9080 formatted.c_str(), TENURED); | 9093 formatted.c_str(), TENURED); |
9081 CallRuntime(Runtime::kGlobalPrint, NoContextConstant(), | 9094 CallRuntime(Runtime::kGlobalPrint, NoContextConstant(), |
9082 HeapConstant(string)); | 9095 HeapConstant(string)); |
9083 } | 9096 } |
9084 CallRuntime(Runtime::kDebugPrint, NoContextConstant(), tagged_value); | 9097 CallRuntime(Runtime::kDebugPrint, NoContextConstant(), tagged_value); |
9085 #endif | 9098 #endif |
9086 } | 9099 } |
9087 | 9100 |
9088 } // namespace internal | 9101 } // namespace internal |
9089 } // namespace v8 | 9102 } // namespace v8 |
OLD | NEW |