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

Side by Side Diff: src/runtime.cc

Issue 9320: Semi-weekly merge from bleeding_edge to the toiger branch. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/toiger/
Patch Set: Created 12 years, 1 month 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 | Annotate | Revision Log
« no previous file with comments | « src/runtime.h ('k') | test/cctest/test-api.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 2006-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 951 matching lines...) Expand 10 before | Expand all | Expand 10 after
962 return *target; 962 return *target;
963 } 963 }
964 964
965 965
966 static Object* CharCodeAt(String* subject, Object* index) { 966 static Object* CharCodeAt(String* subject, Object* index) {
967 uint32_t i = 0; 967 uint32_t i = 0;
968 if (!Array::IndexFromObject(index, &i)) return Heap::nan_value(); 968 if (!Array::IndexFromObject(index, &i)) return Heap::nan_value();
969 // Flatten the string. If someone wants to get a char at an index 969 // Flatten the string. If someone wants to get a char at an index
970 // in a cons string, it is likely that more indices will be 970 // in a cons string, it is likely that more indices will be
971 // accessed. 971 // accessed.
972 subject->TryFlatten(); 972 StringShape shape(subject);
973 if (i >= static_cast<uint32_t>(subject->length())) return Heap::nan_value(); 973 subject->TryFlatten(shape); // shape no longer valid!
974 return Smi::FromInt(subject->Get(i)); 974 if (i >= static_cast<uint32_t>(subject->length(StringShape(subject)))) {
975 return Heap::nan_value();
976 }
977 return Smi::FromInt(subject->Get(StringShape(subject), i));
975 } 978 }
976 979
977 980
978 static Object* Runtime_StringCharCodeAt(Arguments args) { 981 static Object* Runtime_StringCharCodeAt(Arguments args) {
979 NoHandleAllocation ha; 982 NoHandleAllocation ha;
980 ASSERT(args.length() == 2); 983 ASSERT(args.length() == 2);
981 984
982 CONVERT_CHECKED(String, subject, args[0]); 985 CONVERT_CHECKED(String, subject, args[0]);
983 Object* index = args[1]; 986 Object* index = args[1];
984 return CharCodeAt(subject, index); 987 return CharCodeAt(subject, index);
(...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after
1344 return BoyerMooreIndexOf(sub, pat, idx); 1347 return BoyerMooreIndexOf(sub, pat, idx);
1345 } 1348 }
1346 1349
1347 // Perform string match of pattern on subject, starting at start index. 1350 // Perform string match of pattern on subject, starting at start index.
1348 // Caller must ensure that 0 <= start_index <= sub->length(), 1351 // Caller must ensure that 0 <= start_index <= sub->length(),
1349 // and should check that pat->length() + start_index <= sub->length() 1352 // and should check that pat->length() + start_index <= sub->length()
1350 int Runtime::StringMatch(Handle<String> sub, 1353 int Runtime::StringMatch(Handle<String> sub,
1351 Handle<String> pat, 1354 Handle<String> pat,
1352 int start_index) { 1355 int start_index) {
1353 ASSERT(0 <= start_index); 1356 ASSERT(0 <= start_index);
1354 ASSERT(start_index <= sub->length()); 1357 StringShape sub_shape(*sub);
1358 StringShape pat_shape(*pat);
1359 ASSERT(start_index <= sub->length(sub_shape));
1355 1360
1356 int pattern_length = pat->length(); 1361 int pattern_length = pat->length(pat_shape);
1357 if (pattern_length == 0) return start_index; 1362 if (pattern_length == 0) return start_index;
1358 1363
1359 int subject_length = sub->length(); 1364 int subject_length = sub->length(sub_shape);
1360 if (start_index + pattern_length > subject_length) return -1; 1365 if (start_index + pattern_length > subject_length) return -1;
1361 1366
1362 FlattenString(sub); 1367 if (!sub->IsFlat(sub_shape)) {
1368 FlattenString(sub);
1369 sub_shape = StringShape(*sub);
1370 }
1363 // Searching for one specific character is common. For one 1371 // Searching for one specific character is common. For one
1364 // character patterns linear search is necessary, so any smart 1372 // character patterns linear search is necessary, so any smart
1365 // algorithm is unnecessary overhead. 1373 // algorithm is unnecessary overhead.
1366 if (pattern_length == 1) { 1374 if (pattern_length == 1) {
1367 AssertNoAllocation no_heap_allocation; // ensure vectors stay valid 1375 AssertNoAllocation no_heap_allocation; // ensure vectors stay valid
1368 if (sub->is_ascii_representation()) { 1376 if (sub_shape.IsAsciiRepresentation()) {
1369 return SingleCharIndexOf(sub->ToAsciiVector(), pat->Get(0), start_index); 1377 return SingleCharIndexOf(sub->ToAsciiVector(),
1378 pat->Get(pat_shape, 0),
1379 start_index);
1370 } 1380 }
1371 return SingleCharIndexOf(sub->ToUC16Vector(), pat->Get(0), start_index); 1381 return SingleCharIndexOf(sub->ToUC16Vector(),
1382 pat->Get(pat_shape, 0),
1383 start_index);
1372 } 1384 }
1373 1385
1374 FlattenString(pat); 1386 if (!pat->IsFlat(pat_shape)) {
1387 FlattenString(pat);
1388 pat_shape = StringShape(*pat);
1389 }
1375 1390
1376 AssertNoAllocation no_heap_allocation; // ensure vectors stay valid 1391 AssertNoAllocation no_heap_allocation; // ensure vectors stay valid
1377 // dispatch on type of strings 1392 // dispatch on type of strings
1378 if (pat->is_ascii_representation()) { 1393 if (pat_shape.IsAsciiRepresentation()) {
1379 Vector<const char> pat_vector = pat->ToAsciiVector(); 1394 Vector<const char> pat_vector = pat->ToAsciiVector();
1380 if (sub->is_ascii_representation()) { 1395 if (sub_shape.IsAsciiRepresentation()) {
1381 return StringMatchStrategy(sub->ToAsciiVector(), pat_vector, start_index); 1396 return StringMatchStrategy(sub->ToAsciiVector(), pat_vector, start_index);
1382 } 1397 }
1383 return StringMatchStrategy(sub->ToUC16Vector(), pat_vector, start_index); 1398 return StringMatchStrategy(sub->ToUC16Vector(), pat_vector, start_index);
1384 } 1399 }
1385 Vector<const uc16> pat_vector = pat->ToUC16Vector(); 1400 Vector<const uc16> pat_vector = pat->ToUC16Vector();
1386 if (sub->is_ascii_representation()) { 1401 if (sub_shape.IsAsciiRepresentation()) {
1387 return StringMatchStrategy(sub->ToAsciiVector(), pat_vector, start_index); 1402 return StringMatchStrategy(sub->ToAsciiVector(), pat_vector, start_index);
1388 } 1403 }
1389 return StringMatchStrategy(sub->ToUC16Vector(), pat_vector, start_index); 1404 return StringMatchStrategy(sub->ToUC16Vector(), pat_vector, start_index);
1390 } 1405 }
1391 1406
1392 1407
1393 static Object* Runtime_StringIndexOf(Arguments args) { 1408 static Object* Runtime_StringIndexOf(Arguments args) {
1394 HandleScope scope; // create a new handle scope 1409 HandleScope scope; // create a new handle scope
1395 ASSERT(args.length() == 3); 1410 ASSERT(args.length() == 3);
1396 1411
(...skipping 11 matching lines...) Expand all
1408 1423
1409 1424
1410 static Object* Runtime_StringLastIndexOf(Arguments args) { 1425 static Object* Runtime_StringLastIndexOf(Arguments args) {
1411 NoHandleAllocation ha; 1426 NoHandleAllocation ha;
1412 ASSERT(args.length() == 3); 1427 ASSERT(args.length() == 3);
1413 1428
1414 CONVERT_CHECKED(String, sub, args[0]); 1429 CONVERT_CHECKED(String, sub, args[0]);
1415 CONVERT_CHECKED(String, pat, args[1]); 1430 CONVERT_CHECKED(String, pat, args[1]);
1416 Object* index = args[2]; 1431 Object* index = args[2];
1417 1432
1418 sub->TryFlatten(); 1433 sub->TryFlatten(StringShape(sub));
1419 pat->TryFlatten(); 1434 pat->TryFlatten(StringShape(pat));
1435
1436 StringShape sub_shape(sub);
1437 StringShape pat_shape(pat);
1420 1438
1421 uint32_t start_index; 1439 uint32_t start_index;
1422 if (!Array::IndexFromObject(index, &start_index)) return Smi::FromInt(-1); 1440 if (!Array::IndexFromObject(index, &start_index)) return Smi::FromInt(-1);
1423 1441
1424 uint32_t pattern_length = pat->length(); 1442 uint32_t pattern_length = pat->length(pat_shape);
1425 uint32_t sub_length = sub->length(); 1443 uint32_t sub_length = sub->length(sub_shape);
1426 1444
1427 if (start_index + pattern_length > sub_length) { 1445 if (start_index + pattern_length > sub_length) {
1428 start_index = sub_length - pattern_length; 1446 start_index = sub_length - pattern_length;
1429 } 1447 }
1430 1448
1431 for (int i = start_index; i >= 0; i--) { 1449 for (int i = start_index; i >= 0; i--) {
1432 bool found = true; 1450 bool found = true;
1433 for (uint32_t j = 0; j < pattern_length; j++) { 1451 for (uint32_t j = 0; j < pattern_length; j++) {
1434 if (sub->Get(i + j) != pat->Get(j)) { 1452 if (sub->Get(sub_shape, i + j) != pat->Get(pat_shape, j)) {
1435 found = false; 1453 found = false;
1436 break; 1454 break;
1437 } 1455 }
1438 } 1456 }
1439 if (found) return Smi::FromInt(i); 1457 if (found) return Smi::FromInt(i);
1440 } 1458 }
1441 1459
1442 return Smi::FromInt(-1); 1460 return Smi::FromInt(-1);
1443 } 1461 }
1444 1462
1445 1463
1446 static Object* Runtime_StringLocaleCompare(Arguments args) { 1464 static Object* Runtime_StringLocaleCompare(Arguments args) {
1447 NoHandleAllocation ha; 1465 NoHandleAllocation ha;
1448 ASSERT(args.length() == 2); 1466 ASSERT(args.length() == 2);
1449 1467
1450 CONVERT_CHECKED(String, str1, args[0]); 1468 CONVERT_CHECKED(String, str1, args[0]);
1451 CONVERT_CHECKED(String, str2, args[1]); 1469 CONVERT_CHECKED(String, str2, args[1]);
1452 1470
1453 if (str1 == str2) return Smi::FromInt(0); // Equal. 1471 if (str1 == str2) return Smi::FromInt(0); // Equal.
1454 int str1_length = str1->length(); 1472 StringShape shape1(str1);
1455 int str2_length = str2->length(); 1473 StringShape shape2(str2);
1474 int str1_length = str1->length(shape1);
1475 int str2_length = str2->length(shape2);
1456 1476
1457 // Decide trivial cases without flattening. 1477 // Decide trivial cases without flattening.
1458 if (str1_length == 0) { 1478 if (str1_length == 0) {
1459 if (str2_length == 0) return Smi::FromInt(0); // Equal. 1479 if (str2_length == 0) return Smi::FromInt(0); // Equal.
1460 return Smi::FromInt(-str2_length); 1480 return Smi::FromInt(-str2_length);
1461 } else { 1481 } else {
1462 if (str2_length == 0) return Smi::FromInt(str1_length); 1482 if (str2_length == 0) return Smi::FromInt(str1_length);
1463 } 1483 }
1464 1484
1465 int end = str1_length < str2_length ? str1_length : str2_length; 1485 int end = str1_length < str2_length ? str1_length : str2_length;
1466 1486
1467 // No need to flatten if we are going to find the answer on the first 1487 // No need to flatten if we are going to find the answer on the first
1468 // character. At this point we know there is at least one character 1488 // character. At this point we know there is at least one character
1469 // in each string, due to the trivial case handling above. 1489 // in each string, due to the trivial case handling above.
1470 int d = str1->Get(0) - str2->Get(0); 1490 int d = str1->Get(shape1, 0) - str2->Get(shape2, 0);
1471 if (d != 0) return Smi::FromInt(d); 1491 if (d != 0) return Smi::FromInt(d);
1472 1492
1473 str1->TryFlatten(); 1493 str1->TryFlatten(shape1); // Shapes are no longer valid now!
1474 str2->TryFlatten(); 1494 str2->TryFlatten(shape2);
1475 1495
1476 static StringInputBuffer buf1; 1496 static StringInputBuffer buf1;
1477 static StringInputBuffer buf2; 1497 static StringInputBuffer buf2;
1478 1498
1479 buf1.Reset(str1); 1499 buf1.Reset(str1);
1480 buf2.Reset(str2); 1500 buf2.Reset(str2);
1481 1501
1482 for (int i = 0; i < end; i++) { 1502 for (int i = 0; i < end; i++) {
1483 uint16_t char1 = buf1.GetNext(); 1503 uint16_t char1 = buf1.GetNext();
1484 uint16_t char2 = buf2.GetNext(); 1504 uint16_t char2 = buf2.GetNext();
1485 if (char1 != char2) return Smi::FromInt(char1 - char2); 1505 if (char1 != char2) return Smi::FromInt(char1 - char2);
1486 } 1506 }
1487 1507
1488 return Smi::FromInt(str1_length - str2_length); 1508 return Smi::FromInt(str1_length - str2_length);
1489 } 1509 }
1490 1510
1491 1511
1492 static Object* Runtime_StringSlice(Arguments args) { 1512 static Object* Runtime_StringSlice(Arguments args) {
1493 NoHandleAllocation ha; 1513 NoHandleAllocation ha;
1494 ASSERT(args.length() == 3); 1514 ASSERT(args.length() == 3);
1495 1515
1496 CONVERT_CHECKED(String, value, args[0]); 1516 CONVERT_CHECKED(String, value, args[0]);
1497 CONVERT_DOUBLE_CHECKED(from_number, args[1]); 1517 CONVERT_DOUBLE_CHECKED(from_number, args[1]);
1498 CONVERT_DOUBLE_CHECKED(to_number, args[2]); 1518 CONVERT_DOUBLE_CHECKED(to_number, args[2]);
1499 1519
1500 int start = FastD2I(from_number); 1520 int start = FastD2I(from_number);
1501 int end = FastD2I(to_number); 1521 int end = FastD2I(to_number);
1502 1522
1523 StringShape shape(value);
1524
1503 RUNTIME_ASSERT(end >= start); 1525 RUNTIME_ASSERT(end >= start);
1504 RUNTIME_ASSERT(start >= 0); 1526 RUNTIME_ASSERT(start >= 0);
1505 RUNTIME_ASSERT(end <= value->length()); 1527 RUNTIME_ASSERT(end <= value->length(shape));
1506 return value->Slice(start, end); 1528 return value->Slice(shape, start, end);
1507 } 1529 }
1508 1530
1509 1531
1510 static Object* Runtime_NumberToRadixString(Arguments args) { 1532 static Object* Runtime_NumberToRadixString(Arguments args) {
1511 NoHandleAllocation ha; 1533 NoHandleAllocation ha;
1512 ASSERT(args.length() == 2); 1534 ASSERT(args.length() == 2);
1513 1535
1514 CONVERT_DOUBLE_CHECKED(value, args[0]); 1536 CONVERT_DOUBLE_CHECKED(value, args[0]);
1515 if (isnan(value)) { 1537 if (isnan(value)) {
1516 return Heap::AllocateStringFromAscii(CStrVector("NaN")); 1538 return Heap::AllocateStringFromAscii(CStrVector("NaN"));
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
1599 char* str = DoubleToPrecisionCString(value, f); 1621 char* str = DoubleToPrecisionCString(value, f);
1600 Object* res = Heap::AllocateStringFromAscii(CStrVector(str)); 1622 Object* res = Heap::AllocateStringFromAscii(CStrVector(str));
1601 DeleteArray(str); 1623 DeleteArray(str);
1602 return res; 1624 return res;
1603 } 1625 }
1604 1626
1605 1627
1606 // Returns a single character string where first character equals 1628 // Returns a single character string where first character equals
1607 // string->Get(index). 1629 // string->Get(index).
1608 static Handle<Object> GetCharAt(Handle<String> string, uint32_t index) { 1630 static Handle<Object> GetCharAt(Handle<String> string, uint32_t index) {
1609 if (index < static_cast<uint32_t>(string->length())) { 1631 StringShape shape(*string);
1610 string->TryFlatten(); 1632 if (index < static_cast<uint32_t>(string->length(shape))) {
1611 return LookupSingleCharacterStringFromCode(string->Get(index)); 1633 string->TryFlatten(shape); // Invalidates shape!
1634 return LookupSingleCharacterStringFromCode(
1635 string->Get(StringShape(*string), index));
1612 } 1636 }
1613 return Execution::CharAt(string, index); 1637 return Execution::CharAt(string, index);
1614 } 1638 }
1615 1639
1616 1640
1617 Object* Runtime::GetElementOrCharAt(Handle<Object> object, uint32_t index) { 1641 Object* Runtime::GetElementOrCharAt(Handle<Object> object, uint32_t index) {
1618 // Handle [] indexing on Strings 1642 // Handle [] indexing on Strings
1619 if (object->IsString()) { 1643 if (object->IsString()) {
1620 Handle<Object> result = GetCharAt(Handle<String>::cast(object), index); 1644 Handle<Object> result = GetCharAt(Handle<String>::cast(object), index);
1621 if (!result->IsUndefined()) return *result; 1645 if (!result->IsUndefined()) return *result;
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
1786 return *value; 1810 return *value;
1787 } 1811 }
1788 1812
1789 if (key->IsString()) { 1813 if (key->IsString()) {
1790 Handle<Object> result; 1814 Handle<Object> result;
1791 if (Handle<String>::cast(key)->AsArrayIndex(&index)) { 1815 if (Handle<String>::cast(key)->AsArrayIndex(&index)) {
1792 ASSERT(attr == NONE); 1816 ASSERT(attr == NONE);
1793 result = SetElement(js_object, index, value); 1817 result = SetElement(js_object, index, value);
1794 } else { 1818 } else {
1795 Handle<String> key_string = Handle<String>::cast(key); 1819 Handle<String> key_string = Handle<String>::cast(key);
1796 key_string->TryFlatten(); 1820 key_string->TryFlatten(StringShape(*key_string));
1797 result = SetProperty(js_object, key_string, value, attr); 1821 result = SetProperty(js_object, key_string, value, attr);
1798 } 1822 }
1799 if (result.is_null()) return Failure::Exception(); 1823 if (result.is_null()) return Failure::Exception();
1800 return *value; 1824 return *value;
1801 } 1825 }
1802 1826
1803 // Call-back into JavaScript to convert the key to a string. 1827 // Call-back into JavaScript to convert the key to a string.
1804 bool has_pending_exception = false; 1828 bool has_pending_exception = false;
1805 Handle<Object> converted = Execution::ToString(key, &has_pending_exception); 1829 Handle<Object> converted = Execution::ToString(key, &has_pending_exception);
1806 if (has_pending_exception) return Failure::Exception(); 1830 if (has_pending_exception) return Failure::Exception();
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
1877 1901
1878 // Only JS objects can have properties. 1902 // Only JS objects can have properties.
1879 if (args[0]->IsJSObject()) { 1903 if (args[0]->IsJSObject()) {
1880 JSObject* object = JSObject::cast(args[0]); 1904 JSObject* object = JSObject::cast(args[0]);
1881 if (object->HasLocalProperty(key)) return Heap::true_value(); 1905 if (object->HasLocalProperty(key)) return Heap::true_value();
1882 } else if (args[0]->IsString()) { 1906 } else if (args[0]->IsString()) {
1883 // Well, there is one exception: Handle [] on strings. 1907 // Well, there is one exception: Handle [] on strings.
1884 uint32_t index; 1908 uint32_t index;
1885 if (key->AsArrayIndex(&index)) { 1909 if (key->AsArrayIndex(&index)) {
1886 String* string = String::cast(args[0]); 1910 String* string = String::cast(args[0]);
1887 if (index < static_cast<uint32_t>(string->length())) 1911 StringShape shape(string);
1912 if (index < static_cast<uint32_t>(string->length(shape)))
1888 return Heap::true_value(); 1913 return Heap::true_value();
1889 } 1914 }
1890 } 1915 }
1891 return Heap::false_value(); 1916 return Heap::false_value();
1892 } 1917 }
1893 1918
1894 1919
1895 static Object* Runtime_HasProperty(Arguments args) { 1920 static Object* Runtime_HasProperty(Arguments args) {
1896 NoHandleAllocation na; 1921 NoHandleAllocation na;
1897 ASSERT(args.length() == 2); 1922 ASSERT(args.length() == 2);
(...skipping 28 matching lines...) Expand all
1926 ASSERT(args.length() == 2); 1951 ASSERT(args.length() == 2);
1927 1952
1928 CONVERT_CHECKED(JSObject, object, args[0]); 1953 CONVERT_CHECKED(JSObject, object, args[0]);
1929 CONVERT_CHECKED(String, key, args[1]); 1954 CONVERT_CHECKED(String, key, args[1]);
1930 1955
1931 uint32_t index; 1956 uint32_t index;
1932 if (key->AsArrayIndex(&index)) { 1957 if (key->AsArrayIndex(&index)) {
1933 return Heap::ToBoolean(object->HasElement(index)); 1958 return Heap::ToBoolean(object->HasElement(index));
1934 } 1959 }
1935 1960
1936 LookupResult result; 1961 PropertyAttributes att = object->GetLocalPropertyAttribute(key);
1937 object->LocalLookup(key, &result); 1962 return Heap::ToBoolean(att != ABSENT && (att & DONT_ENUM) == 0);
1938 if (!result.IsProperty()) return Heap::false_value();
1939 return Heap::ToBoolean(!result.IsDontEnum());
1940 } 1963 }
1941 1964
1942 1965
1943 static Object* Runtime_GetPropertyNames(Arguments args) { 1966 static Object* Runtime_GetPropertyNames(Arguments args) {
1944 HandleScope scope; 1967 HandleScope scope;
1945 ASSERT(args.length() == 1); 1968 ASSERT(args.length() == 1);
1946 1969
1947 CONVERT_CHECKED(JSObject, raw_object, args[0]); 1970 CONVERT_CHECKED(JSObject, raw_object, args[0]);
1948 Handle<JSObject> object(raw_object); 1971 Handle<JSObject> object(raw_object);
1949 return *GetKeysFor(object); 1972 return *GetKeysFor(object);
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
2060 // host objects gives that it is okay to return "object" 2083 // host objects gives that it is okay to return "object"
2061 return Heap::object_symbol(); 2084 return Heap::object_symbol();
2062 } 2085 }
2063 } 2086 }
2064 2087
2065 2088
2066 static Object* Runtime_StringToNumber(Arguments args) { 2089 static Object* Runtime_StringToNumber(Arguments args) {
2067 NoHandleAllocation ha; 2090 NoHandleAllocation ha;
2068 ASSERT(args.length() == 1); 2091 ASSERT(args.length() == 1);
2069 CONVERT_CHECKED(String, subject, args[0]); 2092 CONVERT_CHECKED(String, subject, args[0]);
2070 subject->TryFlatten(); 2093 subject->TryFlatten(StringShape(subject));
2071 return Heap::NumberFromDouble(StringToDouble(subject, ALLOW_HEX)); 2094 return Heap::NumberFromDouble(StringToDouble(subject, ALLOW_HEX));
2072 } 2095 }
2073 2096
2074 2097
2075 static Object* Runtime_StringFromCharCodeArray(Arguments args) { 2098 static Object* Runtime_StringFromCharCodeArray(Arguments args) {
2076 NoHandleAllocation ha; 2099 NoHandleAllocation ha;
2077 ASSERT(args.length() == 1); 2100 ASSERT(args.length() == 1);
2078 2101
2079 CONVERT_CHECKED(JSArray, codes, args[0]); 2102 CONVERT_CHECKED(JSArray, codes, args[0]);
2080 int length = Smi::cast(codes->length())->value(); 2103 int length = Smi::cast(codes->length())->value();
2081 2104
2082 // Check if the string can be ASCII. 2105 // Check if the string can be ASCII.
2083 int i; 2106 int i;
2084 for (i = 0; i < length; i++) { 2107 for (i = 0; i < length; i++) {
2085 Object* element = codes->GetElement(i); 2108 Object* element = codes->GetElement(i);
2086 CONVERT_NUMBER_CHECKED(int, chr, Int32, element); 2109 CONVERT_NUMBER_CHECKED(int, chr, Int32, element);
2087 if ((chr & 0xffff) > String::kMaxAsciiCharCode) 2110 if ((chr & 0xffff) > String::kMaxAsciiCharCode)
2088 break; 2111 break;
2089 } 2112 }
2090 2113
2091 Object* object = NULL; 2114 Object* object = NULL;
2092 if (i == length) { // The string is ASCII. 2115 if (i == length) { // The string is ASCII.
2093 object = Heap::AllocateRawAsciiString(length); 2116 object = Heap::AllocateRawAsciiString(length);
2094 } else { // The string is not ASCII. 2117 } else { // The string is not ASCII.
2095 object = Heap::AllocateRawTwoByteString(length); 2118 object = Heap::AllocateRawTwoByteString(length);
2096 } 2119 }
2097 2120
2098 if (object->IsFailure()) return object; 2121 if (object->IsFailure()) return object;
2099 String* result = String::cast(object); 2122 String* result = String::cast(object);
2123 StringShape result_shape(result);
2100 for (int i = 0; i < length; i++) { 2124 for (int i = 0; i < length; i++) {
2101 Object* element = codes->GetElement(i); 2125 Object* element = codes->GetElement(i);
2102 CONVERT_NUMBER_CHECKED(int, chr, Int32, element); 2126 CONVERT_NUMBER_CHECKED(int, chr, Int32, element);
2103 result->Set(i, chr & 0xffff); 2127 result->Set(result_shape, i, chr & 0xffff);
2104 } 2128 }
2105 return result; 2129 return result;
2106 } 2130 }
2107 2131
2108 2132
2109 // kNotEscaped is generated by the following: 2133 // kNotEscaped is generated by the following:
2110 // 2134 //
2111 // #!/bin/perl 2135 // #!/bin/perl
2112 // for (my $i = 0; $i < 256; $i++) { 2136 // for (my $i = 0; $i < 256; $i++) {
2113 // print "\n" if $i % 16 == 0; 2137 // print "\n" if $i % 16 == 0;
(...skipping 28 matching lines...) Expand all
2142 return kNotEscaped[character] != 0; 2166 return kNotEscaped[character] != 0;
2143 } 2167 }
2144 2168
2145 2169
2146 static Object* Runtime_URIEscape(Arguments args) { 2170 static Object* Runtime_URIEscape(Arguments args) {
2147 const char hex_chars[] = "0123456789ABCDEF"; 2171 const char hex_chars[] = "0123456789ABCDEF";
2148 NoHandleAllocation ha; 2172 NoHandleAllocation ha;
2149 ASSERT(args.length() == 1); 2173 ASSERT(args.length() == 1);
2150 CONVERT_CHECKED(String, source, args[0]); 2174 CONVERT_CHECKED(String, source, args[0]);
2151 2175
2152 source->TryFlatten(); 2176 source->TryFlatten(StringShape(source));
2153 2177
2154 int escaped_length = 0; 2178 int escaped_length = 0;
2155 int length = source->length(); 2179 int length = source->length();
2156 { 2180 {
2157 Access<StringInputBuffer> buffer(&string_input_buffer); 2181 Access<StringInputBuffer> buffer(&string_input_buffer);
2158 buffer->Reset(source); 2182 buffer->Reset(source);
2159 while (buffer->has_more()) { 2183 while (buffer->has_more()) {
2160 uint16_t character = buffer->GetNext(); 2184 uint16_t character = buffer->GetNext();
2161 if (character >= 256) { 2185 if (character >= 256) {
2162 escaped_length += 6; 2186 escaped_length += 6;
2163 } else if (IsNotEscaped(character)) { 2187 } else if (IsNotEscaped(character)) {
2164 escaped_length++; 2188 escaped_length++;
2165 } else { 2189 } else {
2166 escaped_length += 3; 2190 escaped_length += 3;
2167 } 2191 }
2168 // We don't allow strings that are longer than Smi range. 2192 // We don't allow strings that are longer than Smi range.
2169 if (!Smi::IsValid(escaped_length)) { 2193 if (!Smi::IsValid(escaped_length)) {
2170 Top::context()->mark_out_of_memory(); 2194 Top::context()->mark_out_of_memory();
2171 return Failure::OutOfMemoryException(); 2195 return Failure::OutOfMemoryException();
2172 } 2196 }
2173 } 2197 }
2174 } 2198 }
2175 // No length change implies no change. Return original string if no change. 2199 // No length change implies no change. Return original string if no change.
2176 if (escaped_length == length) { 2200 if (escaped_length == length) {
2177 return source; 2201 return source;
2178 } 2202 }
2179 Object* o = Heap::AllocateRawAsciiString(escaped_length); 2203 Object* o = Heap::AllocateRawAsciiString(escaped_length);
2180 if (o->IsFailure()) return o; 2204 if (o->IsFailure()) return o;
2181 String* destination = String::cast(o); 2205 String* destination = String::cast(o);
2206 StringShape dshape(destination);
2182 int dest_position = 0; 2207 int dest_position = 0;
2183 2208
2184 Access<StringInputBuffer> buffer(&string_input_buffer); 2209 Access<StringInputBuffer> buffer(&string_input_buffer);
2185 buffer->Rewind(); 2210 buffer->Rewind();
2186 while (buffer->has_more()) { 2211 while (buffer->has_more()) {
2187 uint16_t character = buffer->GetNext(); 2212 uint16_t chr = buffer->GetNext();
2188 if (character >= 256) { 2213 if (chr >= 256) {
2189 destination->Set(dest_position, '%'); 2214 destination->Set(dshape, dest_position, '%');
2190 destination->Set(dest_position+1, 'u'); 2215 destination->Set(dshape, dest_position+1, 'u');
2191 destination->Set(dest_position+2, hex_chars[character >> 12]); 2216 destination->Set(dshape, dest_position+2, hex_chars[chr >> 12]);
2192 destination->Set(dest_position+3, hex_chars[(character >> 8) & 0xf]); 2217 destination->Set(dshape, dest_position+3, hex_chars[(chr >> 8) & 0xf]);
2193 destination->Set(dest_position+4, hex_chars[(character >> 4) & 0xf]); 2218 destination->Set(dshape, dest_position+4, hex_chars[(chr >> 4) & 0xf]);
2194 destination->Set(dest_position+5, hex_chars[character & 0xf]); 2219 destination->Set(dshape, dest_position+5, hex_chars[chr & 0xf]);
2195 dest_position += 6; 2220 dest_position += 6;
2196 } else if (IsNotEscaped(character)) { 2221 } else if (IsNotEscaped(chr)) {
2197 destination->Set(dest_position, character); 2222 destination->Set(dshape, dest_position, chr);
2198 dest_position++; 2223 dest_position++;
2199 } else { 2224 } else {
2200 destination->Set(dest_position, '%'); 2225 destination->Set(dshape, dest_position, '%');
2201 destination->Set(dest_position+1, hex_chars[character >> 4]); 2226 destination->Set(dshape, dest_position+1, hex_chars[chr >> 4]);
2202 destination->Set(dest_position+2, hex_chars[character & 0xf]); 2227 destination->Set(dshape, dest_position+2, hex_chars[chr & 0xf]);
2203 dest_position += 3; 2228 dest_position += 3;
2204 } 2229 }
2205 } 2230 }
2206 return destination; 2231 return destination;
2207 } 2232 }
2208 2233
2209 2234
2210 static inline int TwoDigitHex(uint16_t character1, uint16_t character2) { 2235 static inline int TwoDigitHex(uint16_t character1, uint16_t character2) {
2211 static const signed char kHexValue['g'] = { 2236 static const signed char kHexValue['g'] = {
2212 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2237 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
2213 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2238 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
2214 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2239 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
2215 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, 2240 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
2216 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2241 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
2217 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2242 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
2218 -1, 10, 11, 12, 13, 14, 15 }; 2243 -1, 10, 11, 12, 13, 14, 15 };
2219 2244
2220 if (character1 > 'f') return -1; 2245 if (character1 > 'f') return -1;
2221 int hi = kHexValue[character1]; 2246 int hi = kHexValue[character1];
2222 if (hi == -1) return -1; 2247 if (hi == -1) return -1;
2223 if (character2 > 'f') return -1; 2248 if (character2 > 'f') return -1;
2224 int lo = kHexValue[character2]; 2249 int lo = kHexValue[character2];
2225 if (lo == -1) return -1; 2250 if (lo == -1) return -1;
2226 return (hi << 4) + lo; 2251 return (hi << 4) + lo;
2227 } 2252 }
2228 2253
2229 2254
2230 static inline int Unescape(String* source, int i, int length, int* step) { 2255 static inline int Unescape(String* source,
2231 uint16_t character = source->Get(i); 2256 StringShape shape,
2232 int32_t hi, lo; 2257 int i,
2258 int length,
2259 int* step) {
2260 uint16_t character = source->Get(shape, i);
2261 int32_t hi = 0;
2262 int32_t lo = 0;
2233 if (character == '%' && 2263 if (character == '%' &&
2234 i <= length - 6 && 2264 i <= length - 6 &&
2235 source->Get(i + 1) == 'u' && 2265 source->Get(shape, i + 1) == 'u' &&
2236 (hi = TwoDigitHex(source->Get(i + 2), source->Get(i + 3))) != -1 && 2266 (hi = TwoDigitHex(source->Get(shape, i + 2),
2237 (lo = TwoDigitHex(source->Get(i + 4), source->Get(i + 5))) != -1) { 2267 source->Get(shape, i + 3))) != -1 &&
2268 (lo = TwoDigitHex(source->Get(shape, i + 4),
2269 source->Get(shape, i + 5))) != -1) {
2238 *step = 6; 2270 *step = 6;
2239 return (hi << 8) + lo; 2271 return (hi << 8) + lo;
2240 } else if (character == '%' && 2272 } else if (character == '%' &&
2241 i <= length - 3 && 2273 i <= length - 3 &&
2242 (lo = TwoDigitHex(source->Get(i + 1), source->Get(i + 2))) != -1) { 2274 (lo = TwoDigitHex(source->Get(shape, i + 1),
2275 source->Get(shape, i + 2))) != -1) {
2243 *step = 3; 2276 *step = 3;
2244 return lo; 2277 return lo;
2245 } else { 2278 } else {
2246 *step = 1; 2279 *step = 1;
2247 return character; 2280 return character;
2248 } 2281 }
2249 } 2282 }
2250 2283
2251 2284
2252 static Object* Runtime_URIUnescape(Arguments args) { 2285 static Object* Runtime_URIUnescape(Arguments args) {
2253 NoHandleAllocation ha; 2286 NoHandleAllocation ha;
2254 ASSERT(args.length() == 1); 2287 ASSERT(args.length() == 1);
2255 CONVERT_CHECKED(String, source, args[0]); 2288 CONVERT_CHECKED(String, source, args[0]);
2256 2289
2257 source->TryFlatten(); 2290 source->TryFlatten(StringShape(source));
2291 StringShape source_shape(source);
2258 2292
2259 bool ascii = true; 2293 bool ascii = true;
2260 int length = source->length(); 2294 int length = source->length(source_shape);
2261 2295
2262 int unescaped_length = 0; 2296 int unescaped_length = 0;
2263 for (int i = 0; i < length; unescaped_length++) { 2297 for (int i = 0; i < length; unescaped_length++) {
2264 int step; 2298 int step;
2265 if (Unescape(source, i, length, &step) > String::kMaxAsciiCharCode) 2299 if (Unescape(source,
2300 source_shape,
2301 i,
2302 length,
2303 &step) >
2304 String::kMaxAsciiCharCode)
2266 ascii = false; 2305 ascii = false;
2267 i += step; 2306 i += step;
2268 } 2307 }
2269 2308
2270 // No length change implies no change. Return original string if no change. 2309 // No length change implies no change. Return original string if no change.
2271 if (unescaped_length == length) 2310 if (unescaped_length == length)
2272 return source; 2311 return source;
2273 2312
2274 Object* o = ascii ? 2313 Object* o = ascii ?
2275 Heap::AllocateRawAsciiString(unescaped_length) : 2314 Heap::AllocateRawAsciiString(unescaped_length) :
2276 Heap::AllocateRawTwoByteString(unescaped_length); 2315 Heap::AllocateRawTwoByteString(unescaped_length);
2277 if (o->IsFailure()) return o; 2316 if (o->IsFailure()) return o;
2278 String* destination = String::cast(o); 2317 String* destination = String::cast(o);
2318 StringShape destination_shape(destination);
2279 2319
2280 int dest_position = 0; 2320 int dest_position = 0;
2281 for (int i = 0; i < length; dest_position++) { 2321 for (int i = 0; i < length; dest_position++) {
2282 int step; 2322 int step;
2283 destination->Set(dest_position, Unescape(source, i, length, &step)); 2323 destination->Set(destination_shape,
2324 dest_position,
2325 Unescape(source, source_shape, i, length, &step));
2284 i += step; 2326 i += step;
2285 } 2327 }
2286 return destination; 2328 return destination;
2287 } 2329 }
2288 2330
2289 2331
2290 static Object* Runtime_StringParseInt(Arguments args) { 2332 static Object* Runtime_StringParseInt(Arguments args) {
2291 NoHandleAllocation ha; 2333 NoHandleAllocation ha;
2292 2334
2293 CONVERT_CHECKED(String, s, args[0]); 2335 CONVERT_CHECKED(String, s, args[0]);
2294 CONVERT_DOUBLE_CHECKED(n, args[1]); 2336 CONVERT_DOUBLE_CHECKED(n, args[1]);
2295 int radix = FastD2I(n); 2337 int radix = FastD2I(n);
2296 2338
2297 s->TryFlatten(); 2339 s->TryFlatten(StringShape(s));
2298 2340
2299 int len = s->length(); 2341 StringShape shape(s);
2342
2343 int len = s->length(shape);
2300 int i; 2344 int i;
2301 2345
2302 // Skip leading white space. 2346 // Skip leading white space.
2303 for (i = 0; i < len && Scanner::kIsWhiteSpace.get(s->Get(i)); i++) ; 2347 for (i = 0; i < len && Scanner::kIsWhiteSpace.get(s->Get(shape, i)); i++) ;
2304 if (i == len) return Heap::nan_value(); 2348 if (i == len) return Heap::nan_value();
2305 2349
2306 // Compute the sign (default to +). 2350 // Compute the sign (default to +).
2307 int sign = 1; 2351 int sign = 1;
2308 if (s->Get(i) == '-') { 2352 if (s->Get(shape, i) == '-') {
2309 sign = -1; 2353 sign = -1;
2310 i++; 2354 i++;
2311 } else if (s->Get(i) == '+') { 2355 } else if (s->Get(shape, i) == '+') {
2312 i++; 2356 i++;
2313 } 2357 }
2314 2358
2315 // Compute the radix if 0. 2359 // Compute the radix if 0.
2316 if (radix == 0) { 2360 if (radix == 0) {
2317 radix = 10; 2361 radix = 10;
2318 if (i < len && s->Get(i) == '0') { 2362 if (i < len && s->Get(shape, i) == '0') {
2319 radix = 8; 2363 radix = 8;
2320 if (i + 1 < len) { 2364 if (i + 1 < len) {
2321 int c = s->Get(i + 1); 2365 int c = s->Get(shape, i + 1);
2322 if (c == 'x' || c == 'X') { 2366 if (c == 'x' || c == 'X') {
2323 radix = 16; 2367 radix = 16;
2324 i += 2; 2368 i += 2;
2325 } 2369 }
2326 } 2370 }
2327 } 2371 }
2328 } else if (radix == 16) { 2372 } else if (radix == 16) {
2329 // Allow 0x or 0X prefix if radix is 16. 2373 // Allow 0x or 0X prefix if radix is 16.
2330 if (i + 1 < len && s->Get(i) == '0') { 2374 if (i + 1 < len && s->Get(shape, i) == '0') {
2331 int c = s->Get(i + 1); 2375 int c = s->Get(shape, i + 1);
2332 if (c == 'x' || c == 'X') i += 2; 2376 if (c == 'x' || c == 'X') i += 2;
2333 } 2377 }
2334 } 2378 }
2335 2379
2336 RUNTIME_ASSERT(2 <= radix && radix <= 36); 2380 RUNTIME_ASSERT(2 <= radix && radix <= 36);
2337 double value; 2381 double value;
2338 int end_index = StringToInt(s, i, radix, &value); 2382 int end_index = StringToInt(s, i, radix, &value);
2339 if (end_index != i) { 2383 if (end_index != i) {
2340 return Heap::NumberFromDouble(sign * value); 2384 return Heap::NumberFromDouble(sign * value);
2341 } 2385 }
(...skipping 16 matching lines...) Expand all
2358 static unibrow::Mapping<unibrow::ToUppercase, 128> to_upper_mapping; 2402 static unibrow::Mapping<unibrow::ToUppercase, 128> to_upper_mapping;
2359 static unibrow::Mapping<unibrow::ToLowercase, 128> to_lower_mapping; 2403 static unibrow::Mapping<unibrow::ToLowercase, 128> to_lower_mapping;
2360 2404
2361 2405
2362 template <class Converter> 2406 template <class Converter>
2363 static Object* ConvertCase(Arguments args, 2407 static Object* ConvertCase(Arguments args,
2364 unibrow::Mapping<Converter, 128>* mapping) { 2408 unibrow::Mapping<Converter, 128>* mapping) {
2365 NoHandleAllocation ha; 2409 NoHandleAllocation ha;
2366 2410
2367 CONVERT_CHECKED(String, s, args[0]); 2411 CONVERT_CHECKED(String, s, args[0]);
2368 int raw_string_length = s->length(); 2412 s->TryFlatten(StringShape(s));
2413 StringShape shape(s);
2414
2415 int raw_string_length = s->length(shape);
2369 // Assume that the string is not empty; we need this assumption later 2416 // Assume that the string is not empty; we need this assumption later
2370 if (raw_string_length == 0) return s; 2417 if (raw_string_length == 0) return s;
2371 int length = raw_string_length; 2418 int length = raw_string_length;
2372 2419
2373 s->TryFlatten();
2374 2420
2375 // We try this twice, once with the assumption that the result is 2421 // We try this twice, once with the assumption that the result is
2376 // no longer than the input and, if that assumption breaks, again 2422 // no longer than the input and, if that assumption breaks, again
2377 // with the exact length. This is implemented using a goto back 2423 // with the exact length. This is implemented using a goto back
2378 // to this label if we discover that the assumption doesn't hold. 2424 // to this label if we discover that the assumption doesn't hold.
2379 // I apologize sincerely for this and will give a vaffel-is to 2425 // I apologize sincerely for this and will give a vaffel-is to
2380 // the first person who can implement it in a nicer way. 2426 // the first person who can implement it in a nicer way.
2381 try_convert: 2427 try_convert:
2382 2428
2383 // Allocate the resulting string. 2429 // Allocate the resulting string.
2384 // 2430 //
2385 // NOTE: This assumes that the upper/lower case of an ascii 2431 // NOTE: This assumes that the upper/lower case of an ascii
2386 // character is also ascii. This is currently the case, but it 2432 // character is also ascii. This is currently the case, but it
2387 // might break in the future if we implement more context and locale 2433 // might break in the future if we implement more context and locale
2388 // dependent upper/lower conversions. 2434 // dependent upper/lower conversions.
2389 Object* o = s->IsAsciiRepresentation() 2435 Object* o = shape.IsAsciiRepresentation()
2390 ? Heap::AllocateRawAsciiString(length) 2436 ? Heap::AllocateRawAsciiString(length)
2391 : Heap::AllocateRawTwoByteString(length); 2437 : Heap::AllocateRawTwoByteString(length);
2392 if (o->IsFailure()) return o; 2438 if (o->IsFailure()) return o;
2393 String* result = String::cast(o); 2439 String* result = String::cast(o);
2440 StringShape result_shape(result);
2394 bool has_changed_character = false; 2441 bool has_changed_character = false;
2395 2442
2396 // Convert all characters to upper case, assuming that they will fit 2443 // Convert all characters to upper case, assuming that they will fit
2397 // in the buffer 2444 // in the buffer
2398 Access<StringInputBuffer> buffer(&string_input_buffer); 2445 Access<StringInputBuffer> buffer(&string_input_buffer);
2399 buffer->Reset(s); 2446 buffer->Reset(s);
2400 unibrow::uchar chars[unibrow::kMaxCaseConvertedSize]; 2447 unibrow::uchar chars[unibrow::kMaxCaseConvertedSize];
2401 int i = 0; 2448 int i = 0;
2402 // We can assume that the string is not empty 2449 // We can assume that the string is not empty
2403 uc32 current = buffer->GetNext(); 2450 uc32 current = buffer->GetNext();
2404 while (i < length) { 2451 while (i < length) {
2405 bool has_next = buffer->has_more(); 2452 bool has_next = buffer->has_more();
2406 uc32 next = has_next ? buffer->GetNext() : 0; 2453 uc32 next = has_next ? buffer->GetNext() : 0;
2407 int char_length = mapping->get(current, next, chars); 2454 int char_length = mapping->get(current, next, chars);
2408 if (char_length == 0) { 2455 if (char_length == 0) {
2409 // The case conversion of this character is the character itself. 2456 // The case conversion of this character is the character itself.
2410 result->Set(i, current); 2457 result->Set(result_shape, i, current);
2411 i++; 2458 i++;
2412 } else if (char_length == 1) { 2459 } else if (char_length == 1) {
2413 // Common case: converting the letter resulted in one character. 2460 // Common case: converting the letter resulted in one character.
2414 ASSERT(static_cast<uc32>(chars[0]) != current); 2461 ASSERT(static_cast<uc32>(chars[0]) != current);
2415 result->Set(i, chars[0]); 2462 result->Set(result_shape, i, chars[0]);
2416 has_changed_character = true; 2463 has_changed_character = true;
2417 i++; 2464 i++;
2418 } else if (length == raw_string_length) { 2465 } else if (length == raw_string_length) {
2419 // We've assumed that the result would be as long as the 2466 // We've assumed that the result would be as long as the
2420 // input but here is a character that converts to several 2467 // input but here is a character that converts to several
2421 // characters. No matter, we calculate the exact length 2468 // characters. No matter, we calculate the exact length
2422 // of the result and try the whole thing again. 2469 // of the result and try the whole thing again.
2423 // 2470 //
2424 // Note that this leaves room for optimization. We could just 2471 // Note that this leaves room for optimization. We could just
2425 // memcpy what we already have to the result string. Also, 2472 // memcpy what we already have to the result string. Also,
(...skipping 14 matching lines...) Expand all
2440 // it does not in any case affect the length of what it convert 2487 // it does not in any case affect the length of what it convert
2441 // to. 2488 // to.
2442 int char_length = mapping->get(current, 0, chars); 2489 int char_length = mapping->get(current, 0, chars);
2443 if (char_length == 0) char_length = 1; 2490 if (char_length == 0) char_length = 1;
2444 current_length += char_length; 2491 current_length += char_length;
2445 } 2492 }
2446 length = current_length; 2493 length = current_length;
2447 goto try_convert; 2494 goto try_convert;
2448 } else { 2495 } else {
2449 for (int j = 0; j < char_length; j++) { 2496 for (int j = 0; j < char_length; j++) {
2450 result->Set(i, chars[j]); 2497 result->Set(result_shape, i, chars[j]);
2451 i++; 2498 i++;
2452 } 2499 }
2453 has_changed_character = true; 2500 has_changed_character = true;
2454 } 2501 }
2455 current = next; 2502 current = next;
2456 } 2503 }
2457 if (has_changed_character) { 2504 if (has_changed_character) {
2458 return result; 2505 return result;
2459 } else { 2506 } else {
2460 // If we didn't actually change anything in doing the conversion 2507 // If we didn't actually change anything in doing the conversion
2461 // we simple return the result and let the converted string 2508 // we simple return the result and let the converted string
2462 // become garbage; there is no reason to keep two identical strings 2509 // become garbage; there is no reason to keep two identical strings
2463 // alive. 2510 // alive.
2464 return s; 2511 return s;
2465 } 2512 }
2466 } 2513 }
2467 2514
2468 2515
2469 static Object* Runtime_StringToLowerCase(Arguments args) { 2516 static Object* Runtime_StringToLowerCase(Arguments args) {
2470 return ConvertCase<unibrow::ToLowercase>(args, &to_lower_mapping); 2517 return ConvertCase<unibrow::ToLowercase>(args, &to_lower_mapping);
2471 } 2518 }
2472 2519
2473 2520
2474 static Object* Runtime_StringToUpperCase(Arguments args) { 2521 static Object* Runtime_StringToUpperCase(Arguments args) {
2475 return ConvertCase<unibrow::ToUppercase>(args, &to_upper_mapping); 2522 return ConvertCase<unibrow::ToUppercase>(args, &to_upper_mapping);
2476 } 2523 }
2477 2524
2478 2525
2479 static Object* Runtime_ConsStringFst(Arguments args) {
2480 NoHandleAllocation ha;
2481
2482 CONVERT_CHECKED(ConsString, str, args[0]);
2483 return str->first();
2484 }
2485
2486
2487 static Object* Runtime_ConsStringSnd(Arguments args) {
2488 NoHandleAllocation ha;
2489
2490 CONVERT_CHECKED(ConsString, str, args[0]);
2491 return str->second();
2492 }
2493
2494
2495 static Object* Runtime_NumberToString(Arguments args) { 2526 static Object* Runtime_NumberToString(Arguments args) {
2496 NoHandleAllocation ha; 2527 NoHandleAllocation ha;
2497 ASSERT(args.length() == 1); 2528 ASSERT(args.length() == 1);
2498 2529
2499 Object* number = args[0]; 2530 Object* number = args[0];
2500 RUNTIME_ASSERT(number->IsNumber()); 2531 RUNTIME_ASSERT(number->IsNumber());
2501 2532
2502 Object* cached = Heap::GetNumberStringCache(number); 2533 Object* cached = Heap::GetNumberStringCache(number);
2503 if (cached != Heap::undefined_value()) { 2534 if (cached != Heap::undefined_value()) {
2504 return cached; 2535 return cached;
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
2549 NoHandleAllocation ha; 2580 NoHandleAllocation ha;
2550 ASSERT(args.length() == 1); 2581 ASSERT(args.length() == 1);
2551 2582
2552 Object* obj = args[0]; 2583 Object* obj = args[0];
2553 if (obj->IsSmi()) return obj; 2584 if (obj->IsSmi()) return obj;
2554 CONVERT_DOUBLE_CHECKED(number, obj); 2585 CONVERT_DOUBLE_CHECKED(number, obj);
2555 return Heap::NumberFromInt32(DoubleToInt32(number)); 2586 return Heap::NumberFromInt32(DoubleToInt32(number));
2556 } 2587 }
2557 2588
2558 2589
2590 // Converts a Number to a Smi, if possible. Returns NaN if the number is not
2591 // a small integer.
2592 static Object* Runtime_NumberToSmi(Arguments args) {
2593 NoHandleAllocation ha;
2594 ASSERT(args.length() == 1);
2595
2596 Object* obj = args[0];
2597 if (obj->IsSmi()) {
2598 return obj;
2599 }
2600 if (obj->IsHeapNumber()) {
2601 double value = HeapNumber::cast(obj)->value();
2602 int int_value = FastD2I(value);
2603 if (value == FastI2D(int_value) && Smi::IsValid(int_value)) {
2604 return Smi::FromInt(int_value);
2605 }
2606 }
2607 return Heap::nan_value();
2608 }
2609
2559 static Object* Runtime_NumberAdd(Arguments args) { 2610 static Object* Runtime_NumberAdd(Arguments args) {
2560 NoHandleAllocation ha; 2611 NoHandleAllocation ha;
2561 ASSERT(args.length() == 2); 2612 ASSERT(args.length() == 2);
2562 2613
2563 CONVERT_DOUBLE_CHECKED(x, args[0]); 2614 CONVERT_DOUBLE_CHECKED(x, args[0]);
2564 CONVERT_DOUBLE_CHECKED(y, args[1]); 2615 CONVERT_DOUBLE_CHECKED(y, args[1]);
2565 return Heap::AllocateHeapNumber(x + y); 2616 return Heap::AllocateHeapNumber(x + y);
2566 } 2617 }
2567 2618
2568 2619
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
2624 return Heap::NewNumberFromDouble(x); 2675 return Heap::NewNumberFromDouble(x);
2625 } 2676 }
2626 2677
2627 2678
2628 static Object* Runtime_StringAdd(Arguments args) { 2679 static Object* Runtime_StringAdd(Arguments args) {
2629 NoHandleAllocation ha; 2680 NoHandleAllocation ha;
2630 ASSERT(args.length() == 2); 2681 ASSERT(args.length() == 2);
2631 2682
2632 CONVERT_CHECKED(String, str1, args[0]); 2683 CONVERT_CHECKED(String, str1, args[0]);
2633 CONVERT_CHECKED(String, str2, args[1]); 2684 CONVERT_CHECKED(String, str2, args[1]);
2634 int len1 = str1->length(); 2685 StringShape shape1(str1);
2635 int len2 = str2->length(); 2686 StringShape shape2(str2);
2687 int len1 = str1->length(shape1);
2688 int len2 = str2->length(shape2);
2636 if (len1 == 0) return str2; 2689 if (len1 == 0) return str2;
2637 if (len2 == 0) return str1; 2690 if (len2 == 0) return str1;
2638 int length_sum = len1 + len2; 2691 int length_sum = len1 + len2;
2639 // Make sure that an out of memory exception is thrown if the length 2692 // Make sure that an out of memory exception is thrown if the length
2640 // of the new cons string is too large to fit in a Smi. 2693 // of the new cons string is too large to fit in a Smi.
2641 if (length_sum > Smi::kMaxValue || length_sum < 0) { 2694 if (length_sum > Smi::kMaxValue || length_sum < 0) {
2642 Top::context()->mark_out_of_memory(); 2695 Top::context()->mark_out_of_memory();
2643 return Failure::OutOfMemoryException(); 2696 return Failure::OutOfMemoryException();
2644 } 2697 }
2645 return Heap::AllocateConsString(str1, str2); 2698 return Heap::AllocateConsString(str1, shape1, str2, shape2);
2646 } 2699 }
2647 2700
2648 2701
2649 template<typename sinkchar> 2702 template<typename sinkchar>
2650 static inline void StringBuilderConcatHelper(String* special, 2703 static inline void StringBuilderConcatHelper(String* special,
2704 StringShape special_shape,
2651 sinkchar* sink, 2705 sinkchar* sink,
2652 FixedArray* fixed_array, 2706 FixedArray* fixed_array,
2653 int array_length) { 2707 int array_length) {
2654 int position = 0; 2708 int position = 0;
2655 for (int i = 0; i < array_length; i++) { 2709 for (int i = 0; i < array_length; i++) {
2656 Object* element = fixed_array->get(i); 2710 Object* element = fixed_array->get(i);
2657 if (element->IsSmi()) { 2711 if (element->IsSmi()) {
2658 int len = Smi::cast(element)->value(); 2712 int len = Smi::cast(element)->value();
2659 int pos = len >> 11; 2713 int pos = len >> 11;
2660 len &= 0x7ff; 2714 len &= 0x7ff;
2661 String::WriteToFlat(special, sink + position, pos, pos + len); 2715 String::WriteToFlat(special,
2716 special_shape,
2717 sink + position,
2718 pos,
2719 pos + len);
2662 position += len; 2720 position += len;
2663 } else { 2721 } else {
2664 String* string = String::cast(element); 2722 String* string = String::cast(element);
2665 int element_length = string->length(); 2723 StringShape shape(string);
2666 String::WriteToFlat(string, sink + position, 0, element_length); 2724 int element_length = string->length(shape);
2725 String::WriteToFlat(string, shape, sink + position, 0, element_length);
2667 position += element_length; 2726 position += element_length;
2668 } 2727 }
2669 } 2728 }
2670 } 2729 }
2671 2730
2672 2731
2673 static Object* Runtime_StringBuilderConcat(Arguments args) { 2732 static Object* Runtime_StringBuilderConcat(Arguments args) {
2674 NoHandleAllocation ha; 2733 NoHandleAllocation ha;
2675 ASSERT(args.length() == 2); 2734 ASSERT(args.length() == 2);
2676 CONVERT_CHECKED(JSArray, array, args[0]); 2735 CONVERT_CHECKED(JSArray, array, args[0]);
2677 CONVERT_CHECKED(String, special, args[1]); 2736 CONVERT_CHECKED(String, special, args[1]);
2678 int special_length = special->length(); 2737 StringShape special_shape(special);
2738 int special_length = special->length(special_shape);
2679 Object* smi_array_length = array->length(); 2739 Object* smi_array_length = array->length();
2680 if (!smi_array_length->IsSmi()) { 2740 if (!smi_array_length->IsSmi()) {
2681 Top::context()->mark_out_of_memory(); 2741 Top::context()->mark_out_of_memory();
2682 return Failure::OutOfMemoryException(); 2742 return Failure::OutOfMemoryException();
2683 } 2743 }
2684 int array_length = Smi::cast(smi_array_length)->value(); 2744 int array_length = Smi::cast(smi_array_length)->value();
2685 if (!array->HasFastElements()) { 2745 if (!array->HasFastElements()) {
2686 return Top::Throw(Heap::illegal_argument_symbol()); 2746 return Top::Throw(Heap::illegal_argument_symbol());
2687 } 2747 }
2688 FixedArray* fixed_array = FixedArray::cast(array->elements()); 2748 FixedArray* fixed_array = FixedArray::cast(array->elements());
2689 if (fixed_array->length() < array_length) { 2749 if (fixed_array->length() < array_length) {
2690 array_length = fixed_array->length(); 2750 array_length = fixed_array->length();
2691 } 2751 }
2692 2752
2693 if (array_length == 0) { 2753 if (array_length == 0) {
2694 return Heap::empty_string(); 2754 return Heap::empty_string();
2695 } else if (array_length == 1) { 2755 } else if (array_length == 1) {
2696 Object* first = fixed_array->get(0); 2756 Object* first = fixed_array->get(0);
2697 if (first->IsString()) return first; 2757 if (first->IsString()) return first;
2698 } 2758 }
2699 2759
2700 bool ascii = special->IsAsciiRepresentation(); 2760 bool ascii = special_shape.IsAsciiRepresentation();
2701 int position = 0; 2761 int position = 0;
2702 for (int i = 0; i < array_length; i++) { 2762 for (int i = 0; i < array_length; i++) {
2703 Object* elt = fixed_array->get(i); 2763 Object* elt = fixed_array->get(i);
2704 if (elt->IsSmi()) { 2764 if (elt->IsSmi()) {
2705 int len = Smi::cast(elt)->value(); 2765 int len = Smi::cast(elt)->value();
2706 int pos = len >> 11; 2766 int pos = len >> 11;
2707 len &= 0x7ff; 2767 len &= 0x7ff;
2708 if (pos + len > special_length) { 2768 if (pos + len > special_length) {
2709 return Top::Throw(Heap::illegal_argument_symbol()); 2769 return Top::Throw(Heap::illegal_argument_symbol());
2710 } 2770 }
2711 position += len; 2771 position += len;
2712 } else if (elt->IsString()) { 2772 } else if (elt->IsString()) {
2713 String* element = String::cast(elt); 2773 String* element = String::cast(elt);
2714 int element_length = element->length(); 2774 StringShape element_shape(element);
2775 int element_length = element->length(element_shape);
2715 if (!Smi::IsValid(element_length + position)) { 2776 if (!Smi::IsValid(element_length + position)) {
2716 Top::context()->mark_out_of_memory(); 2777 Top::context()->mark_out_of_memory();
2717 return Failure::OutOfMemoryException(); 2778 return Failure::OutOfMemoryException();
2718 } 2779 }
2719 position += element_length; 2780 position += element_length;
2720 if (ascii && !element->IsAsciiRepresentation()) { 2781 if (ascii && !element_shape.IsAsciiRepresentation()) {
2721 ascii = false; 2782 ascii = false;
2722 } 2783 }
2723 } else { 2784 } else {
2724 return Top::Throw(Heap::illegal_argument_symbol()); 2785 return Top::Throw(Heap::illegal_argument_symbol());
2725 } 2786 }
2726 } 2787 }
2727 2788
2728 int length = position; 2789 int length = position;
2729 Object* object; 2790 Object* object;
2730 2791
2731 if (ascii) { 2792 if (ascii) {
2732 object = Heap::AllocateRawAsciiString(length); 2793 object = Heap::AllocateRawAsciiString(length);
2733 if (object->IsFailure()) return object; 2794 if (object->IsFailure()) return object;
2734 SeqAsciiString* answer = SeqAsciiString::cast(object); 2795 SeqAsciiString* answer = SeqAsciiString::cast(object);
2735 StringBuilderConcatHelper(special, 2796 StringBuilderConcatHelper(special,
2797 special_shape,
2736 answer->GetChars(), 2798 answer->GetChars(),
2737 fixed_array, 2799 fixed_array,
2738 array_length); 2800 array_length);
2739 return answer; 2801 return answer;
2740 } else { 2802 } else {
2741 object = Heap::AllocateRawTwoByteString(length); 2803 object = Heap::AllocateRawTwoByteString(length);
2742 if (object->IsFailure()) return object; 2804 if (object->IsFailure()) return object;
2743 SeqTwoByteString* answer = SeqTwoByteString::cast(object); 2805 SeqTwoByteString* answer = SeqTwoByteString::cast(object);
2744 StringBuilderConcatHelper(special, 2806 StringBuilderConcatHelper(special,
2807 special_shape,
2745 answer->GetChars(), 2808 answer->GetChars(),
2746 fixed_array, 2809 fixed_array,
2747 array_length); 2810 array_length);
2748 return answer; 2811 return answer;
2749 } 2812 }
2750 } 2813 }
2751 2814
2752 2815
2753 static Object* Runtime_NumberOr(Arguments args) { 2816 static Object* Runtime_NumberOr(Arguments args) {
2754 NoHandleAllocation ha; 2817 NoHandleAllocation ha;
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
2929 } 2992 }
2930 2993
2931 2994
2932 static Object* Runtime_StringCompare(Arguments args) { 2995 static Object* Runtime_StringCompare(Arguments args) {
2933 NoHandleAllocation ha; 2996 NoHandleAllocation ha;
2934 ASSERT(args.length() == 2); 2997 ASSERT(args.length() == 2);
2935 2998
2936 CONVERT_CHECKED(String, x, args[0]); 2999 CONVERT_CHECKED(String, x, args[0]);
2937 CONVERT_CHECKED(String, y, args[1]); 3000 CONVERT_CHECKED(String, y, args[1]);
2938 3001
3002 StringShape x_shape(x);
3003 StringShape y_shape(y);
3004
2939 // A few fast case tests before we flatten. 3005 // A few fast case tests before we flatten.
2940 if (x == y) return Smi::FromInt(EQUAL); 3006 if (x == y) return Smi::FromInt(EQUAL);
2941 if (y->length() == 0) { 3007 if (y->length(y_shape) == 0) {
2942 if (x->length() == 0) return Smi::FromInt(EQUAL); 3008 if (x->length(x_shape) == 0) return Smi::FromInt(EQUAL);
2943 return Smi::FromInt(GREATER); 3009 return Smi::FromInt(GREATER);
2944 } else if (x->length() == 0) { 3010 } else if (x->length(x_shape) == 0) {
2945 return Smi::FromInt(LESS); 3011 return Smi::FromInt(LESS);
2946 } 3012 }
2947 3013
2948 int d = x->Get(0) - y->Get(0); 3014 int d = x->Get(x_shape, 0) - y->Get(y_shape, 0);
2949 if (d < 0) return Smi::FromInt(LESS); 3015 if (d < 0) return Smi::FromInt(LESS);
2950 else if (d > 0) return Smi::FromInt(GREATER); 3016 else if (d > 0) return Smi::FromInt(GREATER);
2951 3017
2952 x->TryFlatten(); 3018 x->TryFlatten(x_shape); // Shapes are no longer valid!
2953 y->TryFlatten(); 3019 y->TryFlatten(y_shape);
2954 3020
2955 static StringInputBuffer bufx; 3021 static StringInputBuffer bufx;
2956 static StringInputBuffer bufy; 3022 static StringInputBuffer bufy;
2957 bufx.Reset(x); 3023 bufx.Reset(x);
2958 bufy.Reset(y); 3024 bufy.Reset(y);
2959 while (bufx.has_more() && bufy.has_more()) { 3025 while (bufx.has_more() && bufy.has_more()) {
2960 int d = bufx.GetNext() - bufy.GetNext(); 3026 int d = bufx.GetNext() - bufy.GetNext();
2961 if (d < 0) return Smi::FromInt(LESS); 3027 if (d < 0) return Smi::FromInt(LESS);
2962 else if (d > 0) return Smi::FromInt(GREATER); 3028 else if (d > 0) return Smi::FromInt(GREATER);
2963 } 3029 }
(...skipping 2841 matching lines...) Expand 10 before | Expand all | Expand 10 after
5805 } else { 5871 } else {
5806 // Handle last resort GC and make sure to allow future allocations 5872 // Handle last resort GC and make sure to allow future allocations
5807 // to grow the heap without causing GCs (if possible). 5873 // to grow the heap without causing GCs (if possible).
5808 Counters::gc_last_resort_from_js.Increment(); 5874 Counters::gc_last_resort_from_js.Increment();
5809 Heap::CollectAllGarbage(); 5875 Heap::CollectAllGarbage();
5810 } 5876 }
5811 } 5877 }
5812 5878
5813 5879
5814 } } // namespace v8::internal 5880 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/runtime.h ('k') | test/cctest/test-api.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698