summaryrefslogtreecommitdiff
path: root/deps/v8/src/builtins/builtins-string-gen.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/builtins/builtins-string-gen.cc')
-rw-r--r--deps/v8/src/builtins/builtins-string-gen.cc328
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);
}
}