Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(824)

Unified Diff: src/builtins/builtins-regexp.cc

Issue 2415663007: [regexp] RegExp.prototype.replace fast-paths (Closed)
Patch Set: Remove unused variable Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | src/runtime/runtime.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/builtins/builtins-regexp.cc
diff --git a/src/builtins/builtins-regexp.cc b/src/builtins/builtins-regexp.cc
index 80b16dbe160b83bf226aa9b959d87ba8c061f0da..1c2f331930401a6449dd35e96efaa56a47fd59af 100644
--- a/src/builtins/builtins-regexp.cc
+++ b/src/builtins/builtins-regexp.cc
@@ -750,6 +750,20 @@ BUILTIN(RegExpPrototypeSpeciesGetter) {
namespace {
+// Fast-path implementation for flag checks on an unmodified JSRegExp instance.
+compiler::Node* FastFlagGetter(CodeStubAssembler* a,
+ compiler::Node* const regexp,
+ JSRegExp::Flag flag) {
+ typedef compiler::Node Node;
+
+ Node* const smi_zero = a->SmiConstant(Smi::kZero);
+ Node* const flags = a->LoadObjectField(regexp, JSRegExp::kFlagsOffset);
+ Node* const mask = a->SmiConstant(Smi::FromInt(flag));
+ Node* const is_flag_set = a->WordNotEqual(a->WordAnd(flags, mask), smi_zero);
+
+ return is_flag_set;
+}
+
void Generate_FlagGetter(CodeStubAssembler* a, JSRegExp::Flag flag,
v8::Isolate::UseCounterFeature counter,
const char* method_name) {
@@ -760,7 +774,6 @@ void Generate_FlagGetter(CodeStubAssembler* a, JSRegExp::Flag flag,
Node* const context = a->Parameter(3);
Isolate* isolate = a->isolate();
- Node* const int_zero = a->IntPtrConstant(0);
// Check whether we have an unmodified regexp instance.
Label if_isunmodifiedjsregexp(a),
@@ -777,13 +790,8 @@ void Generate_FlagGetter(CodeStubAssembler* a, JSRegExp::Flag flag,
a->Bind(&if_isunmodifiedjsregexp);
{
// Refer to JSRegExp's flag property on the fast-path.
- Node* const flags_smi =
- a->LoadObjectField(receiver, JSRegExp::kFlagsOffset);
- Node* const flags_intptr = a->SmiUntag(flags_smi);
- Node* const mask = a->IntPtrConstant(flag);
- Node* const is_global =
- a->WordNotEqual(a->WordAnd(flags_intptr, mask), int_zero);
- a->Return(a->Select(is_global, a->TrueConstant(), a->FalseConstant()));
+ Node* const is_flag_set = FastFlagGetter(a, receiver, flag);
+ a->Return(a->Select(is_flag_set, a->TrueConstant(), a->FalseConstant()));
jgruber 2016/10/15 18:23:18 TODO(me): Is this equivalent to a->Return(is_flag_
Yang 2016/10/17 13:30:54 Pretty sure you need to use Select, which turns th
}
a->Bind(&if_isnotunmodifiedjsregexp);
@@ -1572,6 +1580,7 @@ void Builtins::Generate_RegExpPrototypeReplace(CodeStubAssembler* a) {
Node* const context = a->Parameter(5);
Node* const int_zero = a->IntPtrConstant(0);
+ Node* const smi_zero = a->SmiConstant(Smi::kZero);
// Ensure {receiver} is a JSReceiver.
Node* const map =
@@ -1592,7 +1601,7 @@ void Builtins::Generate_RegExpPrototypeReplace(CodeStubAssembler* a) {
Node* const regexp = receiver;
// 2. Is {replace_value} callable?
- Label checkreplacestring(a);
+ Label checkreplacestring(a), if_iscallable(a, Label::kDeferred);
a->GotoIf(a->TaggedIsSmi(replace_value), &checkreplacestring);
Node* const replace_value_map = a->LoadMap(replace_value);
@@ -1600,7 +1609,7 @@ void Builtins::Generate_RegExpPrototypeReplace(CodeStubAssembler* a) {
a->Word32Equal(a->Word32And(a->LoadMapBitField(replace_value_map),
a->Int32Constant(1 << Map::kIsCallable)),
a->Int32Constant(0)),
- &checkreplacestring, &runtime);
+ &checkreplacestring, &if_iscallable);
// 3. Does ToString({replace_value}) contain '$'?
a->Bind(&checkreplacestring);
@@ -1618,6 +1627,34 @@ void Builtins::Generate_RegExpPrototypeReplace(CodeStubAssembler* a) {
a->Return(ReplaceFastPath(a, context, regexp, string, replace_string));
}
+ // {regexp} is unmodified and {replace_value} is callable.
+ a->Bind(&if_iscallable);
+ {
+ Node* const replace_callable = replace_value;
+
+ // Check if the {regexp} is global.
+ Label if_isglobal(a), if_isnotglobal(a);
+ Node* const is_global = FastFlagGetter(a, regexp, JSRegExp::kGlobal);
+ a->Branch(is_global, &if_isglobal, &if_isnotglobal);
+
+ a->Bind(&if_isglobal);
+ {
+ FastStoreLastIndex(a, context, regexp, smi_zero);
+ Node* const result =
+ a->CallRuntime(Runtime::kStringReplaceGlobalRegExpWithFunction,
+ context, string, regexp, replace_callable);
+ a->Return(result);
+ }
+
+ a->Bind(&if_isnotglobal);
+ {
+ Node* const result =
+ a->CallRuntime(Runtime::kStringReplaceNonGlobalRegExpWithFunction,
+ context, string, regexp, replace_callable);
+ a->Return(result);
+ }
+ }
+
a->Bind(&runtime);
{
Node* const result = a->CallRuntime(Runtime::kRegExpReplace, context,
« no previous file with comments | « no previous file | src/runtime/runtime.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698