Index: src/builtins/builtins-regexp-gen.cc |
diff --git a/src/builtins/builtins-regexp-gen.cc b/src/builtins/builtins-regexp-gen.cc |
index 414e38d96b2cc73fad55c99245c7d09a60537523..eeb7b5ebebf8211411149c13a5652044b801c768 100644 |
--- a/src/builtins/builtins-regexp-gen.cc |
+++ b/src/builtins/builtins-regexp-gen.cc |
@@ -2295,13 +2295,23 @@ TF_BUILTIN(RegExpSplit, RegExpBuiltinsAssembler) { |
// been changed. |
// 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); |
+ Variable var_limit(this, MachineRepresentation::kTagged, maybe_limit); |
+ Label if_limitissmimax(this), limit_done(this), runtime(this); |
GotoIf(IsUndefined(maybe_limit), &if_limitissmimax); |
+ GotoIf(TaggedIsPositiveSmi(maybe_limit), &limit_done); |
+ Node* const limit = ToUint32(context, maybe_limit); |
{ |
- 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); |
+ Bind(&next); |
+ } |
+ |
GotoIfNot(TaggedIsSmi(limit), &if_limitissmimax); |
var_limit.Bind(limit); |
@@ -2321,6 +2331,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))); |
+ Return(CallRuntime(Runtime::kRegExpSplit, context, regexp, string, limit)); |
+ } |
} |
// ES#sec-regexp.prototype-@@split |
@@ -2692,6 +2710,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 = |