Commit ae4529f9 authored by peterwmwong's avatar peterwmwong Committed by Commit Bot

[builtins] Add fast paths to String.p.matchAll

Add fast paths when RegExp and RegExp result are fast wherever possible.

As shown below, this CL improves the performance of calling S.p.matchAll and
iterating over matches.

Before:

StringMatchAllBuiltinRegExpIteratorCreation-Strings(Score): 5002
StringMatchAllBuiltinStringIteratorCreation-Strings(Score): 13798
StringMatchAllBuiltinString-Strings(Score): 197
StringMatchAllManualString-Strings(Score): 454
StringMatchAllBuiltinRegExp-Strings(Score): 193
StringMatchAllManualRegExp-Strings(Score): 453
StringMatchAllBuiltinZeroWidth-Strings(Score): 97.2
StringMatchAllBuiltinZeroWidthUnicode-Strings(Score): 95.9

After:

StringMatchAllBuiltinRegExpIteratorCreation-Strings(Score): 15437
StringMatchAllBuiltinStringIteratorCreation-Strings(Score): 16708
StringMatchAllBuiltinString-Strings(Score): 392
StringMatchAllManualString-Strings(Score): 452
StringMatchAllBuiltinRegExp-Strings(Score): 394
StringMatchAllManualRegExp-Strings(Score): 484
StringMatchAllBuiltinZeroWidth-Strings(Score): 409
StringMatchAllBuiltinZeroWidthUnicode-Strings(Score): 413

Bug: v8:6890
Change-Id: I6fcc1003a471314cf412aac456d42286b2926810
Reviewed-on: https://chromium-review.googlesource.com/1005400
Commit-Queue: Peter Wong <peter.wm.wong@gmail.com>
Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Cr-Commit-Position: refs/heads/master@{#52581}
parent 4d7ad46d
This diff is collapsed.
......@@ -29,7 +29,8 @@ class RegExpBuiltinsAssembler : public CodeStubAssembler {
TNode<Object> MatchAllIterator(TNode<Context> context,
TNode<Context> native_context,
TNode<Object> regexp, TNode<Object> string,
TNode<Object> regexp, TNode<String> string,
TNode<BoolT> is_fast_regexp,
char const* method_name);
protected:
......@@ -77,13 +78,14 @@ class RegExpBuiltinsAssembler : public CodeStubAssembler {
MessageTemplate::Template msg_template,
char const* method_name);
// Analogous to BranchIfFastRegExp, for use in asserts.
TNode<BoolT> IsFastRegExp(SloppyTNode<Context> context,
SloppyTNode<Object> object);
void BranchIfFastRegExp(Node* const context, Node* const object,
Label* const if_isunmodified,
Label* const if_ismodified);
// Analogous to BranchIfFastRegExp, for use in asserts.
Node* IsFastRegExp(Node* const context, Node* const object);
// Performs fast path checks on the given object itself, but omits prototype
// checks.
Node* IsFastRegExpNoPrototype(Node* const context, Node* const object);
......@@ -104,6 +106,10 @@ class RegExpBuiltinsAssembler : public CodeStubAssembler {
int counter, const char* method_name);
Node* IsRegExp(Node* const context, Node* const maybe_receiver);
TNode<Object> LoadRegExpResultFirstMatch(SloppyTNode<Context> context,
SloppyTNode<JSObject> maybe_array);
Node* RegExpInitialize(Node* const context, Node* const regexp,
Node* const maybe_pattern, Node* const maybe_flags);
......
......@@ -1507,13 +1507,24 @@ TF_BUILTIN(StringPrototypeMatchAll, StringBuiltinsAssembler) {
RequireObjectCoercible(context, receiver, method_name);
// 2. If regexp is neither undefined nor null, then
Label return_match_all_iterator(this);
GotoIf(IsNullOrUndefined(maybe_regexp), &return_match_all_iterator);
Label return_match_all_iterator(this),
tostring_and_return_match_all_iterator(this, Label::kDeferred);
TVARIABLE(BoolT, var_is_fast_regexp);
TVARIABLE(String, var_receiver_string);
GotoIf(IsNullOrUndefined(maybe_regexp),
&tostring_and_return_match_all_iterator);
{
// a. Let matcher be ? GetMethod(regexp, @@matchAll).
// b. If matcher is not undefined, then
// i. Return ? Call(matcher, regexp, « O »).
auto if_regexp_call = [&] { Goto(&return_match_all_iterator); };
auto if_regexp_call = [&] {
// MaybeCallFunctionAtSymbol guarantees fast path is chosen only if
// maybe_regexp is a fast regexp and receiver is a string.
CSA_ASSERT(this, IsString(receiver));
var_receiver_string = CAST(receiver);
var_is_fast_regexp = Int32TrueConstant();
Goto(&return_match_all_iterator);
};
auto if_generic_call = [=](Node* fn) {
Callable call_callable = CodeFactory::Call(isolate());
Return(CallJS(call_callable, context, fn, maybe_regexp, receiver));
......@@ -1521,6 +1532,12 @@ TF_BUILTIN(StringPrototypeMatchAll, StringBuiltinsAssembler) {
MaybeCallFunctionAtSymbol(context, maybe_regexp, receiver,
isolate()->factory()->match_all_symbol(),
if_regexp_call, if_generic_call);
Goto(&tostring_and_return_match_all_iterator);
}
BIND(&tostring_and_return_match_all_iterator);
{
var_receiver_string = ToString_Inline(context, receiver);
var_is_fast_regexp = Int32FalseConstant();
Goto(&return_match_all_iterator);
}
BIND(&return_match_all_iterator);
......@@ -1528,7 +1545,8 @@ TF_BUILTIN(StringPrototypeMatchAll, StringBuiltinsAssembler) {
// 3. Return ? MatchAllIterator(regexp, O).
RegExpBuiltinsAssembler regexp_asm(state());
TNode<Object> iterator = regexp_asm.MatchAllIterator(
context, native_context, maybe_regexp, receiver, method_name);
context, native_context, maybe_regexp, var_receiver_string.value(),
var_is_fast_regexp.value(), method_name);
Return(iterator);
}
}
......
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