| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/heap/spaces.h" | 5 #include "src/heap/spaces.h" |
| 6 | 6 |
| 7 #include "src/base/bits.h" | 7 #include "src/base/bits.h" |
| 8 #include "src/base/platform/platform.h" | 8 #include "src/base/platform/platform.h" |
| 9 #include "src/base/platform/semaphore.h" | 9 #include "src/base/platform/semaphore.h" |
| 10 #include "src/full-codegen/full-codegen.h" | 10 #include "src/full-codegen/full-codegen.h" |
| (...skipping 1368 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1379 DeleteArray(promoted_histogram_); | 1379 DeleteArray(promoted_histogram_); |
| 1380 promoted_histogram_ = NULL; | 1380 promoted_histogram_ = NULL; |
| 1381 } | 1381 } |
| 1382 | 1382 |
| 1383 allocation_info_.Reset(nullptr, nullptr); | 1383 allocation_info_.Reset(nullptr, nullptr); |
| 1384 | 1384 |
| 1385 to_space_.TearDown(); | 1385 to_space_.TearDown(); |
| 1386 from_space_.TearDown(); | 1386 from_space_.TearDown(); |
| 1387 } | 1387 } |
| 1388 | 1388 |
| 1389 | |
| 1390 void NewSpace::Flip() { SemiSpace::Swap(&from_space_, &to_space_); } | 1389 void NewSpace::Flip() { SemiSpace::Swap(&from_space_, &to_space_); } |
| 1391 | 1390 |
| 1392 | 1391 |
| 1393 void NewSpace::Grow() { | 1392 void NewSpace::Grow() { |
| 1394 // Double the semispace size but only up to maximum capacity. | 1393 // Double the semispace size but only up to maximum capacity. |
| 1395 DCHECK(TotalCapacity() < MaximumCapacity()); | 1394 DCHECK(TotalCapacity() < MaximumCapacity()); |
| 1396 int new_capacity = | 1395 int new_capacity = |
| 1397 Min(MaximumCapacity(), | 1396 Min(MaximumCapacity(), |
| 1398 FLAG_semi_space_growth_factor * static_cast<int>(TotalCapacity())); | 1397 FLAG_semi_space_growth_factor * static_cast<int>(TotalCapacity())); |
| 1399 if (to_space_.GrowTo(new_capacity)) { | 1398 if (to_space_.GrowTo(new_capacity)) { |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1425 if (!to_space_.GrowTo(from_space_.current_capacity())) { | 1424 if (!to_space_.GrowTo(from_space_.current_capacity())) { |
| 1426 // We are in an inconsistent state because we could not | 1425 // We are in an inconsistent state because we could not |
| 1427 // commit/uncommit memory from new space. | 1426 // commit/uncommit memory from new space. |
| 1428 CHECK(false); | 1427 CHECK(false); |
| 1429 } | 1428 } |
| 1430 } | 1429 } |
| 1431 } | 1430 } |
| 1432 DCHECK_SEMISPACE_ALLOCATION_INFO(allocation_info_, to_space_); | 1431 DCHECK_SEMISPACE_ALLOCATION_INFO(allocation_info_, to_space_); |
| 1433 } | 1432 } |
| 1434 | 1433 |
| 1434 bool NewSpace::Rebalance() { |
| 1435 CHECK(heap()->promotion_queue()->is_empty()); |
| 1436 // Order here is important to make use of the page pool. |
| 1437 return to_space_.EnsureCurrentCapacity() && |
| 1438 from_space_.EnsureCurrentCapacity(); |
| 1439 } |
| 1440 |
| 1441 bool SemiSpace::EnsureCurrentCapacity() { |
| 1442 if (is_committed()) { |
| 1443 const int expected_pages = current_capacity_ / Page::kPageSize; |
| 1444 int actual_pages = 0; |
| 1445 Page* current_page = anchor()->next_page(); |
| 1446 while (current_page != anchor()) { |
| 1447 actual_pages++; |
| 1448 current_page = current_page->next_page(); |
| 1449 if (actual_pages > expected_pages) { |
| 1450 Page* to_remove = current_page->prev_page(); |
| 1451 // Make sure we don't overtake the actual top pointer. |
| 1452 CHECK_NE(to_remove, current_page_); |
| 1453 to_remove->Unlink(); |
| 1454 heap()->memory_allocator()->Free<MemoryAllocator::kPooledAndQueue>( |
| 1455 to_remove); |
| 1456 } |
| 1457 } |
| 1458 while (actual_pages < expected_pages) { |
| 1459 actual_pages++; |
| 1460 current_page = |
| 1461 heap()->memory_allocator()->AllocatePage<MemoryAllocator::kPooled>( |
| 1462 Page::kAllocatableMemory, this, executable()); |
| 1463 if (current_page == nullptr) return false; |
| 1464 DCHECK_NOT_NULL(current_page); |
| 1465 current_page->InsertAfter(anchor()); |
| 1466 Bitmap::Clear(current_page); |
| 1467 current_page->SetFlags(anchor()->prev_page()->GetFlags(), |
| 1468 Page::kCopyAllFlags); |
| 1469 heap()->CreateFillerObjectAt(current_page->area_start(), |
| 1470 current_page->area_size(), |
| 1471 ClearRecordedSlots::kNo); |
| 1472 } |
| 1473 } |
| 1474 return true; |
| 1475 } |
| 1435 | 1476 |
| 1436 void LocalAllocationBuffer::Close() { | 1477 void LocalAllocationBuffer::Close() { |
| 1437 if (IsValid()) { | 1478 if (IsValid()) { |
| 1438 heap_->CreateFillerObjectAt( | 1479 heap_->CreateFillerObjectAt( |
| 1439 allocation_info_.top(), | 1480 allocation_info_.top(), |
| 1440 static_cast<int>(allocation_info_.limit() - allocation_info_.top()), | 1481 static_cast<int>(allocation_info_.limit() - allocation_info_.top()), |
| 1441 ClearRecordedSlots::kNo); | 1482 ClearRecordedSlots::kNo); |
| 1442 } | 1483 } |
| 1443 } | 1484 } |
| 1444 | 1485 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1481 allocation_info_.Reset(to_space_.page_low(), to_space_.page_high()); | 1522 allocation_info_.Reset(to_space_.page_low(), to_space_.page_high()); |
| 1482 UpdateInlineAllocationLimit(0); | 1523 UpdateInlineAllocationLimit(0); |
| 1483 DCHECK_SEMISPACE_ALLOCATION_INFO(allocation_info_, to_space_); | 1524 DCHECK_SEMISPACE_ALLOCATION_INFO(allocation_info_, to_space_); |
| 1484 } | 1525 } |
| 1485 | 1526 |
| 1486 | 1527 |
| 1487 void NewSpace::ResetAllocationInfo() { | 1528 void NewSpace::ResetAllocationInfo() { |
| 1488 Address old_top = allocation_info_.top(); | 1529 Address old_top = allocation_info_.top(); |
| 1489 to_space_.Reset(); | 1530 to_space_.Reset(); |
| 1490 UpdateAllocationInfo(); | 1531 UpdateAllocationInfo(); |
| 1491 pages_used_ = 0; | |
| 1492 // Clear all mark-bits in the to-space. | 1532 // Clear all mark-bits in the to-space. |
| 1493 NewSpacePageIterator it(&to_space_); | 1533 NewSpacePageIterator it(&to_space_); |
| 1494 while (it.has_next()) { | 1534 while (it.has_next()) { |
| 1495 Bitmap::Clear(it.next()); | 1535 Bitmap::Clear(it.next()); |
| 1496 } | 1536 } |
| 1497 InlineAllocationStep(old_top, allocation_info_.top(), nullptr, 0); | 1537 InlineAllocationStep(old_top, allocation_info_.top(), nullptr, 0); |
| 1498 } | 1538 } |
| 1499 | 1539 |
| 1500 | 1540 |
| 1501 void NewSpace::UpdateInlineAllocationLimit(int size_in_bytes) { | 1541 void NewSpace::UpdateInlineAllocationLimit(int size_in_bytes) { |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1527 } | 1567 } |
| 1528 | 1568 |
| 1529 // Clear remainder of current page. | 1569 // Clear remainder of current page. |
| 1530 Address limit = Page::FromAllocationAreaAddress(top)->area_end(); | 1570 Address limit = Page::FromAllocationAreaAddress(top)->area_end(); |
| 1531 if (heap()->gc_state() == Heap::SCAVENGE) { | 1571 if (heap()->gc_state() == Heap::SCAVENGE) { |
| 1532 heap()->promotion_queue()->SetNewLimit(limit); | 1572 heap()->promotion_queue()->SetNewLimit(limit); |
| 1533 } | 1573 } |
| 1534 | 1574 |
| 1535 int remaining_in_page = static_cast<int>(limit - top); | 1575 int remaining_in_page = static_cast<int>(limit - top); |
| 1536 heap()->CreateFillerObjectAt(top, remaining_in_page, ClearRecordedSlots::kNo); | 1576 heap()->CreateFillerObjectAt(top, remaining_in_page, ClearRecordedSlots::kNo); |
| 1537 pages_used_++; | |
| 1538 UpdateAllocationInfo(); | 1577 UpdateAllocationInfo(); |
| 1539 | 1578 |
| 1540 return true; | 1579 return true; |
| 1541 } | 1580 } |
| 1542 | 1581 |
| 1543 | 1582 |
| 1544 bool NewSpace::AddFreshPageSynchronized() { | 1583 bool NewSpace::AddFreshPageSynchronized() { |
| 1545 base::LockGuard<base::Mutex> guard(&mutex_); | 1584 base::LockGuard<base::Mutex> guard(&mutex_); |
| 1546 return AddFreshPage(); | 1585 return AddFreshPage(); |
| 1547 } | 1586 } |
| (...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1865 } | 1904 } |
| 1866 DCHECK(page->IsFlagSet(MemoryChunk::IN_TO_SPACE) || | 1905 DCHECK(page->IsFlagSet(MemoryChunk::IN_TO_SPACE) || |
| 1867 page->IsFlagSet(MemoryChunk::IN_FROM_SPACE)); | 1906 page->IsFlagSet(MemoryChunk::IN_FROM_SPACE)); |
| 1868 } | 1907 } |
| 1869 } | 1908 } |
| 1870 | 1909 |
| 1871 | 1910 |
| 1872 void SemiSpace::Reset() { | 1911 void SemiSpace::Reset() { |
| 1873 DCHECK_NE(anchor_.next_page(), &anchor_); | 1912 DCHECK_NE(anchor_.next_page(), &anchor_); |
| 1874 current_page_ = anchor_.next_page(); | 1913 current_page_ = anchor_.next_page(); |
| 1914 pages_used_ = 0; |
| 1875 } | 1915 } |
| 1876 | 1916 |
| 1877 bool SemiSpace::ReplaceWithEmptyPage(Page* old_page) { | 1917 void SemiSpace::RemovePage(Page* page) { |
| 1878 // TODO(mlippautz): We do not have to get a new page here when the semispace | 1918 if (current_page_ == page) { |
| 1879 // is uncommitted later on. | 1919 current_page_ = page->prev_page(); |
| 1880 Page* new_page = heap()->memory_allocator()->AllocatePage( | 1920 } |
| 1881 Page::kAllocatableMemory, this, executable()); | 1921 page->Unlink(); |
| 1882 if (new_page == nullptr) return false; | 1922 } |
| 1883 Bitmap::Clear(new_page); | 1923 |
| 1884 new_page->SetFlags(old_page->GetFlags(), Page::kCopyAllFlags); | 1924 void SemiSpace::PrependPage(Page* page) { |
| 1885 new_page->set_next_page(old_page->next_page()); | 1925 page->SetFlags(current_page()->GetFlags(), Page::kCopyAllFlags); |
| 1886 new_page->set_prev_page(old_page->prev_page()); | 1926 page->set_owner(this); |
| 1887 old_page->next_page()->set_prev_page(new_page); | 1927 page->InsertAfter(anchor()); |
| 1888 old_page->prev_page()->set_next_page(new_page); | 1928 pages_used_++; |
| 1889 heap()->CreateFillerObjectAt(new_page->area_start(), new_page->area_size(), | |
| 1890 ClearRecordedSlots::kNo); | |
| 1891 return true; | |
| 1892 } | 1929 } |
| 1893 | 1930 |
| 1894 void SemiSpace::Swap(SemiSpace* from, SemiSpace* to) { | 1931 void SemiSpace::Swap(SemiSpace* from, SemiSpace* to) { |
| 1895 // We won't be swapping semispaces without data in them. | 1932 // We won't be swapping semispaces without data in them. |
| 1896 DCHECK_NE(from->anchor_.next_page(), &from->anchor_); | 1933 DCHECK_NE(from->anchor_.next_page(), &from->anchor_); |
| 1897 DCHECK_NE(to->anchor_.next_page(), &to->anchor_); | 1934 DCHECK_NE(to->anchor_.next_page(), &to->anchor_); |
| 1898 | 1935 |
| 1899 intptr_t saved_to_space_flags = to->current_page()->GetFlags(); | 1936 intptr_t saved_to_space_flags = to->current_page()->GetFlags(); |
| 1900 | 1937 |
| 1901 // We swap all properties but id_. | 1938 // We swap all properties but id_. |
| (...skipping 1318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3220 object->ShortPrint(); | 3257 object->ShortPrint(); |
| 3221 PrintF("\n"); | 3258 PrintF("\n"); |
| 3222 } | 3259 } |
| 3223 printf(" --------------------------------------\n"); | 3260 printf(" --------------------------------------\n"); |
| 3224 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); | 3261 printf(" Marked: %x, LiveCount: %x\n", mark_size, LiveBytes()); |
| 3225 } | 3262 } |
| 3226 | 3263 |
| 3227 #endif // DEBUG | 3264 #endif // DEBUG |
| 3228 } // namespace internal | 3265 } // namespace internal |
| 3229 } // namespace v8 | 3266 } // namespace v8 |
| OLD | NEW |