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, |