OLD | NEW |
---|---|
1 // Copyright 2017 the V8 project authors. All rights reserved. | 1 // Copyright 2017 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/builtins/builtins-regexp-gen.h" | 5 #include "src/builtins/builtins-regexp-gen.h" |
6 | 6 |
7 #include "src/builtins/builtins-constructor-gen.h" | 7 #include "src/builtins/builtins-constructor-gen.h" |
8 #include "src/builtins/builtins-utils-gen.h" | 8 #include "src/builtins/builtins-utils-gen.h" |
9 #include "src/builtins/builtins.h" | 9 #include "src/builtins/builtins.h" |
10 #include "src/code-factory.h" | 10 #include "src/code-factory.h" |
(...skipping 1510 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1521 | 1521 |
1522 // Return true iff exec matched successfully. | 1522 // Return true iff exec matched successfully. |
1523 Node* const result = | 1523 Node* const result = |
1524 SelectBooleanConstant(WordNotEqual(match_indices, NullConstant())); | 1524 SelectBooleanConstant(WordNotEqual(match_indices, NullConstant())); |
1525 Return(result); | 1525 Return(result); |
1526 } | 1526 } |
1527 } | 1527 } |
1528 | 1528 |
1529 Node* RegExpBuiltinsAssembler::AdvanceStringIndex(Node* const string, | 1529 Node* RegExpBuiltinsAssembler::AdvanceStringIndex(Node* const string, |
1530 Node* const index, | 1530 Node* const index, |
1531 Node* const is_unicode) { | 1531 Node* const is_unicode, |
1532 bool is_fastpath) { | |
1533 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
| |
1534 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.
| |
1535 Variable var_index(this, MachineRepresentation::kTagged, index); | |
1536 if (!is_fastpath) { | |
1537 // Slow Smi normalization. Binds var_index to a Smi representation if | |
1538 // {index} is in Smi range, and to a HeapNumber otherwise. | |
1539 Label next(this); | |
1540 GotoIf(TaggedIsSmi(index), &next); | |
1541 | |
1542 CSA_ASSERT(this, IsHeapNumber(index)); | |
1543 Node* const value = LoadHeapNumberValue(index); | |
1544 var_index.Bind(ChangeFloat64ToTagged(value)); | |
1545 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-
| |
1546 | |
1547 Bind(&next); | |
1548 } | |
1549 | |
1532 // Default to last_index + 1. | 1550 // Default to last_index + 1. |
1533 Node* const index_plus_one = SmiAdd(index, SmiConstant(1)); | 1551 Node* const index_plus_one = NumberInc(var_index.value()); |
1534 Variable var_result(this, MachineRepresentation::kTagged, index_plus_one); | 1552 Variable var_result(this, MachineRepresentation::kTagged, index_plus_one); |
1535 | 1553 |
1554 // Advancing the index has some subtle issues involving the distinction | |
1555 // between Smis and HeapNumbers. There's three cases: | |
1556 // * {index} is a Smi, {index_plus_one} is a Smi. The standard case. | |
1557 // * {index} is a Smi, {index_plus_one} overflows into a HeapNumber. | |
1558 // In this case we can return the result early, because | |
1559 // {index_plus_one} > {string}.length. | |
1560 // * {index} is a HeapNumber, {index_plus_one} is a HeapNumber. This can only | |
1561 // occur when {index} is outside the Smi range since we normalize | |
1562 // explicitly. Again we can return early. | |
1563 if (is_fastpath) { | |
1564 // Must be in Smi range on the fast path. We control the value of {index} | |
1565 // on all call-sites and can never exceed the length of the string. | |
1566 STATIC_ASSERT(String::kMaxLength + 2 < Smi::kMaxValue); | |
1567 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.
| |
1568 } | |
1569 | |
1536 Label if_isunicode(this), out(this); | 1570 Label if_isunicode(this), out(this); |
1537 Branch(is_unicode, &if_isunicode, &out); | 1571 GotoIfNot(is_unicode, &out); |
1572 | |
1573 // Keep this unconditional (even on the fast path) just to be safe. | |
1574 Branch(TaggedIsSmi(index_plus_one), &if_isunicode, &out); | |
jgruber
2017/04/06 16:28:33
Also changed this to TaggedIsPositiveSmi.
| |
1538 | 1575 |
1539 Bind(&if_isunicode); | 1576 Bind(&if_isunicode); |
1540 { | 1577 { |
1541 Node* const string_length = LoadStringLength(string); | 1578 Node* const string_length = LoadStringLength(string); |
1542 GotoIfNot(SmiLessThan(index_plus_one, string_length), &out); | 1579 GotoIfNot(SmiLessThan(index_plus_one, string_length), &out); |
1543 | 1580 |
1544 Node* const lead = StringCharCodeAt(string, index); | 1581 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.
| |
1545 GotoIfNot(Word32Equal(Word32And(lead, Int32Constant(0xFC00)), | 1582 GotoIfNot(Word32Equal(Word32And(lead, Int32Constant(0xFC00)), |
1546 Int32Constant(0xD800)), | 1583 Int32Constant(0xD800)), |
1547 &out); | 1584 &out); |
1548 | 1585 |
1549 Node* const trail = StringCharCodeAt(string, index_plus_one); | 1586 Node* const trail = StringCharCodeAt(string, index_plus_one); |
1550 GotoIfNot(Word32Equal(Word32And(trail, Int32Constant(0xFC00)), | 1587 GotoIfNot(Word32Equal(Word32And(trail, Int32Constant(0xFC00)), |
1551 Int32Constant(0xDC00)), | 1588 Int32Constant(0xDC00)), |
1552 &out); | 1589 &out); |
1553 | 1590 |
1554 // At a surrogate pair, return index + 2. | 1591 // At a surrogate pair, return index + 2. |
1555 Node* const index_plus_two = SmiAdd(index, SmiConstant(2)); | 1592 Node* const index_plus_two = NumberInc(index_plus_one); |
1556 var_result.Bind(index_plus_two); | 1593 var_result.Bind(index_plus_two); |
1557 | 1594 |
1558 Goto(&out); | 1595 Goto(&out); |
1559 } | 1596 } |
1560 | 1597 |
1561 Bind(&out); | 1598 Bind(&out); |
1562 return var_result.value(); | 1599 return var_result.value(); |
1563 } | 1600 } |
1564 | 1601 |
1565 namespace { | 1602 namespace { |
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1831 GotoIfNot(SmiEqual(match_length, smi_zero), &loop); | 1868 GotoIfNot(SmiEqual(match_length, smi_zero), &loop); |
1832 | 1869 |
1833 Node* last_index = LoadLastIndex(context, regexp, is_fastpath); | 1870 Node* last_index = LoadLastIndex(context, regexp, is_fastpath); |
1834 if (is_fastpath) { | 1871 if (is_fastpath) { |
1835 CSA_ASSERT(this, TaggedIsPositiveSmi(last_index)); | 1872 CSA_ASSERT(this, TaggedIsPositiveSmi(last_index)); |
1836 } else { | 1873 } else { |
1837 last_index = CallBuiltin(Builtins::kToLength, context, last_index); | 1874 last_index = CallBuiltin(Builtins::kToLength, context, last_index); |
1838 } | 1875 } |
1839 | 1876 |
1840 Node* const new_last_index = | 1877 Node* const new_last_index = |
1841 AdvanceStringIndex(string, last_index, is_unicode); | 1878 AdvanceStringIndex(string, last_index, is_unicode, is_fastpath); |
1842 | 1879 |
1843 if (is_fastpath) { | 1880 if (is_fastpath) { |
1844 // On the fast path, we can be certain that lastIndex can never be | 1881 // On the fast path, we can be certain that lastIndex can never be |
1845 // incremented to overflow the Smi range since the maximal string | 1882 // incremented to overflow the Smi range since the maximal string |
1846 // length is less than the maximal Smi value. | 1883 // length is less than the maximal Smi value. |
1847 STATIC_ASSERT(String::kMaxLength < Smi::kMaxValue); | 1884 STATIC_ASSERT(String::kMaxLength < Smi::kMaxValue); |
1848 CSA_ASSERT(this, TaggedIsPositiveSmi(new_last_index)); | 1885 CSA_ASSERT(this, TaggedIsPositiveSmi(new_last_index)); |
1849 } | 1886 } |
1850 | 1887 |
1851 StoreLastIndex(context, regexp, new_last_index, is_fastpath); | 1888 StoreLastIndex(context, regexp, new_last_index, is_fastpath); |
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2136 | 2173 |
2137 // Advance index and continue if the match is empty. | 2174 // Advance index and continue if the match is empty. |
2138 { | 2175 { |
2139 Label next(this); | 2176 Label next(this); |
2140 | 2177 |
2141 GotoIfNot(SmiEqual(match_to, next_search_from), &next); | 2178 GotoIfNot(SmiEqual(match_to, next_search_from), &next); |
2142 GotoIfNot(SmiEqual(match_to, last_matched_until), &next); | 2179 GotoIfNot(SmiEqual(match_to, last_matched_until), &next); |
2143 | 2180 |
2144 Node* const is_unicode = FastFlagGetter(regexp, JSRegExp::kUnicode); | 2181 Node* const is_unicode = FastFlagGetter(regexp, JSRegExp::kUnicode); |
2145 Node* const new_next_search_from = | 2182 Node* const new_next_search_from = |
2146 AdvanceStringIndex(string, next_search_from, is_unicode); | 2183 AdvanceStringIndex(string, next_search_from, is_unicode, true); |
2147 var_next_search_from.Bind(new_next_search_from); | 2184 var_next_search_from.Bind(new_next_search_from); |
2148 Goto(&loop); | 2185 Goto(&loop); |
2149 | 2186 |
2150 Bind(&next); | 2187 Bind(&next); |
2151 } | 2188 } |
2152 | 2189 |
2153 // A valid match was found, add the new substring to the array. | 2190 // A valid match was found, add the new substring to the array. |
2154 { | 2191 { |
2155 Node* const from = last_matched_until; | 2192 Node* const from = last_matched_until; |
2156 Node* const to = match_from; | 2193 Node* const to = match_from; |
(...skipping 610 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2767 Bind(&if_matched); | 2804 Bind(&if_matched); |
2768 { | 2805 { |
2769 Node* result = | 2806 Node* result = |
2770 ConstructNewResultFromMatchInfo(context, regexp, match_indices, string); | 2807 ConstructNewResultFromMatchInfo(context, regexp, match_indices, string); |
2771 Return(result); | 2808 Return(result); |
2772 } | 2809 } |
2773 } | 2810 } |
2774 | 2811 |
2775 } // namespace internal | 2812 } // namespace internal |
2776 } // namespace v8 | 2813 } // namespace v8 |
OLD | NEW |