| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |