[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:
parent
9bdae1a13a
commit
b0c70d55c1
@ -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",
|
||||
|
@ -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 */ \
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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_; }
|
||||
|
Loading…
Reference in New Issue
Block a user