diff options
Diffstat (limited to 'deps/v8/src/builtins/builtins-string-gen.cc')
-rw-r--r-- | deps/v8/src/builtins/builtins-string-gen.cc | 328 |
1 files changed, 134 insertions, 194 deletions
diff --git a/deps/v8/src/builtins/builtins-string-gen.cc b/deps/v8/src/builtins/builtins-string-gen.cc index 195572de8e..5cc4621b84 100644 --- a/deps/v8/src/builtins/builtins-string-gen.cc +++ b/deps/v8/src/builtins/builtins-string-gen.cc @@ -124,42 +124,6 @@ Node* StringBuiltinsAssembler::PointerToStringDataAtIndex( return IntPtrAdd(string_data, offset_in_bytes); } -void StringBuiltinsAssembler::ConvertAndBoundsCheckStartArgument( - Node* context, Variable* var_start, Node* start, Node* string_length) { - TNode<Object> const start_int = ToInteger_Inline( - CAST(context), CAST(start), CodeStubAssembler::kTruncateMinusZero); - TNode<Smi> const zero = SmiConstant(0); - - Label done(this); - Label if_issmi(this), if_isheapnumber(this, Label::kDeferred); - Branch(TaggedIsSmi(start_int), &if_issmi, &if_isheapnumber); - - BIND(&if_issmi); - { - TNode<Smi> const start_int_smi = CAST(start_int); - var_start->Bind(Select( - SmiLessThan(start_int_smi, zero), - [&] { return SmiMax(SmiAdd(string_length, start_int_smi), zero); }, - [&] { return start_int_smi; }, MachineRepresentation::kTagged)); - Goto(&done); - } - - BIND(&if_isheapnumber); - { - // If {start} is a heap number, it is definitely out of bounds. If it is - // negative, {start} = max({string_length} + {start}),0) = 0'. If it is - // positive, set {start} to {string_length} which ultimately results in - // returning an empty string. - TNode<HeapNumber> const start_int_hn = CAST(start_int); - TNode<Float64T> const float_zero = Float64Constant(0.); - TNode<Float64T> const start_float = LoadHeapNumberValue(start_int_hn); - var_start->Bind(SelectTaggedConstant<Smi>( - Float64LessThan(start_float, float_zero), zero, string_length)); - Goto(&done); - } - BIND(&done); -} - void StringBuiltinsAssembler::GenerateStringEqual(Node* context, Node* left, Node* right) { VARIABLE(var_left, MachineRepresentation::kTagged, left); @@ -300,21 +264,23 @@ void StringBuiltinsAssembler::StringEqual_Loop( { // If {offset} equals {end}, no difference was found, so the // strings are equal. - GotoIf(WordEqual(var_offset, length), if_equal); + GotoIf(WordEqual(var_offset.value(), length), if_equal); // Load the next characters from {lhs} and {rhs}. Node* lhs_value = Load(lhs_type, lhs_data, - WordShl(var_offset, ElementSizeLog2Of(lhs_type.representation()))); + WordShl(var_offset.value(), + ElementSizeLog2Of(lhs_type.representation()))); Node* rhs_value = Load(rhs_type, rhs_data, - WordShl(var_offset, ElementSizeLog2Of(rhs_type.representation()))); + WordShl(var_offset.value(), + ElementSizeLog2Of(rhs_type.representation()))); // Check if the characters match. GotoIf(Word32NotEqual(lhs_value, rhs_value), if_not_equal); // Advance to next character. - var_offset = IntPtrAdd(var_offset, IntPtrConstant(1)); + var_offset = IntPtrAdd(var_offset.value(), IntPtrConstant(1)); Goto(&loop); } } @@ -408,13 +374,13 @@ void StringBuiltinsAssembler::GenerateStringRelationalComparison(Node* context, { // Check if {offset} equals {end}. Label if_done(this), if_notdone(this); - Branch(WordEqual(var_offset, end), &if_done, &if_notdone); + Branch(WordEqual(var_offset.value(), end), &if_done, &if_notdone); BIND(&if_notdone); { // Load the next characters from {lhs} and {rhs}. - Node* lhs_value = Load(MachineType::Uint8(), lhs, var_offset); - Node* rhs_value = Load(MachineType::Uint8(), rhs, var_offset); + Node* lhs_value = Load(MachineType::Uint8(), lhs, var_offset.value()); + Node* rhs_value = Load(MachineType::Uint8(), rhs, var_offset.value()); // Check if the characters match. Label if_valueissame(this), if_valueisnotsame(this); @@ -424,7 +390,7 @@ void StringBuiltinsAssembler::GenerateStringRelationalComparison(Node* context, BIND(&if_valueissame); { // Advance to next character. - var_offset = IntPtrAdd(var_offset, IntPtrConstant(1)); + var_offset = IntPtrAdd(var_offset.value(), IntPtrConstant(1)); } Goto(&loop); @@ -563,20 +529,21 @@ TF_BUILTIN(StringCharAt, StringBuiltinsAssembler) { Return(result); } -TF_BUILTIN(StringCharCodeAt, StringBuiltinsAssembler) { +TF_BUILTIN(StringCodePointAtUTF16, StringBuiltinsAssembler) { Node* receiver = Parameter(Descriptor::kReceiver); Node* position = Parameter(Descriptor::kPosition); - + // TODO(sigurds) Figure out if passing length as argument pays off. + TNode<IntPtrT> length = LoadStringLengthAsWord(receiver); // Load the character code at the {position} from the {receiver}. - TNode<Int32T> code = StringCharCodeAt(receiver, position); - + TNode<Int32T> code = + LoadSurrogatePairAt(receiver, length, position, UnicodeEncoding::UTF16); // And return it as TaggedSigned value. // TODO(turbofan): Allow builtins to return values untagged. - TNode<Smi> result = SmiFromWord32(code); + TNode<Smi> result = SmiFromInt32(code); Return(result); } -TF_BUILTIN(StringCodePointAt, StringBuiltinsAssembler) { +TF_BUILTIN(StringCodePointAtUTF32, StringBuiltinsAssembler) { Node* receiver = Parameter(Descriptor::kReceiver); Node* position = Parameter(Descriptor::kPosition); @@ -587,7 +554,7 @@ TF_BUILTIN(StringCodePointAt, StringBuiltinsAssembler) { LoadSurrogatePairAt(receiver, length, position, UnicodeEncoding::UTF32); // And return it as TaggedSigned value. // TODO(turbofan): Allow builtins to return values untagged. - TNode<Smi> result = SmiFromWord32(code); + TNode<Smi> result = SmiFromInt32(code); Return(result); } @@ -648,11 +615,12 @@ TF_BUILTIN(StringFromCharCode, CodeStubAssembler) { // The {code16} fits into the SeqOneByteString {one_byte_result}. Node* offset = ElementOffsetFromIndex( - var_max_index, UINT8_ELEMENTS, CodeStubAssembler::INTPTR_PARAMETERS, + var_max_index.value(), UINT8_ELEMENTS, + CodeStubAssembler::INTPTR_PARAMETERS, SeqOneByteString::kHeaderSize - kHeapObjectTag); StoreNoWriteBarrier(MachineRepresentation::kWord8, one_byte_result, offset, code16); - var_max_index = IntPtrAdd(var_max_index, IntPtrConstant(1)); + var_max_index = IntPtrAdd(var_max_index.value(), IntPtrConstant(1)); }); arguments.PopAndReturn(one_byte_result); @@ -667,16 +635,17 @@ TF_BUILTIN(StringFromCharCode, CodeStubAssembler) { // their corresponding positions in the new 16-bit string. TNode<IntPtrT> zero = IntPtrConstant(0); CopyStringCharacters(one_byte_result, two_byte_result, zero, zero, - var_max_index, String::ONE_BYTE_ENCODING, + var_max_index.value(), String::ONE_BYTE_ENCODING, String::TWO_BYTE_ENCODING); // Write the character that caused the 8-bit to 16-bit fault. - Node* max_index_offset = ElementOffsetFromIndex( - var_max_index, UINT16_ELEMENTS, CodeStubAssembler::INTPTR_PARAMETERS, - SeqTwoByteString::kHeaderSize - kHeapObjectTag); + Node* max_index_offset = + ElementOffsetFromIndex(var_max_index.value(), UINT16_ELEMENTS, + CodeStubAssembler::INTPTR_PARAMETERS, + SeqTwoByteString::kHeaderSize - kHeapObjectTag); StoreNoWriteBarrier(MachineRepresentation::kWord16, two_byte_result, max_index_offset, code16); - var_max_index = IntPtrAdd(var_max_index, IntPtrConstant(1)); + var_max_index = IntPtrAdd(var_max_index.value(), IntPtrConstant(1)); // Resume copying the passed-in arguments from the same place where the // 8-bit copy stopped, but this time copying over all of the characters @@ -689,14 +658,14 @@ TF_BUILTIN(StringFromCharCode, CodeStubAssembler) { Word32And(code32, Int32Constant(String::kMaxUtf16CodeUnit)); Node* offset = ElementOffsetFromIndex( - var_max_index, UINT16_ELEMENTS, + var_max_index.value(), UINT16_ELEMENTS, CodeStubAssembler::INTPTR_PARAMETERS, SeqTwoByteString::kHeaderSize - kHeapObjectTag); StoreNoWriteBarrier(MachineRepresentation::kWord16, two_byte_result, offset, code16); - var_max_index = IntPtrAdd(var_max_index, IntPtrConstant(1)); + var_max_index = IntPtrAdd(var_max_index.value(), IntPtrConstant(1)); }, - var_max_index); + var_max_index.value()); arguments.PopAndReturn(two_byte_result); } @@ -728,7 +697,7 @@ TF_BUILTIN(StringPrototypeCharCodeAt, StringBuiltinsAssembler) { [this](TNode<String> receiver, TNode<IntPtrT> length, TNode<IntPtrT> index) { Node* value = StringCharCodeAt(receiver, index); - return SmiFromWord32(value); + return SmiFromInt32(value); }); } @@ -742,9 +711,11 @@ TF_BUILTIN(StringPrototypeCodePointAt, StringBuiltinsAssembler) { maybe_position, UndefinedConstant(), [this](TNode<String> receiver, TNode<IntPtrT> length, TNode<IntPtrT> index) { + // This is always a call to a builtin from Javascript, + // so we need to produce UTF32. Node* value = LoadSurrogatePairAt(receiver, length, index, UnicodeEncoding::UTF32); - return SmiFromWord32(value); + return SmiFromInt32(value); }); } @@ -1044,8 +1015,8 @@ void StringBuiltinsAssembler::RequireObjectCoercible(Node* const context, Branch(IsNullOrUndefined(value), &throw_exception, &out); BIND(&throw_exception); - TailCallRuntime(Runtime::kThrowCalledOnNullOrUndefined, context, - StringConstant(method_name)); + ThrowTypeError(context, MessageTemplate::kCalledOnNullOrUndefined, + method_name); BIND(&out); } @@ -1173,8 +1144,8 @@ compiler::Node* StringBuiltinsAssembler::GetSubstitution( CSA_ASSERT(this, TaggedIsPositiveSmi(dollar_index)); Node* const matched = - CallBuiltin(Builtins::kSubString, context, subject_string, - match_start_index, match_end_index); + CallBuiltin(Builtins::kStringSubstring, context, subject_string, + SmiUntag(match_start_index), SmiUntag(match_end_index)); Node* const replacement_string = CallRuntime(Runtime::kGetSubstitution, context, matched, subject_string, match_start_index, replace_string, dollar_index); @@ -1242,11 +1213,10 @@ TF_BUILTIN(StringPrototypeRepeat, StringBuiltinsAssembler) { BIND(&invalid_count); { - CallRuntime(Runtime::kThrowRangeError, context, - SmiConstant(MessageTemplate::kInvalidCountValue), - var_count.value()); - Unreachable(); + ThrowRangeError(context, MessageTemplate::kInvalidCountValue, + var_count.value()); } + BIND(&invalid_string_length); { CallRuntime(Runtime::kThrowInvalidStringLength, context); @@ -1288,7 +1258,7 @@ TF_BUILTIN(StringRepeat, StringBuiltinsAssembler) { { { Label next(this); - GotoIfNot(SmiToWord32(SmiAnd(var_count.value(), SmiConstant(1))), &next); + GotoIfNot(SmiToInt32(SmiAnd(var_count.value(), SmiConstant(1))), &next); var_result.Bind(CallStub(stringadd_callable, context, var_result.value(), var_temp.value())); Goto(&next); @@ -1412,8 +1382,8 @@ TF_BUILTIN(StringPrototypeReplace, StringBuiltinsAssembler) { GotoIf(SmiEqual(match_start_index, smi_zero), &next); Node* const prefix = - CallBuiltin(Builtins::kSubString, context, subject_string, smi_zero, - match_start_index); + CallBuiltin(Builtins::kStringSubstring, context, subject_string, + IntPtrConstant(0), SmiUntag(match_start_index)); var_result.Bind(prefix); Goto(&next); @@ -1453,8 +1423,8 @@ TF_BUILTIN(StringPrototypeReplace, StringBuiltinsAssembler) { BIND(&out); { Node* const suffix = - CallBuiltin(Builtins::kSubString, context, subject_string, - match_end_index, subject_length); + CallBuiltin(Builtins::kStringSubstring, context, subject_string, + SmiUntag(match_end_index), SmiUntag(subject_length)); Node* const result = CallStub(stringadd_callable, context, var_result.value(), suffix); Return(result); @@ -1587,14 +1557,15 @@ class StringPadAssembler : public StringBuiltinsAssembler { GotoIf(IsUndefined(fill), &pad); var_fill_string = ToString_Inline(context, fill); - var_fill_length = LoadStringLengthAsWord(var_fill_string); + var_fill_length = LoadStringLengthAsWord(var_fill_string.value()); - Branch(IntPtrGreaterThan(var_fill_length, IntPtrConstant(0)), &pad, - &dont_pad); + Branch(IntPtrGreaterThan(var_fill_length.value(), IntPtrConstant(0)), + &pad, &dont_pad); } BIND(&pad); { - CSA_ASSERT(this, IntPtrGreaterThan(var_fill_length, IntPtrConstant(0))); + CSA_ASSERT(this, + IntPtrGreaterThan(var_fill_length.value(), IntPtrConstant(0))); CSA_ASSERT(this, SmiGreaterThan(max_length, string_length)); Callable stringadd_callable = @@ -1604,38 +1575,37 @@ class StringPadAssembler : public StringBuiltinsAssembler { VARIABLE(var_pad, MachineRepresentation::kTagged); Label single_char_fill(this), multi_char_fill(this), return_result(this); - Branch(IntPtrEqual(var_fill_length, IntPtrConstant(1)), &single_char_fill, - &multi_char_fill); + Branch(IntPtrEqual(var_fill_length.value(), IntPtrConstant(1)), + &single_char_fill, &multi_char_fill); // Fast path for a single character fill. No need to calculate number of // repetitions or remainder. BIND(&single_char_fill); { var_pad.Bind(CallBuiltin(Builtins::kStringRepeat, context, - static_cast<Node*>(var_fill_string), + static_cast<Node*>(var_fill_string.value()), pad_length)); Goto(&return_result); } BIND(&multi_char_fill); { TNode<Int32T> const fill_length_word32 = - TruncateWordToWord32(var_fill_length); - TNode<Int32T> const pad_length_word32 = SmiToWord32(pad_length); + TruncateIntPtrToInt32(var_fill_length.value()); + TNode<Int32T> const pad_length_word32 = SmiToInt32(pad_length); TNode<Int32T> const repetitions_word32 = Int32Div(pad_length_word32, fill_length_word32); TNode<Int32T> const remaining_word32 = Int32Mod(pad_length_word32, fill_length_word32); var_pad.Bind(CallBuiltin(Builtins::kStringRepeat, context, - static_cast<Node*>(var_fill_string), - SmiFromWord32(repetitions_word32))); + var_fill_string.value(), + SmiFromInt32(repetitions_word32))); GotoIfNot(remaining_word32, &return_result); { - Node* const remainder_string = - CallBuiltin(Builtins::kSubString, context, - static_cast<Node*>(var_fill_string), SmiConstant(0), - SmiFromWord32(remaining_word32)); + Node* const remainder_string = CallBuiltin( + Builtins::kStringSubstring, context, var_fill_string.value(), + IntPtrConstant(0), ChangeInt32ToIntPtr(remaining_word32)); var_pad.Bind(CallStub(stringadd_callable, context, var_pad.value(), remainder_string)); Goto(&return_result); @@ -1679,8 +1649,8 @@ TF_BUILTIN(StringPrototypeSearch, StringMatchSearchAssembler) { // ES6 section 21.1.3.18 String.prototype.slice ( start, end ) TF_BUILTIN(StringPrototypeSlice, StringBuiltinsAssembler) { Label out(this); - VARIABLE(var_start, MachineRepresentation::kTagged); - VARIABLE(var_end, MachineRepresentation::kTagged); + TVARIABLE(IntPtrT, var_start); + TVARIABLE(IntPtrT, var_end); const int kStart = 0; const int kEnd = 1; @@ -1688,69 +1658,38 @@ TF_BUILTIN(StringPrototypeSlice, StringBuiltinsAssembler) { ChangeInt32ToIntPtr(Parameter(BuiltinDescriptor::kArgumentsCount)); CodeStubArguments args(this, argc); Node* const receiver = args.GetReceiver(); - Node* const start = args.GetOptionalArgumentValue(kStart); - TNode<Object> end = CAST(args.GetOptionalArgumentValue(kEnd)); + TNode<Object> start = args.GetOptionalArgumentValue(kStart); + TNode<Object> end = args.GetOptionalArgumentValue(kEnd); TNode<Context> context = CAST(Parameter(BuiltinDescriptor::kContext)); - TNode<Smi> const smi_zero = SmiConstant(0); - // 1. Let O be ? RequireObjectCoercible(this value). RequireObjectCoercible(context, receiver, "String.prototype.slice"); // 2. Let S be ? ToString(O). - Node* const subject_string = - CallBuiltin(Builtins::kToString, context, receiver); + TNode<String> const subject_string = + CAST(CallBuiltin(Builtins::kToString, context, receiver)); // 3. Let len be the number of elements in S. - TNode<Smi> const length = LoadStringLengthAsSmi(subject_string); + TNode<IntPtrT> const length = LoadStringLengthAsWord(subject_string); - // Conversions and bounds-checks for {start}. - ConvertAndBoundsCheckStartArgument(context, &var_start, start, length); + // Convert {start} to a relative index. + var_start = ConvertToRelativeIndex(context, start, length); // 5. If end is undefined, let intEnd be len; - var_end.Bind(length); + var_end = length; GotoIf(IsUndefined(end), &out); - // else let intEnd be ? ToInteger(end). - Node* const end_int = - ToInteger_Inline(context, end, CodeStubAssembler::kTruncateMinusZero); - - // 7. If intEnd < 0, let to be max(len + intEnd, 0); - // otherwise let to be min(intEnd, len). - Label if_issmi(this), if_isheapnumber(this, Label::kDeferred); - Branch(TaggedIsSmi(end_int), &if_issmi, &if_isheapnumber); - - BIND(&if_issmi); - { - Node* const length_plus_end = SmiAdd(length, end_int); - var_end.Bind(Select(SmiLessThan(end_int, smi_zero), - [&] { return SmiMax(length_plus_end, smi_zero); }, - [&] { return SmiMin(length, end_int); }, - MachineRepresentation::kTagged)); - Goto(&out); - } - - BIND(&if_isheapnumber); - { - // If {end} is a heap number, it is definitely out of bounds. If it is - // negative, {int_end} = max({length} + {int_end}),0) = 0'. If it is - // positive, set {int_end} to {length} which ultimately results in - // returning an empty string. - Node* const float_zero = Float64Constant(0.); - Node* const end_float = LoadHeapNumberValue(end_int); - var_end.Bind(SelectTaggedConstant<Smi>( - Float64LessThan(end_float, float_zero), smi_zero, length)); - Goto(&out); - } + // Convert {end} to a relative index. + var_end = ConvertToRelativeIndex(context, end, length); + Goto(&out); Label return_emptystring(this); BIND(&out); { - GotoIf(SmiLessThanOrEqual(var_end.value(), var_start.value()), + GotoIf(IntPtrLessThanOrEqual(var_end.value(), var_start.value()), &return_emptystring); - Node* const result = - SubString(context, subject_string, var_start.value(), var_end.value(), - SubStringFlags::FROM_TO_ARE_BOUNDED); + TNode<String> const result = + SubString(subject_string, var_start.value(), var_end.value()); args.PopAndReturn(result); } @@ -1868,25 +1807,25 @@ TF_BUILTIN(StringPrototypeSubstr, StringBuiltinsAssembler) { CodeStubArguments args(this, argc); Node* const receiver = args.GetReceiver(); - Node* const start = args.GetOptionalArgumentValue(kStartArg); - TNode<Object> length = CAST(args.GetOptionalArgumentValue(kLengthArg)); + TNode<Object> start = args.GetOptionalArgumentValue(kStartArg); + TNode<Object> length = args.GetOptionalArgumentValue(kLengthArg); TNode<Context> context = CAST(Parameter(BuiltinDescriptor::kContext)); Label out(this); - TVARIABLE(Smi, var_start); + TVARIABLE(IntPtrT, var_start); TVARIABLE(Number, var_length); - TNode<Smi> const zero = SmiConstant(0); + TNode<IntPtrT> const zero = IntPtrConstant(0); // Check that {receiver} is coercible to Object and convert it to a String. - Node* const string = + TNode<String> const string = ToThisString(context, receiver, "String.prototype.substr"); - TNode<Smi> const string_length = LoadStringLengthAsSmi(string); + TNode<IntPtrT> const string_length = LoadStringLengthAsWord(string); - // Conversions and bounds-checks for {start}. - ConvertAndBoundsCheckStartArgument(context, &var_start, start, string_length); + // Convert {start} to a relative index. + var_start = ConvertToRelativeIndex(context, start, string_length); // Conversions and bounds-checks for {length}. Label if_issmi(this), if_isheapnumber(this, Label::kDeferred); @@ -1897,7 +1836,7 @@ TF_BUILTIN(StringPrototypeSubstr, StringBuiltinsAssembler) { Branch(IsUndefined(length), &if_isundefined, &if_isnotundefined); BIND(&if_isundefined); - var_length = string_length; + var_length = SmiTag(string_length); Goto(&if_issmi); BIND(&if_isnotundefined); @@ -1905,18 +1844,20 @@ TF_BUILTIN(StringPrototypeSubstr, StringBuiltinsAssembler) { CodeStubAssembler::kTruncateMinusZero); } - TVARIABLE(Smi, var_result_length); + TVARIABLE(IntPtrT, var_result_length); - Branch(TaggedIsSmi(var_length), &if_issmi, &if_isheapnumber); + Branch(TaggedIsSmi(var_length.value()), &if_issmi, &if_isheapnumber); // Set {length} to min(max({length}, 0), {string_length} - {start} BIND(&if_issmi); { - TNode<Smi> const positive_length = SmiMax(CAST(var_length), zero); - TNode<Smi> const minimal_length = SmiSub(string_length, var_start); - var_result_length = SmiMin(positive_length, minimal_length); + TNode<IntPtrT> const positive_length = + IntPtrMax(SmiUntag(CAST(var_length.value())), zero); + TNode<IntPtrT> const minimal_length = + IntPtrSub(string_length, var_start.value()); + var_result_length = IntPtrMin(positive_length, minimal_length); - GotoIfNot(SmiLessThanOrEqual(var_result_length, zero), &out); + GotoIfNot(IntPtrLessThanOrEqual(var_result_length.value(), zero), &out); args.PopAndReturn(EmptyStringConstant()); } @@ -1926,11 +1867,12 @@ TF_BUILTIN(StringPrototypeSubstr, StringBuiltinsAssembler) { // two cases according to the spec: if it is negative, "" is returned; if // it is positive, then length is set to {string_length} - {start}. - CSA_ASSERT(this, IsHeapNumber(var_length)); + CSA_ASSERT(this, IsHeapNumber(var_length.value())); Label if_isnegative(this), if_ispositive(this); TNode<Float64T> const float_zero = Float64Constant(0.); - TNode<Float64T> const length_float = LoadHeapNumberValue(CAST(var_length)); + TNode<Float64T> const length_float = + LoadHeapNumberValue(CAST(var_length.value())); Branch(Float64LessThan(length_float, float_zero), &if_isnegative, &if_ispositive); @@ -1939,17 +1881,17 @@ TF_BUILTIN(StringPrototypeSubstr, StringBuiltinsAssembler) { BIND(&if_ispositive); { - var_result_length = SmiSub(string_length, var_start); - GotoIfNot(SmiLessThanOrEqual(var_result_length, zero), &out); + var_result_length = IntPtrSub(string_length, var_start.value()); + GotoIfNot(IntPtrLessThanOrEqual(var_result_length.value(), zero), &out); args.PopAndReturn(EmptyStringConstant()); } } BIND(&out); { - TNode<Smi> const end = SmiAdd(var_start, var_result_length); - Node* const result = SubString(context, string, var_start, end); - args.PopAndReturn(result); + TNode<IntPtrT> const end = + IntPtrAdd(var_start.value(), var_result_length.value()); + args.PopAndReturn(SubString(string, var_start.value(), end)); } } @@ -1959,7 +1901,7 @@ TNode<Smi> StringBuiltinsAssembler::ToSmiBetweenZeroAnd( Label out(this); TVARIABLE(Smi, var_result); - TNode<Object> const value_int = + TNode<Number> const value_int = ToInteger_Inline(context, value, CodeStubAssembler::kTruncateMinusZero); Label if_issmi(this), if_isnotsmi(this, Label::kDeferred); @@ -1967,8 +1909,9 @@ TNode<Smi> StringBuiltinsAssembler::ToSmiBetweenZeroAnd( BIND(&if_issmi); { + TNode<Smi> value_smi = CAST(value_int); Label if_isinbounds(this), if_isoutofbounds(this, Label::kDeferred); - Branch(SmiAbove(value_int, limit), &if_isoutofbounds, &if_isinbounds); + Branch(SmiAbove(value_smi, limit), &if_isoutofbounds, &if_isinbounds); BIND(&if_isinbounds); { @@ -1980,7 +1923,7 @@ TNode<Smi> StringBuiltinsAssembler::ToSmiBetweenZeroAnd( { TNode<Smi> const zero = SmiConstant(0); var_result = - SelectTaggedConstant(SmiLessThan(value_int, zero), zero, limit); + SelectTaggedConstant(SmiLessThan(value_smi, zero), zero, limit); Goto(&out); } } @@ -1999,16 +1942,15 @@ TNode<Smi> StringBuiltinsAssembler::ToSmiBetweenZeroAnd( } BIND(&out); - return var_result; + return var_result.value(); } -TF_BUILTIN(SubString, CodeStubAssembler) { - Node* context = Parameter(Descriptor::kContext); - Node* string = Parameter(Descriptor::kString); - Node* from = Parameter(Descriptor::kFrom); - Node* to = Parameter(Descriptor::kTo); +TF_BUILTIN(StringSubstring, CodeStubAssembler) { + TNode<String> string = CAST(Parameter(Descriptor::kString)); + TNode<IntPtrT> from = UncheckedCast<IntPtrT>(Parameter(Descriptor::kFrom)); + TNode<IntPtrT> to = UncheckedCast<IntPtrT>(Parameter(Descriptor::kTo)); - Return(SubString(context, string, from, to)); + Return(SubString(string, from, to)); } // ES6 #sec-string.prototype.substring @@ -2031,7 +1973,7 @@ TF_BUILTIN(StringPrototypeSubstring, StringBuiltinsAssembler) { VARIABLE(var_end, MachineRepresentation::kTagged); // Check that {receiver} is coercible to Object and convert it to a String. - Node* const string = + TNode<String> const string = ToThisString(context, receiver, "String.prototype.substring"); Node* const length = LoadStringLengthAsSmi(string); @@ -2061,9 +2003,8 @@ TF_BUILTIN(StringPrototypeSubstring, StringBuiltinsAssembler) { BIND(&out); { - Node* result = - SubString(context, string, var_start.value(), var_end.value()); - args.PopAndReturn(result); + args.PopAndReturn(SubString(string, SmiUntag(var_start.value()), + SmiUntag(var_end.value()))); } } @@ -2072,14 +2013,14 @@ TF_BUILTIN(StringPrototypeTrim, StringTrimAssembler) { Generate(String::kTrim, "String.prototype.trim"); } -// Non-standard WebKit extension -TF_BUILTIN(StringPrototypeTrimLeft, StringTrimAssembler) { - Generate(String::kTrimLeft, "String.prototype.trimLeft"); +// https://github.com/tc39/proposal-string-left-right-trim +TF_BUILTIN(StringPrototypeTrimStart, StringTrimAssembler) { + Generate(String::kTrimStart, "String.prototype.trimLeft"); } -// Non-standard WebKit extension -TF_BUILTIN(StringPrototypeTrimRight, StringTrimAssembler) { - Generate(String::kTrimRight, "String.prototype.trimRight"); +// https://github.com/tc39/proposal-string-left-right-trim +TF_BUILTIN(StringPrototypeTrimEnd, StringTrimAssembler) { + Generate(String::kTrimEnd, "String.prototype.trimRight"); } void StringTrimAssembler::Generate(String::TrimMode mode, @@ -2092,7 +2033,7 @@ void StringTrimAssembler::Generate(String::TrimMode mode, Node* const receiver = arguments.GetReceiver(); // Check that {receiver} is coercible to Object and convert it to a String. - Node* const string = ToThisString(context, receiver, method_name); + TNode<String> const string = ToThisString(context, receiver, method_name); TNode<IntPtrT> const string_length = LoadStringLengthAsWord(string); ToDirectStringAssembler to_direct(state(), string); @@ -2105,20 +2046,20 @@ void StringTrimAssembler::Generate(String::TrimMode mode, TVARIABLE(IntPtrT, var_start, IntPtrConstant(0)); TVARIABLE(IntPtrT, var_end, IntPtrSub(string_length, IntPtrConstant(1))); - if (mode == String::kTrimLeft || mode == String::kTrim) { + if (mode == String::kTrimStart || mode == String::kTrim) { ScanForNonWhiteSpaceOrLineTerminator(string_data, string_data_offset, is_stringonebyte, &var_start, string_length, 1, &return_emptystring); } - if (mode == String::kTrimRight || mode == String::kTrim) { + if (mode == String::kTrimEnd || mode == String::kTrim) { ScanForNonWhiteSpaceOrLineTerminator( string_data, string_data_offset, is_stringonebyte, &var_end, IntPtrConstant(-1), -1, &return_emptystring); } - arguments.PopAndReturn(SubString(context, string, SmiTag(var_start), - SmiAdd(SmiTag(var_end), SmiConstant(1)), - SubStringFlags::FROM_TO_ARE_BOUNDED)); + arguments.PopAndReturn( + SubString(string, var_start.value(), + IntPtrAdd(var_end.value(), IntPtrConstant(1)))); BIND(&if_runtime); arguments.PopAndReturn( @@ -2281,21 +2222,21 @@ TNode<Int32T> StringBuiltinsAssembler::LoadSurrogatePairAt( var_result = StringCharCodeAt(string, index); var_trail = Int32Constant(0); - GotoIf(Word32NotEqual(Word32And(var_result, Int32Constant(0xFC00)), + GotoIf(Word32NotEqual(Word32And(var_result.value(), Int32Constant(0xFC00)), Int32Constant(0xD800)), &return_result); TNode<IntPtrT> next_index = IntPtrAdd(index, IntPtrConstant(1)); GotoIfNot(IntPtrLessThan(next_index, length), &return_result); var_trail = StringCharCodeAt(string, next_index); - Branch(Word32Equal(Word32And(var_trail, Int32Constant(0xFC00)), + Branch(Word32Equal(Word32And(var_trail.value(), Int32Constant(0xFC00)), Int32Constant(0xDC00)), &handle_surrogate_pair, &return_result); BIND(&handle_surrogate_pair); { - TNode<Int32T> lead = var_result; - TNode<Int32T> trail = var_trail; + TNode<Int32T> lead = var_result.value(); + TNode<Int32T> trail = var_trail.value(); // Check that this path is only taken if a surrogate pair is found CSA_SLOW_ASSERT(this, @@ -2332,7 +2273,7 @@ TNode<Int32T> StringBuiltinsAssembler::LoadSurrogatePairAt( } BIND(&return_result); - return var_result; + return var_result.value(); } // ES6 #sec-%stringiteratorprototype%.next @@ -2383,9 +2324,8 @@ TF_BUILTIN(StringIteratorPrototypeNext, StringBuiltinsAssembler) { BIND(&throw_bad_receiver); { // The {receiver} is not a valid JSGeneratorObject. - CallRuntime(Runtime::kThrowIncompatibleMethodReceiver, context, - StringConstant("String Iterator.prototype.next"), iterator); - Unreachable(); + ThrowTypeError(context, MessageTemplate::kIncompatibleMethodReceiver, + StringConstant("String Iterator.prototype.next"), iterator); } } |