Chromium Code Reviews| Index: src/builtins/builtins-regexp-gen.cc |
| diff --git a/src/builtins/builtins-regexp-gen.cc b/src/builtins/builtins-regexp-gen.cc |
| index d87fdf600d9f23978f1eea03b0a4fa5ba3d329d0..85452d9e98b156f9e9ac3935a98ee91d3e6a3db3 100644 |
| --- a/src/builtins/builtins-regexp-gen.cc |
| +++ b/src/builtins/builtins-regexp-gen.cc |
| @@ -1528,20 +1528,57 @@ 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, IsHeapNumberMap(LoadReceiverMap(index))); |
|
Camillo Bruni
2017/04/06 15:10:57
nit: add IsNumber()
jgruber
2017/04/06 16:28:33
Acknowledged - pushing to a follow-up to keep this
|
| + if (is_fastpath) CSA_ASSERT(this, TaggedIsSmi(index)); |
|
Camillo Bruni
2017/04/06 15:10:57
This should probably be TaggedIsPositiveSmi(index)
jgruber
2017/04/06 16:28:33
Done.
|
| + Variable var_index(this, MachineRepresentation::kTagged, index); |
| + if (!is_fastpath) { |
| + // Slow Smi normalization. Binds var_index to a Smi representation if |
| + // {index} is in Smi range, and to a HeapNumber otherwise. |
| + Label next(this); |
| + GotoIf(TaggedIsSmi(index), &next); |
| + |
| + CSA_ASSERT(this, IsHeapNumber(index)); |
| + Node* const value = LoadHeapNumberValue(index); |
| + var_index.Bind(ChangeFloat64ToTagged(value)); |
| + Goto(&next); |
|
Camillo Bruni
2017/04/06 15:10:58
as discussed offline: probably not worth the effor
jgruber
2017/04/06 16:28:33
Done. I'll add a corresponding assert in a follow-
|
| + |
| + Bind(&next); |
| + } |
| + |
| // Default to last_index + 1. |
| - Node* const index_plus_one = SmiAdd(index, SmiConstant(1)); |
| + Node* const index_plus_one = NumberInc(var_index.value()); |
| 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, TaggedIsSmi(index_plus_one)); |
|
Camillo Bruni
2017/04/06 15:10:57
TaggedIsPositiveSmi(index_plus_one)
jgruber
2017/04/06 16:28:34
Done.
|
| + } |
| + |
| 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(TaggedIsSmi(index_plus_one), &if_isunicode, &out); |
|
jgruber
2017/04/06 16:28:33
Also changed this to TaggedIsPositiveSmi.
|
| Bind(&if_isunicode); |
| { |
| Node* const string_length = LoadStringLength(string); |
| GotoIfNot(SmiLessThan(index_plus_one, string_length), &out); |
| - Node* const lead = StringCharCodeAt(string, index); |
| + Node* const lead = StringCharCodeAt(string, var_index.value()); |
|
Camillo Bruni
2017/04/06 15:10:57
Please add CSA_ASSERT(this, TaggedIsPositiveSmi(in
jgruber
2017/04/06 16:28:33
Will do in a follow-up.
|
| GotoIfNot(Word32Equal(Word32And(lead, Int32Constant(0xFC00)), |
| Int32Constant(0xD800)), |
| &out); |
| @@ -1552,7 +1589,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); |
| @@ -1838,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 |
| @@ -2143,7 +2180,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); |