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

Side by Side Diff: src/runtime.cc

Issue 9038: Create an abstraction for the string type flags so that they can be cached.... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
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
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 934 matching lines...) Expand 10 before | Expand all | Expand 10 after
945 return *target; 945 return *target;
946 } 946 }
947 947
948 948
949 static Object* CharCodeAt(String* subject, Object* index) { 949 static Object* CharCodeAt(String* subject, Object* index) {
950 uint32_t i = 0; 950 uint32_t i = 0;
951 if (!Array::IndexFromObject(index, &i)) return Heap::nan_value(); 951 if (!Array::IndexFromObject(index, &i)) return Heap::nan_value();
952 // Flatten the string. If someone wants to get a char at an index 952 // Flatten the string. If someone wants to get a char at an index
953 // in a cons string, it is likely that more indices will be 953 // in a cons string, it is likely that more indices will be
954 // accessed. 954 // accessed.
955 subject->TryFlatten(); 955 StringShape shape(subject);
956 if (i >= static_cast<uint32_t>(subject->length())) return Heap::nan_value(); 956 subject->TryFlatten(shape); // shape no longer valid!
957 return Smi::FromInt(subject->Get(i)); 957 if (i >= static_cast<uint32_t>(subject->length(StringShape(subject)))) {
958 return Heap::nan_value();
959 }
960 return Smi::FromInt(subject->Get(StringShape(subject), i));
958 } 961 }
959 962
960 963
961 static Object* Runtime_StringCharCodeAt(Arguments args) { 964 static Object* Runtime_StringCharCodeAt(Arguments args) {
962 NoHandleAllocation ha; 965 NoHandleAllocation ha;
963 ASSERT(args.length() == 2); 966 ASSERT(args.length() == 2);
964 967
965 CONVERT_CHECKED(String, subject, args[0]); 968 CONVERT_CHECKED(String, subject, args[0]);
966 Object* index = args[1]; 969 Object* index = args[1];
967 return CharCodeAt(subject, index); 970 return CharCodeAt(subject, index);
(...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after
1327 return BoyerMooreIndexOf(sub, pat, idx); 1330 return BoyerMooreIndexOf(sub, pat, idx);
1328 } 1331 }
1329 1332
1330 // Perform string match of pattern on subject, starting at start index. 1333 // Perform string match of pattern on subject, starting at start index.
1331 // Caller must ensure that 0 <= start_index <= sub->length(), 1334 // Caller must ensure that 0 <= start_index <= sub->length(),
1332 // and should check that pat->length() + start_index <= sub->length() 1335 // and should check that pat->length() + start_index <= sub->length()
1333 int Runtime::StringMatch(Handle<String> sub, 1336 int Runtime::StringMatch(Handle<String> sub,
1334 Handle<String> pat, 1337 Handle<String> pat,
1335 int start_index) { 1338 int start_index) {
1336 ASSERT(0 <= start_index); 1339 ASSERT(0 <= start_index);
1337 ASSERT(start_index <= sub->length()); 1340 StringShape sub_shape(*sub);
1341 StringShape pat_shape(*pat);
1342 ASSERT(start_index <= sub->length(sub_shape));
1338 1343
1339 int pattern_length = pat->length(); 1344 int pattern_length = pat->length(pat_shape);
1340 if (pattern_length == 0) return start_index; 1345 if (pattern_length == 0) return start_index;
1341 1346
1342 int subject_length = sub->length(); 1347 int subject_length = sub->length(sub_shape);
1343 if (start_index + pattern_length > subject_length) return -1; 1348 if (start_index + pattern_length > subject_length) return -1;
1344 1349
1345 FlattenString(sub); 1350 if (!sub->IsFlat(sub_shape)) {
1351 FlattenString(sub);
1352 sub_shape = StringShape(*sub);
1353 }
1346 // Searching for one specific character is common. For one 1354 // Searching for one specific character is common. For one
1347 // character patterns linear search is necessary, so any smart 1355 // character patterns linear search is necessary, so any smart
1348 // algorithm is unnecessary overhead. 1356 // algorithm is unnecessary overhead.
1349 if (pattern_length == 1) { 1357 if (pattern_length == 1) {
1350 AssertNoAllocation no_heap_allocation; // ensure vectors stay valid 1358 AssertNoAllocation no_heap_allocation; // ensure vectors stay valid
1351 if (sub->is_ascii_representation()) { 1359 if (sub_shape.IsAsciiRepresentation()) {
1352 return SingleCharIndexOf(sub->ToAsciiVector(), pat->Get(0), start_index); 1360 return SingleCharIndexOf(sub->ToAsciiVector(), pat->Get(pat_shape, 0), sta rt_index);
1353 } 1361 }
1354 return SingleCharIndexOf(sub->ToUC16Vector(), pat->Get(0), start_index); 1362 return SingleCharIndexOf(sub->ToUC16Vector(), pat->Get(pat_shape, 0), start_ index);
1355 } 1363 }
1356 1364
1357 FlattenString(pat); 1365 if (!pat->IsFlat(pat_shape)) {
1366 FlattenString(pat);
1367 pat_shape = StringShape(*pat);
1368 }
1358 1369
1359 AssertNoAllocation no_heap_allocation; // ensure vectors stay valid 1370 AssertNoAllocation no_heap_allocation; // ensure vectors stay valid
1360 // dispatch on type of strings 1371 // dispatch on type of strings
1361 if (pat->is_ascii_representation()) { 1372 if (pat_shape.IsAsciiRepresentation()) {
1362 Vector<const char> pat_vector = pat->ToAsciiVector(); 1373 Vector<const char> pat_vector = pat->ToAsciiVector();
1363 if (sub->is_ascii_representation()) { 1374 if (sub_shape.IsAsciiRepresentation()) {
1364 return StringMatchStrategy(sub->ToAsciiVector(), pat_vector, start_index); 1375 return StringMatchStrategy(sub->ToAsciiVector(), pat_vector, start_index);
1365 } 1376 }
1366 return StringMatchStrategy(sub->ToUC16Vector(), pat_vector, start_index); 1377 return StringMatchStrategy(sub->ToUC16Vector(), pat_vector, start_index);
1367 } 1378 }
1368 Vector<const uc16> pat_vector = pat->ToUC16Vector(); 1379 Vector<const uc16> pat_vector = pat->ToUC16Vector();
1369 if (sub->is_ascii_representation()) { 1380 if (sub_shape.IsAsciiRepresentation()) {
1370 return StringMatchStrategy(sub->ToAsciiVector(), pat_vector, start_index); 1381 return StringMatchStrategy(sub->ToAsciiVector(), pat_vector, start_index);
1371 } 1382 }
1372 return StringMatchStrategy(sub->ToUC16Vector(), pat_vector, start_index); 1383 return StringMatchStrategy(sub->ToUC16Vector(), pat_vector, start_index);
1373 } 1384 }
1374 1385
1375 1386
1376 static Object* Runtime_StringIndexOf(Arguments args) { 1387 static Object* Runtime_StringIndexOf(Arguments args) {
1377 HandleScope scope; // create a new handle scope 1388 HandleScope scope; // create a new handle scope
1378 ASSERT(args.length() == 3); 1389 ASSERT(args.length() == 3);
1379 1390
(...skipping 10 matching lines...) Expand all
1390 1401
1391 1402
1392 static Object* Runtime_StringLastIndexOf(Arguments args) { 1403 static Object* Runtime_StringLastIndexOf(Arguments args) {
1393 NoHandleAllocation ha; 1404 NoHandleAllocation ha;
1394 ASSERT(args.length() == 3); 1405 ASSERT(args.length() == 3);
1395 1406
1396 CONVERT_CHECKED(String, sub, args[0]); 1407 CONVERT_CHECKED(String, sub, args[0]);
1397 CONVERT_CHECKED(String, pat, args[1]); 1408 CONVERT_CHECKED(String, pat, args[1]);
1398 Object* index = args[2]; 1409 Object* index = args[2];
1399 1410
1400 sub->TryFlatten(); 1411 sub->TryFlatten(StringShape(sub));
1401 pat->TryFlatten(); 1412 pat->TryFlatten(StringShape(pat));
1413
1414 StringShape sub_shape(sub);
1415 StringShape pat_shape(pat);
1402 1416
1403 uint32_t start_index; 1417 uint32_t start_index;
1404 if (!Array::IndexFromObject(index, &start_index)) return Smi::FromInt(-1); 1418 if (!Array::IndexFromObject(index, &start_index)) return Smi::FromInt(-1);
1405 1419
1406 uint32_t pattern_length = pat->length(); 1420 uint32_t pattern_length = pat->length(pat_shape);
1407 uint32_t sub_length = sub->length(); 1421 uint32_t sub_length = sub->length(sub_shape);
1408 1422
1409 if (start_index + pattern_length > sub_length) { 1423 if (start_index + pattern_length > sub_length) {
1410 start_index = sub_length - pattern_length; 1424 start_index = sub_length - pattern_length;
1411 } 1425 }
1412 1426
1413 for (int i = start_index; i >= 0; i--) { 1427 for (int i = start_index; i >= 0; i--) {
1414 bool found = true; 1428 bool found = true;
1415 for (uint32_t j = 0; j < pattern_length; j++) { 1429 for (uint32_t j = 0; j < pattern_length; j++) {
1416 if (sub->Get(i + j) != pat->Get(j)) { 1430 if (sub->Get(sub_shape, i + j) != pat->Get(pat_shape, j)) {
1417 found = false; 1431 found = false;
1418 break; 1432 break;
1419 } 1433 }
1420 } 1434 }
1421 if (found) return Smi::FromInt(i); 1435 if (found) return Smi::FromInt(i);
1422 } 1436 }
1423 1437
1424 return Smi::FromInt(-1); 1438 return Smi::FromInt(-1);
1425 } 1439 }
1426 1440
1427 1441
1428 static Object* Runtime_StringLocaleCompare(Arguments args) { 1442 static Object* Runtime_StringLocaleCompare(Arguments args) {
1429 NoHandleAllocation ha; 1443 NoHandleAllocation ha;
1430 ASSERT(args.length() == 2); 1444 ASSERT(args.length() == 2);
1431 1445
1432 CONVERT_CHECKED(String, str1, args[0]); 1446 CONVERT_CHECKED(String, str1, args[0]);
1433 CONVERT_CHECKED(String, str2, args[1]); 1447 CONVERT_CHECKED(String, str2, args[1]);
1434 1448
1435 if (str1 == str2) return Smi::FromInt(0); // Equal. 1449 if (str1 == str2) return Smi::FromInt(0); // Equal.
1436 int str1_length = str1->length(); 1450 StringShape shape1(str1);
1437 int str2_length = str2->length(); 1451 StringShape shape2(str2);
1452 int str1_length = str1->length(shape1);
1453 int str2_length = str2->length(shape2);
1438 1454
1439 // Decide trivial cases without flattening. 1455 // Decide trivial cases without flattening.
1440 if (str1_length == 0) { 1456 if (str1_length == 0) {
1441 if (str2_length == 0) return Smi::FromInt(0); // Equal. 1457 if (str2_length == 0) return Smi::FromInt(0); // Equal.
1442 return Smi::FromInt(-str2_length); 1458 return Smi::FromInt(-str2_length);
1443 } else { 1459 } else {
1444 if (str2_length == 0) return Smi::FromInt(str1_length); 1460 if (str2_length == 0) return Smi::FromInt(str1_length);
1445 } 1461 }
1446 1462
1447 int end = str1_length < str2_length ? str1_length : str2_length; 1463 int end = str1_length < str2_length ? str1_length : str2_length;
1448 1464
1449 // No need to flatten if we are going to find the answer on the first 1465 // No need to flatten if we are going to find the answer on the first
1450 // character. At this point we know there is at least one character 1466 // character. At this point we know there is at least one character
1451 // in each string, due to the trivial case handling above. 1467 // in each string, due to the trivial case handling above.
1452 int d = str1->Get(0) - str2->Get(0); 1468 int d = str1->Get(shape1, 0) - str2->Get(shape2, 0);
1453 if (d != 0) return Smi::FromInt(d); 1469 if (d != 0) return Smi::FromInt(d);
1454 1470
1455 str1->TryFlatten(); 1471 str1->TryFlatten(shape1); // Shapes are no longer valid now!
1456 str2->TryFlatten(); 1472 str2->TryFlatten(shape2);
1457 1473
1458 static StringInputBuffer buf1; 1474 static StringInputBuffer buf1;
1459 static StringInputBuffer buf2; 1475 static StringInputBuffer buf2;
1460 1476
1461 buf1.Reset(str1); 1477 buf1.Reset(str1);
1462 buf2.Reset(str2); 1478 buf2.Reset(str2);
1463 1479
1464 for (int i = 0; i < end; i++) { 1480 for (int i = 0; i < end; i++) {
1465 uint16_t char1 = buf1.GetNext(); 1481 uint16_t char1 = buf1.GetNext();
1466 uint16_t char2 = buf2.GetNext(); 1482 uint16_t char2 = buf2.GetNext();
1467 if (char1 != char2) return Smi::FromInt(char1 - char2); 1483 if (char1 != char2) return Smi::FromInt(char1 - char2);
1468 } 1484 }
1469 1485
1470 return Smi::FromInt(str1_length - str2_length); 1486 return Smi::FromInt(str1_length - str2_length);
1471 } 1487 }
1472 1488
1473 1489
1474 static Object* Runtime_StringSlice(Arguments args) { 1490 static Object* Runtime_StringSlice(Arguments args) {
1475 NoHandleAllocation ha; 1491 NoHandleAllocation ha;
1476 ASSERT(args.length() == 3); 1492 ASSERT(args.length() == 3);
1477 1493
1478 CONVERT_CHECKED(String, value, args[0]); 1494 CONVERT_CHECKED(String, value, args[0]);
1479 CONVERT_DOUBLE_CHECKED(from_number, args[1]); 1495 CONVERT_DOUBLE_CHECKED(from_number, args[1]);
1480 CONVERT_DOUBLE_CHECKED(to_number, args[2]); 1496 CONVERT_DOUBLE_CHECKED(to_number, args[2]);
1481 1497
1482 int start = FastD2I(from_number); 1498 int start = FastD2I(from_number);
1483 int end = FastD2I(to_number); 1499 int end = FastD2I(to_number);
1484 1500
1501 StringShape shape(value);
1502
1485 RUNTIME_ASSERT(end >= start); 1503 RUNTIME_ASSERT(end >= start);
1486 RUNTIME_ASSERT(start >= 0); 1504 RUNTIME_ASSERT(start >= 0);
1487 RUNTIME_ASSERT(end <= value->length()); 1505 RUNTIME_ASSERT(end <= value->length(shape));
1488 return value->Slice(start, end); 1506 return value->Slice(shape, start, end);
1489 } 1507 }
1490 1508
1491 1509
1492 static Object* Runtime_NumberToRadixString(Arguments args) { 1510 static Object* Runtime_NumberToRadixString(Arguments args) {
1493 NoHandleAllocation ha; 1511 NoHandleAllocation ha;
1494 ASSERT(args.length() == 2); 1512 ASSERT(args.length() == 2);
1495 1513
1496 CONVERT_DOUBLE_CHECKED(value, args[0]); 1514 CONVERT_DOUBLE_CHECKED(value, args[0]);
1497 if (isnan(value)) { 1515 if (isnan(value)) {
1498 return Heap::AllocateStringFromAscii(CStrVector("NaN")); 1516 return Heap::AllocateStringFromAscii(CStrVector("NaN"));
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
1581 char* str = DoubleToPrecisionCString(value, f); 1599 char* str = DoubleToPrecisionCString(value, f);
1582 Object* res = Heap::AllocateStringFromAscii(CStrVector(str)); 1600 Object* res = Heap::AllocateStringFromAscii(CStrVector(str));
1583 DeleteArray(str); 1601 DeleteArray(str);
1584 return res; 1602 return res;
1585 } 1603 }
1586 1604
1587 1605
1588 // Returns a single character string where first character equals 1606 // Returns a single character string where first character equals
1589 // string->Get(index). 1607 // string->Get(index).
1590 static Handle<Object> GetCharAt(Handle<String> string, uint32_t index) { 1608 static Handle<Object> GetCharAt(Handle<String> string, uint32_t index) {
1591 if (index < static_cast<uint32_t>(string->length())) { 1609 StringShape shape(*string);
1592 string->TryFlatten(); 1610 if (index < static_cast<uint32_t>(string->length(shape))) {
1593 return LookupSingleCharacterStringFromCode(string->Get(index)); 1611 string->TryFlatten(shape); // Invalidates shape!
1612 return LookupSingleCharacterStringFromCode(
1613 string->Get(StringShape(*string), index));
1594 } 1614 }
1595 return Execution::CharAt(string, index); 1615 return Execution::CharAt(string, index);
1596 } 1616 }
1597 1617
1598 1618
1599 Object* Runtime::GetElementOrCharAt(Handle<Object> object, uint32_t index) { 1619 Object* Runtime::GetElementOrCharAt(Handle<Object> object, uint32_t index) {
1600 // Handle [] indexing on Strings 1620 // Handle [] indexing on Strings
1601 if (object->IsString()) { 1621 if (object->IsString()) {
1602 Handle<Object> result = GetCharAt(Handle<String>::cast(object), index); 1622 Handle<Object> result = GetCharAt(Handle<String>::cast(object), index);
1603 if (!result->IsUndefined()) return *result; 1623 if (!result->IsUndefined()) return *result;
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
1768 return *value; 1788 return *value;
1769 } 1789 }
1770 1790
1771 if (key->IsString()) { 1791 if (key->IsString()) {
1772 Handle<Object> result; 1792 Handle<Object> result;
1773 if (Handle<String>::cast(key)->AsArrayIndex(&index)) { 1793 if (Handle<String>::cast(key)->AsArrayIndex(&index)) {
1774 ASSERT(attr == NONE); 1794 ASSERT(attr == NONE);
1775 result = SetElement(js_object, index, value); 1795 result = SetElement(js_object, index, value);
1776 } else { 1796 } else {
1777 Handle<String> key_string = Handle<String>::cast(key); 1797 Handle<String> key_string = Handle<String>::cast(key);
1778 key_string->TryFlatten(); 1798 key_string->TryFlatten(StringShape(*key_string));
1779 result = SetProperty(js_object, key_string, value, attr); 1799 result = SetProperty(js_object, key_string, value, attr);
1780 } 1800 }
1781 if (result.is_null()) return Failure::Exception(); 1801 if (result.is_null()) return Failure::Exception();
1782 return *value; 1802 return *value;
1783 } 1803 }
1784 1804
1785 // Call-back into JavaScript to convert the key to a string. 1805 // Call-back into JavaScript to convert the key to a string.
1786 bool has_pending_exception = false; 1806 bool has_pending_exception = false;
1787 Handle<Object> converted = Execution::ToString(key, &has_pending_exception); 1807 Handle<Object> converted = Execution::ToString(key, &has_pending_exception);
1788 if (has_pending_exception) return Failure::Exception(); 1808 if (has_pending_exception) return Failure::Exception();
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
1859 1879
1860 // Only JS objects can have properties. 1880 // Only JS objects can have properties.
1861 if (args[0]->IsJSObject()) { 1881 if (args[0]->IsJSObject()) {
1862 JSObject* object = JSObject::cast(args[0]); 1882 JSObject* object = JSObject::cast(args[0]);
1863 if (object->HasLocalProperty(key)) return Heap::true_value(); 1883 if (object->HasLocalProperty(key)) return Heap::true_value();
1864 } else if (args[0]->IsString()) { 1884 } else if (args[0]->IsString()) {
1865 // Well, there is one exception: Handle [] on strings. 1885 // Well, there is one exception: Handle [] on strings.
1866 uint32_t index; 1886 uint32_t index;
1867 if (key->AsArrayIndex(&index)) { 1887 if (key->AsArrayIndex(&index)) {
1868 String* string = String::cast(args[0]); 1888 String* string = String::cast(args[0]);
1869 if (index < static_cast<uint32_t>(string->length())) 1889 StringShape shape(string);
1890 if (index < static_cast<uint32_t>(string->length(shape)))
1870 return Heap::true_value(); 1891 return Heap::true_value();
1871 } 1892 }
1872 } 1893 }
1873 return Heap::false_value(); 1894 return Heap::false_value();
1874 } 1895 }
1875 1896
1876 1897
1877 static Object* Runtime_HasProperty(Arguments args) { 1898 static Object* Runtime_HasProperty(Arguments args) {
1878 NoHandleAllocation na; 1899 NoHandleAllocation na;
1879 ASSERT(args.length() == 2); 1900 ASSERT(args.length() == 2);
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
2042 // host objects gives that it is okay to return "object" 2063 // host objects gives that it is okay to return "object"
2043 return Heap::object_symbol(); 2064 return Heap::object_symbol();
2044 } 2065 }
2045 } 2066 }
2046 2067
2047 2068
2048 static Object* Runtime_StringToNumber(Arguments args) { 2069 static Object* Runtime_StringToNumber(Arguments args) {
2049 NoHandleAllocation ha; 2070 NoHandleAllocation ha;
2050 ASSERT(args.length() == 1); 2071 ASSERT(args.length() == 1);
2051 CONVERT_CHECKED(String, subject, args[0]); 2072 CONVERT_CHECKED(String, subject, args[0]);
2052 subject->TryFlatten(); 2073 subject->TryFlatten(StringShape(subject));
2053 return Heap::NumberFromDouble(StringToDouble(subject, ALLOW_HEX)); 2074 return Heap::NumberFromDouble(StringToDouble(subject, ALLOW_HEX));
2054 } 2075 }
2055 2076
2056 2077
2057 static Object* Runtime_StringFromCharCodeArray(Arguments args) { 2078 static Object* Runtime_StringFromCharCodeArray(Arguments args) {
2058 NoHandleAllocation ha; 2079 NoHandleAllocation ha;
2059 ASSERT(args.length() == 1); 2080 ASSERT(args.length() == 1);
2060 2081
2061 CONVERT_CHECKED(JSArray, codes, args[0]); 2082 CONVERT_CHECKED(JSArray, codes, args[0]);
2062 int length = Smi::cast(codes->length())->value(); 2083 int length = Smi::cast(codes->length())->value();
2063 2084
2064 // Check if the string can be ASCII. 2085 // Check if the string can be ASCII.
2065 int i; 2086 int i;
2066 for (i = 0; i < length; i++) { 2087 for (i = 0; i < length; i++) {
2067 Object* element = codes->GetElement(i); 2088 Object* element = codes->GetElement(i);
2068 CONVERT_NUMBER_CHECKED(int, chr, Int32, element); 2089 CONVERT_NUMBER_CHECKED(int, chr, Int32, element);
2069 if ((chr & 0xffff) > String::kMaxAsciiCharCode) 2090 if ((chr & 0xffff) > String::kMaxAsciiCharCode)
2070 break; 2091 break;
2071 } 2092 }
2072 2093
2073 Object* object = NULL; 2094 Object* object = NULL;
2074 if (i == length) { // The string is ASCII. 2095 if (i == length) { // The string is ASCII.
2075 object = Heap::AllocateRawAsciiString(length); 2096 object = Heap::AllocateRawAsciiString(length);
2076 } else { // The string is not ASCII. 2097 } else { // The string is not ASCII.
2077 object = Heap::AllocateRawTwoByteString(length); 2098 object = Heap::AllocateRawTwoByteString(length);
2078 } 2099 }
2079 2100
2080 if (object->IsFailure()) return object; 2101 if (object->IsFailure()) return object;
2081 String* result = String::cast(object); 2102 String* result = String::cast(object);
2103 StringShape result_shape(result);
2082 for (int i = 0; i < length; i++) { 2104 for (int i = 0; i < length; i++) {
2083 Object* element = codes->GetElement(i); 2105 Object* element = codes->GetElement(i);
2084 CONVERT_NUMBER_CHECKED(int, chr, Int32, element); 2106 CONVERT_NUMBER_CHECKED(int, chr, Int32, element);
2085 result->Set(i, chr & 0xffff); 2107 result->Set(result_shape, i, chr & 0xffff);
2086 } 2108 }
2087 return result; 2109 return result;
2088 } 2110 }
2089 2111
2090 2112
2091 // kNotEscaped is generated by the following: 2113 // kNotEscaped is generated by the following:
2092 // 2114 //
2093 // #!/bin/perl 2115 // #!/bin/perl
2094 // for (my $i = 0; $i < 256; $i++) { 2116 // for (my $i = 0; $i < 256; $i++) {
2095 // print "\n" if $i % 16 == 0; 2117 // print "\n" if $i % 16 == 0;
(...skipping 28 matching lines...) Expand all
2124 return kNotEscaped[character] != 0; 2146 return kNotEscaped[character] != 0;
2125 } 2147 }
2126 2148
2127 2149
2128 static Object* Runtime_URIEscape(Arguments args) { 2150 static Object* Runtime_URIEscape(Arguments args) {
2129 const char hex_chars[] = "0123456789ABCDEF"; 2151 const char hex_chars[] = "0123456789ABCDEF";
2130 NoHandleAllocation ha; 2152 NoHandleAllocation ha;
2131 ASSERT(args.length() == 1); 2153 ASSERT(args.length() == 1);
2132 CONVERT_CHECKED(String, source, args[0]); 2154 CONVERT_CHECKED(String, source, args[0]);
2133 2155
2134 source->TryFlatten(); 2156 source->TryFlatten(StringShape(source));
2135 2157
2158 StringShape sshape(source);
Mads Ager (chromium) 2008/11/03 08:45:49 How about source_shape?
2136 int escaped_length = 0; 2159 int escaped_length = 0;
2137 int length = source->length(); 2160 int length = source->length(sshape);
2138 { 2161 {
2139 Access<StringInputBuffer> buffer(&string_input_buffer); 2162 Access<StringInputBuffer> buffer(&string_input_buffer);
2140 buffer->Reset(source); 2163 buffer->Reset(source);
2141 while (buffer->has_more()) { 2164 while (buffer->has_more()) {
2142 uint16_t character = buffer->GetNext(); 2165 uint16_t character = buffer->GetNext();
2143 if (character >= 256) { 2166 if (character >= 256) {
2144 escaped_length += 6; 2167 escaped_length += 6;
2145 } else if (IsNotEscaped(character)) { 2168 } else if (IsNotEscaped(character)) {
2146 escaped_length++; 2169 escaped_length++;
2147 } else { 2170 } else {
2148 escaped_length += 3; 2171 escaped_length += 3;
2149 } 2172 }
2150 // We don't allow strings that are longer than Smi range. 2173 // We don't allow strings that are longer than Smi range.
2151 if (!Smi::IsValid(escaped_length)) { 2174 if (!Smi::IsValid(escaped_length)) {
2152 Top::context()->mark_out_of_memory(); 2175 Top::context()->mark_out_of_memory();
2153 return Failure::OutOfMemoryException(); 2176 return Failure::OutOfMemoryException();
2154 } 2177 }
2155 } 2178 }
2156 } 2179 }
2157 // No length change implies no change. Return original string if no change. 2180 // No length change implies no change. Return original string if no change.
2158 if (escaped_length == length) { 2181 if (escaped_length == length) {
2159 return source; 2182 return source;
2160 } 2183 }
2161 Object* o = Heap::AllocateRawAsciiString(escaped_length); 2184 Object* o = Heap::AllocateRawAsciiString(escaped_length);
2162 if (o->IsFailure()) return o; 2185 if (o->IsFailure()) return o;
2163 String* destination = String::cast(o); 2186 String* destination = String::cast(o);
2187 StringShape dshape(destination);
Mads Ager (chromium) 2008/11/03 08:45:49 dest_shape or even destination_shape?
Erik Corry 2008/11/03 09:33:54 I changed the other one, but I left this in, becau
2164 int dest_position = 0; 2188 int dest_position = 0;
2165 2189
2166 Access<StringInputBuffer> buffer(&string_input_buffer); 2190 Access<StringInputBuffer> buffer(&string_input_buffer);
2167 buffer->Rewind(); 2191 buffer->Rewind();
2168 while (buffer->has_more()) { 2192 while (buffer->has_more()) {
2169 uint16_t character = buffer->GetNext(); 2193 uint16_t chr = buffer->GetNext();
2170 if (character >= 256) { 2194 if (chr >= 256) {
2171 destination->Set(dest_position, '%'); 2195 destination->Set(dshape, dest_position, '%');
2172 destination->Set(dest_position+1, 'u'); 2196 destination->Set(dshape, dest_position+1, 'u');
2173 destination->Set(dest_position+2, hex_chars[character >> 12]); 2197 destination->Set(dshape, dest_position+2, hex_chars[chr >> 12]);
2174 destination->Set(dest_position+3, hex_chars[(character >> 8) & 0xf]); 2198 destination->Set(dshape, dest_position+3, hex_chars[(chr >> 8) & 0xf]);
2175 destination->Set(dest_position+4, hex_chars[(character >> 4) & 0xf]); 2199 destination->Set(dshape, dest_position+4, hex_chars[(chr >> 4) & 0xf]);
2176 destination->Set(dest_position+5, hex_chars[character & 0xf]); 2200 destination->Set(dshape, dest_position+5, hex_chars[chr & 0xf]);
2177 dest_position += 6; 2201 dest_position += 6;
2178 } else if (IsNotEscaped(character)) { 2202 } else if (IsNotEscaped(chr)) {
2179 destination->Set(dest_position, character); 2203 destination->Set(dshape, dest_position, chr);
2180 dest_position++; 2204 dest_position++;
2181 } else { 2205 } else {
2182 destination->Set(dest_position, '%'); 2206 destination->Set(dshape, dest_position, '%');
2183 destination->Set(dest_position+1, hex_chars[character >> 4]); 2207 destination->Set(dshape, dest_position+1, hex_chars[chr >> 4]);
2184 destination->Set(dest_position+2, hex_chars[character & 0xf]); 2208 destination->Set(dshape, dest_position+2, hex_chars[chr & 0xf]);
2185 dest_position += 3; 2209 dest_position += 3;
2186 } 2210 }
2187 } 2211 }
2188 return destination; 2212 return destination;
2189 } 2213 }
2190 2214
2191 2215
2192 static inline int TwoDigitHex(uint16_t character1, uint16_t character2) { 2216 static inline int TwoDigitHex(uint16_t character1, uint16_t character2) {
2193 static const signed char kHexValue['g'] = { 2217 static const signed char kHexValue['g'] = {
2194 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2218 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
2195 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2219 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
2196 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2220 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
2197 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, 2221 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
2198 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2222 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
2199 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2223 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
2200 -1, 10, 11, 12, 13, 14, 15 }; 2224 -1, 10, 11, 12, 13, 14, 15 };
2201 2225
2202 if (character1 > 'f') return -1; 2226 if (character1 > 'f') return -1;
2203 int hi = kHexValue[character1]; 2227 int hi = kHexValue[character1];
2204 if (hi == -1) return -1; 2228 if (hi == -1) return -1;
2205 if (character2 > 'f') return -1; 2229 if (character2 > 'f') return -1;
2206 int lo = kHexValue[character2]; 2230 int lo = kHexValue[character2];
2207 if (lo == -1) return -1; 2231 if (lo == -1) return -1;
2208 return (hi << 4) + lo; 2232 return (hi << 4) + lo;
2209 } 2233 }
2210 2234
2211 2235
2212 static inline int Unescape(String* source, int i, int length, int* step) { 2236 static inline int Unescape(String* source,
2213 uint16_t character = source->Get(i); 2237 StringShape shape,
2238 int i,
2239 int length,
2240 int* step) {
2241 uint16_t character = source->Get(shape, i);
2214 int32_t hi, lo; 2242 int32_t hi, lo;
2215 if (character == '%' && 2243 if (character == '%' &&
2216 i <= length - 6 && 2244 i <= length - 6 &&
2217 source->Get(i + 1) == 'u' && 2245 source->Get(shape, i + 1) == 'u' &&
2218 (hi = TwoDigitHex(source->Get(i + 2), source->Get(i + 3))) != -1 && 2246 (hi = TwoDigitHex(source->Get(shape, i + 2),
2219 (lo = TwoDigitHex(source->Get(i + 4), source->Get(i + 5))) != -1) { 2247 source->Get(shape, i + 3))) != -1 &&
2248 (lo = TwoDigitHex(source->Get(shape, i + 4),
2249 source->Get(shape, i + 5))) != -1) {
2220 *step = 6; 2250 *step = 6;
2221 return (hi << 8) + lo; 2251 return (hi << 8) + lo;
2222 } else if (character == '%' && 2252 } else if (character == '%' &&
2223 i <= length - 3 && 2253 i <= length - 3 &&
2224 (lo = TwoDigitHex(source->Get(i + 1), source->Get(i + 2))) != -1) { 2254 (lo = TwoDigitHex(source->Get(shape, i + 1),
2255 source->Get(shape, i + 2))) != -1) {
2225 *step = 3; 2256 *step = 3;
2226 return lo; 2257 return lo;
2227 } else { 2258 } else {
2228 *step = 1; 2259 *step = 1;
2229 return character; 2260 return character;
2230 } 2261 }
2231 } 2262 }
2232 2263
2233 2264
2234 static Object* Runtime_URIUnescape(Arguments args) { 2265 static Object* Runtime_URIUnescape(Arguments args) {
2235 NoHandleAllocation ha; 2266 NoHandleAllocation ha;
2236 ASSERT(args.length() == 1); 2267 ASSERT(args.length() == 1);
2237 CONVERT_CHECKED(String, source, args[0]); 2268 CONVERT_CHECKED(String, source, args[0]);
2238 2269
2239 source->TryFlatten(); 2270 source->TryFlatten(StringShape(source));
2271 StringShape sshape(source);
Mads Ager (chromium) 2008/11/03 08:45:49 source_shape?
2240 2272
2241 bool ascii = true; 2273 bool ascii = true;
2242 int length = source->length(); 2274 int length = source->length(sshape);
2243 2275
2244 int unescaped_length = 0; 2276 int unescaped_length = 0;
2245 for (int i = 0; i < length; unescaped_length++) { 2277 for (int i = 0; i < length; unescaped_length++) {
2246 int step; 2278 int step;
2247 if (Unescape(source, i, length, &step) > String::kMaxAsciiCharCode) 2279 if (Unescape(source, sshape, i, length, &step) > String::kMaxAsciiCharCode)
2248 ascii = false; 2280 ascii = false;
2249 i += step; 2281 i += step;
2250 } 2282 }
2251 2283
2252 // No length change implies no change. Return original string if no change. 2284 // No length change implies no change. Return original string if no change.
2253 if (unescaped_length == length) 2285 if (unescaped_length == length)
2254 return source; 2286 return source;
2255 2287
2256 Object* o = ascii ? 2288 Object* o = ascii ?
2257 Heap::AllocateRawAsciiString(unescaped_length) : 2289 Heap::AllocateRawAsciiString(unescaped_length) :
2258 Heap::AllocateRawTwoByteString(unescaped_length); 2290 Heap::AllocateRawTwoByteString(unescaped_length);
2259 if (o->IsFailure()) return o; 2291 if (o->IsFailure()) return o;
2260 String* destination = String::cast(o); 2292 String* destination = String::cast(o);
2293 StringShape dshape(destination);
Mads Ager (chromium) 2008/11/03 08:45:49 destination_shape?
2261 2294
2262 int dest_position = 0; 2295 int dest_position = 0;
2263 for (int i = 0; i < length; dest_position++) { 2296 for (int i = 0; i < length; dest_position++) {
2264 int step; 2297 int step;
2265 destination->Set(dest_position, Unescape(source, i, length, &step)); 2298 destination->Set(dshape,
2299 dest_position,
2300 Unescape(source, sshape, i, length, &step));
2266 i += step; 2301 i += step;
2267 } 2302 }
2268 return destination; 2303 return destination;
2269 } 2304 }
2270 2305
2271 2306
2272 static Object* Runtime_StringParseInt(Arguments args) { 2307 static Object* Runtime_StringParseInt(Arguments args) {
2273 NoHandleAllocation ha; 2308 NoHandleAllocation ha;
2274 2309
2275 CONVERT_CHECKED(String, s, args[0]); 2310 CONVERT_CHECKED(String, s, args[0]);
2276 CONVERT_DOUBLE_CHECKED(n, args[1]); 2311 CONVERT_DOUBLE_CHECKED(n, args[1]);
2277 int radix = FastD2I(n); 2312 int radix = FastD2I(n);
2278 2313
2279 s->TryFlatten(); 2314 s->TryFlatten(StringShape(s));
2280 2315
2281 int len = s->length(); 2316 StringShape shape(s);
2317
2318 int len = s->length(shape);
2282 int i; 2319 int i;
2283 2320
2284 // Skip leading white space. 2321 // Skip leading white space.
2285 for (i = 0; i < len && Scanner::kIsWhiteSpace.get(s->Get(i)); i++) ; 2322 for (i = 0; i < len && Scanner::kIsWhiteSpace.get(s->Get(shape, i)); i++) ;
2286 if (i == len) return Heap::nan_value(); 2323 if (i == len) return Heap::nan_value();
2287 2324
2288 // Compute the sign (default to +). 2325 // Compute the sign (default to +).
2289 int sign = 1; 2326 int sign = 1;
2290 if (s->Get(i) == '-') { 2327 if (s->Get(shape, i) == '-') {
2291 sign = -1; 2328 sign = -1;
2292 i++; 2329 i++;
2293 } else if (s->Get(i) == '+') { 2330 } else if (s->Get(shape, i) == '+') {
2294 i++; 2331 i++;
2295 } 2332 }
2296 2333
2297 // Compute the radix if 0. 2334 // Compute the radix if 0.
2298 if (radix == 0) { 2335 if (radix == 0) {
2299 radix = 10; 2336 radix = 10;
2300 if (i < len && s->Get(i) == '0') { 2337 if (i < len && s->Get(shape, i) == '0') {
2301 radix = 8; 2338 radix = 8;
2302 if (i + 1 < len) { 2339 if (i + 1 < len) {
2303 int c = s->Get(i + 1); 2340 int c = s->Get(shape, i + 1);
2304 if (c == 'x' || c == 'X') { 2341 if (c == 'x' || c == 'X') {
2305 radix = 16; 2342 radix = 16;
2306 i += 2; 2343 i += 2;
2307 } 2344 }
2308 } 2345 }
2309 } 2346 }
2310 } else if (radix == 16) { 2347 } else if (radix == 16) {
2311 // Allow 0x or 0X prefix if radix is 16. 2348 // Allow 0x or 0X prefix if radix is 16.
2312 if (i + 1 < len && s->Get(i) == '0') { 2349 if (i + 1 < len && s->Get(shape, i) == '0') {
2313 int c = s->Get(i + 1); 2350 int c = s->Get(shape, i + 1);
2314 if (c == 'x' || c == 'X') i += 2; 2351 if (c == 'x' || c == 'X') i += 2;
2315 } 2352 }
2316 } 2353 }
2317 2354
2318 RUNTIME_ASSERT(2 <= radix && radix <= 36); 2355 RUNTIME_ASSERT(2 <= radix && radix <= 36);
2319 double value; 2356 double value;
2320 int end_index = StringToInt(s, i, radix, &value); 2357 int end_index = StringToInt(s, i, radix, &value);
2321 if (end_index != i) { 2358 if (end_index != i) {
2322 return Heap::NumberFromDouble(sign * value); 2359 return Heap::NumberFromDouble(sign * value);
2323 } 2360 }
(...skipping 16 matching lines...) Expand all
2340 static unibrow::Mapping<unibrow::ToUppercase, 128> to_upper_mapping; 2377 static unibrow::Mapping<unibrow::ToUppercase, 128> to_upper_mapping;
2341 static unibrow::Mapping<unibrow::ToLowercase, 128> to_lower_mapping; 2378 static unibrow::Mapping<unibrow::ToLowercase, 128> to_lower_mapping;
2342 2379
2343 2380
2344 template <class Converter> 2381 template <class Converter>
2345 static Object* ConvertCase(Arguments args, 2382 static Object* ConvertCase(Arguments args,
2346 unibrow::Mapping<Converter, 128>* mapping) { 2383 unibrow::Mapping<Converter, 128>* mapping) {
2347 NoHandleAllocation ha; 2384 NoHandleAllocation ha;
2348 2385
2349 CONVERT_CHECKED(String, s, args[0]); 2386 CONVERT_CHECKED(String, s, args[0]);
2350 int raw_string_length = s->length(); 2387 s->TryFlatten(StringShape(s));
2388 StringShape shape(s);
2389
2390 int raw_string_length = s->length(shape);
2351 // Assume that the string is not empty; we need this assumption later 2391 // Assume that the string is not empty; we need this assumption later
2352 if (raw_string_length == 0) return s; 2392 if (raw_string_length == 0) return s;
2353 int length = raw_string_length; 2393 int length = raw_string_length;
2354 2394
2355 s->TryFlatten();
2356 2395
2357 // We try this twice, once with the assumption that the result is 2396 // We try this twice, once with the assumption that the result is
2358 // no longer than the input and, if that assumption breaks, again 2397 // no longer than the input and, if that assumption breaks, again
2359 // with the exact length. This is implemented using a goto back 2398 // with the exact length. This is implemented using a goto back
2360 // to this label if we discover that the assumption doesn't hold. 2399 // to this label if we discover that the assumption doesn't hold.
2361 // I apologize sincerely for this and will give a vaffel-is to 2400 // I apologize sincerely for this and will give a vaffel-is to
2362 // the first person who can implement it in a nicer way. 2401 // the first person who can implement it in a nicer way.
2363 try_convert: 2402 try_convert:
2364 2403
2365 // Allocate the resulting string. 2404 // Allocate the resulting string.
2366 // 2405 //
2367 // NOTE: This assumes that the upper/lower case of an ascii 2406 // NOTE: This assumes that the upper/lower case of an ascii
2368 // character is also ascii. This is currently the case, but it 2407 // character is also ascii. This is currently the case, but it
2369 // might break in the future if we implement more context and locale 2408 // might break in the future if we implement more context and locale
2370 // dependent upper/lower conversions. 2409 // dependent upper/lower conversions.
2371 Object* o = s->IsAsciiRepresentation() 2410 Object* o = shape.IsAsciiRepresentation()
2372 ? Heap::AllocateRawAsciiString(length) 2411 ? Heap::AllocateRawAsciiString(length)
2373 : Heap::AllocateRawTwoByteString(length); 2412 : Heap::AllocateRawTwoByteString(length);
2374 if (o->IsFailure()) return o; 2413 if (o->IsFailure()) return o;
2375 String* result = String::cast(o); 2414 String* result = String::cast(o);
2415 StringShape result_shape(result);
2376 bool has_changed_character = false; 2416 bool has_changed_character = false;
2377 2417
2378 // Convert all characters to upper case, assuming that they will fit 2418 // Convert all characters to upper case, assuming that they will fit
2379 // in the buffer 2419 // in the buffer
2380 Access<StringInputBuffer> buffer(&string_input_buffer); 2420 Access<StringInputBuffer> buffer(&string_input_buffer);
2381 buffer->Reset(s); 2421 buffer->Reset(s);
2382 unibrow::uchar chars[unibrow::kMaxCaseConvertedSize]; 2422 unibrow::uchar chars[unibrow::kMaxCaseConvertedSize];
2383 int i = 0; 2423 int i = 0;
2384 // We can assume that the string is not empty 2424 // We can assume that the string is not empty
2385 uc32 current = buffer->GetNext(); 2425 uc32 current = buffer->GetNext();
2386 while (i < length) { 2426 while (i < length) {
2387 bool has_next = buffer->has_more(); 2427 bool has_next = buffer->has_more();
2388 uc32 next = has_next ? buffer->GetNext() : 0; 2428 uc32 next = has_next ? buffer->GetNext() : 0;
2389 int char_length = mapping->get(current, next, chars); 2429 int char_length = mapping->get(current, next, chars);
2390 if (char_length == 0) { 2430 if (char_length == 0) {
2391 // The case conversion of this character is the character itself. 2431 // The case conversion of this character is the character itself.
2392 result->Set(i, current); 2432 result->Set(result_shape, i, current);
2393 i++; 2433 i++;
2394 } else if (char_length == 1) { 2434 } else if (char_length == 1) {
2395 // Common case: converting the letter resulted in one character. 2435 // Common case: converting the letter resulted in one character.
2396 ASSERT(static_cast<uc32>(chars[0]) != current); 2436 ASSERT(static_cast<uc32>(chars[0]) != current);
2397 result->Set(i, chars[0]); 2437 result->Set(result_shape, i, chars[0]);
2398 has_changed_character = true; 2438 has_changed_character = true;
2399 i++; 2439 i++;
2400 } else if (length == raw_string_length) { 2440 } else if (length == raw_string_length) {
2401 // We've assumed that the result would be as long as the 2441 // We've assumed that the result would be as long as the
2402 // input but here is a character that converts to several 2442 // input but here is a character that converts to several
2403 // characters. No matter, we calculate the exact length 2443 // characters. No matter, we calculate the exact length
2404 // of the result and try the whole thing again. 2444 // of the result and try the whole thing again.
2405 // 2445 //
2406 // Note that this leaves room for optimization. We could just 2446 // Note that this leaves room for optimization. We could just
2407 // memcpy what we already have to the result string. Also, 2447 // memcpy what we already have to the result string. Also,
(...skipping 14 matching lines...) Expand all
2422 // it does not in any case affect the length of what it convert 2462 // it does not in any case affect the length of what it convert
2423 // to. 2463 // to.
2424 int char_length = mapping->get(current, 0, chars); 2464 int char_length = mapping->get(current, 0, chars);
2425 if (char_length == 0) char_length = 1; 2465 if (char_length == 0) char_length = 1;
2426 current_length += char_length; 2466 current_length += char_length;
2427 } 2467 }
2428 length = current_length; 2468 length = current_length;
2429 goto try_convert; 2469 goto try_convert;
2430 } else { 2470 } else {
2431 for (int j = 0; j < char_length; j++) { 2471 for (int j = 0; j < char_length; j++) {
2432 result->Set(i, chars[j]); 2472 result->Set(result_shape, i, chars[j]);
2433 i++; 2473 i++;
2434 } 2474 }
2435 has_changed_character = true; 2475 has_changed_character = true;
2436 } 2476 }
2437 current = next; 2477 current = next;
2438 } 2478 }
2439 if (has_changed_character) { 2479 if (has_changed_character) {
2440 return result; 2480 return result;
2441 } else { 2481 } else {
2442 // If we didn't actually change anything in doing the conversion 2482 // If we didn't actually change anything in doing the conversion
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
2606 return Heap::NewNumberFromDouble(x); 2646 return Heap::NewNumberFromDouble(x);
2607 } 2647 }
2608 2648
2609 2649
2610 static Object* Runtime_StringAdd(Arguments args) { 2650 static Object* Runtime_StringAdd(Arguments args) {
2611 NoHandleAllocation ha; 2651 NoHandleAllocation ha;
2612 ASSERT(args.length() == 2); 2652 ASSERT(args.length() == 2);
2613 2653
2614 CONVERT_CHECKED(String, str1, args[0]); 2654 CONVERT_CHECKED(String, str1, args[0]);
2615 CONVERT_CHECKED(String, str2, args[1]); 2655 CONVERT_CHECKED(String, str2, args[1]);
2616 int len1 = str1->length(); 2656 StringShape shape1(str1);
2617 int len2 = str2->length(); 2657 StringShape shape2(str2);
2658 int len1 = str1->length(shape1);
2659 int len2 = str2->length(shape2);
2618 if (len1 == 0) return str2; 2660 if (len1 == 0) return str2;
2619 if (len2 == 0) return str1; 2661 if (len2 == 0) return str1;
2620 int length_sum = len1 + len2; 2662 int length_sum = len1 + len2;
2621 // Make sure that an out of memory exception is thrown if the length 2663 // Make sure that an out of memory exception is thrown if the length
2622 // of the new cons string is too large to fit in a Smi. 2664 // of the new cons string is too large to fit in a Smi.
2623 if (length_sum > Smi::kMaxValue || length_sum < 0) { 2665 if (length_sum > Smi::kMaxValue || length_sum < 0) {
2624 Top::context()->mark_out_of_memory(); 2666 Top::context()->mark_out_of_memory();
2625 return Failure::OutOfMemoryException(); 2667 return Failure::OutOfMemoryException();
2626 } 2668 }
2627 return Heap::AllocateConsString(str1, str2); 2669 return Heap::AllocateConsString(str1, shape1, str2, shape2);
2628 } 2670 }
2629 2671
2630 2672
2631 template<typename sinkchar> 2673 template<typename sinkchar>
2632 static inline void StringBuilderConcatHelper(String* special, 2674 static inline void StringBuilderConcatHelper(String* special,
2675 StringShape special_shape,
2633 sinkchar* sink, 2676 sinkchar* sink,
2634 FixedArray* fixed_array, 2677 FixedArray* fixed_array,
2635 int array_length) { 2678 int array_length) {
2636 int position = 0; 2679 int position = 0;
2637 for (int i = 0; i < array_length; i++) { 2680 for (int i = 0; i < array_length; i++) {
2638 Object* element = fixed_array->get(i); 2681 Object* element = fixed_array->get(i);
2639 if (element->IsSmi()) { 2682 if (element->IsSmi()) {
2640 int len = Smi::cast(element)->value(); 2683 int len = Smi::cast(element)->value();
2641 int pos = len >> 11; 2684 int pos = len >> 11;
2642 len &= 0x7ff; 2685 len &= 0x7ff;
2643 String::WriteToFlat(special, sink + position, pos, pos + len); 2686 String::WriteToFlat(special,
2687 special_shape,
2688 sink + position,
2689 pos,
2690 pos + len);
2644 position += len; 2691 position += len;
2645 } else { 2692 } else {
2646 String* string = String::cast(element); 2693 String* string = String::cast(element);
2647 int element_length = string->length(); 2694 StringShape shape(string);
2648 String::WriteToFlat(string, sink + position, 0, element_length); 2695 int element_length = string->length(shape);
2696 String::WriteToFlat(string, shape, sink + position, 0, element_length);
2649 position += element_length; 2697 position += element_length;
2650 } 2698 }
2651 } 2699 }
2652 } 2700 }
2653 2701
2654 2702
2655 static Object* Runtime_StringBuilderConcat(Arguments args) { 2703 static Object* Runtime_StringBuilderConcat(Arguments args) {
2656 NoHandleAllocation ha; 2704 NoHandleAllocation ha;
2657 ASSERT(args.length() == 2); 2705 ASSERT(args.length() == 2);
2658 CONVERT_CHECKED(JSArray, array, args[0]); 2706 CONVERT_CHECKED(JSArray, array, args[0]);
2659 CONVERT_CHECKED(String, special, args[1]); 2707 CONVERT_CHECKED(String, special, args[1]);
2660 int special_length = special->length(); 2708 StringShape special_shape(special);
2709 int special_length = special->length(special_shape);
2661 Object* smi_array_length = array->length(); 2710 Object* smi_array_length = array->length();
2662 if (!smi_array_length->IsSmi()) { 2711 if (!smi_array_length->IsSmi()) {
2663 Top::context()->mark_out_of_memory(); 2712 Top::context()->mark_out_of_memory();
2664 return Failure::OutOfMemoryException(); 2713 return Failure::OutOfMemoryException();
2665 } 2714 }
2666 int array_length = Smi::cast(smi_array_length)->value(); 2715 int array_length = Smi::cast(smi_array_length)->value();
2667 if (!array->HasFastElements()) { 2716 if (!array->HasFastElements()) {
2668 return Top::Throw(Heap::illegal_argument_symbol()); 2717 return Top::Throw(Heap::illegal_argument_symbol());
2669 } 2718 }
2670 FixedArray* fixed_array = FixedArray::cast(array->elements()); 2719 FixedArray* fixed_array = FixedArray::cast(array->elements());
2671 if (fixed_array->length() < array_length) { 2720 if (fixed_array->length() < array_length) {
2672 array_length = fixed_array->length(); 2721 array_length = fixed_array->length();
2673 } 2722 }
2674 2723
2675 if (array_length == 0) { 2724 if (array_length == 0) {
2676 return Heap::empty_string(); 2725 return Heap::empty_string();
2677 } else if (array_length == 1) { 2726 } else if (array_length == 1) {
2678 Object* first = fixed_array->get(0); 2727 Object* first = fixed_array->get(0);
2679 if (first->IsString()) return first; 2728 if (first->IsString()) return first;
2680 } 2729 }
2681 2730
2682 bool ascii = special->IsAsciiRepresentation(); 2731 bool ascii = special_shape.IsAsciiRepresentation();
2683 int position = 0; 2732 int position = 0;
2684 for (int i = 0; i < array_length; i++) { 2733 for (int i = 0; i < array_length; i++) {
2685 Object* elt = fixed_array->get(i); 2734 Object* elt = fixed_array->get(i);
2686 if (elt->IsSmi()) { 2735 if (elt->IsSmi()) {
2687 int len = Smi::cast(elt)->value(); 2736 int len = Smi::cast(elt)->value();
2688 int pos = len >> 11; 2737 int pos = len >> 11;
2689 len &= 0x7ff; 2738 len &= 0x7ff;
2690 if (pos + len > special_length) { 2739 if (pos + len > special_length) {
2691 return Top::Throw(Heap::illegal_argument_symbol()); 2740 return Top::Throw(Heap::illegal_argument_symbol());
2692 } 2741 }
2693 position += len; 2742 position += len;
2694 } else if (elt->IsString()) { 2743 } else if (elt->IsString()) {
2695 String* element = String::cast(elt); 2744 String* element = String::cast(elt);
2696 int element_length = element->length(); 2745 StringShape element_shape(element);
2746 int element_length = element->length(element_shape);
2697 if (!Smi::IsValid(element_length + position)) { 2747 if (!Smi::IsValid(element_length + position)) {
2698 Top::context()->mark_out_of_memory(); 2748 Top::context()->mark_out_of_memory();
2699 return Failure::OutOfMemoryException(); 2749 return Failure::OutOfMemoryException();
2700 } 2750 }
2701 position += element_length; 2751 position += element_length;
2702 if (ascii && !element->IsAsciiRepresentation()) { 2752 if (ascii && !element_shape.IsAsciiRepresentation()) {
2703 ascii = false; 2753 ascii = false;
2704 } 2754 }
2705 } else { 2755 } else {
2706 return Top::Throw(Heap::illegal_argument_symbol()); 2756 return Top::Throw(Heap::illegal_argument_symbol());
2707 } 2757 }
2708 } 2758 }
2709 2759
2710 int length = position; 2760 int length = position;
2711 Object* object; 2761 Object* object;
2712 2762
2713 if (ascii) { 2763 if (ascii) {
2714 object = Heap::AllocateRawAsciiString(length); 2764 object = Heap::AllocateRawAsciiString(length);
2715 if (object->IsFailure()) return object; 2765 if (object->IsFailure()) return object;
2716 SeqAsciiString* answer = SeqAsciiString::cast(object); 2766 SeqAsciiString* answer = SeqAsciiString::cast(object);
2717 StringBuilderConcatHelper(special, 2767 StringBuilderConcatHelper(special,
2768 special_shape,
2718 answer->GetChars(), 2769 answer->GetChars(),
2719 fixed_array, 2770 fixed_array,
2720 array_length); 2771 array_length);
2721 return answer; 2772 return answer;
2722 } else { 2773 } else {
2723 object = Heap::AllocateRawTwoByteString(length); 2774 object = Heap::AllocateRawTwoByteString(length);
2724 if (object->IsFailure()) return object; 2775 if (object->IsFailure()) return object;
2725 SeqTwoByteString* answer = SeqTwoByteString::cast(object); 2776 SeqTwoByteString* answer = SeqTwoByteString::cast(object);
2726 StringBuilderConcatHelper(special, 2777 StringBuilderConcatHelper(special,
2778 special_shape,
2727 answer->GetChars(), 2779 answer->GetChars(),
2728 fixed_array, 2780 fixed_array,
2729 array_length); 2781 array_length);
2730 return answer; 2782 return answer;
2731 } 2783 }
2732 } 2784 }
2733 2785
2734 2786
2735 static Object* Runtime_NumberOr(Arguments args) { 2787 static Object* Runtime_NumberOr(Arguments args) {
2736 NoHandleAllocation ha; 2788 NoHandleAllocation ha;
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
2911 } 2963 }
2912 2964
2913 2965
2914 static Object* Runtime_StringCompare(Arguments args) { 2966 static Object* Runtime_StringCompare(Arguments args) {
2915 NoHandleAllocation ha; 2967 NoHandleAllocation ha;
2916 ASSERT(args.length() == 2); 2968 ASSERT(args.length() == 2);
2917 2969
2918 CONVERT_CHECKED(String, x, args[0]); 2970 CONVERT_CHECKED(String, x, args[0]);
2919 CONVERT_CHECKED(String, y, args[1]); 2971 CONVERT_CHECKED(String, y, args[1]);
2920 2972
2973 StringShape x_shape(x);
2974 StringShape y_shape(y);
2975
2921 // A few fast case tests before we flatten. 2976 // A few fast case tests before we flatten.
2922 if (x == y) return Smi::FromInt(EQUAL); 2977 if (x == y) return Smi::FromInt(EQUAL);
2923 if (y->length() == 0) { 2978 if (y->length(y_shape) == 0) {
2924 if (x->length() == 0) return Smi::FromInt(EQUAL); 2979 if (x->length(x_shape) == 0) return Smi::FromInt(EQUAL);
2925 return Smi::FromInt(GREATER); 2980 return Smi::FromInt(GREATER);
2926 } else if (x->length() == 0) { 2981 } else if (x->length(x_shape) == 0) {
2927 return Smi::FromInt(LESS); 2982 return Smi::FromInt(LESS);
2928 } 2983 }
2929 2984
2930 int d = x->Get(0) - y->Get(0); 2985 int d = x->Get(x_shape, 0) - y->Get(y_shape, 0);
2931 if (d < 0) return Smi::FromInt(LESS); 2986 if (d < 0) return Smi::FromInt(LESS);
2932 else if (d > 0) return Smi::FromInt(GREATER); 2987 else if (d > 0) return Smi::FromInt(GREATER);
2933 2988
2934 x->TryFlatten(); 2989 x->TryFlatten(x_shape); // Shapes are no longer valid!
2935 y->TryFlatten(); 2990 y->TryFlatten(y_shape);
2936 2991
2937 static StringInputBuffer bufx; 2992 static StringInputBuffer bufx;
2938 static StringInputBuffer bufy; 2993 static StringInputBuffer bufy;
2939 bufx.Reset(x); 2994 bufx.Reset(x);
2940 bufy.Reset(y); 2995 bufy.Reset(y);
2941 while (bufx.has_more() && bufy.has_more()) { 2996 while (bufx.has_more() && bufy.has_more()) {
2942 int d = bufx.GetNext() - bufy.GetNext(); 2997 int d = bufx.GetNext() - bufy.GetNext();
2943 if (d < 0) return Smi::FromInt(LESS); 2998 if (d < 0) return Smi::FromInt(LESS);
2944 else if (d > 0) return Smi::FromInt(GREATER); 2999 else if (d > 0) return Smi::FromInt(GREATER);
2945 } 3000 }
(...skipping 2841 matching lines...) Expand 10 before | Expand all | Expand 10 after
5787 } else { 5842 } else {
5788 // Handle last resort GC and make sure to allow future allocations 5843 // Handle last resort GC and make sure to allow future allocations
5789 // to grow the heap without causing GCs (if possible). 5844 // to grow the heap without causing GCs (if possible).
5790 Counters::gc_last_resort_from_js.Increment(); 5845 Counters::gc_last_resort_from_js.Increment();
5791 Heap::CollectAllGarbage(); 5846 Heap::CollectAllGarbage();
5792 } 5847 }
5793 } 5848 }
5794 5849
5795 5850
5796 } } // namespace v8::internal 5851 } } // namespace v8::internal
OLDNEW
« src/objects-inl.h ('K') | « src/property.h ('k') | test/cctest/test-heap.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698