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

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

Issue 2577143002: [runtime] Add PositiveNumberToUint32 helper to avoid double to uint roundtrip (Closed)
Patch Set: avoid overflows Created 4 years 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/objects-inl.h ('k') | test/cctest/test-conversions.cc » ('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 2014 the V8 project authors. All rights reserved. 1 // Copyright 2014 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/runtime/runtime-utils.h" 5 #include "src/runtime/runtime-utils.h"
6 6
7 #include "src/arguments.h" 7 #include "src/arguments.h"
8 #include "src/conversions-inl.h" 8 #include "src/conversions-inl.h"
9 #include "src/isolate-inl.h" 9 #include "src/isolate-inl.h"
10 #include "src/messages.h" 10 #include "src/messages.h"
(...skipping 1372 matching lines...) Expand 10 before | Expand all | Expand 10 after
1383 Handle<Object> splitter_obj; 1383 Handle<Object> splitter_obj;
1384 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 1384 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1385 isolate, splitter_obj, Execution::New(ctor_fun, argc, argv.start())); 1385 isolate, splitter_obj, Execution::New(ctor_fun, argc, argv.start()));
1386 1386
1387 splitter = Handle<JSReceiver>::cast(splitter_obj); 1387 splitter = Handle<JSReceiver>::cast(splitter_obj);
1388 } 1388 }
1389 1389
1390 uint32_t limit; 1390 uint32_t limit;
1391 RETURN_FAILURE_ON_EXCEPTION(isolate, ToUint32(isolate, limit_obj, &limit)); 1391 RETURN_FAILURE_ON_EXCEPTION(isolate, ToUint32(isolate, limit_obj, &limit));
1392 1392
1393 const int length = string->length(); 1393 const uint32_t length = string->length();
1394 1394
1395 if (limit == 0) return *factory->NewJSArray(0); 1395 if (limit == 0) return *factory->NewJSArray(0);
1396 1396
1397 if (length == 0) { 1397 if (length == 0) {
1398 Handle<Object> result; 1398 Handle<Object> result;
1399 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 1399 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1400 isolate, result, RegExpUtils::RegExpExec(isolate, splitter, string, 1400 isolate, result, RegExpUtils::RegExpExec(isolate, splitter, string,
1401 factory->undefined_value())); 1401 factory->undefined_value()));
1402 1402
1403 if (!result->IsNull(isolate)) return *factory->NewJSArray(0); 1403 if (!result->IsNull(isolate)) return *factory->NewJSArray(0);
1404 1404
1405 Handle<FixedArray> elems = factory->NewUninitializedFixedArray(1); 1405 Handle<FixedArray> elems = factory->NewUninitializedFixedArray(1);
1406 elems->set(0, *string); 1406 elems->set(0, *string);
1407 return *factory->NewJSArrayWithElements(elems); 1407 return *factory->NewJSArrayWithElements(elems);
1408 } 1408 }
1409 1409
1410 static const int kInitialArraySize = 8; 1410 static const int kInitialArraySize = 8;
1411 Handle<FixedArray> elems = factory->NewFixedArrayWithHoles(kInitialArraySize); 1411 Handle<FixedArray> elems = factory->NewFixedArrayWithHoles(kInitialArraySize);
1412 int num_elems = 0; 1412 int num_elems = 0;
1413 1413
1414 int string_index = 0; 1414 uint32_t string_index = 0;
1415 int prev_string_index = 0; 1415 uint32_t prev_string_index = 0;
1416 while (string_index < length) { 1416 while (string_index < length) {
1417 RETURN_FAILURE_ON_EXCEPTION( 1417 RETURN_FAILURE_ON_EXCEPTION(
1418 isolate, RegExpUtils::SetLastIndex(isolate, splitter, string_index)); 1418 isolate, RegExpUtils::SetLastIndex(isolate, splitter, string_index));
1419 1419
1420 Handle<Object> result; 1420 Handle<Object> result;
1421 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 1421 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1422 isolate, result, RegExpUtils::RegExpExec(isolate, splitter, string, 1422 isolate, result, RegExpUtils::RegExpExec(isolate, splitter, string,
1423 factory->undefined_value())); 1423 factory->undefined_value()));
1424 1424
1425 if (result->IsNull(isolate)) { 1425 if (result->IsNull(isolate)) {
1426 string_index = RegExpUtils::AdvanceStringIndex(isolate, string, 1426 string_index = RegExpUtils::AdvanceStringIndex(isolate, string,
1427 string_index, unicode); 1427 string_index, unicode);
1428 continue; 1428 continue;
1429 } 1429 }
1430 1430
1431 Handle<Object> last_index_obj; 1431 Handle<Object> last_index_obj;
1432 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 1432 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1433 isolate, last_index_obj, RegExpUtils::GetLastIndex(isolate, splitter)); 1433 isolate, last_index_obj, RegExpUtils::GetLastIndex(isolate, splitter));
1434 1434
1435 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 1435 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1436 isolate, last_index_obj, Object::ToLength(isolate, last_index_obj)); 1436 isolate, last_index_obj, Object::ToLength(isolate, last_index_obj));
1437 const int last_index = Handle<Smi>::cast(last_index_obj)->value();
1438 1437
1439 const int end = std::min(last_index, length); 1438 const uint32_t end =
1439 std::min(PositiveNumberToUint32(*last_index_obj), length);
1440 if (end == prev_string_index) { 1440 if (end == prev_string_index) {
1441 string_index = RegExpUtils::AdvanceStringIndex(isolate, string, 1441 string_index = RegExpUtils::AdvanceStringIndex(isolate, string,
1442 string_index, unicode); 1442 string_index, unicode);
1443 continue; 1443 continue;
1444 } 1444 }
1445 1445
1446 { 1446 {
1447 Handle<String> substr = 1447 Handle<String> substr =
1448 factory->NewSubString(string, prev_string_index, string_index); 1448 factory->NewSubString(string, prev_string_index, string_index);
1449 elems = FixedArray::SetAndGrow(elems, num_elems++, substr); 1449 elems = FixedArray::SetAndGrow(elems, num_elems++, substr);
1450 if (static_cast<uint32_t>(num_elems) == limit) { 1450 if (static_cast<uint32_t>(num_elems) == limit) {
1451 return *NewJSArrayWithElements(isolate, elems, num_elems); 1451 return *NewJSArrayWithElements(isolate, elems, num_elems);
1452 } 1452 }
1453 } 1453 }
1454 1454
1455 prev_string_index = end; 1455 prev_string_index = end;
1456 1456
1457 Handle<Object> num_captures_obj; 1457 Handle<Object> num_captures_obj;
1458 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 1458 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1459 isolate, num_captures_obj, 1459 isolate, num_captures_obj,
1460 Object::GetProperty(result, isolate->factory()->length_string())); 1460 Object::GetProperty(result, isolate->factory()->length_string()));
1461 1461
1462 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 1462 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1463 isolate, num_captures_obj, Object::ToLength(isolate, num_captures_obj)); 1463 isolate, num_captures_obj, Object::ToLength(isolate, num_captures_obj));
1464 const int num_captures = 1464 const int num_captures = PositiveNumberToUint32(*num_captures_obj);
1465 std::max(Handle<Smi>::cast(num_captures_obj)->value(), 0);
1466 1465
1467 for (int i = 1; i < num_captures; i++) { 1466 for (int i = 1; i < num_captures; i++) {
1468 Handle<Object> capture; 1467 Handle<Object> capture;
1469 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 1468 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1470 isolate, capture, Object::GetElement(isolate, result, i)); 1469 isolate, capture, Object::GetElement(isolate, result, i));
1471 elems = FixedArray::SetAndGrow(elems, num_elems++, capture); 1470 elems = FixedArray::SetAndGrow(elems, num_elems++, capture);
1472 if (static_cast<uint32_t>(num_elems) == limit) { 1471 if (static_cast<uint32_t>(num_elems) == limit) {
1473 return *NewJSArrayWithElements(isolate, elems, num_elems); 1472 return *NewJSArrayWithElements(isolate, elems, num_elems);
1474 } 1473 }
1475 } 1474 }
(...skipping 25 matching lines...) Expand all
1501 1500
1502 string = String::Flatten(string); 1501 string = String::Flatten(string);
1503 1502
1504 // Fast-path for unmodified JSRegExps. 1503 // Fast-path for unmodified JSRegExps.
1505 if (RegExpUtils::IsUnmodifiedRegExp(isolate, recv)) { 1504 if (RegExpUtils::IsUnmodifiedRegExp(isolate, recv)) {
1506 RETURN_RESULT_OR_FAILURE( 1505 RETURN_RESULT_OR_FAILURE(
1507 isolate, RegExpReplace(isolate, Handle<JSRegExp>::cast(recv), string, 1506 isolate, RegExpReplace(isolate, Handle<JSRegExp>::cast(recv), string,
1508 replace_obj)); 1507 replace_obj));
1509 } 1508 }
1510 1509
1511 const int length = string->length(); 1510 const uint32_t length = string->length();
1512 const bool functional_replace = replace_obj->IsCallable(); 1511 const bool functional_replace = replace_obj->IsCallable();
1513 1512
1514 Handle<String> replace; 1513 Handle<String> replace;
1515 if (!functional_replace) { 1514 if (!functional_replace) {
1516 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, replace, 1515 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, replace,
1517 Object::ToString(isolate, replace_obj)); 1516 Object::ToString(isolate, replace_obj));
1518 } 1517 }
1519 1518
1520 Handle<Object> global_obj; 1519 Handle<Object> global_obj;
1521 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 1520 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
1558 Object::ToString(isolate, match_obj)); 1557 Object::ToString(isolate, match_obj));
1559 1558
1560 if (match->length() == 0) { 1559 if (match->length() == 0) {
1561 RETURN_FAILURE_ON_EXCEPTION(isolate, RegExpUtils::SetAdvancedStringIndex( 1560 RETURN_FAILURE_ON_EXCEPTION(isolate, RegExpUtils::SetAdvancedStringIndex(
1562 isolate, recv, string, unicode)); 1561 isolate, recv, string, unicode));
1563 } 1562 }
1564 } 1563 }
1565 1564
1566 // TODO(jgruber): Look into ReplacementStringBuilder instead. 1565 // TODO(jgruber): Look into ReplacementStringBuilder instead.
1567 IncrementalStringBuilder builder(isolate); 1566 IncrementalStringBuilder builder(isolate);
1568 int next_source_position = 0; 1567 uint32_t next_source_position = 0;
1569 1568
1570 for (const auto& result : results) { 1569 for (const auto& result : results) {
1571 Handle<Object> captures_length_obj; 1570 Handle<Object> captures_length_obj;
1572 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 1571 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1573 isolate, captures_length_obj, 1572 isolate, captures_length_obj,
1574 Object::GetProperty(result, factory->length_string())); 1573 Object::GetProperty(result, factory->length_string()));
1575 1574
1576 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 1575 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1577 isolate, captures_length_obj, 1576 isolate, captures_length_obj,
1578 Object::ToLength(isolate, captures_length_obj)); 1577 Object::ToLength(isolate, captures_length_obj));
1579 const int captures_length = 1578 const int captures_length = PositiveNumberToUint32(*captures_length_obj);
1580 std::max(Handle<Smi>::cast(captures_length_obj)->value(), 0);
1581 1579
1582 Handle<Object> match_obj; 1580 Handle<Object> match_obj;
1583 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, match_obj, 1581 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, match_obj,
1584 Object::GetElement(isolate, result, 0)); 1582 Object::GetElement(isolate, result, 0));
1585 1583
1586 Handle<String> match; 1584 Handle<String> match;
1587 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, match, 1585 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, match,
1588 Object::ToString(isolate, match_obj)); 1586 Object::ToString(isolate, match_obj));
1589 1587
1590 const int match_length = match->length(); 1588 const int match_length = match->length();
1591 1589
1592 Handle<Object> position_obj; 1590 Handle<Object> position_obj;
1593 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 1591 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1594 isolate, position_obj, 1592 isolate, position_obj,
1595 Object::GetProperty(result, factory->index_string())); 1593 Object::GetProperty(result, factory->index_string()));
1596 1594
1597 // TODO(jgruber): Extract and correct error handling. Since we can go up to 1595 // TODO(jgruber): Extract and correct error handling. Since we can go up to
1598 // 2^53 - 1 (at least for ToLength), we might actually need uint64_t here? 1596 // 2^53 - 1 (at least for ToLength), we might actually need uint64_t here?
1599 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 1597 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1600 isolate, position_obj, Object::ToInteger(isolate, position_obj)); 1598 isolate, position_obj, Object::ToInteger(isolate, position_obj));
1601 const int position = 1599 const uint32_t position =
1602 std::max(std::min(Handle<Smi>::cast(position_obj)->value(), length), 0); 1600 std::min(PositiveNumberToUint32(*position_obj), length);
1603 1601
1604 ZoneVector<Handle<Object>> captures(&zone); 1602 ZoneVector<Handle<Object>> captures(&zone);
1605 for (int n = 0; n < captures_length; n++) { 1603 for (int n = 0; n < captures_length; n++) {
1606 Handle<Object> capture; 1604 Handle<Object> capture;
1607 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 1605 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1608 isolate, capture, Object::GetElement(isolate, result, n)); 1606 isolate, capture, Object::GetElement(isolate, result, n));
1609 1607
1610 if (!capture->IsUndefined(isolate)) { 1608 if (!capture->IsUndefined(isolate)) {
1611 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, capture, 1609 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, capture,
1612 Object::ToString(isolate, capture)); 1610 Object::ToString(isolate, capture));
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
1680 1678
1681 RUNTIME_FUNCTION(Runtime_IsRegExp) { 1679 RUNTIME_FUNCTION(Runtime_IsRegExp) {
1682 SealHandleScope shs(isolate); 1680 SealHandleScope shs(isolate);
1683 DCHECK(args.length() == 1); 1681 DCHECK(args.length() == 1);
1684 CONVERT_ARG_CHECKED(Object, obj, 0); 1682 CONVERT_ARG_CHECKED(Object, obj, 0);
1685 return isolate->heap()->ToBoolean(obj->IsJSRegExp()); 1683 return isolate->heap()->ToBoolean(obj->IsJSRegExp());
1686 } 1684 }
1687 1685
1688 } // namespace internal 1686 } // namespace internal
1689 } // namespace v8 1687 } // namespace v8
OLDNEW
« no previous file with comments | « src/objects-inl.h ('k') | test/cctest/test-conversions.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698