[string] Don't adapt arguments for split, substr & substring

Mechanical change to remove argument adaption (should be a tad faster
this way).

BUG=v8:6369

Change-Id: Ibc3dfa1161115e3feb5407615410c596698b5e44
Reviewed-on: https://chromium-review.googlesource.com/527440
Reviewed-by: Camillo Bruni <cbruni@chromium.org>
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#45896}
This commit is contained in:
jgruber 2017-06-08 16:29:09 +02:00 committed by Commit Bot
parent 9bdae1a13a
commit b0c70d55c1
5 changed files with 70 additions and 35 deletions

View File

@ -1812,11 +1812,11 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
SimpleInstallFunction(prototype, "slice", Builtins::kStringPrototypeSlice,
2, false);
SimpleInstallFunction(prototype, "split", Builtins::kStringPrototypeSplit,
2, true);
2, false);
SimpleInstallFunction(prototype, "substr", Builtins::kStringPrototypeSubstr,
2, true);
2, false);
SimpleInstallFunction(prototype, "substring",
Builtins::kStringPrototypeSubstring, 2, true);
Builtins::kStringPrototypeSubstring, 2, false);
SimpleInstallFunction(prototype, "startsWith",
Builtins::kStringPrototypeStartsWith, 1, false);
SimpleInstallFunction(prototype, "toString",

View File

@ -899,11 +899,12 @@ namespace internal {
/* ES6 #sec-string.prototype.slice */ \
TFJ(StringPrototypeSlice, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
/* ES6 #sec-string.prototype.split */ \
TFJ(StringPrototypeSplit, 2, kSeparator, kLimit) \
TFJ(StringPrototypeSplit, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
/* ES6 #sec-string.prototype.substr */ \
TFJ(StringPrototypeSubstr, 2, kStart, kLength) \
TFJ(StringPrototypeSubstr, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
/* ES6 #sec-string.prototype.substring */ \
TFJ(StringPrototypeSubstring, 2, kStart, kEnd) \
TFJ(StringPrototypeSubstring, \
SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
/* ES6 #sec-string.prototype.startswith */ \
CPP(StringPrototypeStartsWith) \
/* ES6 #sec-string.prototype.tostring */ \

View File

@ -1006,7 +1006,8 @@ void StringBuiltinsAssembler::RequireObjectCoercible(Node* const context,
void StringBuiltinsAssembler::MaybeCallFunctionAtSymbol(
Node* const context, Node* const object, Handle<Symbol> symbol,
const NodeFunction0& regexp_call, const NodeFunction1& generic_call) {
const NodeFunction0& regexp_call, const NodeFunction1& generic_call,
CodeStubArguments* args) {
Label out(this);
// Smis definitely don't have an attached symbol.
@ -1044,7 +1045,12 @@ void StringBuiltinsAssembler::MaybeCallFunctionAtSymbol(
&slow_lookup);
BIND(&stub_call);
Return(regexp_call());
Node* const result = regexp_call();
if (args == nullptr) {
Return(result);
} else {
args->PopAndReturn(result);
}
BIND(&slow_lookup);
}
@ -1065,7 +1071,11 @@ void StringBuiltinsAssembler::MaybeCallFunctionAtSymbol(
// Attempt to call the function.
Node* const result = generic_call(maybe_func);
Return(result);
if (args == nullptr) {
Return(result);
} else {
args->PopAndReturn(result);
}
BIND(&out);
}
@ -1367,12 +1377,17 @@ TF_BUILTIN(StringPrototypeSlice, StringBuiltinsAssembler) {
// ES6 section 21.1.3.19 String.prototype.split ( separator, limit )
TF_BUILTIN(StringPrototypeSplit, StringBuiltinsAssembler) {
Label out(this);
const int kSeparatorArg = 0;
const int kLimitArg = 1;
Node* const receiver = Parameter(Descriptor::kReceiver);
Node* const separator = Parameter(Descriptor::kSeparator);
Node* const limit = Parameter(Descriptor::kLimit);
Node* const context = Parameter(Descriptor::kContext);
Node* const argc =
ChangeInt32ToIntPtr(Parameter(BuiltinDescriptor::kArgumentsCount));
CodeStubArguments args(this, argc);
Node* const receiver = args.GetReceiver();
Node* const separator = args.GetOptionalArgumentValue(kSeparatorArg);
Node* const limit = args.GetOptionalArgumentValue(kLimitArg);
Node* const context = Parameter(BuiltinDescriptor::kContext);
Node* const smi_zero = SmiConstant(0);
@ -1391,7 +1406,8 @@ TF_BUILTIN(StringPrototypeSplit, StringBuiltinsAssembler) {
[=](Node* fn) {
Callable call_callable = CodeFactory::Call(isolate());
return CallJS(call_callable, context, fn, separator, receiver, limit);
});
},
&args);
// String and integer conversions.
@ -1415,7 +1431,7 @@ TF_BUILTIN(StringPrototypeSplit, StringBuiltinsAssembler) {
Node* const capacity = IntPtrConstant(0);
Node* const result = AllocateJSArray(kind, array_map, capacity, length);
Return(result);
args.PopAndReturn(result);
BIND(&next);
}
@ -1437,7 +1453,7 @@ TF_BUILTIN(StringPrototypeSplit, StringBuiltinsAssembler) {
Node* const fixed_array = LoadElements(result);
StoreFixedArrayElement(fixed_array, 0, subject_string);
Return(result);
args.PopAndReturn(result);
BIND(&next);
}
@ -1449,7 +1465,7 @@ TF_BUILTIN(StringPrototypeSplit, StringBuiltinsAssembler) {
Node* const result = CallRuntime(Runtime::kStringToArray, context,
subject_string, limit_number);
Return(result);
args.PopAndReturn(result);
BIND(&next);
}
@ -1457,21 +1473,28 @@ TF_BUILTIN(StringPrototypeSplit, StringBuiltinsAssembler) {
Node* const result =
CallRuntime(Runtime::kStringSplit, context, subject_string,
separator_string, limit_number);
Return(result);
args.PopAndReturn(result);
}
// ES6 #sec-string.prototype.substr
TF_BUILTIN(StringPrototypeSubstr, StringBuiltinsAssembler) {
const int kStartArg = 0;
const int kLengthArg = 1;
Node* const argc =
ChangeInt32ToIntPtr(Parameter(BuiltinDescriptor::kArgumentsCount));
CodeStubArguments args(this, argc);
Node* const receiver = args.GetReceiver();
Node* const start = args.GetOptionalArgumentValue(kStartArg);
Node* const length = args.GetOptionalArgumentValue(kLengthArg);
Node* const context = Parameter(BuiltinDescriptor::kContext);
Label out(this);
VARIABLE(var_start, MachineRepresentation::kTagged);
VARIABLE(var_length, MachineRepresentation::kTagged);
Node* const receiver = Parameter(Descriptor::kReceiver);
Node* const start = Parameter(Descriptor::kStart);
Node* const length = Parameter(Descriptor::kLength);
Node* const context = Parameter(Descriptor::kContext);
Node* const zero = SmiConstant(Smi::kZero);
// Check that {receiver} is coercible to Object and convert it to a String.
@ -1512,7 +1535,7 @@ TF_BUILTIN(StringPrototypeSubstr, StringBuiltinsAssembler) {
var_length.Bind(SmiMin(positive_length, minimal_length));
GotoIfNot(SmiLessThanOrEqual(var_length.value(), zero), &out);
Return(EmptyStringConstant());
args.PopAndReturn(EmptyStringConstant());
}
BIND(&if_isheapnumber);
@ -1530,13 +1553,13 @@ TF_BUILTIN(StringPrototypeSubstr, StringBuiltinsAssembler) {
&if_ispositive);
BIND(&if_isnegative);
Return(EmptyStringConstant());
args.PopAndReturn(EmptyStringConstant());
BIND(&if_ispositive);
{
var_length.Bind(SmiSub(string_length, var_start.value()));
GotoIfNot(SmiLessThanOrEqual(var_length.value(), zero), &out);
Return(EmptyStringConstant());
args.PopAndReturn(EmptyStringConstant());
}
}
@ -1544,7 +1567,7 @@ TF_BUILTIN(StringPrototypeSubstr, StringBuiltinsAssembler) {
{
Node* const end = SmiAdd(var_start.value(), var_length.value());
Node* const result = SubString(context, string, var_start.value(), end);
Return(result);
args.PopAndReturn(result);
}
}
@ -1599,16 +1622,23 @@ compiler::Node* StringBuiltinsAssembler::ToSmiBetweenZeroAnd(Node* context,
// ES6 #sec-string.prototype.substring
TF_BUILTIN(StringPrototypeSubstring, StringBuiltinsAssembler) {
const int kStartArg = 0;
const int kEndArg = 1;
Node* const argc =
ChangeInt32ToIntPtr(Parameter(BuiltinDescriptor::kArgumentsCount));
CodeStubArguments args(this, argc);
Node* const receiver = args.GetReceiver();
Node* const start = args.GetOptionalArgumentValue(kStartArg);
Node* const end = args.GetOptionalArgumentValue(kEndArg);
Node* const context = Parameter(BuiltinDescriptor::kContext);
Label out(this);
VARIABLE(var_start, MachineRepresentation::kTagged);
VARIABLE(var_end, MachineRepresentation::kTagged);
Node* const receiver = Parameter(Descriptor::kReceiver);
Node* const start = Parameter(Descriptor::kStart);
Node* const end = Parameter(Descriptor::kEnd);
Node* const context = Parameter(Descriptor::kContext);
// Check that {receiver} is coercible to Object and convert it to a String.
Node* const string =
ToThisString(context, receiver, "String.prototype.substring");
@ -1642,7 +1672,7 @@ TF_BUILTIN(StringPrototypeSubstring, StringBuiltinsAssembler) {
{
Node* result =
SubString(context, string, var_start.value(), var_end.value());
Return(result);
args.PopAndReturn(result);
}
}

View File

@ -94,7 +94,8 @@ class StringBuiltinsAssembler : public CodeStubAssembler {
void MaybeCallFunctionAtSymbol(Node* const context, Node* const object,
Handle<Symbol> symbol,
const NodeFunction0& regexp_call,
const NodeFunction1& generic_call);
const NodeFunction1& generic_call,
CodeStubArguments* args = nullptr);
};
} // namespace internal

View File

@ -1551,6 +1551,9 @@ class CodeStubArguments {
Node* AtIndex(int index) const;
Node* GetOptionalArgumentValue(int index) {
return GetOptionalArgumentValue(index, assembler_->UndefinedConstant());
}
Node* GetOptionalArgumentValue(int index, Node* default_value);
Node* GetLength() const { return argc_; }