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);
GotoIf(SmiGreaterThan(smi_byte_length,
SmiConstant(V8_TYPED_ARRAY_MAX_SIZE_IN_HEAP)),
&allocate_off_heap); &allocate_off_heap);
TNode<IntPtrT> word_byte_length = SmiToIntPtr(CAST(byte_length)); 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,15 +1249,18 @@ TF_BUILTIN(TypedArrayPrototypeSlice, TypedArrayBuiltinsAssembler) { ...@@ -1245,15 +1249,18 @@ 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); }, [=] {
return SmiTag(ConvertToRelativeIndex(
context, end, SmiUntag(source_length)));
},
MachineRepresentation::kTagged); MachineRepresentation::kTagged);
// Create a result array by invoking TypedArraySpeciesCreate. // Create a result array by invoking TypedArraySpeciesCreate.
...@@ -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);
......
...@@ -616,14 +616,13 @@ TNode<Object> CodeStubAssembler::NumberMin(SloppyTNode<Object> a, ...@@ -616,14 +616,13 @@ TNode<Object> CodeStubAssembler::NumberMin(SloppyTNode<Object> a,
return TNode<Object>::UncheckedCast(result.value()); return TNode<Object>::UncheckedCast(result.value());
} }
TNode<Smi> CodeStubAssembler::ConvertToRelativeIndex(TNode<Context> context, TNode<IntPtrT> CodeStubAssembler::ConvertToRelativeIndex(
TNode<Object> index, TNode<Context> context, TNode<Object> index, TNode<IntPtrT> length) {
TNode<Smi> length) { TVARIABLE(IntPtrT, result);
TVARIABLE(Smi, result);
TNode<Number> const index_int = TNode<Number> const index_int =
ToInteger_Inline(context, index, CodeStubAssembler::kTruncateMinusZero); ToInteger_Inline(context, index, CodeStubAssembler::kTruncateMinusZero);
TNode<Smi> const zero = SmiConstant(0); TNode<IntPtrT> zero = IntPtrConstant(0);
Label done(this); Label done(this);
Label if_issmi(this), if_isheapnumber(this, Label::kDeferred); Label if_issmi(this), if_isheapnumber(this, Label::kDeferred);
...@@ -632,11 +631,11 @@ TNode<Smi> CodeStubAssembler::ConvertToRelativeIndex(TNode<Context> context, ...@@ -632,11 +631,11 @@ TNode<Smi> CodeStubAssembler::ConvertToRelativeIndex(TNode<Context> context,
BIND(&if_issmi); BIND(&if_issmi);
{ {
TNode<Smi> const index_smi = CAST(index_int); TNode<Smi> const index_smi = CAST(index_int);
result = result = Select<IntPtrT>(
Select<Smi>(SmiLessThan(index_smi, zero), IntPtrLessThan(SmiUntag(index_smi), zero),
[&] { return SmiMax(SmiAdd(length, index_smi), zero); }, [&] { return IntPtrMax(IntPtrAdd(length, SmiUntag(index_smi)), zero); },
[&] { return SmiMin(index_smi, length); }, [&] { return IntPtrMin(SmiUntag(index_smi), length); },
MachineRepresentation::kTagged); MachineType::PointerRepresentation());
Goto(&done); Goto(&done);
} }
...@@ -648,12 +647,11 @@ TNode<Smi> CodeStubAssembler::ConvertToRelativeIndex(TNode<Context> context, ...@@ -648,12 +647,11 @@ TNode<Smi> CodeStubAssembler::ConvertToRelativeIndex(TNode<Context> context,
TNode<HeapNumber> const index_hn = CAST(index_int); TNode<HeapNumber> const index_hn = CAST(index_int);
TNode<Float64T> const float_zero = Float64Constant(0.); TNode<Float64T> const float_zero = Float64Constant(0.);
TNode<Float64T> const index_float = LoadHeapNumberValue(index_hn); TNode<Float64T> const index_float = LoadHeapNumberValue(index_hn);
result = SelectTaggedConstant<Smi>(Float64LessThan(index_float, float_zero), result = SelectConstant(Float64LessThan(index_float, float_zero), zero,
zero, length); length, MachineType::PointerRepresentation());
Goto(&done); Goto(&done);
} }
BIND(&done); BIND(&done);
CSA_ASSERT(this, TaggedIsPositiveSmi(result.value()));
return result.value(); return result.value();
} }
...@@ -2586,12 +2584,10 @@ TNode<String> CodeStubAssembler::AllocateSeqTwoByteString( ...@@ -2586,12 +2584,10 @@ TNode<String> CodeStubAssembler::AllocateSeqTwoByteString(
} }
TNode<String> CodeStubAssembler::AllocateSlicedString( TNode<String> CodeStubAssembler::AllocateSlicedString(
Heap::RootListIndex map_root_index, TNode<Smi> length, Node* parent, Heap::RootListIndex map_root_index, TNode<Smi> length, TNode<String> parent,
Node* offset) { TNode<Smi> offset) {
DCHECK(map_root_index == Heap::kSlicedOneByteStringMapRootIndex || DCHECK(map_root_index == Heap::kSlicedOneByteStringMapRootIndex ||
map_root_index == Heap::kSlicedStringMapRootIndex); map_root_index == Heap::kSlicedStringMapRootIndex);
CSA_ASSERT(this, IsString(parent));
CSA_ASSERT(this, TaggedIsSmi(offset));
Node* result = Allocate(SlicedString::kSize); Node* result = Allocate(SlicedString::kSize);
DCHECK(Heap::RootIsImmortalImmovable(map_root_index)); DCHECK(Heap::RootIsImmortalImmovable(map_root_index));
StoreMapNoWriteBarrier(result, map_root_index); StoreMapNoWriteBarrier(result, map_root_index);
...@@ -2607,16 +2603,14 @@ TNode<String> CodeStubAssembler::AllocateSlicedString( ...@@ -2607,16 +2603,14 @@ TNode<String> CodeStubAssembler::AllocateSlicedString(
return CAST(result); return CAST(result);
} }
TNode<String> CodeStubAssembler::AllocateSlicedOneByteString(TNode<Smi> length, TNode<String> CodeStubAssembler::AllocateSlicedOneByteString(
Node* parent, TNode<Smi> length, TNode<String> parent, TNode<Smi> offset) {
Node* offset) {
return AllocateSlicedString(Heap::kSlicedOneByteStringMapRootIndex, length, return AllocateSlicedString(Heap::kSlicedOneByteStringMapRootIndex, length,
parent, offset); parent, offset);
} }
TNode<String> CodeStubAssembler::AllocateSlicedTwoByteString(TNode<Smi> length, TNode<String> CodeStubAssembler::AllocateSlicedTwoByteString(
Node* parent, TNode<Smi> length, TNode<String> parent, TNode<Smi> offset) {
Node* offset) {
return AllocateSlicedString(Heap::kSlicedStringMapRootIndex, length, parent, return AllocateSlicedString(Heap::kSlicedStringMapRootIndex, length, parent,
offset); offset);
} }
...@@ -4996,37 +4990,33 @@ TNode<String> CodeStubAssembler::AllocAndCopyStringCharacters( ...@@ -4996,37 +4990,33 @@ TNode<String> CodeStubAssembler::AllocAndCopyStringCharacters(
} }
TNode<String> CodeStubAssembler::SubString(TNode<String> string, TNode<String> CodeStubAssembler::SubString(TNode<String> string,
SloppyTNode<Smi> from, TNode<IntPtrT> from,
SloppyTNode<Smi> to) { TNode<IntPtrT> to) {
TVARIABLE(String, var_result); TVARIABLE(String, var_result);
ToDirectStringAssembler to_direct(state(), string); ToDirectStringAssembler to_direct(state(), string);
Label end(this), runtime(this); Label end(this), runtime(this);
// Make sure that both from and to are non-negative smis. TNode<IntPtrT> const substr_length = IntPtrSub(to, from);
CSA_ASSERT(this, TaggedIsPositiveSmi(from)); TNode<IntPtrT> const string_length = LoadStringLengthAsWord(string);
CSA_ASSERT(this, TaggedIsPositiveSmi(to));
TNode<Smi> const substr_length = SmiSub(to, from);
TNode<Smi> const string_length = LoadStringLengthAsSmi(string);
// Begin dispatching based on substring length. // Begin dispatching based on substring length.
Label original_string_or_invalid_length(this); Label original_string_or_invalid_length(this);
GotoIf(SmiAboveOrEqual(substr_length, string_length), GotoIf(UintPtrGreaterThanOrEqual(substr_length, string_length),
&original_string_or_invalid_length); &original_string_or_invalid_length);
// A real substring (substr_length < string_length). // A real substring (substr_length < string_length).
Label single_char(this); Label single_char(this);
GotoIf(SmiEqual(substr_length, SmiConstant(1)), &single_char); GotoIf(IntPtrEqual(substr_length, IntPtrConstant(1)), &single_char);
// TODO(jgruber): Add an additional case for substring of length == 0? // TODO(jgruber): Add an additional case for substring of length == 0?
// Deal with different string types: update the index if necessary // Deal with different string types: update the index if necessary
// and extract the underlying string. // and extract the underlying string.
Node* const direct_string = to_direct.TryToDirect(&runtime); TNode<String> direct_string = to_direct.TryToDirect(&runtime);
Node* const offset = SmiAdd(from, SmiTag(to_direct.offset())); TNode<IntPtrT> offset = IntPtrAdd(from, to_direct.offset());
Node* const instance_type = to_direct.instance_type(); Node* const instance_type = to_direct.instance_type();
// The subject string can only be external or sequential string of either // The subject string can only be external or sequential string of either
...@@ -5037,7 +5027,8 @@ TNode<String> CodeStubAssembler::SubString(TNode<String> string, ...@@ -5037,7 +5027,8 @@ TNode<String> CodeStubAssembler::SubString(TNode<String> string,
Label next(this); Label next(this);
// Short slice. Copy instead of slicing. // Short slice. Copy instead of slicing.
GotoIf(SmiLessThan(substr_length, SmiConstant(SlicedString::kMinLength)), GotoIf(IntPtrLessThan(substr_length,
IntPtrConstant(SlicedString::kMinLength)),
&next); &next);
// Allocate new sliced string. // Allocate new sliced string.
...@@ -5051,15 +5042,15 @@ TNode<String> CodeStubAssembler::SubString(TNode<String> string, ...@@ -5051,15 +5042,15 @@ TNode<String> CodeStubAssembler::SubString(TNode<String> string,
BIND(&one_byte_slice); BIND(&one_byte_slice);
{ {
var_result = var_result = AllocateSlicedOneByteString(SmiTag(substr_length),
AllocateSlicedOneByteString(substr_length, direct_string, offset); direct_string, SmiTag(offset));
Goto(&end); Goto(&end);
} }
BIND(&two_byte_slice); BIND(&two_byte_slice);
{ {
var_result = var_result = AllocateSlicedTwoByteString(SmiTag(substr_length),
AllocateSlicedTwoByteString(substr_length, direct_string, offset); direct_string, SmiTag(offset));
Goto(&end); Goto(&end);
} }
...@@ -5071,7 +5062,7 @@ TNode<String> CodeStubAssembler::SubString(TNode<String> string, ...@@ -5071,7 +5062,7 @@ TNode<String> CodeStubAssembler::SubString(TNode<String> string,
GotoIf(to_direct.is_external(), &external_string); GotoIf(to_direct.is_external(), &external_string);
var_result = AllocAndCopyStringCharacters(direct_string, instance_type, var_result = AllocAndCopyStringCharacters(direct_string, instance_type,
SmiUntag(offset), substr_length); offset, SmiTag(substr_length));
Counters* counters = isolate()->counters(); Counters* counters = isolate()->counters();
IncrementCounter(counters->sub_string_native(), 1); IncrementCounter(counters->sub_string_native(), 1);
...@@ -5085,7 +5076,7 @@ TNode<String> CodeStubAssembler::SubString(TNode<String> string, ...@@ -5085,7 +5076,7 @@ TNode<String> CodeStubAssembler::SubString(TNode<String> string,
Node* const fake_sequential_string = to_direct.PointerToString(&runtime); Node* const fake_sequential_string = to_direct.PointerToString(&runtime);
var_result = AllocAndCopyStringCharacters( var_result = AllocAndCopyStringCharacters(
fake_sequential_string, instance_type, SmiUntag(offset), substr_length); fake_sequential_string, instance_type, offset, SmiTag(substr_length));
Counters* counters = isolate()->counters(); Counters* counters = isolate()->counters();
IncrementCounter(counters->sub_string_native(), 1); IncrementCounter(counters->sub_string_native(), 1);
...@@ -5096,17 +5087,17 @@ TNode<String> CodeStubAssembler::SubString(TNode<String> string, ...@@ -5096,17 +5087,17 @@ TNode<String> CodeStubAssembler::SubString(TNode<String> string,
// Substrings of length 1 are generated through CharCodeAt and FromCharCode. // Substrings of length 1 are generated through CharCodeAt and FromCharCode.
BIND(&single_char); BIND(&single_char);
{ {
TNode<Int32T> char_code = StringCharCodeAt(string, SmiUntag(from)); TNode<Int32T> char_code = StringCharCodeAt(string, from);
var_result = StringFromCharCode(char_code); var_result = StringFromCharCode(char_code);
Goto(&end); Goto(&end);
} }
BIND(&original_string_or_invalid_length); BIND(&original_string_or_invalid_length);
{ {
CSA_ASSERT(this, SmiEqual(substr_length, string_length)); CSA_ASSERT(this, IntPtrEqual(substr_length, string_length));
// Equal length - check if {from, to} == {0, str.length}. // Equal length - check if {from, to} == {0, str.length}.
GotoIf(SmiAbove(from, SmiConstant(0)), &runtime); GotoIf(UintPtrGreaterThan(from, IntPtrConstant(0)), &runtime);
// Return the original string (substr_length == string_length). // Return the original string (substr_length == string_length).
...@@ -5120,8 +5111,9 @@ TNode<String> CodeStubAssembler::SubString(TNode<String> string, ...@@ -5120,8 +5111,9 @@ TNode<String> CodeStubAssembler::SubString(TNode<String> string,
// Fall back to a runtime call. // Fall back to a runtime call.
BIND(&runtime); BIND(&runtime);
{ {
var_result = CAST(CallRuntime(Runtime::kStringSubstring, var_result =
NoContextConstant(), string, from, to)); CAST(CallRuntime(Runtime::kStringSubstring, NoContextConstant(), string,
SmiTag(from), SmiTag(to)));
Goto(&end); Goto(&end);
} }
...@@ -5146,7 +5138,7 @@ ToDirectStringAssembler::ToDirectStringAssembler( ...@@ -5146,7 +5138,7 @@ ToDirectStringAssembler::ToDirectStringAssembler(
var_is_external_.Bind(Int32Constant(0)); var_is_external_.Bind(Int32Constant(0));
} }
Node* ToDirectStringAssembler::TryToDirect(Label* if_bailout) { TNode<String> ToDirectStringAssembler::TryToDirect(Label* if_bailout) {
VariableList vars({&var_string_, &var_offset_, &var_instance_type_}, zone()); VariableList vars({&var_string_, &var_offset_, &var_instance_type_}, zone());
Label dispatch(this, vars); Label dispatch(this, vars);
Label if_iscons(this); Label if_iscons(this);
...@@ -5229,7 +5221,7 @@ Node* ToDirectStringAssembler::TryToDirect(Label* if_bailout) { ...@@ -5229,7 +5221,7 @@ Node* ToDirectStringAssembler::TryToDirect(Label* if_bailout) {
Goto(&out); Goto(&out);
BIND(&out); BIND(&out);
return var_string_.value(); return CAST(var_string_.value());
} }
Node* ToDirectStringAssembler::TryToSequential(StringPointerKind ptr_kind, Node* ToDirectStringAssembler::TryToSequential(StringPointerKind ptr_kind,
......
...@@ -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