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

Side by Side Diff: src/heap.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 759 matching lines...) Expand 10 before | Expand all | Expand 10 after
770 // copied. 770 // copied.
771 if (first_word.IsForwardingAddress()) { 771 if (first_word.IsForwardingAddress()) {
772 *p = first_word.ToForwardingAddress(); 772 *p = first_word.ToForwardingAddress();
773 return; 773 return;
774 } 774 }
775 775
776 // Call the slow part of scavenge object. 776 // Call the slow part of scavenge object.
777 return ScavengeObjectSlow(p, object); 777 return ScavengeObjectSlow(p, object);
778 } 778 }
779 779
780
780 static inline bool IsShortcutCandidate(HeapObject* object, Map* map) { 781 static inline bool IsShortcutCandidate(HeapObject* object, Map* map) {
781 // A ConString object with Heap::empty_string() as the right side 782 // A ConsString object with Heap::empty_string() as the right side
782 // is a candidate for being shortcut by the scavenger. 783 // is a candidate for being shortcut by the scavenger.
783 ASSERT(object->map() == map); 784 ASSERT(object->map() == map);
784 return (map->instance_type() < FIRST_NONSTRING_TYPE) && 785 if (map->instance_type() >= FIRST_NONSTRING_TYPE) return false;
785 (String::cast(object)->map_representation_tag(map) == kConsStringTag) && 786 StringShape shape(map);
786 (ConsString::cast(object)->second() == Heap::empty_string()); 787 return (shape.representation_tag() == kConsStringTag) &&
788 (ConsString::cast(object)->unchecked_second() == Heap::empty_string());
787 } 789 }
788 790
789 791
790 void Heap::ScavengeObjectSlow(HeapObject** p, HeapObject* object) { 792 void Heap::ScavengeObjectSlow(HeapObject** p, HeapObject* object) {
791 ASSERT(InFromSpace(object)); 793 ASSERT(InFromSpace(object));
792 MapWord first_word = object->map_word(); 794 MapWord first_word = object->map_word();
793 ASSERT(!first_word.IsForwardingAddress()); 795 ASSERT(!first_word.IsForwardingAddress());
794 796
795 // Optimization: Bypass flattened ConsString objects. 797 // Optimization: Bypass flattened ConsString objects.
796 if (IsShortcutCandidate(object, first_word.ToMap())) { 798 if (IsShortcutCandidate(object, first_word.ToMap())) {
797 object = HeapObject::cast(ConsString::cast(object)->first()); 799 object = HeapObject::cast(ConsString::cast(object)->unchecked_first());
798 *p = object; 800 *p = object;
799 // After patching *p we have to repeat the checks that object is in the 801 // After patching *p we have to repeat the checks that object is in the
800 // active semispace of the young generation and not already copied. 802 // active semispace of the young generation and not already copied.
801 if (!InNewSpace(object)) return; 803 if (!InNewSpace(object)) return;
802 first_word = object->map_word(); 804 first_word = object->map_word();
803 if (first_word.IsForwardingAddress()) { 805 if (first_word.IsForwardingAddress()) {
804 *p = first_word.ToForwardingAddress(); 806 *p = first_word.ToForwardingAddress();
805 return; 807 return;
806 } 808 }
807 } 809 }
(...skipping 529 matching lines...) Expand 10 before | Expand all | Expand 10 after
1337 share->set_instance_class_name(Object_symbol()); 1339 share->set_instance_class_name(Object_symbol());
1338 share->set_function_data(undefined_value()); 1340 share->set_function_data(undefined_value());
1339 share->set_lazy_load_data(undefined_value()); 1341 share->set_lazy_load_data(undefined_value());
1340 share->set_script(undefined_value()); 1342 share->set_script(undefined_value());
1341 share->set_start_position_and_type(0); 1343 share->set_start_position_and_type(0);
1342 share->set_debug_info(undefined_value()); 1344 share->set_debug_info(undefined_value());
1343 return result; 1345 return result;
1344 } 1346 }
1345 1347
1346 1348
1347 Object* Heap::AllocateConsString(String* first, String* second) { 1349 Object* Heap::AllocateConsString(String* first, StringShape first_shape, String* second, StringShape second_shape) {
Mads Ager (chromium) 2008/11/03 08:45:49 Isn't this line too long?
1348 int first_length = first->length(); 1350 int first_length = first->length(first_shape);
1349 int second_length = second->length(); 1351 int second_length = second->length(second_shape);
1350 int length = first_length + second_length; 1352 int length = first_length + second_length;
1351 bool is_ascii = first->is_ascii_representation() 1353 bool is_ascii = first_shape.IsAsciiRepresentation()
1352 && second->is_ascii_representation(); 1354 && second_shape.IsAsciiRepresentation();
1353 1355
1354 // If the resulting string is small make a flat string. 1356 // If the resulting string is small make a flat string.
1355 if (length < String::kMinNonFlatLength) { 1357 if (length < String::kMinNonFlatLength) {
1356 ASSERT(first->IsFlat()); 1358 ASSERT(first->IsFlat(first_shape));
1357 ASSERT(second->IsFlat()); 1359 ASSERT(second->IsFlat(second_shape));
1358 if (is_ascii) { 1360 if (is_ascii) {
1359 Object* result = AllocateRawAsciiString(length); 1361 Object* result = AllocateRawAsciiString(length);
1360 if (result->IsFailure()) return result; 1362 if (result->IsFailure()) return result;
1361 // Copy the characters into the new object. 1363 // Copy the characters into the new object.
1362 char* dest = SeqAsciiString::cast(result)->GetChars(); 1364 char* dest = SeqAsciiString::cast(result)->GetChars();
1363 String::WriteToFlat(first, dest, 0, first_length); 1365 String::WriteToFlat(first, first_shape, dest, 0, first_length);
1364 String::WriteToFlat(second, dest + first_length, 0, second_length); 1366 String::WriteToFlat(second, second_shape, dest + first_length, 0, second_l ength);
1365 return result; 1367 return result;
1366 } else { 1368 } else {
1367 Object* result = AllocateRawTwoByteString(length); 1369 Object* result = AllocateRawTwoByteString(length);
1368 if (result->IsFailure()) return result; 1370 if (result->IsFailure()) return result;
1369 // Copy the characters into the new object. 1371 // Copy the characters into the new object.
1370 uc16* dest = SeqTwoByteString::cast(result)->GetChars(); 1372 uc16* dest = SeqTwoByteString::cast(result)->GetChars();
1371 String::WriteToFlat(first, dest, 0, first_length); 1373 String::WriteToFlat(first, first_shape, dest, 0, first_length);
1372 String::WriteToFlat(second, dest + first_length, 0, second_length); 1374 String::WriteToFlat(second, second_shape, dest + first_length, 0, second_l ength);
1373 return result; 1375 return result;
1374 } 1376 }
1375 } 1377 }
1376 1378
1377 Map* map; 1379 Map* map;
1378 if (length <= String::kMaxShortStringSize) { 1380 if (length <= String::kMaxShortStringSize) {
1379 map = is_ascii ? short_cons_ascii_string_map() 1381 map = is_ascii ? short_cons_ascii_string_map()
1380 : short_cons_string_map(); 1382 : short_cons_string_map();
1381 } else if (length <= String::kMaxMediumStringSize) { 1383 } else if (length <= String::kMaxMediumStringSize) {
1382 map = is_ascii ? medium_cons_ascii_string_map() 1384 map = is_ascii ? medium_cons_ascii_string_map()
1383 : medium_cons_string_map(); 1385 : medium_cons_string_map();
1384 } else { 1386 } else {
1385 map = is_ascii ? long_cons_ascii_string_map() 1387 map = is_ascii ? long_cons_ascii_string_map()
1386 : long_cons_string_map(); 1388 : long_cons_string_map();
1387 } 1389 }
1388 1390
1389 Object* result = Allocate(map, NEW_SPACE); 1391 Object* result = Allocate(map, NEW_SPACE);
1390 if (result->IsFailure()) return result; 1392 if (result->IsFailure()) return result;
1391 ASSERT(InNewSpace(result)); 1393 ASSERT(InNewSpace(result));
1392 ConsString* cons_string = ConsString::cast(result); 1394 ConsString* cons_string = ConsString::cast(result);
1393 cons_string->set_first(first, SKIP_WRITE_BARRIER); 1395 cons_string->set_first(first, SKIP_WRITE_BARRIER);
1394 cons_string->set_second(second, SKIP_WRITE_BARRIER); 1396 cons_string->set_second(second, SKIP_WRITE_BARRIER);
1395 cons_string->set_length(length); 1397 cons_string->set_length(length);
1396 return result; 1398 return result;
1397 } 1399 }
1398 1400
1399 1401
1400 Object* Heap::AllocateSlicedString(String* buffer, int start, int end) { 1402 Object* Heap::AllocateSlicedString(String* buffer,
1403 StringShape buffer_shape,
1404 int start,
1405 int end) {
1401 int length = end - start; 1406 int length = end - start;
1402 1407
1403 // If the resulting string is small make a sub string. 1408 // If the resulting string is small make a sub string.
1404 if (end - start <= String::kMinNonFlatLength) { 1409 if (end - start <= String::kMinNonFlatLength) {
1405 return Heap::AllocateSubString(buffer, start, end); 1410 return Heap::AllocateSubString(buffer, buffer_shape, start, end);
1406 } 1411 }
1407 1412
1408 Map* map; 1413 Map* map;
1409 if (length <= String::kMaxShortStringSize) { 1414 if (length <= String::kMaxShortStringSize) {
1410 map = buffer->is_ascii_representation() ? short_sliced_ascii_string_map() 1415 map = buffer_shape.IsAsciiRepresentation() ?
1411 : short_sliced_string_map(); 1416 short_sliced_ascii_string_map() :
1417 short_sliced_string_map();
1412 } else if (length <= String::kMaxMediumStringSize) { 1418 } else if (length <= String::kMaxMediumStringSize) {
1413 map = buffer->is_ascii_representation() ? medium_sliced_ascii_string_map() 1419 map = buffer_shape.IsAsciiRepresentation() ?
1414 : medium_sliced_string_map(); 1420 medium_sliced_ascii_string_map() :
1421 medium_sliced_string_map();
1415 } else { 1422 } else {
1416 map = buffer->is_ascii_representation() ? long_sliced_ascii_string_map() 1423 map = buffer_shape.IsAsciiRepresentation() ?
1417 : long_sliced_string_map(); 1424 long_sliced_ascii_string_map() :
1425 long_sliced_string_map();
1418 } 1426 }
1419 1427
1420 Object* result = Allocate(map, NEW_SPACE); 1428 Object* result = Allocate(map, NEW_SPACE);
1421 if (result->IsFailure()) return result; 1429 if (result->IsFailure()) return result;
1422 1430
1423 SlicedString* sliced_string = SlicedString::cast(result); 1431 SlicedString* sliced_string = SlicedString::cast(result);
1424 sliced_string->set_buffer(buffer); 1432 sliced_string->set_buffer(buffer);
1425 sliced_string->set_start(start); 1433 sliced_string->set_start(start);
1426 sliced_string->set_length(length); 1434 sliced_string->set_length(length);
1427 1435
1428 return result; 1436 return result;
1429 } 1437 }
1430 1438
1431 1439
1432 Object* Heap::AllocateSubString(String* buffer, int start, int end) { 1440 Object* Heap::AllocateSubString(String* buffer,
1441 StringShape buffer_shape,
1442 int start,
1443 int end) {
1433 int length = end - start; 1444 int length = end - start;
1434 1445
1435 if (length == 1) { 1446 if (length == 1) {
1436 return Heap::LookupSingleCharacterStringFromCode(buffer->Get(start)); 1447 return Heap::LookupSingleCharacterStringFromCode(
1448 buffer->Get(buffer_shape, start));
1437 } 1449 }
1438 1450
1439 // Make an attempt to flatten the buffer to reduce access time. 1451 // Make an attempt to flatten the buffer to reduce access time.
1440 buffer->TryFlatten(); 1452 if (!buffer->IsFlat(buffer_shape)) {
1453 buffer->TryFlatten(buffer_shape);
1454 buffer_shape = buffer;
Mads Ager (chromium) 2008/11/03 08:45:49 Please make the conversion explicit here.
1455 }
1441 1456
1442 Object* result = buffer->is_ascii_representation() 1457 Object* result = buffer_shape.IsAsciiRepresentation()
1443 ? AllocateRawAsciiString(length) 1458 ? AllocateRawAsciiString(length)
1444 : AllocateRawTwoByteString(length); 1459 : AllocateRawTwoByteString(length);
1445 if (result->IsFailure()) return result; 1460 if (result->IsFailure()) return result;
1446 1461
1447 // Copy the characters into the new object. 1462 // Copy the characters into the new object.
1448 String* string_result = String::cast(result); 1463 String* string_result = String::cast(result);
1464 StringShape result_shape(string_result);
1449 StringHasher hasher(length); 1465 StringHasher hasher(length);
1450 int i = 0; 1466 int i = 0;
1451 for (; i < length && hasher.is_array_index(); i++) { 1467 for (; i < length && hasher.is_array_index(); i++) {
1452 uc32 c = buffer->Get(start + i); 1468 uc32 c = buffer->Get(buffer_shape, start + i);
1453 hasher.AddCharacter(c); 1469 hasher.AddCharacter(c);
1454 string_result->Set(i, c); 1470 string_result->Set(result_shape, i, c);
1455 } 1471 }
1456 for (; i < length; i++) { 1472 for (; i < length; i++) {
1457 uc32 c = buffer->Get(start + i); 1473 uc32 c = buffer->Get(buffer_shape, start + i);
1458 hasher.AddCharacterNoIndex(c); 1474 hasher.AddCharacterNoIndex(c);
1459 string_result->Set(i, c); 1475 string_result->Set(result_shape, i, c);
1460 } 1476 }
1461 string_result->set_length_field(hasher.GetHashField()); 1477 string_result->set_length_field(hasher.GetHashField());
1462 return result; 1478 return result;
1463 } 1479 }
1464 1480
1465 1481
1466 Object* Heap::AllocateExternalStringFromAscii( 1482 Object* Heap::AllocateExternalStringFromAscii(
1467 ExternalAsciiString::Resource* resource) { 1483 ExternalAsciiString::Resource* resource) {
1468 Map* map; 1484 Map* map;
1469 int length = resource->length(); 1485 int length = resource->length();
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
1518 buffer[0] = static_cast<char>(code); 1534 buffer[0] = static_cast<char>(code);
1519 Object* result = LookupSymbol(Vector<const char>(buffer, 1)); 1535 Object* result = LookupSymbol(Vector<const char>(buffer, 1));
1520 1536
1521 if (result->IsFailure()) return result; 1537 if (result->IsFailure()) return result;
1522 Heap::single_character_string_cache()->set(code, result); 1538 Heap::single_character_string_cache()->set(code, result);
1523 return result; 1539 return result;
1524 } 1540 }
1525 1541
1526 Object* result = Heap::AllocateRawTwoByteString(1); 1542 Object* result = Heap::AllocateRawTwoByteString(1);
1527 if (result->IsFailure()) return result; 1543 if (result->IsFailure()) return result;
1528 String::cast(result)->Set(0, code); 1544 String* answer = String::cast(result);
1529 return result; 1545 answer->Set(StringShape(answer), 0, code);
1546 return answer;
1530 } 1547 }
1531 1548
1532 1549
1533 Object* Heap::AllocateByteArray(int length) { 1550 Object* Heap::AllocateByteArray(int length) {
1534 int size = ByteArray::SizeFor(length); 1551 int size = ByteArray::SizeFor(length);
1535 AllocationSpace space = 1552 AllocationSpace space =
1536 size > MaxHeapObjectSize() ? LO_SPACE : NEW_SPACE; 1553 size > MaxHeapObjectSize() ? LO_SPACE : NEW_SPACE;
1537 1554
1538 Object* result = AllocateRaw(size, space, OLD_DATA_SPACE); 1555 Object* result = AllocateRaw(size, space, OLD_DATA_SPACE);
1539 1556
(...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after
1898 // If the string is ascii, we do not need to convert the characters 1915 // If the string is ascii, we do not need to convert the characters
1899 // since UTF8 is backwards compatible with ascii. 1916 // since UTF8 is backwards compatible with ascii.
1900 if (is_ascii) return AllocateStringFromAscii(string, pretenure); 1917 if (is_ascii) return AllocateStringFromAscii(string, pretenure);
1901 1918
1902 Object* result = AllocateRawTwoByteString(chars, pretenure); 1919 Object* result = AllocateRawTwoByteString(chars, pretenure);
1903 if (result->IsFailure()) return result; 1920 if (result->IsFailure()) return result;
1904 1921
1905 // Convert and copy the characters into the new object. 1922 // Convert and copy the characters into the new object.
1906 String* string_result = String::cast(result); 1923 String* string_result = String::cast(result);
1907 decoder->Reset(string.start(), string.length()); 1924 decoder->Reset(string.start(), string.length());
1925 StringShape result_shape(string_result);
1908 for (int i = 0; i < chars; i++) { 1926 for (int i = 0; i < chars; i++) {
1909 uc32 r = decoder->GetNext(); 1927 uc32 r = decoder->GetNext();
1910 string_result->Set(i, r); 1928 string_result->Set(result_shape, i, r);
1911 } 1929 }
1912 return result; 1930 return result;
1913 } 1931 }
1914 1932
1915 1933
1916 Object* Heap::AllocateStringFromTwoByte(Vector<const uc16> string, 1934 Object* Heap::AllocateStringFromTwoByte(Vector<const uc16> string,
1917 PretenureFlag pretenure) { 1935 PretenureFlag pretenure) {
1918 // Check if the string is an ASCII string. 1936 // Check if the string is an ASCII string.
1919 int i = 0; 1937 int i = 0;
1920 while (i < string.length() && string[i] <= String::kMaxAsciiCharCode) i++; 1938 while (i < string.length() && string[i] <= String::kMaxAsciiCharCode) i++;
1921 1939
1922 Object* result; 1940 Object* result;
1923 if (i == string.length()) { // It's an ASCII string. 1941 if (i == string.length()) { // It's an ASCII string.
1924 result = AllocateRawAsciiString(string.length(), pretenure); 1942 result = AllocateRawAsciiString(string.length(), pretenure);
1925 } else { // It's not an ASCII string. 1943 } else { // It's not an ASCII string.
1926 result = AllocateRawTwoByteString(string.length(), pretenure); 1944 result = AllocateRawTwoByteString(string.length(), pretenure);
1927 } 1945 }
1928 if (result->IsFailure()) return result; 1946 if (result->IsFailure()) return result;
1929 1947
1930 // Copy the characters into the new object, which may be either ASCII or 1948 // Copy the characters into the new object, which may be either ASCII or
1931 // UTF-16. 1949 // UTF-16.
1932 String* string_result = String::cast(result); 1950 String* string_result = String::cast(result);
1951 StringShape result_shape(string_result);
1933 for (int i = 0; i < string.length(); i++) { 1952 for (int i = 0; i < string.length(); i++) {
1934 string_result->Set(i, string[i]); 1953 string_result->Set(result_shape, i, string[i]);
1935 } 1954 }
1936 return result; 1955 return result;
1937 } 1956 }
1938 1957
1939 1958
1940 Map* Heap::SymbolMapForString(String* string) { 1959 Map* Heap::SymbolMapForString(String* string) {
1941 // If the string is in new space it cannot be used as a symbol. 1960 // If the string is in new space it cannot be used as a symbol.
1942 if (InNewSpace(string)) return NULL; 1961 if (InNewSpace(string)) return NULL;
1943 1962
1944 // Find the corresponding symbol map for strings. 1963 // Find the corresponding symbol map for strings.
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
2036 } 2055 }
2037 2056
2038 // Allocate string. 2057 // Allocate string.
2039 AllocationSpace space = 2058 AllocationSpace space =
2040 (size > MaxHeapObjectSize()) ? LO_SPACE : OLD_DATA_SPACE; 2059 (size > MaxHeapObjectSize()) ? LO_SPACE : OLD_DATA_SPACE;
2041 Object* result = AllocateRaw(size, space, OLD_DATA_SPACE); 2060 Object* result = AllocateRaw(size, space, OLD_DATA_SPACE);
2042 if (result->IsFailure()) return result; 2061 if (result->IsFailure()) return result;
2043 2062
2044 reinterpret_cast<HeapObject*>(result)->set_map(map); 2063 reinterpret_cast<HeapObject*>(result)->set_map(map);
2045 // The hash value contains the length of the string. 2064 // The hash value contains the length of the string.
2046 String::cast(result)->set_length_field(length_field); 2065 String* answer = String::cast(result);
2066 StringShape answer_shape(answer);
2067 answer->set_length_field(length_field);
2047 2068
2048 ASSERT_EQ(size, String::cast(result)->Size()); 2069 ASSERT_EQ(size, answer->Size());
2049 2070
2050 // Fill in the characters. 2071 // Fill in the characters.
2051 for (int i = 0; i < chars; i++) { 2072 for (int i = 0; i < chars; i++) {
2052 String::cast(result)->Set(i, buffer->GetNext()); 2073 answer->Set(answer_shape, i, buffer->GetNext());
2053 } 2074 }
2054 return result; 2075 return answer;
2055 } 2076 }
2056 2077
2057 2078
2058 Object* Heap::AllocateRawAsciiString(int length, PretenureFlag pretenure) { 2079 Object* Heap::AllocateRawAsciiString(int length, PretenureFlag pretenure) {
2059 AllocationSpace space = (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE; 2080 AllocationSpace space = (pretenure == TENURED) ? OLD_DATA_SPACE : NEW_SPACE;
2060 int size = SeqAsciiString::SizeFor(length); 2081 int size = SeqAsciiString::SizeFor(length);
2061 if (size > MaxHeapObjectSize()) { 2082 if (size > MaxHeapObjectSize()) {
2062 space = LO_SPACE; 2083 space = LO_SPACE;
2063 } 2084 }
2064 2085
(...skipping 1155 matching lines...) Expand 10 before | Expand all | Expand 10 after
3220 #ifdef DEBUG 3241 #ifdef DEBUG
3221 bool Heap::GarbageCollectionGreedyCheck() { 3242 bool Heap::GarbageCollectionGreedyCheck() {
3222 ASSERT(FLAG_gc_greedy); 3243 ASSERT(FLAG_gc_greedy);
3223 if (Bootstrapper::IsActive()) return true; 3244 if (Bootstrapper::IsActive()) return true;
3224 if (disallow_allocation_failure()) return true; 3245 if (disallow_allocation_failure()) return true;
3225 return CollectGarbage(0, NEW_SPACE); 3246 return CollectGarbage(0, NEW_SPACE);
3226 } 3247 }
3227 #endif 3248 #endif
3228 3249
3229 } } // namespace v8::internal 3250 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698