| OLD | NEW |
| 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 1251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1262 // is big enough to be a ByteArray with at least one extra word (the next | 1262 // is big enough to be a ByteArray with at least one extra word (the next |
| 1263 // pointer), we set its map to be the byte array map and its size to an | 1263 // pointer), we set its map to be the byte array map and its size to an |
| 1264 // appropriate array length for the desired size from HeapObject::Size(). | 1264 // appropriate array length for the desired size from HeapObject::Size(). |
| 1265 // If the block is too small (eg, one or two words), to hold both a size | 1265 // If the block is too small (eg, one or two words), to hold both a size |
| 1266 // field and a next pointer, we give it a filler map that gives it the | 1266 // field and a next pointer, we give it a filler map that gives it the |
| 1267 // correct size. | 1267 // correct size. |
| 1268 if (size_in_bytes > ByteArray::kHeaderSize) { | 1268 if (size_in_bytes > ByteArray::kHeaderSize) { |
| 1269 set_map(Heap::byte_array_map()); | 1269 set_map(Heap::byte_array_map()); |
| 1270 ByteArray::cast(this)->set_length(ByteArray::LengthFor(size_in_bytes)); | 1270 ByteArray::cast(this)->set_length(ByteArray::LengthFor(size_in_bytes)); |
| 1271 } else if (size_in_bytes == kPointerSize) { | 1271 } else if (size_in_bytes == kPointerSize) { |
| 1272 set_map(Heap::one_word_filler_map()); | 1272 set_map(Heap::one_pointer_filler_map()); |
| 1273 } else if (size_in_bytes == 2 * kPointerSize) { | 1273 } else if (size_in_bytes == 2 * kPointerSize) { |
| 1274 set_map(Heap::two_word_filler_map()); | 1274 set_map(Heap::two_pointer_filler_map()); |
| 1275 } else { | 1275 } else { |
| 1276 UNREACHABLE(); | 1276 UNREACHABLE(); |
| 1277 } | 1277 } |
| 1278 ASSERT(Size() == size_in_bytes); | 1278 ASSERT(Size() == size_in_bytes); |
| 1279 } | 1279 } |
| 1280 | 1280 |
| 1281 | 1281 |
| 1282 Address FreeListNode::next() { | 1282 Address FreeListNode::next() { |
| 1283 ASSERT(map() == Heap::byte_array_map()); | 1283 ASSERT(map() == Heap::byte_array_map() || |
| 1284 ASSERT(Size() >= kNextOffset + kPointerSize); | 1284 map() == Heap::two_pointer_filler_map()); |
| 1285 return Memory::Address_at(address() + kNextOffset); | 1285 if (map() == Heap::byte_array_map()) { |
| 1286 ASSERT(Size() >= kNextOffset + kPointerSize); |
| 1287 return Memory::Address_at(address() + kNextOffset); |
| 1288 } else { |
| 1289 return Memory::Address_at(address() + kPointerSize); |
| 1290 } |
| 1286 } | 1291 } |
| 1287 | 1292 |
| 1288 | 1293 |
| 1289 void FreeListNode::set_next(Address next) { | 1294 void FreeListNode::set_next(Address next) { |
| 1290 ASSERT(map() == Heap::byte_array_map()); | 1295 ASSERT(map() == Heap::byte_array_map() || |
| 1291 ASSERT(Size() >= kNextOffset + kPointerSize); | 1296 map() == Heap::two_pointer_filler_map()); |
| 1292 Memory::Address_at(address() + kNextOffset) = next; | 1297 if (map() == Heap::byte_array_map()) { |
| 1298 ASSERT(Size() >= kNextOffset + kPointerSize); |
| 1299 Memory::Address_at(address() + kNextOffset) = next; |
| 1300 } else { |
| 1301 Memory::Address_at(address() + kPointerSize) = next; |
| 1302 } |
| 1293 } | 1303 } |
| 1294 | 1304 |
| 1295 | 1305 |
| 1296 OldSpaceFreeList::OldSpaceFreeList(AllocationSpace owner) : owner_(owner) { | 1306 OldSpaceFreeList::OldSpaceFreeList(AllocationSpace owner) : owner_(owner) { |
| 1297 Reset(); | 1307 Reset(); |
| 1298 } | 1308 } |
| 1299 | 1309 |
| 1300 | 1310 |
| 1301 void OldSpaceFreeList::Reset() { | 1311 void OldSpaceFreeList::Reset() { |
| 1302 available_ = 0; | 1312 available_ = 0; |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1438 FreeListNode* cur_node = FreeListNode::FromAddress(cur_addr); | 1448 FreeListNode* cur_node = FreeListNode::FromAddress(cur_addr); |
| 1439 if (cur_node == node) return true; | 1449 if (cur_node == node) return true; |
| 1440 cur_addr = cur_node->next(); | 1450 cur_addr = cur_node->next(); |
| 1441 } | 1451 } |
| 1442 } | 1452 } |
| 1443 return false; | 1453 return false; |
| 1444 } | 1454 } |
| 1445 #endif | 1455 #endif |
| 1446 | 1456 |
| 1447 | 1457 |
| 1448 MapSpaceFreeList::MapSpaceFreeList(AllocationSpace owner) { | 1458 FixedSizeFreeList::FixedSizeFreeList(AllocationSpace owner, int object_size) |
| 1449 owner_ = owner; | 1459 : owner_(owner), object_size_(object_size) { |
| 1450 Reset(); | 1460 Reset(); |
| 1451 } | 1461 } |
| 1452 | 1462 |
| 1453 | 1463 |
| 1454 void MapSpaceFreeList::Reset() { | 1464 void FixedSizeFreeList::Reset() { |
| 1455 available_ = 0; | 1465 available_ = 0; |
| 1456 head_ = NULL; | 1466 head_ = NULL; |
| 1457 } | 1467 } |
| 1458 | 1468 |
| 1459 | 1469 |
| 1460 void MapSpaceFreeList::Free(Address start) { | 1470 void FixedSizeFreeList::Free(Address start) { |
| 1461 #ifdef DEBUG | 1471 #ifdef DEBUG |
| 1462 for (int i = 0; i < Map::kSize; i += kPointerSize) { | 1472 for (int i = 0; i < object_size_; i += kPointerSize) { |
| 1463 Memory::Address_at(start + i) = kZapValue; | 1473 Memory::Address_at(start + i) = kZapValue; |
| 1464 } | 1474 } |
| 1465 #endif | 1475 #endif |
| 1466 ASSERT(!FLAG_always_compact); // We only use the freelists with mark-sweep. | 1476 ASSERT(!FLAG_always_compact); // We only use the freelists with mark-sweep. |
| 1467 FreeListNode* node = FreeListNode::FromAddress(start); | 1477 FreeListNode* node = FreeListNode::FromAddress(start); |
| 1468 node->set_size(Map::kSize); | 1478 node->set_size(object_size_); |
| 1469 node->set_next(head_); | 1479 node->set_next(head_); |
| 1470 head_ = node->address(); | 1480 head_ = node->address(); |
| 1471 available_ += Map::kSize; | 1481 available_ += object_size_; |
| 1472 } | 1482 } |
| 1473 | 1483 |
| 1474 | 1484 |
| 1475 Object* MapSpaceFreeList::Allocate() { | 1485 Object* FixedSizeFreeList::Allocate() { |
| 1476 if (head_ == NULL) { | 1486 if (head_ == NULL) { |
| 1477 return Failure::RetryAfterGC(Map::kSize, owner_); | 1487 return Failure::RetryAfterGC(object_size_, owner_); |
| 1478 } | 1488 } |
| 1479 | 1489 |
| 1480 ASSERT(!FLAG_always_compact); // We only use the freelists with mark-sweep. | 1490 ASSERT(!FLAG_always_compact); // We only use the freelists with mark-sweep. |
| 1481 FreeListNode* node = FreeListNode::FromAddress(head_); | 1491 FreeListNode* node = FreeListNode::FromAddress(head_); |
| 1482 head_ = node->next(); | 1492 head_ = node->next(); |
| 1483 available_ -= Map::kSize; | 1493 available_ -= object_size_; |
| 1484 return node; | 1494 return node; |
| 1485 } | 1495 } |
| 1486 | 1496 |
| 1487 | 1497 |
| 1488 // ----------------------------------------------------------------------------- | 1498 // ----------------------------------------------------------------------------- |
| 1489 // OldSpace implementation | 1499 // OldSpace implementation |
| 1490 | 1500 |
| 1491 void OldSpace::PrepareForMarkCompact(bool will_compact) { | 1501 void OldSpace::PrepareForMarkCompact(bool will_compact) { |
| 1492 if (will_compact) { | 1502 if (will_compact) { |
| 1493 // Reset relocation info. During a compacting collection, everything in | 1503 // Reset relocation info. During a compacting collection, everything in |
| 1494 // the space is considered 'available' and we will rediscover live data | 1504 // the space is considered 'available' and we will rediscover live data |
| 1495 // and waste during the collection. | 1505 // and waste during the collection. |
| 1496 MCResetRelocationInfo(); | 1506 MCResetRelocationInfo(); |
| 1497 mc_end_of_relocation_ = bottom(); | |
| 1498 ASSERT(Available() == Capacity()); | 1507 ASSERT(Available() == Capacity()); |
| 1499 } else { | 1508 } else { |
| 1500 // During a non-compacting collection, everything below the linear | 1509 // During a non-compacting collection, everything below the linear |
| 1501 // allocation pointer is considered allocated (everything above is | 1510 // allocation pointer is considered allocated (everything above is |
| 1502 // available) and we will rediscover available and wasted bytes during | 1511 // available) and we will rediscover available and wasted bytes during |
| 1503 // the collection. | 1512 // the collection. |
| 1504 accounting_stats_.AllocateBytes(free_list_.available()); | 1513 accounting_stats_.AllocateBytes(free_list_.available()); |
| 1505 accounting_stats_.FillWastedBytes(Waste()); | 1514 accounting_stats_.FillWastedBytes(Waste()); |
| 1506 } | 1515 } |
| 1507 | 1516 |
| 1508 // Clear the free list before a full GC---it will be rebuilt afterward. | 1517 // Clear the free list before a full GC---it will be rebuilt afterward. |
| 1509 free_list_.Reset(); | 1518 free_list_.Reset(); |
| 1510 } | 1519 } |
| 1511 | 1520 |
| 1512 | 1521 |
| 1513 void OldSpace::MCAdjustRelocationEnd(Address address, int size_in_bytes) { | |
| 1514 ASSERT(Contains(address)); | |
| 1515 Address current_top = mc_end_of_relocation_; | |
| 1516 Page* current_page = Page::FromAllocationTop(current_top); | |
| 1517 | |
| 1518 // No more objects relocated to this page? Move to the next. | |
| 1519 ASSERT(current_top <= current_page->mc_relocation_top); | |
| 1520 if (current_top == current_page->mc_relocation_top) { | |
| 1521 // The space should already be properly expanded. | |
| 1522 Page* next_page = current_page->next_page(); | |
| 1523 CHECK(next_page->is_valid()); | |
| 1524 mc_end_of_relocation_ = next_page->ObjectAreaStart(); | |
| 1525 } | |
| 1526 ASSERT(mc_end_of_relocation_ == address); | |
| 1527 mc_end_of_relocation_ += size_in_bytes; | |
| 1528 } | |
| 1529 | |
| 1530 | |
| 1531 void OldSpace::MCCommitRelocationInfo() { | 1522 void OldSpace::MCCommitRelocationInfo() { |
| 1532 // Update fast allocation info. | 1523 // Update fast allocation info. |
| 1533 allocation_info_.top = mc_forwarding_info_.top; | 1524 allocation_info_.top = mc_forwarding_info_.top; |
| 1534 allocation_info_.limit = mc_forwarding_info_.limit; | 1525 allocation_info_.limit = mc_forwarding_info_.limit; |
| 1535 ASSERT(allocation_info_.VerifyPagedAllocation()); | 1526 ASSERT(allocation_info_.VerifyPagedAllocation()); |
| 1536 | 1527 |
| 1537 // The space is compacted and we haven't yet built free lists or | 1528 // The space is compacted and we haven't yet built free lists or |
| 1538 // wasted any space. | 1529 // wasted any space. |
| 1539 ASSERT(Waste() == 0); | 1530 ASSERT(Waste() == 0); |
| 1540 ASSERT(AvailableFree() == 0); | 1531 ASSERT(AvailableFree() == 0); |
| (...skipping 439 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1980 p->AllocationTop()); | 1971 p->AllocationTop()); |
| 1981 PrintF("\n"); | 1972 PrintF("\n"); |
| 1982 } | 1973 } |
| 1983 } | 1974 } |
| 1984 | 1975 |
| 1985 | 1976 |
| 1986 void OldSpace::PrintRSet() { DoPrintRSet("old"); } | 1977 void OldSpace::PrintRSet() { DoPrintRSet("old"); } |
| 1987 #endif | 1978 #endif |
| 1988 | 1979 |
| 1989 // ----------------------------------------------------------------------------- | 1980 // ----------------------------------------------------------------------------- |
| 1990 // MapSpace implementation | 1981 // FixedSpace implementation |
| 1991 | 1982 |
| 1992 void MapSpace::PrepareForMarkCompact(bool will_compact) { | 1983 void FixedSpace::PrepareForMarkCompact(bool will_compact) { |
| 1993 if (will_compact) { | 1984 if (will_compact) { |
| 1994 // Reset relocation info. | 1985 // Reset relocation info. |
| 1995 MCResetRelocationInfo(); | 1986 MCResetRelocationInfo(); |
| 1996 | 1987 |
| 1997 // Initialize map index entry. | |
| 1998 int page_count = 0; | |
| 1999 PageIterator it(this, PageIterator::ALL_PAGES); | |
| 2000 while (it.has_next()) { | |
| 2001 ASSERT_MAP_PAGE_INDEX(page_count); | |
| 2002 | |
| 2003 Page* p = it.next(); | |
| 2004 ASSERT(p->mc_page_index == page_count); | |
| 2005 | |
| 2006 page_addresses_[page_count++] = p->address(); | |
| 2007 } | |
| 2008 | |
| 2009 // During a compacting collection, everything in the space is considered | 1988 // During a compacting collection, everything in the space is considered |
| 2010 // 'available' (set by the call to MCResetRelocationInfo) and we will | 1989 // 'available' (set by the call to MCResetRelocationInfo) and we will |
| 2011 // rediscover live and wasted bytes during the collection. | 1990 // rediscover live and wasted bytes during the collection. |
| 2012 ASSERT(Available() == Capacity()); | 1991 ASSERT(Available() == Capacity()); |
| 2013 } else { | 1992 } else { |
| 2014 // During a non-compacting collection, everything below the linear | 1993 // During a non-compacting collection, everything below the linear |
| 2015 // allocation pointer except wasted top-of-page blocks is considered | 1994 // allocation pointer except wasted top-of-page blocks is considered |
| 2016 // allocated and we will rediscover available bytes during the | 1995 // allocated and we will rediscover available bytes during the |
| 2017 // collection. | 1996 // collection. |
| 2018 accounting_stats_.AllocateBytes(free_list_.available()); | 1997 accounting_stats_.AllocateBytes(free_list_.available()); |
| 2019 } | 1998 } |
| 2020 | 1999 |
| 2021 // Clear the free list before a full GC---it will be rebuilt afterward. | 2000 // Clear the free list before a full GC---it will be rebuilt afterward. |
| 2022 free_list_.Reset(); | 2001 free_list_.Reset(); |
| 2023 } | 2002 } |
| 2024 | 2003 |
| 2025 | 2004 |
| 2026 void MapSpace::MCCommitRelocationInfo() { | 2005 void FixedSpace::MCCommitRelocationInfo() { |
| 2027 // Update fast allocation info. | 2006 // Update fast allocation info. |
| 2028 allocation_info_.top = mc_forwarding_info_.top; | 2007 allocation_info_.top = mc_forwarding_info_.top; |
| 2029 allocation_info_.limit = mc_forwarding_info_.limit; | 2008 allocation_info_.limit = mc_forwarding_info_.limit; |
| 2030 ASSERT(allocation_info_.VerifyPagedAllocation()); | 2009 ASSERT(allocation_info_.VerifyPagedAllocation()); |
| 2031 | 2010 |
| 2032 // The space is compacted and we haven't yet wasted any space. | 2011 // The space is compacted and we haven't yet wasted any space. |
| 2033 ASSERT(Waste() == 0); | 2012 ASSERT(Waste() == 0); |
| 2034 | 2013 |
| 2035 // Update allocation_top of each page in use and compute waste. | 2014 // Update allocation_top of each page in use and compute waste. |
| 2036 int computed_size = 0; | 2015 int computed_size = 0; |
| 2037 PageIterator it(this, PageIterator::PAGES_USED_BY_MC); | 2016 PageIterator it(this, PageIterator::PAGES_USED_BY_MC); |
| 2038 while (it.has_next()) { | 2017 while (it.has_next()) { |
| 2039 Page* page = it.next(); | 2018 Page* page = it.next(); |
| 2040 Address page_top = page->AllocationTop(); | 2019 Address page_top = page->AllocationTop(); |
| 2041 computed_size += page_top - page->ObjectAreaStart(); | 2020 computed_size += page_top - page->ObjectAreaStart(); |
| 2042 if (it.has_next()) { | 2021 if (it.has_next()) { |
| 2043 accounting_stats_.WasteBytes(page->ObjectAreaEnd() - page_top); | 2022 accounting_stats_.WasteBytes(page->ObjectAreaEnd() - page_top); |
| 2044 } | 2023 } |
| 2045 } | 2024 } |
| 2046 | 2025 |
| 2047 // Make sure the computed size - based on the used portion of the | 2026 // Make sure the computed size - based on the used portion of the |
| 2048 // pages in use - matches the size we adjust during allocation. | 2027 // pages in use - matches the size we adjust during allocation. |
| 2049 ASSERT(computed_size == Size()); | 2028 ASSERT(computed_size == Size()); |
| 2050 } | 2029 } |
| 2051 | 2030 |
| 2052 | 2031 |
| 2053 // Slow case for normal allocation. Try in order: (1) allocate in the next | 2032 // Slow case for normal allocation. Try in order: (1) allocate in the next |
| 2054 // page in the space, (2) allocate off the space's free list, (3) expand the | 2033 // page in the space, (2) allocate off the space's free list, (3) expand the |
| 2055 // space, (4) fail. | 2034 // space, (4) fail. |
| 2056 HeapObject* MapSpace::SlowAllocateRaw(int size_in_bytes) { | 2035 HeapObject* FixedSpace::SlowAllocateRaw(int size_in_bytes) { |
| 2036 ASSERT_EQ(object_size_in_bytes_, size_in_bytes); |
| 2057 // Linear allocation in this space has failed. If there is another page | 2037 // Linear allocation in this space has failed. If there is another page |
| 2058 // in the space, move to that page and allocate there. This allocation | 2038 // in the space, move to that page and allocate there. This allocation |
| 2059 // should succeed. | 2039 // should succeed. |
| 2060 Page* current_page = TopPageOf(allocation_info_); | 2040 Page* current_page = TopPageOf(allocation_info_); |
| 2061 if (current_page->next_page()->is_valid()) { | 2041 if (current_page->next_page()->is_valid()) { |
| 2062 return AllocateInNextPage(current_page, size_in_bytes); | 2042 return AllocateInNextPage(current_page, size_in_bytes); |
| 2063 } | 2043 } |
| 2064 | 2044 |
| 2065 // There is no next page in this space. Try free list allocation. The | 2045 // There is no next page in this space. Try free list allocation. |
| 2066 // map space free list implicitly assumes that all free blocks are map | 2046 // The fixed space free list implicitly assumes that all free blocks |
| 2067 // sized. | 2047 // are of the fixed size. |
| 2068 if (size_in_bytes == Map::kSize) { | 2048 if (size_in_bytes == object_size_in_bytes_) { |
| 2069 Object* result = free_list_.Allocate(); | 2049 Object* result = free_list_.Allocate(); |
| 2070 if (!result->IsFailure()) { | 2050 if (!result->IsFailure()) { |
| 2071 accounting_stats_.AllocateBytes(size_in_bytes); | 2051 accounting_stats_.AllocateBytes(size_in_bytes); |
| 2072 return HeapObject::cast(result); | 2052 return HeapObject::cast(result); |
| 2073 } | 2053 } |
| 2074 } | 2054 } |
| 2075 | 2055 |
| 2076 // Free list allocation failed and there is no next page. Fail if we have | 2056 // Free list allocation failed and there is no next page. Fail if we have |
| 2077 // hit the old generation size limit that should cause a garbage | 2057 // hit the old generation size limit that should cause a garbage |
| 2078 // collection. | 2058 // collection. |
| 2079 if (!Heap::always_allocate() && Heap::OldGenerationAllocationLimitReached()) { | 2059 if (!Heap::always_allocate() && Heap::OldGenerationAllocationLimitReached()) { |
| 2080 return NULL; | 2060 return NULL; |
| 2081 } | 2061 } |
| 2082 | 2062 |
| 2083 // Try to expand the space and allocate in the new next page. | 2063 // Try to expand the space and allocate in the new next page. |
| 2084 ASSERT(!current_page->next_page()->is_valid()); | 2064 ASSERT(!current_page->next_page()->is_valid()); |
| 2085 if (Expand(current_page)) { | 2065 if (Expand(current_page)) { |
| 2086 return AllocateInNextPage(current_page, size_in_bytes); | 2066 return AllocateInNextPage(current_page, size_in_bytes); |
| 2087 } | 2067 } |
| 2088 | 2068 |
| 2089 // Finally, fail. | 2069 // Finally, fail. |
| 2090 return NULL; | 2070 return NULL; |
| 2091 } | 2071 } |
| 2092 | 2072 |
| 2093 | 2073 |
| 2094 // Move to the next page (there is assumed to be one) and allocate there. | 2074 // Move to the next page (there is assumed to be one) and allocate there. |
| 2095 // The top of page block is always wasted, because it is too small to hold a | 2075 // The top of page block is always wasted, because it is too small to hold a |
| 2096 // map. | 2076 // map. |
| 2097 HeapObject* MapSpace::AllocateInNextPage(Page* current_page, | 2077 HeapObject* FixedSpace::AllocateInNextPage(Page* current_page, |
| 2098 int size_in_bytes) { | 2078 int size_in_bytes) { |
| 2099 ASSERT(current_page->next_page()->is_valid()); | 2079 ASSERT(current_page->next_page()->is_valid()); |
| 2100 ASSERT(current_page->ObjectAreaEnd() - allocation_info_.top == kPageExtra); | 2080 ASSERT(current_page->ObjectAreaEnd() - allocation_info_.top == page_extra_); |
| 2101 accounting_stats_.WasteBytes(kPageExtra); | 2081 ASSERT_EQ(object_size_in_bytes_, size_in_bytes); |
| 2082 accounting_stats_.WasteBytes(page_extra_); |
| 2102 SetAllocationInfo(&allocation_info_, current_page->next_page()); | 2083 SetAllocationInfo(&allocation_info_, current_page->next_page()); |
| 2103 return AllocateLinearly(&allocation_info_, size_in_bytes); | 2084 return AllocateLinearly(&allocation_info_, size_in_bytes); |
| 2104 } | 2085 } |
| 2105 | 2086 |
| 2106 | 2087 |
| 2107 #ifdef DEBUG | 2088 #ifdef DEBUG |
| 2108 // We do not assume that the PageIterator works, because it depends on the | 2089 // We do not assume that the PageIterator works, because it depends on the |
| 2109 // invariants we are checking during verification. | 2090 // invariants we are checking during verification. |
| 2110 void MapSpace::Verify() { | 2091 void FixedSpace::Verify() { |
| 2111 // The allocation pointer should be valid, and it should be in a page in the | 2092 // The allocation pointer should be valid, and it should be in a page in the |
| 2112 // space. | 2093 // space. |
| 2113 ASSERT(allocation_info_.VerifyPagedAllocation()); | 2094 ASSERT(allocation_info_.VerifyPagedAllocation()); |
| 2114 Page* top_page = Page::FromAllocationTop(allocation_info_.top); | 2095 Page* top_page = Page::FromAllocationTop(allocation_info_.top); |
| 2115 ASSERT(MemoryAllocator::IsPageInSpace(top_page, this)); | 2096 ASSERT(MemoryAllocator::IsPageInSpace(top_page, this)); |
| 2116 | 2097 |
| 2117 // Loop over all the pages. | 2098 // Loop over all the pages. |
| 2118 bool above_allocation_top = false; | 2099 bool above_allocation_top = false; |
| 2119 Page* current_page = first_page_; | 2100 Page* current_page = first_page_; |
| 2120 while (current_page->is_valid()) { | 2101 while (current_page->is_valid()) { |
| 2121 if (above_allocation_top) { | 2102 if (above_allocation_top) { |
| 2122 // We don't care what's above the allocation top. | 2103 // We don't care what's above the allocation top. |
| 2123 } else { | 2104 } else { |
| 2124 // Unless this is the last page in the space containing allocated | 2105 // Unless this is the last page in the space containing allocated |
| 2125 // objects, the allocation top should be at a constant offset from the | 2106 // objects, the allocation top should be at a constant offset from the |
| 2126 // object area end. | 2107 // object area end. |
| 2127 Address top = current_page->AllocationTop(); | 2108 Address top = current_page->AllocationTop(); |
| 2128 if (current_page == top_page) { | 2109 if (current_page == top_page) { |
| 2129 ASSERT(top == allocation_info_.top); | 2110 ASSERT(top == allocation_info_.top); |
| 2130 // The next page will be above the allocation top. | 2111 // The next page will be above the allocation top. |
| 2131 above_allocation_top = true; | 2112 above_allocation_top = true; |
| 2132 } else { | 2113 } else { |
| 2133 ASSERT(top == current_page->ObjectAreaEnd() - kPageExtra); | 2114 ASSERT(top == current_page->ObjectAreaEnd() - page_extra_); |
| 2134 } | 2115 } |
| 2135 | 2116 |
| 2136 // It should be packed with objects from the bottom to the top. | 2117 // It should be packed with objects from the bottom to the top. |
| 2137 Address current = current_page->ObjectAreaStart(); | 2118 Address current = current_page->ObjectAreaStart(); |
| 2138 while (current < top) { | 2119 while (current < top) { |
| 2139 HeapObject* object = HeapObject::FromAddress(current); | 2120 HeapObject* object = HeapObject::FromAddress(current); |
| 2140 | 2121 |
| 2141 // The first word should be a map, and we expect all map pointers to | 2122 // The first word should be a map, and we expect all map pointers to |
| 2142 // be in map space. | 2123 // be in map space. |
| 2143 Map* map = object->map(); | 2124 Map* map = object->map(); |
| 2144 ASSERT(map->IsMap()); | 2125 ASSERT(map->IsMap()); |
| 2145 ASSERT(Heap::map_space()->Contains(map)); | 2126 ASSERT(Heap::map_space()->Contains(map)); |
| 2146 | 2127 |
| 2147 // The object should be a map or a byte array. | 2128 // Verify the object in the space. |
| 2148 ASSERT(object->IsMap() || object->IsByteArray()); | 2129 VerifyObject(object); |
| 2149 | 2130 |
| 2150 // The object itself should look OK. | 2131 // The object itself should look OK. |
| 2151 object->Verify(); | 2132 object->Verify(); |
| 2152 | 2133 |
| 2153 // All the interior pointers should be contained in the heap and | 2134 // All the interior pointers should be contained in the heap and |
| 2154 // have their remembered set bits set if they point to new space. | 2135 // have their remembered set bits set if they point to new space. |
| 2155 VerifyPointersAndRSetVisitor visitor; | 2136 VerifyPointersAndRSetVisitor visitor; |
| 2156 int size = object->Size(); | 2137 int size = object->Size(); |
| 2157 object->IterateBody(map->instance_type(), size, &visitor); | 2138 object->IterateBody(map->instance_type(), size, &visitor); |
| 2158 | 2139 |
| 2159 current += size; | 2140 current += size; |
| 2160 } | 2141 } |
| 2161 | 2142 |
| 2162 // The allocation pointer should not be in the middle of an object. | 2143 // The allocation pointer should not be in the middle of an object. |
| 2163 ASSERT(current == top); | 2144 ASSERT(current == top); |
| 2164 } | 2145 } |
| 2165 | 2146 |
| 2166 current_page = current_page->next_page(); | 2147 current_page = current_page->next_page(); |
| 2167 } | 2148 } |
| 2168 } | 2149 } |
| 2169 | 2150 |
| 2170 | 2151 |
| 2171 void MapSpace::ReportStatistics() { | 2152 void FixedSpace::ReportStatistics() { |
| 2172 int pct = Available() * 100 / Capacity(); | 2153 int pct = Available() * 100 / Capacity(); |
| 2173 PrintF(" capacity: %d, waste: %d, available: %d, %%%d\n", | 2154 PrintF(" capacity: %d, waste: %d, available: %d, %%%d\n", |
| 2174 Capacity(), Waste(), Available(), pct); | 2155 Capacity(), Waste(), Available(), pct); |
| 2175 | 2156 |
| 2176 // Report remembered set statistics. | 2157 // Report remembered set statistics. |
| 2177 int rset_marked_pointers = 0; | 2158 int rset_marked_pointers = 0; |
| 2178 int cross_gen_pointers = 0; | 2159 int cross_gen_pointers = 0; |
| 2179 | 2160 |
| 2180 PageIterator page_it(this, PageIterator::PAGES_IN_USE); | 2161 PageIterator page_it(this, PageIterator::PAGES_IN_USE); |
| 2181 while (page_it.has_next()) { | 2162 while (page_it.has_next()) { |
| (...skipping 26 matching lines...) Expand all Loading... |
| 2208 PrintF(" rset-marked pointers %d, to-new-space %d (%%%d)\n", | 2189 PrintF(" rset-marked pointers %d, to-new-space %d (%%%d)\n", |
| 2209 rset_marked_pointers, cross_gen_pointers, pct); | 2190 rset_marked_pointers, cross_gen_pointers, pct); |
| 2210 | 2191 |
| 2211 ClearHistograms(); | 2192 ClearHistograms(); |
| 2212 HeapObjectIterator obj_it(this); | 2193 HeapObjectIterator obj_it(this); |
| 2213 while (obj_it.has_next()) { CollectHistogramInfo(obj_it.next()); } | 2194 while (obj_it.has_next()) { CollectHistogramInfo(obj_it.next()); } |
| 2214 ReportHistogram(false); | 2195 ReportHistogram(false); |
| 2215 } | 2196 } |
| 2216 | 2197 |
| 2217 | 2198 |
| 2218 void MapSpace::PrintRSet() { DoPrintRSet("map"); } | 2199 void FixedSpace::PrintRSet() { DoPrintRSet(name_); } |
| 2200 #endif |
| 2201 |
| 2202 |
| 2203 // ----------------------------------------------------------------------------- |
| 2204 // MapSpace implementation |
| 2205 |
| 2206 void MapSpace::PrepareForMarkCompact(bool will_compact) { |
| 2207 // Call prepare of the super class. |
| 2208 FixedSpace::PrepareForMarkCompact(will_compact); |
| 2209 |
| 2210 if (will_compact) { |
| 2211 // Initialize map index entry. |
| 2212 int page_count = 0; |
| 2213 PageIterator it(this, PageIterator::ALL_PAGES); |
| 2214 while (it.has_next()) { |
| 2215 ASSERT_MAP_PAGE_INDEX(page_count); |
| 2216 |
| 2217 Page* p = it.next(); |
| 2218 ASSERT(p->mc_page_index == page_count); |
| 2219 |
| 2220 page_addresses_[page_count++] = p->address(); |
| 2221 } |
| 2222 } |
| 2223 } |
| 2224 |
| 2225 |
| 2226 #ifdef DEBUG |
| 2227 void MapSpace::VerifyObject(HeapObject* object) { |
| 2228 // The object should be a map or a free-list node. |
| 2229 ASSERT(object->IsMap() || object->IsByteArray()); |
| 2230 } |
| 2231 #endif |
| 2232 |
| 2233 |
| 2234 // ----------------------------------------------------------------------------- |
| 2235 // GlobalPropertyCellSpace implementation |
| 2236 |
| 2237 #ifdef DEBUG |
| 2238 void CellSpace::VerifyObject(HeapObject* object) { |
| 2239 // The object should be a global object property cell or a free-list node. |
| 2240 ASSERT(object->IsJSGlobalPropertyCell() || |
| 2241 object->map() == Heap::two_pointer_filler_map()); |
| 2242 } |
| 2219 #endif | 2243 #endif |
| 2220 | 2244 |
| 2221 | 2245 |
| 2222 // ----------------------------------------------------------------------------- | 2246 // ----------------------------------------------------------------------------- |
| 2223 // LargeObjectIterator | 2247 // LargeObjectIterator |
| 2224 | 2248 |
| 2225 LargeObjectIterator::LargeObjectIterator(LargeObjectSpace* space) { | 2249 LargeObjectIterator::LargeObjectIterator(LargeObjectSpace* space) { |
| 2226 current_ = space->first_chunk_; | 2250 current_ = space->first_chunk_; |
| 2227 size_func_ = NULL; | 2251 size_func_ = NULL; |
| 2228 } | 2252 } |
| (...skipping 400 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2629 reinterpret_cast<Object**>(object->address() | 2653 reinterpret_cast<Object**>(object->address() |
| 2630 + Page::kObjectAreaSize), | 2654 + Page::kObjectAreaSize), |
| 2631 allocation_top); | 2655 allocation_top); |
| 2632 PrintF("\n"); | 2656 PrintF("\n"); |
| 2633 } | 2657 } |
| 2634 } | 2658 } |
| 2635 } | 2659 } |
| 2636 #endif // DEBUG | 2660 #endif // DEBUG |
| 2637 | 2661 |
| 2638 } } // namespace v8::internal | 2662 } } // namespace v8::internal |
| OLD | NEW |