Commit b0c70d55 authored by jgruber's avatar jgruber Committed by Commit Bot

[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/527440Reviewed-by: 's avatarCamillo Bruni <cbruni@chromium.org>
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#45896}
parent 9bdae1a1
...@@ -1812,11 +1812,11 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object, ...@@ -1812,11 +1812,11 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
SimpleInstallFunction(prototype, "slice", Builtins::kStringPrototypeSlice, SimpleInstallFunction(prototype, "slice", Builtins::kStringPrototypeSlice,
2, false); 2, false);
SimpleInstallFunction(prototype, "split", Builtins::kStringPrototypeSplit, SimpleInstallFunction(prototype, "split", Builtins::kStringPrototypeSplit,
2, true); 2, false);
SimpleInstallFunction(prototype, "substr", Builtins::kStringPrototypeSubstr, SimpleInstallFunction(prototype, "substr", Builtins::kStringPrototypeSubstr,
2, true); 2, false);
SimpleInstallFunction(prototype, "substring", SimpleInstallFunction(prototype, "substring",
Builtins::kStringPrototypeSubstring, 2, true); Builtins::kStringPrototypeSubstring, 2, false);
SimpleInstallFunction(prototype, "startsWith", SimpleInstallFunction(prototype, "startsWith",
Builtins::kStringPrototypeStartsWith, 1, false); Builtins::kStringPrototypeStartsWith, 1, false);
SimpleInstallFunction(prototype, "toString", SimpleInstallFunction(prototype, "toString",
......
...@@ -899,11 +899,12 @@ namespace internal { ...@@ -899,11 +899,12 @@ namespace internal {
/* ES6 #sec-string.prototype.slice */ \ /* ES6 #sec-string.prototype.slice */ \
TFJ(StringPrototypeSlice, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \ TFJ(StringPrototypeSlice, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
/* ES6 #sec-string.prototype.split */ \ /* ES6 #sec-string.prototype.split */ \
TFJ(StringPrototypeSplit, 2, kSeparator, kLimit) \ TFJ(StringPrototypeSplit, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
/* ES6 #sec-string.prototype.substr */ \ /* ES6 #sec-string.prototype.substr */ \
TFJ(StringPrototypeSubstr, 2, kStart, kLength) \ TFJ(StringPrototypeSubstr, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
/* ES6 #sec-string.prototype.substring */ \ /* ES6 #sec-string.prototype.substring */ \
TFJ(StringPrototypeSubstring, 2, kStart, kEnd) \ TFJ(StringPrototypeSubstring, \
SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
/* ES6 #sec-string.prototype.startswith */ \ /* ES6 #sec-string.prototype.startswith */ \
CPP(StringPrototypeStartsWith) \ CPP(StringPrototypeStartsWith) \
/* ES6 #sec-string.prototype.tostring */ \ /* ES6 #sec-string.prototype.tostring */ \
......
...@@ -1006,7 +1006,8 @@ void StringBuiltinsAssembler::RequireObjectCoercible(Node* const context, ...@@ -1006,7 +1006,8 @@ void StringBuiltinsAssembler::RequireObjectCoercible(Node* const context,
void StringBuiltinsAssembler::MaybeCallFunctionAtSymbol( void StringBuiltinsAssembler::MaybeCallFunctionAtSymbol(
Node* const context, Node* const object, Handle<Symbol> symbol, 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); Label out(this);
// Smis definitely don't have an attached symbol. // Smis definitely don't have an attached symbol.
...@@ -1044,7 +1045,12 @@ void StringBuiltinsAssembler::MaybeCallFunctionAtSymbol( ...@@ -1044,7 +1045,12 @@ void StringBuiltinsAssembler::MaybeCallFunctionAtSymbol(
&slow_lookup); &slow_lookup);
BIND(&stub_call); BIND(&stub_call);
Return(regexp_call()); Node* const result = regexp_call();
if (args == nullptr) {
Return(result);
} else {
args->PopAndReturn(result);
}
BIND(&slow_lookup); BIND(&slow_lookup);
} }
...@@ -1065,7 +1071,11 @@ void StringBuiltinsAssembler::MaybeCallFunctionAtSymbol( ...@@ -1065,7 +1071,11 @@ void StringBuiltinsAssembler::MaybeCallFunctionAtSymbol(
// Attempt to call the function. // Attempt to call the function.
Node* const result = generic_call(maybe_func); Node* const result = generic_call(maybe_func);
if (args == nullptr) {
Return(result); Return(result);
} else {
args->PopAndReturn(result);
}
BIND(&out); BIND(&out);
} }
...@@ -1367,12 +1377,17 @@ TF_BUILTIN(StringPrototypeSlice, StringBuiltinsAssembler) { ...@@ -1367,12 +1377,17 @@ TF_BUILTIN(StringPrototypeSlice, StringBuiltinsAssembler) {
// ES6 section 21.1.3.19 String.prototype.split ( separator, limit ) // ES6 section 21.1.3.19 String.prototype.split ( separator, limit )
TF_BUILTIN(StringPrototypeSplit, StringBuiltinsAssembler) { TF_BUILTIN(StringPrototypeSplit, StringBuiltinsAssembler) {
Label out(this); const int kSeparatorArg = 0;
const int kLimitArg = 1;
Node* const receiver = Parameter(Descriptor::kReceiver); Node* const argc =
Node* const separator = Parameter(Descriptor::kSeparator); ChangeInt32ToIntPtr(Parameter(BuiltinDescriptor::kArgumentsCount));
Node* const limit = Parameter(Descriptor::kLimit); CodeStubArguments args(this, argc);
Node* const context = Parameter(Descriptor::kContext);
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); Node* const smi_zero = SmiConstant(0);
...@@ -1391,7 +1406,8 @@ TF_BUILTIN(StringPrototypeSplit, StringBuiltinsAssembler) { ...@@ -1391,7 +1406,8 @@ TF_BUILTIN(StringPrototypeSplit, StringBuiltinsAssembler) {
[=](Node* fn) { [=](Node* fn) {
Callable call_callable = CodeFactory::Call(isolate()); Callable call_callable = CodeFactory::Call(isolate());
return CallJS(call_callable, context, fn, separator, receiver, limit); return CallJS(call_callable, context, fn, separator, receiver, limit);
}); },
&args);
// String and integer conversions. // String and integer conversions.
...@@ -1415,7 +1431,7 @@ TF_BUILTIN(StringPrototypeSplit, StringBuiltinsAssembler) { ...@@ -1415,7 +1431,7 @@ TF_BUILTIN(StringPrototypeSplit, StringBuiltinsAssembler) {
Node* const capacity = IntPtrConstant(0); Node* const capacity = IntPtrConstant(0);
Node* const result = AllocateJSArray(kind, array_map, capacity, length); Node* const result = AllocateJSArray(kind, array_map, capacity, length);
Return(result); args.PopAndReturn(result);
BIND(&next); BIND(&next);
} }
...@@ -1437,7 +1453,7 @@ TF_BUILTIN(StringPrototypeSplit, StringBuiltinsAssembler) { ...@@ -1437,7 +1453,7 @@ TF_BUILTIN(StringPrototypeSplit, StringBuiltinsAssembler) {
Node* const fixed_array = LoadElements(result); Node* const fixed_array = LoadElements(result);
StoreFixedArrayElement(fixed_array, 0, subject_string); StoreFixedArrayElement(fixed_array, 0, subject_string);
Return(result); args.PopAndReturn(result);
BIND(&next); BIND(&next);
} }
...@@ -1449,7 +1465,7 @@ TF_BUILTIN(StringPrototypeSplit, StringBuiltinsAssembler) { ...@@ -1449,7 +1465,7 @@ TF_BUILTIN(StringPrototypeSplit, StringBuiltinsAssembler) {
Node* const result = CallRuntime(Runtime::kStringToArray, context, Node* const result = CallRuntime(Runtime::kStringToArray, context,
subject_string, limit_number); subject_string, limit_number);
Return(result); args.PopAndReturn(result);
BIND(&next); BIND(&next);
} }
...@@ -1457,21 +1473,28 @@ TF_BUILTIN(StringPrototypeSplit, StringBuiltinsAssembler) { ...@@ -1457,21 +1473,28 @@ TF_BUILTIN(StringPrototypeSplit, StringBuiltinsAssembler) {
Node* const result = Node* const result =
CallRuntime(Runtime::kStringSplit, context, subject_string, CallRuntime(Runtime::kStringSplit, context, subject_string,
separator_string, limit_number); separator_string, limit_number);
Return(result); args.PopAndReturn(result);
} }
// ES6 #sec-string.prototype.substr // ES6 #sec-string.prototype.substr
TF_BUILTIN(StringPrototypeSubstr, StringBuiltinsAssembler) { 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); Label out(this);
VARIABLE(var_start, MachineRepresentation::kTagged); VARIABLE(var_start, MachineRepresentation::kTagged);
VARIABLE(var_length, 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); Node* const zero = SmiConstant(Smi::kZero);
// 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.
...@@ -1512,7 +1535,7 @@ TF_BUILTIN(StringPrototypeSubstr, StringBuiltinsAssembler) { ...@@ -1512,7 +1535,7 @@ TF_BUILTIN(StringPrototypeSubstr, StringBuiltinsAssembler) {
var_length.Bind(SmiMin(positive_length, minimal_length)); var_length.Bind(SmiMin(positive_length, minimal_length));
GotoIfNot(SmiLessThanOrEqual(var_length.value(), zero), &out); GotoIfNot(SmiLessThanOrEqual(var_length.value(), zero), &out);
Return(EmptyStringConstant()); args.PopAndReturn(EmptyStringConstant());
} }
BIND(&if_isheapnumber); BIND(&if_isheapnumber);
...@@ -1530,13 +1553,13 @@ TF_BUILTIN(StringPrototypeSubstr, StringBuiltinsAssembler) { ...@@ -1530,13 +1553,13 @@ TF_BUILTIN(StringPrototypeSubstr, StringBuiltinsAssembler) {
&if_ispositive); &if_ispositive);
BIND(&if_isnegative); BIND(&if_isnegative);
Return(EmptyStringConstant()); args.PopAndReturn(EmptyStringConstant());
BIND(&if_ispositive); BIND(&if_ispositive);
{ {
var_length.Bind(SmiSub(string_length, var_start.value())); var_length.Bind(SmiSub(string_length, var_start.value()));
GotoIfNot(SmiLessThanOrEqual(var_length.value(), zero), &out); GotoIfNot(SmiLessThanOrEqual(var_length.value(), zero), &out);
Return(EmptyStringConstant()); args.PopAndReturn(EmptyStringConstant());
} }
} }
...@@ -1544,7 +1567,7 @@ TF_BUILTIN(StringPrototypeSubstr, StringBuiltinsAssembler) { ...@@ -1544,7 +1567,7 @@ TF_BUILTIN(StringPrototypeSubstr, StringBuiltinsAssembler) {
{ {
Node* const end = SmiAdd(var_start.value(), var_length.value()); Node* const end = SmiAdd(var_start.value(), var_length.value());
Node* const result = SubString(context, string, var_start.value(), end); 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, ...@@ -1599,16 +1622,23 @@ compiler::Node* StringBuiltinsAssembler::ToSmiBetweenZeroAnd(Node* context,
// ES6 #sec-string.prototype.substring // ES6 #sec-string.prototype.substring
TF_BUILTIN(StringPrototypeSubstring, StringBuiltinsAssembler) { 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); Label out(this);
VARIABLE(var_start, MachineRepresentation::kTagged); VARIABLE(var_start, MachineRepresentation::kTagged);
VARIABLE(var_end, 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. // Check that {receiver} is coercible to Object and convert it to a String.
Node* const string = Node* const string =
ToThisString(context, receiver, "String.prototype.substring"); ToThisString(context, receiver, "String.prototype.substring");
...@@ -1642,7 +1672,7 @@ TF_BUILTIN(StringPrototypeSubstring, StringBuiltinsAssembler) { ...@@ -1642,7 +1672,7 @@ TF_BUILTIN(StringPrototypeSubstring, StringBuiltinsAssembler) {
{ {
Node* result = Node* result =
SubString(context, string, var_start.value(), var_end.value()); SubString(context, string, var_start.value(), var_end.value());
Return(result); args.PopAndReturn(result);
} }
} }
......
...@@ -94,7 +94,8 @@ class StringBuiltinsAssembler : public CodeStubAssembler { ...@@ -94,7 +94,8 @@ class StringBuiltinsAssembler : public CodeStubAssembler {
void MaybeCallFunctionAtSymbol(Node* const context, Node* const object, void MaybeCallFunctionAtSymbol(Node* const context, Node* const object,
Handle<Symbol> symbol, Handle<Symbol> symbol,
const NodeFunction0& regexp_call, const NodeFunction0& regexp_call,
const NodeFunction1& generic_call); const NodeFunction1& generic_call,
CodeStubArguments* args = nullptr);
}; };
} // namespace internal } // namespace internal
......
...@@ -1551,6 +1551,9 @@ class CodeStubArguments { ...@@ -1551,6 +1551,9 @@ class CodeStubArguments {
Node* AtIndex(int index) const; Node* AtIndex(int index) const;
Node* GetOptionalArgumentValue(int index) {
return GetOptionalArgumentValue(index, assembler_->UndefinedConstant());
}
Node* GetOptionalArgumentValue(int index, Node* default_value); Node* GetOptionalArgumentValue(int index, Node* default_value);
Node* GetLength() const { return argc_; } Node* GetLength() const { return argc_; }
......
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