| Index: src/builtins/builtins-regexp-gen.cc
|
| diff --git a/src/builtins/builtins-regexp-gen.cc b/src/builtins/builtins-regexp-gen.cc
|
| index eeb7b5ebebf8211411149c13a5652044b801c768..a47e3e60186a1c2cff4c35f02f616fff83824e83 100644
|
| --- a/src/builtins/builtins-regexp-gen.cc
|
| +++ b/src/builtins/builtins-regexp-gen.cc
|
| @@ -1535,16 +1535,40 @@ TF_BUILTIN(RegExpPrototypeTest, RegExpBuiltinsAssembler) {
|
|
|
| Node* RegExpBuiltinsAssembler::AdvanceStringIndex(Node* const string,
|
| Node* const index,
|
| - Node* const is_unicode) {
|
| + Node* const is_unicode,
|
| + bool is_fastpath) {
|
| CSA_ASSERT(this, IsString(string));
|
| - // TODO(jgruber): Handle HeapNumber index.
|
| + CSA_ASSERT(this, IsHeapNumberMap(LoadReceiverMap(index)));
|
| + if (is_fastpath) CSA_ASSERT(this, TaggedIsPositiveSmi(index));
|
| +
|
| + // TODO(jgruber): If index is a HeapNumber, assert that it is outside the
|
| + // Smi range.
|
|
|
| // Default to last_index + 1.
|
| - Node* const index_plus_one = SmiAdd(index, SmiConstant(1));
|
| + Node* const index_plus_one = NumberInc(index);
|
| Variable var_result(this, MachineRepresentation::kTagged, index_plus_one);
|
|
|
| + // Advancing the index has some subtle issues involving the distinction
|
| + // between Smis and HeapNumbers. There's three cases:
|
| + // * {index} is a Smi, {index_plus_one} is a Smi. The standard case.
|
| + // * {index} is a Smi, {index_plus_one} overflows into a HeapNumber.
|
| + // In this case we can return the result early, because
|
| + // {index_plus_one} > {string}.length.
|
| + // * {index} is a HeapNumber, {index_plus_one} is a HeapNumber. This can only
|
| + // occur when {index} is outside the Smi range since we normalize
|
| + // explicitly. Again we can return early.
|
| + if (is_fastpath) {
|
| + // Must be in Smi range on the fast path. We control the value of {index}
|
| + // on all call-sites and can never exceed the length of the string.
|
| + STATIC_ASSERT(String::kMaxLength + 2 < Smi::kMaxValue);
|
| + CSA_ASSERT(this, TaggedIsPositiveSmi(index_plus_one));
|
| + }
|
| +
|
| Label if_isunicode(this), out(this);
|
| - Branch(is_unicode, &if_isunicode, &out);
|
| + GotoIfNot(is_unicode, &out);
|
| +
|
| + // Keep this unconditional (even on the fast path) just to be safe.
|
| + Branch(TaggedIsPositiveSmi(index_plus_one), &if_isunicode, &out);
|
|
|
| BIND(&if_isunicode);
|
| {
|
| @@ -1562,7 +1586,7 @@ Node* RegExpBuiltinsAssembler::AdvanceStringIndex(Node* const string,
|
| &out);
|
|
|
| // At a surrogate pair, return index + 2.
|
| - Node* const index_plus_two = SmiAdd(index, SmiConstant(2));
|
| + Node* const index_plus_two = NumberInc(index_plus_one);
|
| var_result.Bind(index_plus_two);
|
|
|
| Goto(&out);
|
| @@ -1851,7 +1875,7 @@ void RegExpBuiltinsAssembler::RegExpPrototypeMatchBody(Node* const context,
|
| }
|
|
|
| Node* const new_last_index =
|
| - AdvanceStringIndex(string, last_index, is_unicode);
|
| + AdvanceStringIndex(string, last_index, is_unicode, is_fastpath);
|
|
|
| if (is_fastpath) {
|
| // On the fast path, we can be certain that lastIndex can never be
|
| @@ -2169,7 +2193,7 @@ void RegExpBuiltinsAssembler::RegExpPrototypeSplitBody(Node* const context,
|
|
|
| Node* const is_unicode = FastFlagGetter(regexp, JSRegExp::kUnicode);
|
| Node* const new_next_search_from =
|
| - AdvanceStringIndex(string, next_search_from, is_unicode);
|
| + AdvanceStringIndex(string, next_search_from, is_unicode, true);
|
| var_next_search_from.Bind(new_next_search_from);
|
| Goto(&loop);
|
|
|
|
|