Port StringPrototypeSubString to Torque

Bug: v8:8996
Change-Id: I63ae821086c42c14a317e866fb4f0f799f4c4f7c
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1597555
Commit-Queue: Z Nguyen-Huu <duongn@microsoft.com>
Reviewed-by: Simon Zünd <szuend@chromium.org>
Cr-Commit-Position: refs/heads/master@{#61360}
This commit is contained in:
Z Duong Nguyen-Huu 2019-05-08 22:16:26 -07:00 committed by Commit Bot
parent 595c8e8efa
commit 47d32fef2b
5 changed files with 52 additions and 112 deletions

View File

@ -956,6 +956,7 @@ torque_files = [
"src/builtins/string-iterator.tq",
"src/builtins/string-repeat.tq",
"src/builtins/string-startswith.tq",
"src/builtins/string-substring.tq",
"src/builtins/typed-array-createtypedarray.tq",
"src/builtins/typed-array-every.tq",
"src/builtins/typed-array-filter.tq",
@ -1010,6 +1011,7 @@ torque_namespaces = [
"string-html",
"string-iterator",
"string-repeat",
"string-substring",
"test",
"typed-array",
"typed-array-createtypedarray",

View File

@ -984,9 +984,6 @@ namespace internal {
TFJ(StringPrototypeSplit, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
/* ES6 #sec-string.prototype.substr */ \
TFJ(StringPrototypeSubstr, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
/* ES6 #sec-string.prototype.substring */ \
TFJ(StringPrototypeSubstring, \
SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
TFJ(StringPrototypeTrim, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
TFJ(StringPrototypeTrimEnd, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
TFJ(StringPrototypeTrimStart, \

View File

@ -1920,56 +1920,6 @@ TF_BUILTIN(StringPrototypeSubstr, StringBuiltinsAssembler) {
}
}
TNode<Smi> StringBuiltinsAssembler::ToSmiBetweenZeroAnd(
SloppyTNode<Context> context, SloppyTNode<Object> value,
SloppyTNode<Smi> limit) {
Label out(this);
TVARIABLE(Smi, var_result);
TNode<Number> const value_int =
ToInteger_Inline(context, value, CodeStubAssembler::kTruncateMinusZero);
Label if_issmi(this), if_isnotsmi(this, Label::kDeferred);
Branch(TaggedIsSmi(value_int), &if_issmi, &if_isnotsmi);
BIND(&if_issmi);
{
TNode<Smi> value_smi = CAST(value_int);
Label if_isinbounds(this), if_isoutofbounds(this, Label::kDeferred);
Branch(SmiAbove(value_smi, limit), &if_isoutofbounds, &if_isinbounds);
BIND(&if_isinbounds);
{
var_result = CAST(value_int);
Goto(&out);
}
BIND(&if_isoutofbounds);
{
TNode<Smi> const zero = SmiConstant(0);
var_result =
SelectConstant<Smi>(SmiLessThan(value_smi, zero), zero, limit);
Goto(&out);
}
}
BIND(&if_isnotsmi);
{
// {value} is a heap number - in this case, it is definitely out of bounds.
TNode<HeapNumber> value_int_hn = CAST(value_int);
TNode<Float64T> const float_zero = Float64Constant(0.);
TNode<Smi> const smi_zero = SmiConstant(0);
TNode<Float64T> const value_float = LoadHeapNumberValue(value_int_hn);
var_result = SelectConstant<Smi>(Float64LessThan(value_float, float_zero),
smi_zero, limit);
Goto(&out);
}
BIND(&out);
return var_result.value();
}
TF_BUILTIN(StringSubstring, CodeStubAssembler) {
TNode<String> string = CAST(Parameter(Descriptor::kString));
TNode<IntPtrT> from = UncheckedCast<IntPtrT>(Parameter(Descriptor::kFrom));
@ -1978,61 +1928,6 @@ TF_BUILTIN(StringSubstring, CodeStubAssembler) {
Return(SubString(string, from, to));
}
// ES6 #sec-string.prototype.substring
TF_BUILTIN(StringPrototypeSubstring, StringBuiltinsAssembler) {
const int kStartArg = 0;
const int kEndArg = 1;
Node* const argc =
ChangeInt32ToIntPtr(Parameter(Descriptor::kJSActualArgumentsCount));
CodeStubArguments args(this, argc);
TNode<Object> receiver = args.GetReceiver();
TNode<Object> start = args.GetOptionalArgumentValue(kStartArg);
TNode<Object> end = args.GetOptionalArgumentValue(kEndArg);
TNode<Context> context = CAST(Parameter(Descriptor::kContext));
Label out(this);
TVARIABLE(Smi, var_start);
TVARIABLE(Smi, var_end);
// Check that {receiver} is coercible to Object and convert it to a String.
TNode<String> const string =
ToThisString(context, receiver, "String.prototype.substring");
TNode<Smi> const length = LoadStringLengthAsSmi(string);
// Conversion and bounds-checks for {start}.
var_start = ToSmiBetweenZeroAnd(context, start, length);
// Conversion and bounds-checks for {end}.
{
var_end = length;
GotoIf(IsUndefined(end), &out);
var_end = ToSmiBetweenZeroAnd(context, end, length);
Label if_endislessthanstart(this);
Branch(SmiLessThan(var_end.value(), var_start.value()),
&if_endislessthanstart, &out);
BIND(&if_endislessthanstart);
{
TNode<Smi> const tmp = var_end.value();
var_end = var_start.value();
var_start = tmp;
Goto(&out);
}
}
BIND(&out);
{
args.PopAndReturn(SubString(string, SmiUntag(var_start.value()),
SmiUntag(var_end.value())));
}
}
// ES6 #sec-string.prototype.trim
TF_BUILTIN(StringPrototypeTrim, StringTrimAssembler) {
TNode<IntPtrT> argc =

View File

@ -64,10 +64,6 @@ class StringBuiltinsAssembler : public CodeStubAssembler {
void GenerateStringRelationalComparison(Node* context, Node* left,
Node* right, Operation op);
TNode<Smi> ToSmiBetweenZeroAnd(SloppyTNode<Context> context,
SloppyTNode<Object> value,
SloppyTNode<Smi> limit);
typedef std::function<TNode<Object>(
TNode<String> receiver, TNode<IntPtrT> length, TNode<IntPtrT> index)>
StringAtAccessor;

View File

@ -0,0 +1,50 @@
// Copyright 2019 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
namespace string_substring {
extern macro SubString(String, intptr, intptr): String;
transitioning macro ToSmiBetweenZeroAnd(implicit context: Context)(
value: Object, limit: Smi): Smi {
const valueInt: Number =
ToInteger_Inline(context, value, kTruncateMinusZero);
typeswitch (valueInt) {
case (valueSmi: Smi): {
if (SmiAbove(valueSmi, limit)) {
return valueSmi < 0 ? 0 : limit;
}
return valueSmi;
}
// {value} is a heap number - in this case, it is definitely out of
// bounds.
case (hn: HeapNumber): {
const valueFloat: float64 = LoadHeapNumberValue(hn);
return valueFloat < 0. ? 0 : limit;
}
}
}
// ES6 #sec-string.prototype.substring
transitioning javascript builtin StringPrototypeSubstring(
implicit context: Context)(receiver: Object, ...arguments): String {
// Check that {receiver} is coercible to Object and convert it to a String.
const string: String = ToThisString(receiver, 'String.prototype.substring');
const length = string.length_smi;
// Conversion and bounds-checks for {start}.
let start: Smi = ToSmiBetweenZeroAnd(arguments[0], length);
// Conversion and bounds-checks for {end}.
let end: Smi = arguments[1] == Undefined ?
length :
ToSmiBetweenZeroAnd(arguments[1], length);
if (end < start) {
const tmp: Smi = end;
end = start;
start = tmp;
}
return SubString(string, SmiUntag(start), SmiUntag(end));
}
}