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

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

Issue 2798933003: [regexp] Properly handle HeapNumbers in AdvanceStringIndex (Closed)
Patch Set: Address comments 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
« no previous file with comments | « src/builtins/builtins-regexp-gen.h ('k') | test/mjsunit/regress/regress-6209.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 1517 matching lines...) Expand 10 before | Expand all | Expand 10 after
1528 1528
1529 // Return true iff exec matched successfully. 1529 // Return true iff exec matched successfully.
1530 Node* const result = 1530 Node* const result =
1531 SelectBooleanConstant(WordNotEqual(match_indices, NullConstant())); 1531 SelectBooleanConstant(WordNotEqual(match_indices, NullConstant()));
1532 Return(result); 1532 Return(result);
1533 } 1533 }
1534 } 1534 }
1535 1535
1536 Node* RegExpBuiltinsAssembler::AdvanceStringIndex(Node* const string, 1536 Node* RegExpBuiltinsAssembler::AdvanceStringIndex(Node* const string,
1537 Node* const index, 1537 Node* const index,
1538 Node* const is_unicode) { 1538 Node* const is_unicode,
1539 bool is_fastpath) {
1539 CSA_ASSERT(this, IsString(string)); 1540 CSA_ASSERT(this, IsString(string));
1540 // TODO(jgruber): Handle HeapNumber index. 1541 CSA_ASSERT(this, IsHeapNumberMap(LoadReceiverMap(index)));
1542 if (is_fastpath) CSA_ASSERT(this, TaggedIsPositiveSmi(index));
1543
1544 // TODO(jgruber): If index is a HeapNumber, assert that it is outside the
1545 // Smi range.
1541 1546
1542 // Default to last_index + 1. 1547 // Default to last_index + 1.
1543 Node* const index_plus_one = SmiAdd(index, SmiConstant(1)); 1548 Node* const index_plus_one = NumberInc(index);
1544 Variable var_result(this, MachineRepresentation::kTagged, index_plus_one); 1549 Variable var_result(this, MachineRepresentation::kTagged, index_plus_one);
1545 1550
1551 // Advancing the index has some subtle issues involving the distinction
1552 // between Smis and HeapNumbers. There's three cases:
1553 // * {index} is a Smi, {index_plus_one} is a Smi. The standard case.
1554 // * {index} is a Smi, {index_plus_one} overflows into a HeapNumber.
1555 // In this case we can return the result early, because
1556 // {index_plus_one} > {string}.length.
1557 // * {index} is a HeapNumber, {index_plus_one} is a HeapNumber. This can only
1558 // occur when {index} is outside the Smi range since we normalize
1559 // explicitly. Again we can return early.
1560 if (is_fastpath) {
1561 // Must be in Smi range on the fast path. We control the value of {index}
1562 // on all call-sites and can never exceed the length of the string.
1563 STATIC_ASSERT(String::kMaxLength + 2 < Smi::kMaxValue);
1564 CSA_ASSERT(this, TaggedIsPositiveSmi(index_plus_one));
1565 }
1566
1546 Label if_isunicode(this), out(this); 1567 Label if_isunicode(this), out(this);
1547 Branch(is_unicode, &if_isunicode, &out); 1568 GotoIfNot(is_unicode, &out);
1569
1570 // Keep this unconditional (even on the fast path) just to be safe.
1571 Branch(TaggedIsPositiveSmi(index_plus_one), &if_isunicode, &out);
1548 1572
1549 BIND(&if_isunicode); 1573 BIND(&if_isunicode);
1550 { 1574 {
1551 Node* const string_length = LoadStringLength(string); 1575 Node* const string_length = LoadStringLength(string);
1552 GotoIfNot(SmiLessThan(index_plus_one, string_length), &out); 1576 GotoIfNot(SmiLessThan(index_plus_one, string_length), &out);
1553 1577
1554 Node* const lead = StringCharCodeAt(string, index); 1578 Node* const lead = StringCharCodeAt(string, index);
1555 GotoIfNot(Word32Equal(Word32And(lead, Int32Constant(0xFC00)), 1579 GotoIfNot(Word32Equal(Word32And(lead, Int32Constant(0xFC00)),
1556 Int32Constant(0xD800)), 1580 Int32Constant(0xD800)),
1557 &out); 1581 &out);
1558 1582
1559 Node* const trail = StringCharCodeAt(string, index_plus_one); 1583 Node* const trail = StringCharCodeAt(string, index_plus_one);
1560 GotoIfNot(Word32Equal(Word32And(trail, Int32Constant(0xFC00)), 1584 GotoIfNot(Word32Equal(Word32And(trail, Int32Constant(0xFC00)),
1561 Int32Constant(0xDC00)), 1585 Int32Constant(0xDC00)),
1562 &out); 1586 &out);
1563 1587
1564 // At a surrogate pair, return index + 2. 1588 // At a surrogate pair, return index + 2.
1565 Node* const index_plus_two = SmiAdd(index, SmiConstant(2)); 1589 Node* const index_plus_two = NumberInc(index_plus_one);
1566 var_result.Bind(index_plus_two); 1590 var_result.Bind(index_plus_two);
1567 1591
1568 Goto(&out); 1592 Goto(&out);
1569 } 1593 }
1570 1594
1571 BIND(&out); 1595 BIND(&out);
1572 return var_result.value(); 1596 return var_result.value();
1573 } 1597 }
1574 1598
1575 namespace { 1599 namespace {
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after
1844 GotoIfNot(SmiEqual(match_length, smi_zero), &loop); 1868 GotoIfNot(SmiEqual(match_length, smi_zero), &loop);
1845 1869
1846 Node* last_index = LoadLastIndex(context, regexp, is_fastpath); 1870 Node* last_index = LoadLastIndex(context, regexp, is_fastpath);
1847 if (is_fastpath) { 1871 if (is_fastpath) {
1848 CSA_ASSERT(this, TaggedIsPositiveSmi(last_index)); 1872 CSA_ASSERT(this, TaggedIsPositiveSmi(last_index));
1849 } else { 1873 } else {
1850 last_index = CallBuiltin(Builtins::kToLength, context, last_index); 1874 last_index = CallBuiltin(Builtins::kToLength, context, last_index);
1851 } 1875 }
1852 1876
1853 Node* const new_last_index = 1877 Node* const new_last_index =
1854 AdvanceStringIndex(string, last_index, is_unicode); 1878 AdvanceStringIndex(string, last_index, is_unicode, is_fastpath);
1855 1879
1856 if (is_fastpath) { 1880 if (is_fastpath) {
1857 // 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
1858 // incremented to overflow the Smi range since the maximal string 1882 // incremented to overflow the Smi range since the maximal string
1859 // length is less than the maximal Smi value. 1883 // length is less than the maximal Smi value.
1860 STATIC_ASSERT(String::kMaxLength < Smi::kMaxValue); 1884 STATIC_ASSERT(String::kMaxLength < Smi::kMaxValue);
1861 CSA_ASSERT(this, TaggedIsPositiveSmi(new_last_index)); 1885 CSA_ASSERT(this, TaggedIsPositiveSmi(new_last_index));
1862 } 1886 }
1863 1887
1864 StoreLastIndex(context, regexp, new_last_index, is_fastpath); 1888 StoreLastIndex(context, regexp, new_last_index, is_fastpath);
(...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after
2162 2186
2163 // Advance index and continue if the match is empty. 2187 // Advance index and continue if the match is empty.
2164 { 2188 {
2165 Label next(this); 2189 Label next(this);
2166 2190
2167 GotoIfNot(SmiEqual(match_to, next_search_from), &next); 2191 GotoIfNot(SmiEqual(match_to, next_search_from), &next);
2168 GotoIfNot(SmiEqual(match_to, last_matched_until), &next); 2192 GotoIfNot(SmiEqual(match_to, last_matched_until), &next);
2169 2193
2170 Node* const is_unicode = FastFlagGetter(regexp, JSRegExp::kUnicode); 2194 Node* const is_unicode = FastFlagGetter(regexp, JSRegExp::kUnicode);
2171 Node* const new_next_search_from = 2195 Node* const new_next_search_from =
2172 AdvanceStringIndex(string, next_search_from, is_unicode); 2196 AdvanceStringIndex(string, next_search_from, is_unicode, true);
2173 var_next_search_from.Bind(new_next_search_from); 2197 var_next_search_from.Bind(new_next_search_from);
2174 Goto(&loop); 2198 Goto(&loop);
2175 2199
2176 BIND(&next); 2200 BIND(&next);
2177 } 2201 }
2178 2202
2179 // A valid match was found, add the new substring to the array. 2203 // A valid match was found, add the new substring to the array.
2180 { 2204 {
2181 Node* const from = last_matched_until; 2205 Node* const from = last_matched_until;
2182 Node* const to = match_from; 2206 Node* const to = match_from;
(...skipping 648 matching lines...) Expand 10 before | Expand all | Expand 10 after
2831 BIND(&if_matched); 2855 BIND(&if_matched);
2832 { 2856 {
2833 Node* result = 2857 Node* result =
2834 ConstructNewResultFromMatchInfo(context, regexp, match_indices, string); 2858 ConstructNewResultFromMatchInfo(context, regexp, match_indices, string);
2835 Return(result); 2859 Return(result);
2836 } 2860 }
2837 } 2861 }
2838 2862
2839 } // namespace internal 2863 } // namespace internal
2840 } // namespace v8 2864 } // namespace v8
OLDNEW
« no previous file with comments | « src/builtins/builtins-regexp-gen.h ('k') | test/mjsunit/regress/regress-6209.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698