Skip to content

Commit

Permalink
[builtins] Proposed changes to reduce IsRegExp checks in String.p.mat…
Browse files Browse the repository at this point in the history
  • Loading branch information
peterwmwong committed Apr 17, 2018
1 parent b40cc63 commit 8430e46
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 67 deletions.
80 changes: 23 additions & 57 deletions src/builtins/builtins-regexp-gen.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1979,12 +1979,11 @@ TF_BUILTIN(RegExpPrototypeMatch, RegExpBuiltinsAssembler) {
}

TNode<Object> RegExpBuiltinsAssembler::MatchAllIterator(
TNode<Context> context, TNode<Context> native_context,
TNode<Object> maybe_regexp, TNode<String> string,
TNode<BoolT> is_fast_regexp, char const* method_name) {
TNode<Context> context, TNode<Context> native_context, TNode<Object> regexp,
TNode<String> string, TNode<BoolT> is_fast_regexp,
TNode<BoolT> create_internal_regexp) {
Label create_iterator(this), if_fast_regexp(this),
if_slow_regexp(this, Label::kDeferred), if_not_regexp(this),
throw_type_error(this, Label::kDeferred);
if_slow_regexp(this, Label::kDeferred);

// 1. Let S be ? ToString(O).
// Handled by the caller of MatchAllIterator.
Expand All @@ -1995,18 +1994,21 @@ TNode<Object> RegExpBuiltinsAssembler::MatchAllIterator(
TVARIABLE(Int32T, var_unicode);

// 2. If ? IsRegExp(R) is true, then
GotoIf(is_fast_regexp, &if_fast_regexp);
Branch(IsRegExp(context, maybe_regexp), &if_slow_regexp, &if_not_regexp);
Branch(is_fast_regexp, &if_fast_regexp, &if_slow_regexp);
BIND(&if_fast_regexp);
{
CSA_ASSERT(this, IsFastRegExp(context, maybe_regexp));
TNode<JSRegExp> fast_regexp = CAST(maybe_regexp);
TNode<Object> source =
LoadObjectField(fast_regexp, JSRegExp::kSourceOffset);
TNode<String> flags = CAST(FlagsGetter(context, fast_regexp, true));
CSA_ASSERT(this, IsFastRegExp(context, regexp));

// c. Let matcher be ? Construct(C, « R, flags »).
var_matcher = RegExpCreate(context, native_context, source, flags);
var_matcher = Select<Object>(
create_internal_regexp,
[&] {
TNode<Object> source =
LoadObjectField(CAST(regexp), JSRegExp::kSourceOffset);
TNode<String> flags = CAST(FlagsGetter(context, regexp, true));
return RegExpCreate(context, native_context, source, flags);
},
[&] { return regexp; });
CSA_ASSERT(this, IsFastRegExp(context, var_matcher.value()));

// d. Let global be ? ToBoolean(? Get(matcher, "global")).
Expand All @@ -2019,7 +2021,7 @@ TNode<Object> RegExpBuiltinsAssembler::MatchAllIterator(

// f. Let lastIndex be ? ToLength(? Get(R, "lastIndex")).
// g. Perform ? Set(matcher, "lastIndex", lastIndex, true).
FastStoreLastIndex(var_matcher.value(), FastLoadLastIndex(fast_regexp));
FastStoreLastIndex(var_matcher.value(), FastLoadLastIndex(regexp));
Goto(&create_iterator);
}
BIND(&if_slow_regexp);
Expand All @@ -2028,17 +2030,16 @@ TNode<Object> RegExpBuiltinsAssembler::MatchAllIterator(
TNode<Object> regexp_fun =
LoadContextElement(native_context, Context::REGEXP_FUNCTION_INDEX);
TNode<Object> species_constructor =
SpeciesConstructor(native_context, maybe_regexp, regexp_fun);
SpeciesConstructor(native_context, regexp, regexp_fun);

// b. Let flags be ? ToString(? Get(R, "flags")).
TNode<Object> flags = GetProperty(context, maybe_regexp,
isolate()->factory()->flags_string());
TNode<Object> flags =
GetProperty(context, regexp, isolate()->factory()->flags_string());
TNode<String> flags_string = ToString_Inline(context, flags);

// c. Let matcher be ? Construct(C, « R, flags »).
var_matcher =
CAST(ConstructJS(CodeFactory::Construct(isolate()), context,
species_constructor, maybe_regexp, flags_string));
var_matcher = CAST(ConstructJS(CodeFactory::Construct(isolate()), context,
species_constructor, regexp, flags_string));

// d. Let global be ? ToBoolean(? Get(matcher, "global")).
var_global = UncheckedCast<Int32T>(
Expand All @@ -2050,48 +2051,13 @@ TNode<Object> RegExpBuiltinsAssembler::MatchAllIterator(

// f. Let lastIndex be ? ToLength(? Get(R, "lastIndex")).
TNode<Number> last_index = UncheckedCast<Number>(
ToLength_Inline(context, SlowLoadLastIndex(context, maybe_regexp)));
ToLength_Inline(context, SlowLoadLastIndex(context, regexp)));

// g. Perform ? Set(matcher, "lastIndex", lastIndex, true).
SlowStoreLastIndex(context, var_matcher.value(), last_index);

Goto(&create_iterator);
}
// 3. Else,
BIND(&if_not_regexp);
{
// a. Let flags be "g".
// b. Let matcher be ? RegExpCreate(R, flags).
var_matcher = RegExpCreate(context, native_context, maybe_regexp,
StringConstant("g"));

// d. Let global be true.
var_global = Int32Constant(1);

// e. Let fullUnicode be false.
var_unicode = Int32Constant(0);

Label if_matcher_slow_regexp(this, Label::kDeferred);
BranchIfFastRegExp(context, var_matcher.value(), &create_iterator,
&if_matcher_slow_regexp);
BIND(&if_matcher_slow_regexp);
{
// c. If ? IsRegExp(matcher) is not true, throw a TypeError exception.
GotoIfNot(IsRegExp(context, var_matcher.value()), &throw_type_error);

// f. If ? Get(matcher, "lastIndex") is not 0, throw a TypeError
// exception.
TNode<Object> last_index =
CAST(LoadLastIndex(context, var_matcher.value(), false));
Branch(SmiEqual(SmiConstant(0), last_index), &create_iterator,
&throw_type_error);
}
}
BIND(&throw_type_error);
{
ThrowTypeError(context, MessageTemplate::kIncompatibleMethodReceiver,
StringConstant(method_name), maybe_regexp);
}
// 4. Return ! CreateRegExpStringIterator(matcher, S, global, fullUnicode).
// CreateRegExpStringIterator ( R, S, global, fullUnicode )
BIND(&create_iterator);
Expand Down Expand Up @@ -2164,7 +2130,7 @@ TF_BUILTIN(RegExpPrototypeMatchAll, RegExpBuiltinsAssembler) {
// 3. Return ? MatchAllIterator(R, string).
Return(MatchAllIterator(
context, native_context, receiver, ToString_Inline(context, string),
IsFastRegExp(context, receiver), "RegExp.prototype.@@matchAll"));
IsFastRegExp(context, receiver), Int32TrueConstant()));
}

// Helper that skips a few initial checks. and assumes...
Expand Down
10 changes: 5 additions & 5 deletions src/builtins/builtins-regexp-gen.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,11 @@ class RegExpBuiltinsAssembler : public CodeStubAssembler {
TNode<Context> native_context,
TNode<Object> regexp, TNode<String> string,
TNode<BoolT> is_fast_regexp,
char const* method_name);
TNode<BoolT> create_internal_regexp);

// Analogous to BranchIfFastRegExp, for use in asserts.
TNode<BoolT> IsFastRegExp(SloppyTNode<Context> context,
SloppyTNode<Object> object);

protected:
// Allocate a RegExpResult with the given length (the number of captures,
Expand Down Expand Up @@ -78,10 +82,6 @@ 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);
Expand Down
24 changes: 19 additions & 5 deletions src/builtins/builtins-string-gen.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1509,8 +1509,10 @@ TF_BUILTIN(StringPrototypeMatchAll, StringBuiltinsAssembler) {
// 2. If regexp is neither undefined nor null, then
Label return_match_all_iterator(this),
tostring_and_return_match_all_iterator(this, Label::kDeferred);
TVARIABLE(BoolT, var_is_fast_regexp);
TVARIABLE(Object, var_regexp);
TVARIABLE(String, var_receiver_string);
TVARIABLE(BoolT, var_is_fast_regexp);
TVARIABLE(BoolT, var_create_internal_regexp);
GotoIf(IsNullOrUndefined(maybe_regexp),
&tostring_and_return_match_all_iterator);
{
Expand All @@ -1521,8 +1523,10 @@ TF_BUILTIN(StringPrototypeMatchAll, StringBuiltinsAssembler) {
// 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_regexp = maybe_regexp;
var_receiver_string = CAST(receiver);
var_is_fast_regexp = Int32TrueConstant();
var_create_internal_regexp = Int32TrueConstant();
Goto(&return_match_all_iterator);
};
auto if_generic_call = [=](Node* fn) {
Expand All @@ -1534,19 +1538,29 @@ TF_BUILTIN(StringPrototypeMatchAll, StringBuiltinsAssembler) {
if_regexp_call, if_generic_call);
Goto(&tostring_and_return_match_all_iterator);
}
RegExpBuiltinsAssembler regexp_asm(state());
BIND(&tostring_and_return_match_all_iterator);
{
// X 3. Let string be ? ToString(O).
var_receiver_string = ToString_Inline(context, receiver);
var_is_fast_regexp = Int32FalseConstant();
// X 4. Let rx be ? RegExpCreate(regexp, `"g"`).
var_regexp = regexp_asm.RegExpCreate(context, native_context, maybe_regexp,
StringConstant("g"));

ThrowIfNotJSReceiver(context, var_regexp.value(),
MessageTemplate::kFirstArgumentNotRegExp, method_name);

var_is_fast_regexp = regexp_asm.IsFastRegExp(context, var_regexp.value());
var_create_internal_regexp = Int32FalseConstant();
Goto(&return_match_all_iterator);
}
BIND(&return_match_all_iterator);
{
// 3. Return ? MatchAllIterator(regexp, O).
RegExpBuiltinsAssembler regexp_asm(state());
TNode<Object> iterator = regexp_asm.MatchAllIterator(
context, native_context, maybe_regexp, var_receiver_string.value(),
var_is_fast_regexp.value(), method_name);
context, native_context, var_regexp.value(),
var_receiver_string.value(), var_is_fast_regexp.value(),
var_create_internal_regexp.value());
Return(iterator);
}
}
Expand Down

0 comments on commit 8430e46

Please sign in to comment.