Commit c64a32b1 authored by Sigurd Schneider's avatar Sigurd Schneider Committed by Commit Bot

[turbofan] Change interface of builtin StringSubstring

This CL changes the builtin
  StringSubstring(string, start, end)
to take start and end as untagged IntPtr values.

Bug: v8:7250, v8:7340

Change-Id: I39700d087da903f076a6ca163a8f880d31eea3a0
Reviewed-on: https://chromium-review.googlesource.com/923961
Commit-Queue: Sigurd Schneider <sigurds@chromium.org>
Reviewed-by: 's avatarBenedikt Meurer <bmeurer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#51556}
parent c1eaae64
...@@ -101,7 +101,7 @@ namespace internal { ...@@ -101,7 +101,7 @@ namespace internal {
TFC(StringLessThan, Compare, 1) \ TFC(StringLessThan, Compare, 1) \
TFC(StringLessThanOrEqual, Compare, 1) \ TFC(StringLessThanOrEqual, Compare, 1) \
TFS(StringRepeat, kString, kCount) \ TFS(StringRepeat, kString, kCount) \
TFS(StringSubstring, kString, kFrom, kTo) \ TFC(StringSubstring, StringSubstring, 1) \
\ \
/* OrderedHashTable helpers */ \ /* OrderedHashTable helpers */ \
TFS(OrderedHashTableHealIndex, kTable, kIndex) \ TFS(OrderedHashTableHealIndex, kTable, kIndex) \
......
...@@ -152,7 +152,8 @@ Node* RegExpBuiltinsAssembler::ConstructNewResultFromMatchInfo( ...@@ -152,7 +152,8 @@ Node* RegExpBuiltinsAssembler::ConstructNewResultFromMatchInfo(
// Calculate the substring of the first match before creating the result array // Calculate the substring of the first match before creating the result array
// to avoid an unnecessary write barrier storing the first result. // to avoid an unnecessary write barrier storing the first result.
TNode<String> const first = SubString(string, start, end);
TNode<String> const first = SubString(string, SmiUntag(start), SmiUntag(end));
Node* const result = Node* const result =
AllocateRegExpResult(context, num_results, start, string); AllocateRegExpResult(context, num_results, start, string);
...@@ -188,7 +189,8 @@ Node* RegExpBuiltinsAssembler::ConstructNewResultFromMatchInfo( ...@@ -188,7 +189,8 @@ Node* RegExpBuiltinsAssembler::ConstructNewResultFromMatchInfo(
Node* const from_cursor_plus1 = IntPtrAdd(from_cursor, IntPtrConstant(1)); Node* const from_cursor_plus1 = IntPtrAdd(from_cursor, IntPtrConstant(1));
Node* const end = LoadFixedArrayElement(match_info, from_cursor_plus1); Node* const end = LoadFixedArrayElement(match_info, from_cursor_plus1);
TNode<String> const capture = SubString(string, start, end); TNode<String> const capture =
SubString(string, SmiUntag(start), SmiUntag(end));
StoreFixedArrayElement(result_elements, to_cursor, capture); StoreFixedArrayElement(result_elements, to_cursor, capture);
Goto(&next_iter); Goto(&next_iter);
...@@ -1830,7 +1832,8 @@ void RegExpBuiltinsAssembler::RegExpPrototypeMatchBody(Node* const context, ...@@ -1830,7 +1832,8 @@ void RegExpBuiltinsAssembler::RegExpPrototypeMatchBody(Node* const context,
Node* const match_to = LoadFixedArrayElement( Node* const match_to = LoadFixedArrayElement(
match_indices, RegExpMatchInfo::kFirstCaptureIndex + 1); match_indices, RegExpMatchInfo::kFirstCaptureIndex + 1);
var_match.Bind(SubString(string, match_from, match_to)); var_match.Bind(
SubString(string, SmiUntag(match_from), SmiUntag(match_to)));
Goto(&if_didmatch); Goto(&if_didmatch);
} else { } else {
DCHECK(!is_fastpath); DCHECK(!is_fastpath);
...@@ -2248,7 +2251,7 @@ void RegExpBuiltinsAssembler::RegExpPrototypeSplitBody(Node* const context, ...@@ -2248,7 +2251,7 @@ void RegExpBuiltinsAssembler::RegExpPrototypeSplitBody(Node* const context,
{ {
Node* const from = last_matched_until; Node* const from = last_matched_until;
Node* const to = match_from; Node* const to = match_from;
array.Push(SubString(string, from, to)); array.Push(SubString(string, SmiUntag(from), SmiUntag(to)));
GotoIf(WordEqual(array.length(), int_limit), &out); GotoIf(WordEqual(array.length(), int_limit), &out);
} }
...@@ -2285,7 +2288,7 @@ void RegExpBuiltinsAssembler::RegExpPrototypeSplitBody(Node* const context, ...@@ -2285,7 +2288,7 @@ void RegExpBuiltinsAssembler::RegExpPrototypeSplitBody(Node* const context,
BIND(&select_capture); BIND(&select_capture);
{ {
var_value.Bind(SubString(string, from, to)); var_value.Bind(SubString(string, SmiUntag(from), SmiUntag(to)));
Goto(&store_value); Goto(&store_value);
} }
...@@ -2320,7 +2323,7 @@ void RegExpBuiltinsAssembler::RegExpPrototypeSplitBody(Node* const context, ...@@ -2320,7 +2323,7 @@ void RegExpBuiltinsAssembler::RegExpPrototypeSplitBody(Node* const context,
{ {
Node* const from = var_last_matched_until.value(); Node* const from = var_last_matched_until.value();
Node* const to = string_length; Node* const to = string_length;
array.Push(SubString(string, from, to)); array.Push(SubString(string, SmiUntag(from), SmiUntag(to)));
Goto(&out); Goto(&out);
} }
...@@ -2690,7 +2693,8 @@ Node* RegExpBuiltinsAssembler::ReplaceSimpleStringFastPath( ...@@ -2690,7 +2693,8 @@ Node* RegExpBuiltinsAssembler::ReplaceSimpleStringFastPath(
// TODO(jgruber): We could skip many of the checks that using SubString // TODO(jgruber): We could skip many of the checks that using SubString
// here entails. // here entails.
TNode<String> const first_part = TNode<String> const first_part =
SubString(string, var_last_match_end.value(), match_start); SubString(string, SmiUntag(var_last_match_end.value()),
SmiUntag(match_start));
var_result = StringAdd(context, var_result.value(), first_part); var_result = StringAdd(context, var_result.value(), first_part);
Goto(&loop_end); Goto(&loop_end);
} }
...@@ -2698,7 +2702,8 @@ Node* RegExpBuiltinsAssembler::ReplaceSimpleStringFastPath( ...@@ -2698,7 +2702,8 @@ Node* RegExpBuiltinsAssembler::ReplaceSimpleStringFastPath(
BIND(&if_replaceisnotempty); BIND(&if_replaceisnotempty);
{ {
TNode<String> const first_part = TNode<String> const first_part =
SubString(string, var_last_match_end.value(), match_start); SubString(string, SmiUntag(var_last_match_end.value()),
SmiUntag(match_start));
TNode<String> result = TNode<String> result =
StringAdd(context, var_result.value(), first_part); StringAdd(context, var_result.value(), first_part);
var_result = StringAdd(context, result, replace_string); var_result = StringAdd(context, result, replace_string);
...@@ -2725,8 +2730,8 @@ Node* RegExpBuiltinsAssembler::ReplaceSimpleStringFastPath( ...@@ -2725,8 +2730,8 @@ Node* RegExpBuiltinsAssembler::ReplaceSimpleStringFastPath(
BIND(&if_nofurthermatches); BIND(&if_nofurthermatches);
{ {
TNode<Smi> const string_length = LoadStringLengthAsSmi(string); TNode<Smi> const string_length = LoadStringLengthAsSmi(string);
TNode<String> const last_part = TNode<String> const last_part = SubString(
SubString(string, var_last_match_end.value(), string_length); string, SmiUntag(var_last_match_end.value()), SmiUntag(string_length));
var_result = StringAdd(context, var_result.value(), last_part); var_result = StringAdd(context, var_result.value(), last_part);
Goto(&out); Goto(&out);
} }
......
...@@ -1145,7 +1145,7 @@ compiler::Node* StringBuiltinsAssembler::GetSubstitution( ...@@ -1145,7 +1145,7 @@ compiler::Node* StringBuiltinsAssembler::GetSubstitution(
Node* const matched = Node* const matched =
CallBuiltin(Builtins::kStringSubstring, context, subject_string, CallBuiltin(Builtins::kStringSubstring, context, subject_string,
match_start_index, match_end_index); SmiUntag(match_start_index), SmiUntag(match_end_index));
Node* const replacement_string = Node* const replacement_string =
CallRuntime(Runtime::kGetSubstitution, context, matched, subject_string, CallRuntime(Runtime::kGetSubstitution, context, matched, subject_string,
match_start_index, replace_string, dollar_index); match_start_index, replace_string, dollar_index);
...@@ -1383,7 +1383,7 @@ TF_BUILTIN(StringPrototypeReplace, StringBuiltinsAssembler) { ...@@ -1383,7 +1383,7 @@ TF_BUILTIN(StringPrototypeReplace, StringBuiltinsAssembler) {
GotoIf(SmiEqual(match_start_index, smi_zero), &next); GotoIf(SmiEqual(match_start_index, smi_zero), &next);
Node* const prefix = Node* const prefix =
CallBuiltin(Builtins::kStringSubstring, context, subject_string, CallBuiltin(Builtins::kStringSubstring, context, subject_string,
smi_zero, match_start_index); IntPtrConstant(0), SmiUntag(match_start_index));
var_result.Bind(prefix); var_result.Bind(prefix);
Goto(&next); Goto(&next);
...@@ -1424,7 +1424,7 @@ TF_BUILTIN(StringPrototypeReplace, StringBuiltinsAssembler) { ...@@ -1424,7 +1424,7 @@ TF_BUILTIN(StringPrototypeReplace, StringBuiltinsAssembler) {
{ {
Node* const suffix = Node* const suffix =
CallBuiltin(Builtins::kStringSubstring, context, subject_string, CallBuiltin(Builtins::kStringSubstring, context, subject_string,
match_end_index, subject_length); SmiUntag(match_end_index), SmiUntag(subject_length));
Node* const result = Node* const result =
CallStub(stringadd_callable, context, var_result.value(), suffix); CallStub(stringadd_callable, context, var_result.value(), suffix);
Return(result); Return(result);
...@@ -1605,7 +1605,7 @@ class StringPadAssembler : public StringBuiltinsAssembler { ...@@ -1605,7 +1605,7 @@ class StringPadAssembler : public StringBuiltinsAssembler {
{ {
Node* const remainder_string = CallBuiltin( Node* const remainder_string = CallBuiltin(
Builtins::kStringSubstring, context, var_fill_string.value(), Builtins::kStringSubstring, context, var_fill_string.value(),
SmiConstant(0), SmiFromInt32(remaining_word32)); IntPtrConstant(0), ChangeInt32ToIntPtr(remaining_word32));
var_pad.Bind(CallStub(stringadd_callable, context, var_pad.value(), var_pad.Bind(CallStub(stringadd_callable, context, var_pad.value(),
remainder_string)); remainder_string));
Goto(&return_result); Goto(&return_result);
...@@ -1649,8 +1649,8 @@ TF_BUILTIN(StringPrototypeSearch, StringMatchSearchAssembler) { ...@@ -1649,8 +1649,8 @@ TF_BUILTIN(StringPrototypeSearch, StringMatchSearchAssembler) {
// ES6 section 21.1.3.18 String.prototype.slice ( start, end ) // ES6 section 21.1.3.18 String.prototype.slice ( start, end )
TF_BUILTIN(StringPrototypeSlice, StringBuiltinsAssembler) { TF_BUILTIN(StringPrototypeSlice, StringBuiltinsAssembler) {
Label out(this); Label out(this);
TVARIABLE(Smi, var_start); TVARIABLE(IntPtrT, var_start);
TVARIABLE(Smi, var_end); TVARIABLE(IntPtrT, var_end);
const int kStart = 0; const int kStart = 0;
const int kEnd = 1; const int kEnd = 1;
...@@ -1670,7 +1670,7 @@ TF_BUILTIN(StringPrototypeSlice, StringBuiltinsAssembler) { ...@@ -1670,7 +1670,7 @@ TF_BUILTIN(StringPrototypeSlice, StringBuiltinsAssembler) {
CAST(CallBuiltin(Builtins::kToString, context, receiver)); CAST(CallBuiltin(Builtins::kToString, context, receiver));
// 3. Let len be the number of elements in S. // 3. Let len be the number of elements in S.
TNode<Smi> const length = LoadStringLengthAsSmi(subject_string); TNode<IntPtrT> const length = LoadStringLengthAsWord(subject_string);
// Convert {start} to a relative index. // Convert {start} to a relative index.
var_start = ConvertToRelativeIndex(context, start, length); var_start = ConvertToRelativeIndex(context, start, length);
...@@ -1686,7 +1686,7 @@ TF_BUILTIN(StringPrototypeSlice, StringBuiltinsAssembler) { ...@@ -1686,7 +1686,7 @@ TF_BUILTIN(StringPrototypeSlice, StringBuiltinsAssembler) {
Label return_emptystring(this); Label return_emptystring(this);
BIND(&out); BIND(&out);
{ {
GotoIf(SmiLessThanOrEqual(var_end.value(), var_start.value()), GotoIf(IntPtrLessThanOrEqual(var_end.value(), var_start.value()),
&return_emptystring); &return_emptystring);
TNode<String> const result = TNode<String> const result =
SubString(subject_string, var_start.value(), var_end.value()); SubString(subject_string, var_start.value(), var_end.value());
...@@ -1813,16 +1813,16 @@ TF_BUILTIN(StringPrototypeSubstr, StringBuiltinsAssembler) { ...@@ -1813,16 +1813,16 @@ TF_BUILTIN(StringPrototypeSubstr, StringBuiltinsAssembler) {
Label out(this); Label out(this);
TVARIABLE(Smi, var_start); TVARIABLE(IntPtrT, var_start);
TVARIABLE(Number, var_length); 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. // Check that {receiver} is coercible to Object and convert it to a String.
TNode<String> const string = TNode<String> const string =
ToThisString(context, receiver, "String.prototype.substr"); ToThisString(context, receiver, "String.prototype.substr");
TNode<Smi> const string_length = LoadStringLengthAsSmi(string); TNode<IntPtrT> const string_length = LoadStringLengthAsWord(string);
// Convert {start} to a relative index. // Convert {start} to a relative index.
var_start = ConvertToRelativeIndex(context, start, string_length); var_start = ConvertToRelativeIndex(context, start, string_length);
...@@ -1836,7 +1836,7 @@ TF_BUILTIN(StringPrototypeSubstr, StringBuiltinsAssembler) { ...@@ -1836,7 +1836,7 @@ TF_BUILTIN(StringPrototypeSubstr, StringBuiltinsAssembler) {
Branch(IsUndefined(length), &if_isundefined, &if_isnotundefined); Branch(IsUndefined(length), &if_isundefined, &if_isnotundefined);
BIND(&if_isundefined); BIND(&if_isundefined);
var_length = string_length; var_length = SmiTag(string_length);
Goto(&if_issmi); Goto(&if_issmi);
BIND(&if_isnotundefined); BIND(&if_isnotundefined);
...@@ -1844,18 +1844,20 @@ TF_BUILTIN(StringPrototypeSubstr, StringBuiltinsAssembler) { ...@@ -1844,18 +1844,20 @@ TF_BUILTIN(StringPrototypeSubstr, StringBuiltinsAssembler) {
CodeStubAssembler::kTruncateMinusZero); CodeStubAssembler::kTruncateMinusZero);
} }
TVARIABLE(Smi, var_result_length); TVARIABLE(IntPtrT, var_result_length);
Branch(TaggedIsSmi(var_length.value()), &if_issmi, &if_isheapnumber); Branch(TaggedIsSmi(var_length.value()), &if_issmi, &if_isheapnumber);
// Set {length} to min(max({length}, 0), {string_length} - {start} // Set {length} to min(max({length}, 0), {string_length} - {start}
BIND(&if_issmi); BIND(&if_issmi);
{ {
TNode<Smi> const positive_length = SmiMax(CAST(var_length.value()), zero); TNode<IntPtrT> const positive_length =
TNode<Smi> const minimal_length = SmiSub(string_length, var_start.value()); IntPtrMax(SmiUntag(CAST(var_length.value())), zero);
var_result_length = SmiMin(positive_length, minimal_length); TNode<IntPtrT> const minimal_length =
IntPtrSub(string_length, var_start.value());
var_result_length = IntPtrMin(positive_length, minimal_length);
GotoIfNot(SmiLessThanOrEqual(var_result_length.value(), zero), &out); GotoIfNot(IntPtrLessThanOrEqual(var_result_length.value(), zero), &out);
args.PopAndReturn(EmptyStringConstant()); args.PopAndReturn(EmptyStringConstant());
} }
...@@ -1879,15 +1881,16 @@ TF_BUILTIN(StringPrototypeSubstr, StringBuiltinsAssembler) { ...@@ -1879,15 +1881,16 @@ TF_BUILTIN(StringPrototypeSubstr, StringBuiltinsAssembler) {
BIND(&if_ispositive); BIND(&if_ispositive);
{ {
var_result_length = SmiSub(string_length, var_start.value()); var_result_length = IntPtrSub(string_length, var_start.value());
GotoIfNot(SmiLessThanOrEqual(var_result_length.value(), zero), &out); GotoIfNot(IntPtrLessThanOrEqual(var_result_length.value(), zero), &out);
args.PopAndReturn(EmptyStringConstant()); args.PopAndReturn(EmptyStringConstant());
} }
} }
BIND(&out); BIND(&out);
{ {
TNode<Smi> const end = SmiAdd(var_start.value(), var_result_length.value()); TNode<IntPtrT> const end =
IntPtrAdd(var_start.value(), var_result_length.value());
args.PopAndReturn(SubString(string, var_start.value(), end)); args.PopAndReturn(SubString(string, var_start.value(), end));
} }
} }
...@@ -1898,7 +1901,7 @@ TNode<Smi> StringBuiltinsAssembler::ToSmiBetweenZeroAnd( ...@@ -1898,7 +1901,7 @@ TNode<Smi> StringBuiltinsAssembler::ToSmiBetweenZeroAnd(
Label out(this); Label out(this);
TVARIABLE(Smi, var_result); TVARIABLE(Smi, var_result);
TNode<Object> const value_int = TNode<Number> const value_int =
ToInteger_Inline(context, value, CodeStubAssembler::kTruncateMinusZero); ToInteger_Inline(context, value, CodeStubAssembler::kTruncateMinusZero);
Label if_issmi(this), if_isnotsmi(this, Label::kDeferred); Label if_issmi(this), if_isnotsmi(this, Label::kDeferred);
...@@ -1906,8 +1909,9 @@ TNode<Smi> StringBuiltinsAssembler::ToSmiBetweenZeroAnd( ...@@ -1906,8 +1909,9 @@ TNode<Smi> StringBuiltinsAssembler::ToSmiBetweenZeroAnd(
BIND(&if_issmi); BIND(&if_issmi);
{ {
TNode<Smi> value_smi = CAST(value_int);
Label if_isinbounds(this), if_isoutofbounds(this, Label::kDeferred); 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); BIND(&if_isinbounds);
{ {
...@@ -1919,7 +1923,7 @@ TNode<Smi> StringBuiltinsAssembler::ToSmiBetweenZeroAnd( ...@@ -1919,7 +1923,7 @@ TNode<Smi> StringBuiltinsAssembler::ToSmiBetweenZeroAnd(
{ {
TNode<Smi> const zero = SmiConstant(0); TNode<Smi> const zero = SmiConstant(0);
var_result = var_result =
SelectTaggedConstant(SmiLessThan(value_int, zero), zero, limit); SelectTaggedConstant(SmiLessThan(value_smi, zero), zero, limit);
Goto(&out); Goto(&out);
} }
} }
...@@ -1943,8 +1947,8 @@ TNode<Smi> StringBuiltinsAssembler::ToSmiBetweenZeroAnd( ...@@ -1943,8 +1947,8 @@ TNode<Smi> StringBuiltinsAssembler::ToSmiBetweenZeroAnd(
TF_BUILTIN(StringSubstring, CodeStubAssembler) { TF_BUILTIN(StringSubstring, CodeStubAssembler) {
TNode<String> string = CAST(Parameter(Descriptor::kString)); TNode<String> string = CAST(Parameter(Descriptor::kString));
Node* from = Parameter(Descriptor::kFrom); TNode<IntPtrT> from = UncheckedCast<IntPtrT>(Parameter(Descriptor::kFrom));
Node* to = Parameter(Descriptor::kTo); TNode<IntPtrT> to = UncheckedCast<IntPtrT>(Parameter(Descriptor::kTo));
Return(SubString(string, from, to)); Return(SubString(string, from, to));
} }
...@@ -1998,7 +2002,10 @@ TF_BUILTIN(StringPrototypeSubstring, StringBuiltinsAssembler) { ...@@ -1998,7 +2002,10 @@ TF_BUILTIN(StringPrototypeSubstring, StringBuiltinsAssembler) {
} }
BIND(&out); BIND(&out);
{ args.PopAndReturn(SubString(string, var_start.value(), var_end.value())); } {
args.PopAndReturn(SubString(string, SmiUntag(var_start.value()),
SmiUntag(var_end.value())));
}
} }
// ES6 #sec-string.prototype.trim // ES6 #sec-string.prototype.trim
...@@ -2051,8 +2058,8 @@ void StringTrimAssembler::Generate(String::TrimMode mode, ...@@ -2051,8 +2058,8 @@ void StringTrimAssembler::Generate(String::TrimMode mode,
} }
arguments.PopAndReturn( arguments.PopAndReturn(
SubString(string, SmiTag(var_start.value()), SubString(string, var_start.value(),
SmiAdd(SmiTag(var_end.value()), SmiConstant(1)))); IntPtrAdd(var_end.value(), IntPtrConstant(1))));
BIND(&if_runtime); BIND(&if_runtime);
arguments.PopAndReturn( arguments.PopAndReturn(
......
...@@ -147,10 +147,12 @@ TF_BUILTIN(TypedArrayInitialize, TypedArrayBuiltinsAssembler) { ...@@ -147,10 +147,12 @@ TF_BUILTIN(TypedArrayInitialize, TypedArrayBuiltinsAssembler) {
TNode<Map> fixed_typed_map = LoadMapForType(holder); TNode<Map> fixed_typed_map = LoadMapForType(holder);
GotoIf(TaggedIsNotSmi(byte_length), &allocate_off_heap); GotoIf(TaggedIsNotSmi(byte_length), &allocate_off_heap);
GotoIf( // The goto above ensures that byte_length is a Smi.
SmiGreaterThan(byte_length, SmiConstant(V8_TYPED_ARRAY_MAX_SIZE_IN_HEAP)), TNode<Smi> smi_byte_length = CAST(byte_length);
&allocate_off_heap); GotoIf(SmiGreaterThan(smi_byte_length,
TNode<IntPtrT> word_byte_length = SmiToIntPtr(CAST(byte_length)); SmiConstant(V8_TYPED_ARRAY_MAX_SIZE_IN_HEAP)),
&allocate_off_heap);
TNode<IntPtrT> word_byte_length = SmiToIntPtr(smi_byte_length);
Goto(&allocate_on_heap); Goto(&allocate_on_heap);
BIND(&allocate_on_heap); BIND(&allocate_on_heap);
...@@ -305,7 +307,9 @@ void TypedArrayBuiltinsAssembler::ConstructByLength(TNode<Context> context, ...@@ -305,7 +307,9 @@ void TypedArrayBuiltinsAssembler::ConstructByLength(TNode<Context> context,
// Note: this is not per spec, but rather a constraint of our current // Note: this is not per spec, but rather a constraint of our current
// representation (which uses Smis). // representation (which uses Smis).
GotoIf(TaggedIsNotSmi(converted_length), &invalid_length); GotoIf(TaggedIsNotSmi(converted_length), &invalid_length);
GotoIf(SmiLessThan(converted_length, SmiConstant(0)), &invalid_length); // The goto above ensures that byte_length is a Smi.
TNode<Smi> smi_converted_length = CAST(converted_length);
GotoIf(SmiLessThan(smi_converted_length, SmiConstant(0)), &invalid_length);
Node* initialize = TrueConstant(); Node* initialize = TrueConstant();
CallBuiltin(Builtins::kTypedArrayInitialize, context, holder, CallBuiltin(Builtins::kTypedArrayInitialize, context, holder,
...@@ -1245,16 +1249,19 @@ TF_BUILTIN(TypedArrayPrototypeSlice, TypedArrayBuiltinsAssembler) { ...@@ -1245,16 +1249,19 @@ TF_BUILTIN(TypedArrayPrototypeSlice, TypedArrayBuiltinsAssembler) {
// Convert start offset argument to integer, and calculate relative offset. // Convert start offset argument to integer, and calculate relative offset.
TNode<Object> start = args.GetOptionalArgumentValue(0, SmiConstant(0)); TNode<Object> start = args.GetOptionalArgumentValue(0, SmiConstant(0));
TNode<Smi> start_index = TNode<Smi> start_index =
ConvertToRelativeIndex(context, start, source_length); SmiTag(ConvertToRelativeIndex(context, start, SmiUntag(source_length)));
// Convert end offset argument to integer, and calculate relative offset. // Convert end offset argument to integer, and calculate relative offset.
// If end offset is not given or undefined is given, set source_length to // If end offset is not given or undefined is given, set source_length to
// "end_index". // "end_index".
TNode<Object> end = args.GetOptionalArgumentValue(1, UndefinedConstant()); TNode<Object> end = args.GetOptionalArgumentValue(1, UndefinedConstant());
TNode<Smi> end_index = Select<Smi>( TNode<Smi> end_index =
IsUndefined(end), [=] { return source_length; }, Select<Smi>(IsUndefined(end), [=] { return source_length; },
[=] { return ConvertToRelativeIndex(context, end, source_length); }, [=] {
MachineRepresentation::kTagged); return SmiTag(ConvertToRelativeIndex(
context, end, SmiUntag(source_length)));
},
MachineRepresentation::kTagged);
// Create a result array by invoking TypedArraySpeciesCreate. // Create a result array by invoking TypedArraySpeciesCreate.
TNode<Smi> count = SmiMax(SmiSub(end_index, start_index), SmiConstant(0)); TNode<Smi> count = SmiMax(SmiSub(end_index, start_index), SmiConstant(0));
...@@ -1367,7 +1374,8 @@ TF_BUILTIN(TypedArrayPrototypeSubArray, TypedArrayBuiltinsAssembler) { ...@@ -1367,7 +1374,8 @@ TF_BUILTIN(TypedArrayPrototypeSubArray, TypedArrayBuiltinsAssembler) {
// 8. If relativeBegin < 0, let beginIndex be max((srcLength + relativeBegin), // 8. If relativeBegin < 0, let beginIndex be max((srcLength + relativeBegin),
// 0); else let beginIndex be min(relativeBegin, srcLength). // 0); else let beginIndex be min(relativeBegin, srcLength).
TNode<Object> begin = args.GetOptionalArgumentValue(0, SmiConstant(0)); TNode<Object> begin = args.GetOptionalArgumentValue(0, SmiConstant(0));
var_begin = ConvertToRelativeIndex(context, begin, source_length); var_begin =
SmiTag(ConvertToRelativeIndex(context, begin, SmiUntag(source_length)));
TNode<Object> end = args.GetOptionalArgumentValue(1, UndefinedConstant()); TNode<Object> end = args.GetOptionalArgumentValue(1, UndefinedConstant());
// 9. If end is undefined, let relativeEnd be srcLength; // 9. If end is undefined, let relativeEnd be srcLength;
...@@ -1377,7 +1385,8 @@ TF_BUILTIN(TypedArrayPrototypeSubArray, TypedArrayBuiltinsAssembler) { ...@@ -1377,7 +1385,8 @@ TF_BUILTIN(TypedArrayPrototypeSubArray, TypedArrayBuiltinsAssembler) {
// else, let relativeEnd be ? ToInteger(end). // else, let relativeEnd be ? ToInteger(end).
// 10. If relativeEnd < 0, let endIndex be max((srcLength + relativeEnd), 0); // 10. If relativeEnd < 0, let endIndex be max((srcLength + relativeEnd), 0);
// else let endIndex be min(relativeEnd, srcLength). // else let endIndex be min(relativeEnd, srcLength).
var_end = ConvertToRelativeIndex(context, end, source_length); var_end =
SmiTag(ConvertToRelativeIndex(context, end, SmiUntag(source_length)));
Goto(&offset_done); Goto(&offset_done);
BIND(&offset_done); BIND(&offset_done);
......
This diff is collapsed.
...@@ -220,8 +220,9 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler { ...@@ -220,8 +220,9 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
// After converting an index to an integer, calculate a relative index: if // After converting an index to an integer, calculate a relative index: if
// index < 0, max(length + index, 0); else min(index, length) // index < 0, max(length + index, 0); else min(index, length)
TNode<Smi> ConvertToRelativeIndex(TNode<Context> context, TNode<Object> index, TNode<IntPtrT> ConvertToRelativeIndex(TNode<Context> context,
TNode<Smi> length); TNode<Object> index,
TNode<IntPtrT> length);
// Tag an IntPtr as a Smi value. // Tag an IntPtr as a Smi value.
TNode<Smi> SmiTag(SloppyTNode<IntPtrT> value); TNode<Smi> SmiTag(SloppyTNode<IntPtrT> value);
...@@ -773,12 +774,15 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler { ...@@ -773,12 +774,15 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
// Allocate a SlicedOneByteString with the given length, parent and offset. // Allocate a SlicedOneByteString with the given length, parent and offset.
// |length| and |offset| are expected to be tagged. // |length| and |offset| are expected to be tagged.
TNode<String> AllocateSlicedOneByteString(TNode<Smi> length, Node* parent,
Node* offset); TNode<String> AllocateSlicedOneByteString(TNode<Smi> length,
TNode<String> parent,
TNode<Smi> offset);
// Allocate a SlicedTwoByteString with the given length, parent and offset. // Allocate a SlicedTwoByteString with the given length, parent and offset.
// |length| and |offset| are expected to be tagged. // |length| and |offset| are expected to be tagged.
TNode<String> AllocateSlicedTwoByteString(TNode<Smi> length, Node* parent, TNode<String> AllocateSlicedTwoByteString(TNode<Smi> length,
Node* offset); TNode<String> parent,
TNode<Smi> offset);
// Allocate a one-byte ConsString with the given length, first and second // Allocate a one-byte ConsString with the given length, first and second
// parts. |length| is expected to be tagged, and |first| and |second| are // parts. |length| is expected to be tagged, and |first| and |second| are
...@@ -1219,8 +1223,8 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler { ...@@ -1219,8 +1223,8 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
// Return a new string object which holds a substring containing the range // Return a new string object which holds a substring containing the range
// [from,to[ of string. |from| and |to| are expected to be tagged. // [from,to[ of string. |from| and |to| are expected to be tagged.
TNode<String> SubString(TNode<String> string, SloppyTNode<Smi> from, TNode<String> SubString(TNode<String> string, TNode<IntPtrT> from,
SloppyTNode<Smi> to); TNode<IntPtrT> to);
// Return a new string object produced by concatenating |first| with |second|. // Return a new string object produced by concatenating |first| with |second|.
TNode<String> StringAdd(Node* context, TNode<String> first, TNode<String> StringAdd(Node* context, TNode<String> first,
...@@ -2026,8 +2030,8 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler { ...@@ -2026,8 +2030,8 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
Label* bailout); Label* bailout);
TNode<String> AllocateSlicedString(Heap::RootListIndex map_root_index, TNode<String> AllocateSlicedString(Heap::RootListIndex map_root_index,
TNode<Smi> length, Node* parent, TNode<Smi> length, TNode<String> parent,
Node* offset); TNode<Smi> offset);
TNode<String> AllocateConsString(Heap::RootListIndex map_root_index, TNode<String> AllocateConsString(Heap::RootListIndex map_root_index,
TNode<Smi> length, TNode<String> first, TNode<Smi> length, TNode<String> first,
...@@ -2161,7 +2165,7 @@ class ToDirectStringAssembler : public CodeStubAssembler { ...@@ -2161,7 +2165,7 @@ class ToDirectStringAssembler : public CodeStubAssembler {
// string. The result can be either a sequential or external string. // string. The result can be either a sequential or external string.
// Jumps to if_bailout if the string if the string is indirect and cannot // Jumps to if_bailout if the string if the string is indirect and cannot
// be unpacked. // be unpacked.
Node* TryToDirect(Label* if_bailout); TNode<String> TryToDirect(Label* if_bailout);
// Returns a pointer to the beginning of the string data. // Returns a pointer to the beginning of the string data.
// Jumps to if_bailout if the external string cannot be unpacked. // Jumps to if_bailout if the external string cannot be unpacked.
...@@ -2177,7 +2181,9 @@ class ToDirectStringAssembler : public CodeStubAssembler { ...@@ -2177,7 +2181,9 @@ class ToDirectStringAssembler : public CodeStubAssembler {
Node* string() { return var_string_.value(); } Node* string() { return var_string_.value(); }
Node* instance_type() { return var_instance_type_.value(); } Node* instance_type() { return var_instance_type_.value(); }
Node* offset() { return var_offset_.value(); } TNode<IntPtrT> offset() {
return UncheckedCast<IntPtrT>(var_offset_.value());
}
Node* is_external() { return var_is_external_.value(); } Node* is_external() { return var_is_external_.value(); }
private: private:
......
...@@ -3196,8 +3196,8 @@ Node* EffectControlLinearizer::LowerStringComparison(Callable const& callable, ...@@ -3196,8 +3196,8 @@ Node* EffectControlLinearizer::LowerStringComparison(Callable const& callable,
Node* EffectControlLinearizer::LowerStringSubstring(Node* node) { Node* EffectControlLinearizer::LowerStringSubstring(Node* node) {
Node* receiver = node->InputAt(0); Node* receiver = node->InputAt(0);
Node* start = node->InputAt(1); Node* start = ChangeInt32ToIntPtr(node->InputAt(1));
Node* end = node->InputAt(2); Node* end = ChangeInt32ToIntPtr(node->InputAt(2));
Callable callable = Callable callable =
Builtins::CallableFor(isolate(), Builtins::kStringSubstring); Builtins::CallableFor(isolate(), Builtins::kStringSubstring);
......
...@@ -2410,8 +2410,8 @@ class RepresentationSelector { ...@@ -2410,8 +2410,8 @@ class RepresentationSelector {
} }
case IrOpcode::kStringSubstring: { case IrOpcode::kStringSubstring: {
ProcessInput(node, 0, UseInfo::AnyTagged()); ProcessInput(node, 0, UseInfo::AnyTagged());
ProcessInput(node, 1, UseInfo::TaggedSigned()); ProcessInput(node, 1, UseInfo::TruncatingWord32());
ProcessInput(node, 2, UseInfo::TaggedSigned()); ProcessInput(node, 2, UseInfo::TruncatingWord32());
SetOutput(node, MachineRepresentation::kTaggedPointer); SetOutput(node, MachineRepresentation::kTaggedPointer);
return; return;
} }
......
...@@ -284,6 +284,21 @@ void StringAtDescriptor::InitializePlatformSpecific( ...@@ -284,6 +284,21 @@ void StringAtDescriptor::InitializePlatformSpecific(
DefaultInitializePlatformSpecific(data, kParameterCount); DefaultInitializePlatformSpecific(data, kParameterCount);
} }
void StringSubstringDescriptor::InitializePlatformIndependent(
CallInterfaceDescriptorData* data) {
// kString, kFrom, kTo
// TODO(turbofan): Allow builtins to return untagged values.
MachineType machine_types[] = {MachineType::AnyTagged(),
MachineType::IntPtr(), MachineType::IntPtr()};
data->InitializePlatformIndependent(arraysize(machine_types), 0,
machine_types);
}
void StringSubstringDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
DefaultInitializePlatformSpecific(data, kParameterCount);
}
void TypeConversionDescriptor::InitializePlatformSpecific( void TypeConversionDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) { CallInterfaceDescriptorData* data) {
Register registers[] = {ArgumentRegister()}; Register registers[] = {ArgumentRegister()};
......
...@@ -62,6 +62,7 @@ class PlatformInterfaceDescriptor; ...@@ -62,6 +62,7 @@ class PlatformInterfaceDescriptor;
V(BinaryOp) \ V(BinaryOp) \
V(StringAdd) \ V(StringAdd) \
V(StringAt) \ V(StringAt) \
V(StringSubstring) \
V(ForInPrepare) \ V(ForInPrepare) \
V(GetProperty) \ V(GetProperty) \
V(ArgumentAdaptor) \ V(ArgumentAdaptor) \
...@@ -764,6 +765,13 @@ class StringAtDescriptor final : public CallInterfaceDescriptor { ...@@ -764,6 +765,13 @@ class StringAtDescriptor final : public CallInterfaceDescriptor {
CallInterfaceDescriptor) CallInterfaceDescriptor)
}; };
class StringSubstringDescriptor final : public CallInterfaceDescriptor {
public:
DEFINE_PARAMETERS(kString, kFrom, kTo)
DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(StringSubstringDescriptor,
CallInterfaceDescriptor)
};
class ArgumentAdaptorDescriptor : public CallInterfaceDescriptor { class ArgumentAdaptorDescriptor : public CallInterfaceDescriptor {
public: public:
DEFINE_PARAMETERS(kFunction, kNewTarget, kActualArgumentsCount, DEFINE_PARAMETERS(kFunction, kNewTarget, kActualArgumentsCount,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment