[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}
This commit is contained in:
parent
261d750ea5
commit
e3222de330
@ -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;
|
||||
});
|
||||
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user