Commit e3222de3 authored by jgruber's avatar jgruber Committed by Commit bot

[stubs] Port String.prototype.substring to TurboFan

BUG=v8:5415

Committed: https://crrev.com/cc37dff7ba21345b3a867a86127a208e34a3f707
Review-Url: https://codereview.chromium.org/2358133004
Cr-Original-Commit-Position: refs/heads/master@{#39717}
Cr-Commit-Position: refs/heads/master@{#39852}
parent 261d750e
......@@ -1404,6 +1404,8 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
Builtins::kStringPrototypeLocaleCompare, 1, true);
SimpleInstallFunction(prototype, "normalize",
Builtins::kStringPrototypeNormalize, 0, false);
SimpleInstallFunction(prototype, "substring",
Builtins::kStringPrototypeSubstring, 2, true);
SimpleInstallFunction(prototype, "toString",
Builtins::kStringPrototypeToString, 0, true);
SimpleInstallFunction(prototype, "trim", Builtins::kStringPrototypeTrim, 0,
......
......@@ -873,6 +873,116 @@ BUILTIN(StringPrototypeNormalize) {
return *string;
}
namespace {
compiler::Node* ToSmiBetweenZeroAnd(CodeStubAssembler* a,
compiler::Node* context,
compiler::Node* value,
compiler::Node* limit) {
typedef CodeStubAssembler::Label Label;
typedef compiler::Node Node;
typedef CodeStubAssembler::Variable Variable;
Label out(a);
Variable var_result(a, MachineRepresentation::kTagged);
Node* const value_int =
a->ToInteger(context, value, CodeStubAssembler::kTruncateMinusZero);
Label if_issmi(a), if_isnotsmi(a, Label::kDeferred);
a->Branch(a->WordIsSmi(value_int), &if_issmi, &if_isnotsmi);
a->Bind(&if_issmi);
{
Label if_isinbounds(a), if_isoutofbounds(a, Label::kDeferred);
a->Branch(a->SmiAbove(value_int, limit), &if_isoutofbounds, &if_isinbounds);
a->Bind(&if_isinbounds);
{
var_result.Bind(value_int);
a->Goto(&out);
}
a->Bind(&if_isoutofbounds);
{
Node* const zero = a->SmiConstant(Smi::FromInt(0));
var_result.Bind(a->Select(a->SmiLessThan(value_int, zero), zero, limit));
a->Goto(&out);
}
}
a->Bind(&if_isnotsmi);
{
// {value} is a heap number - in this case, it is definitely out of bounds.
a->Assert(a->WordEqual(a->LoadMap(value_int), a->HeapNumberMapConstant()));
Node* const float_zero = a->Float64Constant(0.);
Node* const smi_zero = a->SmiConstant(Smi::FromInt(0));
Node* const value_float = a->LoadHeapNumberValue(value_int);
var_result.Bind(a->Select(a->Float64LessThan(value_float, float_zero),
smi_zero, limit));
a->Goto(&out);
}
a->Bind(&out);
return var_result.value();
}
} // namespace
// ES6 section 21.1.3.19 String.prototype.substring ( start, end )
void Builtins::Generate_StringPrototypeSubstring(CodeStubAssembler* a) {
typedef CodeStubAssembler::Label Label;
typedef compiler::Node Node;
typedef CodeStubAssembler::Variable Variable;
Label out(a);
Variable var_start(a, MachineRepresentation::kTagged);
Variable var_end(a, MachineRepresentation::kTagged);
Node* const receiver = a->Parameter(0);
Node* const start = a->Parameter(1);
Node* const end = a->Parameter(2);
Node* const context = a->Parameter(5);
// Check that {receiver} is coercible to Object and convert it to a String.
Node* const string =
a->ToThisString(context, receiver, "String.prototype.substring");
Node* const length = a->LoadStringLength(string);
// Conversion and bounds-checks for {start}.
var_start.Bind(ToSmiBetweenZeroAnd(a, context, start, length));
// Conversion and bounds-checks for {end}.
{
var_end.Bind(length);
a->GotoIf(a->WordEqual(end, a->UndefinedConstant()), &out);
var_end.Bind(ToSmiBetweenZeroAnd(a, context, end, length));
Label if_endislessthanstart(a);
a->Branch(a->SmiLessThan(var_end.value(), var_start.value()),
&if_endislessthanstart, &out);
a->Bind(&if_endislessthanstart);
{
Node* const tmp = var_end.value();
var_end.Bind(var_start.value());
var_start.Bind(tmp);
a->Goto(&out);
}
}
a->Bind(&out);
{
Node* result =
a->SubString(context, string, var_start.value(), var_end.value());
a->Return(result);
}
}
// ES6 section 21.1.3.25 String.prototype.toString ()
void Builtins::Generate_StringPrototypeToString(CodeStubAssembler* assembler) {
typedef compiler::Node Node;
......
......@@ -553,6 +553,8 @@ namespace internal {
CPP(StringPrototypeLocaleCompare) \
/* ES6 section 21.1.3.12 String.prototype.normalize ( [form] ) */ \
CPP(StringPrototypeNormalize) \
/* ES6 section 21.1.3.19 String.prototype.substring ( start, end ) */ \
TFJ(StringPrototypeSubstring, 3) \
/* ES6 section 21.1.3.25 String.prototype.toString () */ \
TFJ(StringPrototypeToString, 1) \
CPP(StringPrototypeTrim) \
......
......@@ -35,7 +35,7 @@ var resolvedSymbol = utils.ImportNow("intl_resolved_symbol");
var SetFunctionName = utils.SetFunctionName;
var StringIndexOf;
var StringSubstr;
var StringSubstring;
var StringSubstring = GlobalString.prototype.substring;
utils.Import(function(from) {
ArrayJoin = from.ArrayJoin;
......@@ -44,7 +44,6 @@ utils.Import(function(from) {
InternalRegExpReplace = from.InternalRegExpReplace;
StringIndexOf = from.StringIndexOf;
StringSubstr = from.StringSubstr;
StringSubstring = from.StringSubstring;
});
// Utilities for definitions
......
......@@ -237,40 +237,6 @@ function StringSplitJS(separator, limit) {
return %StringSplit(subject, separator_string, limit);
}
// ECMA-262 section 15.5.4.15
function StringSubstring(start, end) {
CHECK_OBJECT_COERCIBLE(this, "String.prototype.subString");
var s = TO_STRING(this);
var s_len = s.length;
var start_i = TO_INTEGER(start);
if (start_i < 0) {
start_i = 0;
} else if (start_i > s_len) {
start_i = s_len;
}
var end_i = s_len;
if (!IS_UNDEFINED(end)) {
end_i = TO_INTEGER(end);
if (end_i > s_len) {
end_i = s_len;
} else {
if (end_i < 0) end_i = 0;
if (start_i > end_i) {
var tmp = end_i;
end_i = start_i;
start_i = tmp;
}
}
}
return %_SubString(s, start_i, end_i);
}
// ecma262/#sec-string.prototype.substr
function StringSubstr(start, length) {
CHECK_OBJECT_COERCIBLE(this, "String.prototype.substr");
......@@ -591,7 +557,6 @@ utils.InstallFunctions(GlobalString.prototype, DONT_ENUM, [
"search", StringSearch,
"slice", StringSlice,
"split", StringSplitJS,
"substring", StringSubstring,
"substr", StringSubstr,
"startsWith", StringStartsWith,
"toLowerCase", StringToLowerCaseJS,
......@@ -624,7 +589,6 @@ utils.Export(function(to) {
to.StringSlice = StringSlice;
to.StringSplit = StringSplitJS;
to.StringSubstr = StringSubstr;
to.StringSubstring = StringSubstring;
});
})
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