Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(536)

Side by Side Diff: src/builtins/builtins-regexp-gen.cc

Issue 2798933003: [regexp] Properly handle HeapNumbers in AdvanceStringIndex (Closed)
Patch Set: Rebase Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698