Chromium Code Reviews| 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 |