Index: src/builtins/builtins-regexp-gen.cc |
diff --git a/src/builtins/builtins-regexp-gen.cc b/src/builtins/builtins-regexp-gen.cc |
index 86772ecd398e0d66c9deddd94c8c156ad349758a..f9851bf42e0c07b8314d9bc7d3e93701dfcebe8e 100644 |
--- a/src/builtins/builtins-regexp-gen.cc |
+++ b/src/builtins/builtins-regexp-gen.cc |
@@ -2303,12 +2303,21 @@ TF_BUILTIN(RegExpSplit, RegExpBuiltinsAssembler) { |
// Convert {maybe_limit} to a uint32, capping at the maximal smi value. |
Variable var_limit(this, MachineRepresentation::kTagged); |
- Label if_limitissmimax(this), limit_done(this); |
+ Label if_limitissmimax(this), limit_done(this), runtime(this); |
GotoIf(IsUndefined(maybe_limit), &if_limitissmimax); |
+ Node* const limit = ToUint32(context, maybe_limit); |
Camillo Bruni
2017/04/06 14:54:15
future-nit: something like ToUint32(..., &was_fast
jgruber
2017/04/06 15:21:12
Sounds reasonable. I want to keep this CL small an
|
{ |
- Node* const limit = ToUint32(context, maybe_limit); |
+ // ToUint32(limit) could potentially change the shape of the RegExp |
+ // object. Recheck that we are still on the fast path and bail to runtime |
+ // otherwise. |
+ { |
+ Label next(this); |
+ BranchIfFastRegExp(context, regexp, LoadMap(regexp), &next, &runtime); |
Camillo Bruni
2017/04/06 14:54:15
site-note: You'd probably be better off with a Got
jgruber
2017/04/06 15:21:12
Acknowledged.
|
+ Bind(&next); |
+ } |
+ |
GotoIfNot(TaggedIsSmi(limit), &if_limitissmimax); |
var_limit.Bind(limit); |
@@ -2328,6 +2337,14 @@ TF_BUILTIN(RegExpSplit, RegExpBuiltinsAssembler) { |
Node* const limit = var_limit.value(); |
RegExpPrototypeSplitBody(context, regexp, string, limit); |
} |
+ |
+ Bind(&runtime); |
+ { |
+ // The runtime call passes in limit to ensure the second ToUint32(limit) |
+ // call is not observable. |
+ CSA_ASSERT(this, IsHeapNumberMap(LoadReceiverMap(limit))); |
Camillo Bruni
2017/04/06 14:54:15
nit: CSA_ASSERT(this, IsNumber(limit));
jgruber
2017/04/06 15:21:12
Can do in a follow-up (don't want to touch c-s-a.{
|
+ Return(CallRuntime(Runtime::kRegExpSplit, context, regexp, string, limit)); |
+ } |
} |
// ES#sec-regexp.prototype-@@split |
@@ -2699,6 +2716,15 @@ TF_BUILTIN(RegExpReplace, RegExpBuiltinsAssembler) { |
Node* const replace_string = |
CallBuiltin(Builtins::kToString, context, replace_value); |
+ // ToString(replaceValue) could potentially change the shape of the RegExp |
+ // object. Recheck that we are still on the fast path and bail to runtime |
+ // otherwise. |
+ { |
+ Label next(this); |
+ BranchIfFastRegExp(context, regexp, LoadMap(regexp), &next, &runtime); |
+ Bind(&next); |
+ } |
+ |
Node* const dollar_string = HeapConstant( |
isolate()->factory()->LookupSingleCharacterStringFromCode('$')); |
Node* const dollar_ix = |