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

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

Issue 2808033002: [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
« no previous file with comments | « src/builtins/builtins-regexp.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 2016 the V8 project authors. All rights reserved. 1 // Copyright 2016 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.h" 5 #include "src/builtins/builtins-regexp.h"
6 6
7 #include "src/builtins/builtins-constructor.h" 7 #include "src/builtins/builtins-constructor.h"
8 #include "src/builtins/builtins-utils.h" 8 #include "src/builtins/builtins-utils.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 1304 matching lines...) Expand 10 before | Expand all | Expand 10 after
1315 1315
1316 // Return true iff exec matched successfully. 1316 // Return true iff exec matched successfully.
1317 Node* const result = 1317 Node* const result =
1318 SelectBooleanConstant(WordNotEqual(match_indices, NullConstant())); 1318 SelectBooleanConstant(WordNotEqual(match_indices, NullConstant()));
1319 Return(result); 1319 Return(result);
1320 } 1320 }
1321 } 1321 }
1322 1322
1323 Node* RegExpBuiltinsAssembler::AdvanceStringIndex(Node* const string, 1323 Node* RegExpBuiltinsAssembler::AdvanceStringIndex(Node* const string,
1324 Node* const index, 1324 Node* const index,
1325 Node* const is_unicode) { 1325 Node* const is_unicode,
1326 bool is_fastpath) {
1327 CSA_ASSERT(this, IsHeapNumberMap(LoadReceiverMap(index)));
1328 if (is_fastpath) CSA_ASSERT(this, TaggedIsPositiveSmi(index));
1329
1326 // Default to last_index + 1. 1330 // Default to last_index + 1.
1327 Node* const index_plus_one = SmiAdd(index, SmiConstant(1)); 1331 Node* const index_plus_one = NumberInc(index);
1328 Variable var_result(this, MachineRepresentation::kTagged, index_plus_one); 1332 Variable var_result(this, MachineRepresentation::kTagged, index_plus_one);
1329 1333
1334 // Advancing the index has some subtle issues involving the distinction
1335 // between Smis and HeapNumbers. There's three cases:
1336 // * {index} is a Smi, {index_plus_one} is a Smi. The standard case.
1337 // * {index} is a Smi, {index_plus_one} overflows into a HeapNumber.
1338 // In this case we can return the result early, because
1339 // {index_plus_one} > {string}.length.
1340 // * {index} is a HeapNumber, {index_plus_one} is a HeapNumber. This can only
1341 // occur when {index} is outside the Smi range since we normalize
1342 // explicitly. Again we can return early.
1343 if (is_fastpath) {
1344 // Must be in Smi range on the fast path. We control the value of {index}
1345 // on all call-sites and can never exceed the length of the string.
1346 STATIC_ASSERT(String::kMaxLength + 2 < Smi::kMaxValue);
1347 CSA_ASSERT(this, TaggedIsPositiveSmi(index_plus_one));
1348 }
1349
1330 Label if_isunicode(this), out(this); 1350 Label if_isunicode(this), out(this);
1331 Branch(is_unicode, &if_isunicode, &out); 1351 GotoIfNot(is_unicode, &out);
1352
1353 // Keep this unconditional (even on the fast path) just to be safe.
1354 Branch(TaggedIsPositiveSmi(index_plus_one), &if_isunicode, &out);
1332 1355
1333 Bind(&if_isunicode); 1356 Bind(&if_isunicode);
1334 { 1357 {
1335 Node* const string_length = LoadStringLength(string); 1358 Node* const string_length = LoadStringLength(string);
1336 GotoIfNot(SmiLessThan(index_plus_one, string_length), &out); 1359 GotoIfNot(SmiLessThan(index_plus_one, string_length), &out);
1337 1360
1338 Node* const lead = StringCharCodeAt(string, index); 1361 Node* const lead = StringCharCodeAt(string, index);
1339 GotoIfNot(Word32Equal(Word32And(lead, Int32Constant(0xFC00)), 1362 GotoIfNot(Word32Equal(Word32And(lead, Int32Constant(0xFC00)),
1340 Int32Constant(0xD800)), 1363 Int32Constant(0xD800)),
1341 &out); 1364 &out);
1342 1365
1343 Node* const trail = StringCharCodeAt(string, index_plus_one); 1366 Node* const trail = StringCharCodeAt(string, index_plus_one);
1344 GotoIfNot(Word32Equal(Word32And(trail, Int32Constant(0xFC00)), 1367 GotoIfNot(Word32Equal(Word32And(trail, Int32Constant(0xFC00)),
1345 Int32Constant(0xDC00)), 1368 Int32Constant(0xDC00)),
1346 &out); 1369 &out);
1347 1370
1348 // At a surrogate pair, return index + 2. 1371 // At a surrogate pair, return index + 2.
1349 Node* const index_plus_two = SmiAdd(index, SmiConstant(2)); 1372 Node* const index_plus_two = NumberInc(index_plus_one);
1350 var_result.Bind(index_plus_two); 1373 var_result.Bind(index_plus_two);
1351 1374
1352 Goto(&out); 1375 Goto(&out);
1353 } 1376 }
1354 1377
1355 Bind(&out); 1378 Bind(&out);
1356 return var_result.value(); 1379 return var_result.value();
1357 } 1380 }
1358 1381
1359 namespace { 1382 namespace {
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after
1628 1651
1629 Node* const match_length = LoadStringLength(match); 1652 Node* const match_length = LoadStringLength(match);
1630 GotoIfNot(SmiEqual(match_length, smi_zero), &loop); 1653 GotoIfNot(SmiEqual(match_length, smi_zero), &loop);
1631 1654
1632 Node* last_index = LoadLastIndex(context, regexp, is_fastpath); 1655 Node* last_index = LoadLastIndex(context, regexp, is_fastpath);
1633 1656
1634 Callable tolength_callable = CodeFactory::ToLength(isolate); 1657 Callable tolength_callable = CodeFactory::ToLength(isolate);
1635 last_index = CallStub(tolength_callable, context, last_index); 1658 last_index = CallStub(tolength_callable, context, last_index);
1636 1659
1637 Node* const new_last_index = 1660 Node* const new_last_index =
1638 AdvanceStringIndex(string, last_index, is_unicode); 1661 AdvanceStringIndex(string, last_index, is_unicode, is_fastpath);
1639 1662
1640 StoreLastIndex(context, regexp, new_last_index, is_fastpath); 1663 StoreLastIndex(context, regexp, new_last_index, is_fastpath);
1641 1664
1642 Goto(&loop); 1665 Goto(&loop);
1643 } 1666 }
1644 } 1667 }
1645 1668
1646 Bind(&out); 1669 Bind(&out);
1647 { 1670 {
1648 // Wrap the match in a JSArray. 1671 // Wrap the match in a JSArray.
(...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after
1932 1955
1933 // Advance index and continue if the match is empty. 1956 // Advance index and continue if the match is empty.
1934 { 1957 {
1935 Label next(this); 1958 Label next(this);
1936 1959
1937 GotoIfNot(SmiEqual(match_to, next_search_from), &next); 1960 GotoIfNot(SmiEqual(match_to, next_search_from), &next);
1938 GotoIfNot(SmiEqual(match_to, last_matched_until), &next); 1961 GotoIfNot(SmiEqual(match_to, last_matched_until), &next);
1939 1962
1940 Node* const is_unicode = FastFlagGetter(regexp, JSRegExp::kUnicode); 1963 Node* const is_unicode = FastFlagGetter(regexp, JSRegExp::kUnicode);
1941 Node* const new_next_search_from = 1964 Node* const new_next_search_from =
1942 AdvanceStringIndex(string, next_search_from, is_unicode); 1965 AdvanceStringIndex(string, next_search_from, is_unicode, true);
1943 var_next_search_from.Bind(new_next_search_from); 1966 var_next_search_from.Bind(new_next_search_from);
1944 Goto(&loop); 1967 Goto(&loop);
1945 1968
1946 Bind(&next); 1969 Bind(&next);
1947 } 1970 }
1948 1971
1949 // A valid match was found, add the new substring to the array. 1972 // A valid match was found, add the new substring to the array.
1950 { 1973 {
1951 Node* const from = last_matched_until; 1974 Node* const from = last_matched_until;
1952 Node* const to = match_from; 1975 Node* const to = match_from;
(...skipping 615 matching lines...) Expand 10 before | Expand all | Expand 10 after
2568 Bind(&if_matched); 2591 Bind(&if_matched);
2569 { 2592 {
2570 Node* result = 2593 Node* result =
2571 ConstructNewResultFromMatchInfo(context, regexp, match_indices, string); 2594 ConstructNewResultFromMatchInfo(context, regexp, match_indices, string);
2572 Return(result); 2595 Return(result);
2573 } 2596 }
2574 } 2597 }
2575 2598
2576 } // namespace internal 2599 } // namespace internal
2577 } // namespace v8 2600 } // namespace v8
OLDNEW
« no previous file with comments | « src/builtins/builtins-regexp.h ('k') | test/mjsunit/regress/regress-6209.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698