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

Side by Side Diff: src/spaces.h

Issue 14208005: Use worst-fit allocation in old space for prentured objects. Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/runtime.cc ('k') | src/spaces.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 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 1309 matching lines...) Expand 10 before | Expand all | Expand 10 after
1320 // decreases to the non-capacity stats. 1320 // decreases to the non-capacity stats.
1321 class AllocationStats BASE_EMBEDDED { 1321 class AllocationStats BASE_EMBEDDED {
1322 public: 1322 public:
1323 AllocationStats() { Clear(); } 1323 AllocationStats() { Clear(); }
1324 1324
1325 // Zero out all the allocation statistics (i.e., no capacity). 1325 // Zero out all the allocation statistics (i.e., no capacity).
1326 void Clear() { 1326 void Clear() {
1327 capacity_ = 0; 1327 capacity_ = 0;
1328 size_ = 0; 1328 size_ = 0;
1329 waste_ = 0; 1329 waste_ = 0;
1330 pretenure_ = 0;
1330 } 1331 }
1331 1332
1332 void ClearSizeWaste() { 1333 void ClearSizeWaste() {
1333 size_ = capacity_; 1334 size_ = capacity_;
1334 waste_ = 0; 1335 waste_ = 0;
1336 pretenure_ = 0;
1335 } 1337 }
1336 1338
1337 // Reset the allocation statistics (i.e., available = capacity with no 1339 // Reset the allocation statistics (i.e., available = capacity with no
1338 // wasted or allocated bytes). 1340 // wasted or allocated bytes).
1339 void Reset() { 1341 void Reset() {
1340 size_ = 0; 1342 size_ = 0;
1341 waste_ = 0; 1343 waste_ = 0;
1344 pretenure_ = 0;
1342 } 1345 }
1343 1346
1344 // Accessors for the allocation statistics. 1347 // Accessors for the allocation statistics.
1345 intptr_t Capacity() { return capacity_; } 1348 intptr_t Capacity() { return capacity_; }
1346 intptr_t Size() { return size_; } 1349 intptr_t Size() { return size_; }
1347 intptr_t Waste() { return waste_; } 1350 intptr_t Waste() { return waste_; }
1351 intptr_t Pretenure() { return pretenure_; }
1348 1352
1349 // Grow the space by adding available bytes. They are initially marked as 1353 // Grow the space by adding available bytes. They are initially marked as
1350 // being in use (part of the size), but will normally be immediately freed, 1354 // being in use (part of the size), but will normally be immediately freed,
1351 // putting them on the free list and removing them from size_. 1355 // putting them on the free list and removing them from size_.
1352 void ExpandSpace(int size_in_bytes) { 1356 void ExpandSpace(int size_in_bytes) {
1353 capacity_ += size_in_bytes; 1357 capacity_ += size_in_bytes;
1354 size_ += size_in_bytes; 1358 size_ += size_in_bytes;
1355 ASSERT(size_ >= 0); 1359 ASSERT(size_ >= 0);
1356 } 1360 }
1357 1361
1358 // Shrink the space by removing available bytes. Since shrinking is done 1362 // Shrink the space by removing available bytes. Since shrinking is done
1359 // during sweeping, bytes have been marked as being in use (part of the size) 1363 // during sweeping, bytes have been marked as being in use (part of the size)
1360 // and are hereby freed. 1364 // and are hereby freed.
1361 void ShrinkSpace(int size_in_bytes) { 1365 void ShrinkSpace(int size_in_bytes) {
1362 capacity_ -= size_in_bytes; 1366 capacity_ -= size_in_bytes;
1363 size_ -= size_in_bytes; 1367 size_ -= size_in_bytes;
1364 ASSERT(size_ >= 0); 1368 ASSERT(size_ >= 0);
1365 } 1369 }
1366 1370
1367 // Allocate from available bytes (available -> size). 1371 // Allocate from available bytes (available -> size).
1368 void AllocateBytes(intptr_t size_in_bytes) { 1372 void AllocateBytes(intptr_t size_in_bytes) {
1369 size_ += size_in_bytes; 1373 size_ += size_in_bytes;
1370 ASSERT(size_ >= 0); 1374 ASSERT(size_ >= 0);
1371 } 1375 }
1372 1376
1377 void AllocatePretenureBytes(intptr_t size_in_bytes) {
1378 pretenure_ += size_in_bytes;
1379 ASSERT(pretenure_ >= 0);
1380 }
1381
1373 // Free allocated bytes, making them available (size -> available). 1382 // Free allocated bytes, making them available (size -> available).
1374 void DeallocateBytes(intptr_t size_in_bytes) { 1383 void DeallocateBytes(intptr_t size_in_bytes) {
1375 size_ -= size_in_bytes; 1384 size_ -= size_in_bytes;
1376 ASSERT(size_ >= 0); 1385 ASSERT(size_ >= 0);
1377 } 1386 }
1378 1387
1379 // Waste free bytes (available -> waste). 1388 // Waste free bytes (available -> waste).
1380 void WasteBytes(int size_in_bytes) { 1389 void WasteBytes(int size_in_bytes) {
1381 size_ -= size_in_bytes; 1390 size_ -= size_in_bytes;
1382 waste_ += size_in_bytes; 1391 waste_ += size_in_bytes;
1383 ASSERT(size_ >= 0); 1392 ASSERT(size_ >= 0);
1384 } 1393 }
1385 1394
1386 private: 1395 private:
1387 intptr_t capacity_; 1396 intptr_t capacity_;
1388 intptr_t size_; 1397 intptr_t size_;
1389 intptr_t waste_; 1398 intptr_t waste_;
1399 // TODO(hpayer): We can remove the bookkeeping of pretenured objects when
1400 // we provide pretenuring support for all kinds of objects.
1401 intptr_t pretenure_;
1390 }; 1402 };
1391 1403
1392 1404
1393 // ----------------------------------------------------------------------------- 1405 // -----------------------------------------------------------------------------
1394 // Free lists for old object spaces 1406 // Free lists for old object spaces
1395 // 1407 //
1396 // Free-list nodes are free blocks in the heap. They look like heap objects 1408 // Free-list nodes are free blocks in the heap. They look like heap objects
1397 // (free-list node pointers have the heap object tag, and they have a map like 1409 // (free-list node pointers have the heap object tag, and they have a map like
1398 // a heap object). They have a size and a next pointer. The next pointer is 1410 // a heap object). They have a size and a next pointer. The next pointer is
1399 // the raw address of the next free list node (or NULL). 1411 // the raw address of the next free list node (or NULL).
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
1519 1531
1520 // Clear the free list. 1532 // Clear the free list.
1521 void Reset(); 1533 void Reset();
1522 1534
1523 // Return the number of bytes available on the free list. 1535 // Return the number of bytes available on the free list.
1524 intptr_t available() { 1536 intptr_t available() {
1525 return small_list_.available() + medium_list_.available() + 1537 return small_list_.available() + medium_list_.available() +
1526 large_list_.available() + huge_list_.available(); 1538 large_list_.available() + huge_list_.available();
1527 } 1539 }
1528 1540
1541 enum AllocationStrategy {
1542 BEST_FIT,
1543 WORST_FIT
1544 };
1545
1529 // Place a node on the free list. The block of size 'size_in_bytes' 1546 // Place a node on the free list. The block of size 'size_in_bytes'
1530 // starting at 'start' is placed on the free list. The return value is the 1547 // starting at 'start' is placed on the free list. The return value is the
1531 // number of bytes that have been lost due to internal fragmentation by 1548 // number of bytes that have been lost due to internal fragmentation by
1532 // freeing the block. Bookkeeping information will be written to the block, 1549 // freeing the block. Bookkeeping information will be written to the block,
1533 // i.e., its contents will be destroyed. The start address should be word 1550 // i.e., its contents will be destroyed. The start address should be word
1534 // aligned, and the size should be a non-zero multiple of the word size. 1551 // aligned, and the size should be a non-zero multiple of the word size.
1535 int Free(Address start, int size_in_bytes); 1552 int Free(Address start, int size_in_bytes);
1536 1553
1537 // Allocate a block of size 'size_in_bytes' from the free list. The block 1554 // Allocate a block of size 'size_in_bytes' from the free list. The block
1538 // is unitialized. A failure is returned if no block is available. The 1555 // is unitialized. A failure is returned if no block is available. The
1539 // number of bytes lost to fragmentation is returned in the output parameter 1556 // number of bytes lost to fragmentation is returned in the output parameter
1540 // 'wasted_bytes'. The size should be a non-zero multiple of the word size. 1557 // 'wasted_bytes'. The size should be a non-zero multiple of the word size.
1558 template<AllocationStrategy strategy>
1541 MUST_USE_RESULT HeapObject* Allocate(int size_in_bytes); 1559 MUST_USE_RESULT HeapObject* Allocate(int size_in_bytes);
1542 1560
1543 #ifdef DEBUG 1561 #ifdef DEBUG
1544 void Zap(); 1562 void Zap();
1545 intptr_t SumFreeLists(); 1563 intptr_t SumFreeLists();
1546 bool IsVeryLong(); 1564 bool IsVeryLong();
1547 #endif 1565 #endif
1548 1566
1549 // Used after booting the VM. 1567 // Used after booting the VM.
1550 void RepairLists(Heap* heap); 1568 void RepairLists(Heap* heap);
1551 1569
1552 intptr_t EvictFreeListItems(Page* p); 1570 intptr_t EvictFreeListItems(Page* p);
1553 1571
1554 FreeListCategory* small_list() { return &small_list_; } 1572 FreeListCategory* small_list() { return &small_list_; }
1555 FreeListCategory* medium_list() { return &medium_list_; } 1573 FreeListCategory* medium_list() { return &medium_list_; }
1556 FreeListCategory* large_list() { return &large_list_; } 1574 FreeListCategory* large_list() { return &large_list_; }
1557 FreeListCategory* huge_list() { return &huge_list_; } 1575 FreeListCategory* huge_list() { return &huge_list_; }
1558 1576
1559 private: 1577 private:
1560 // The size range of blocks, in bytes. 1578 // The size range of blocks, in bytes.
1561 static const int kMinBlockSize = 3 * kPointerSize; 1579 static const int kMinBlockSize = 3 * kPointerSize;
1562 static const int kMaxBlockSize = Page::kMaxNonCodeHeapObjectSize; 1580 static const int kMaxBlockSize = Page::kMaxNonCodeHeapObjectSize;
1563 1581
1564 FreeListNode* FindNodeFor(int size_in_bytes, int* node_size); 1582 FreeListNode* FindNodeInHugeList(int size_in_bytes, int* node_size);
1583
1584 // Finds a node in the free-list using the best-fit allocation strategy.
1585 FreeListNode* FindNodeForBestFit(int size_in_bytes, int* node_size);
1586
1587 // Finds a node in the free-list using the worst-fit allocation strategy
1588 // and it ignores the smallest category.
1589 FreeListNode* FindNodeForWorstFit(int size_in_bytes, int* node_size);
1565 1590
1566 PagedSpace* owner_; 1591 PagedSpace* owner_;
1567 Heap* heap_; 1592 Heap* heap_;
1568 1593
1569 static const int kSmallListMin = 0x20 * kPointerSize; 1594 static const int kSmallListMin = 0x20 * kPointerSize;
1570 static const int kSmallListMax = 0xff * kPointerSize; 1595 static const int kSmallListMax = 0xff * kPointerSize;
1571 static const int kMediumListMax = 0x7ff * kPointerSize; 1596 static const int kMediumListMax = 0x7ff * kPointerSize;
1572 static const int kLargeListMax = 0x3fff * kPointerSize; 1597 static const int kLargeListMax = 0x3fff * kPointerSize;
1573 static const int kSmallAllocationMax = kSmallListMin - kPointerSize; 1598 static const int kSmallAllocationMax = kSmallListMin - kPointerSize;
1574 static const int kMediumAllocationMax = kSmallListMax; 1599 static const int kMediumAllocationMax = kSmallListMax;
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
1666 // The bytes in the linear allocation area are not included in this total 1691 // The bytes in the linear allocation area are not included in this total
1667 // because updating the stats would slow down allocation. New pages are 1692 // because updating the stats would slow down allocation. New pages are
1668 // immediately added to the free list so they show up here. 1693 // immediately added to the free list so they show up here.
1669 intptr_t Available() { return free_list_.available(); } 1694 intptr_t Available() { return free_list_.available(); }
1670 1695
1671 // Allocated bytes in this space. Garbage bytes that were not found due to 1696 // Allocated bytes in this space. Garbage bytes that were not found due to
1672 // lazy sweeping are counted as being allocated! The bytes in the current 1697 // lazy sweeping are counted as being allocated! The bytes in the current
1673 // linear allocation area (between top and limit) are also counted here. 1698 // linear allocation area (between top and limit) are also counted here.
1674 virtual intptr_t Size() { return accounting_stats_.Size(); } 1699 virtual intptr_t Size() { return accounting_stats_.Size(); }
1675 1700
1701 intptr_t Pretenure() { return accounting_stats_.Pretenure(); }
1702
1676 // As size, but the bytes in lazily swept pages are estimated and the bytes 1703 // As size, but the bytes in lazily swept pages are estimated and the bytes
1677 // in the current linear allocation area are not included. 1704 // in the current linear allocation area are not included.
1678 virtual intptr_t SizeOfObjects(); 1705 virtual intptr_t SizeOfObjects();
1679 1706
1680 // Wasted bytes in this space. These are just the bytes that were thrown away 1707 // Wasted bytes in this space. These are just the bytes that were thrown away
1681 // due to being too small to use for allocation. They do not include the 1708 // due to being too small to use for allocation. They do not include the
1682 // free bytes that were not found at all due to lazy sweeping. 1709 // free bytes that were not found at all due to lazy sweeping.
1683 virtual intptr_t Waste() { return accounting_stats_.Waste(); } 1710 virtual intptr_t Waste() { return accounting_stats_.Waste(); }
1684 1711
1685 // Returns the allocation pointer in this space. 1712 // Returns the allocation pointer in this space.
1686 Address top() { return allocation_info_.top; } 1713 Address top() { return allocation_info_.top; }
1687 Address limit() { return allocation_info_.limit; } 1714 Address limit() { return allocation_info_.limit; }
1688 1715
1689 // The allocation top and limit addresses. 1716 // The allocation top and limit addresses.
1690 Address* allocation_top_address() { return &allocation_info_.top; } 1717 Address* allocation_top_address() { return &allocation_info_.top; }
1691 Address* allocation_limit_address() { return &allocation_info_.limit; } 1718 Address* allocation_limit_address() { return &allocation_info_.limit; }
1692 1719
1693 // Allocate the requested number of bytes in the space if possible, return a 1720 // Allocate the requested number of bytes in the space if possible, return a
1694 // failure object if not. 1721 // failure object if not.
1722 template<FreeList::AllocationStrategy strategy>
1695 MUST_USE_RESULT inline MaybeObject* AllocateRaw(int size_in_bytes); 1723 MUST_USE_RESULT inline MaybeObject* AllocateRaw(int size_in_bytes);
1696 1724
1697 virtual bool ReserveSpace(int bytes); 1725 virtual bool ReserveSpace(int bytes);
1698 1726
1699 // Give a block of memory to the space's free list. It might be added to 1727 // Give a block of memory to the space's free list. It might be added to
1700 // the free list or accounted as waste. 1728 // the free list or accounted as waste.
1701 // If add_to_freelist is false then just accounting stats are updated and 1729 // If add_to_freelist is false then just accounting stats are updated and
1702 // no attempt to add area to free list is made. 1730 // no attempt to add area to free list is made.
1703 int Free(Address start, int size_in_bytes) { 1731 int Free(Address start, int size_in_bytes) {
1704 int wasted = free_list_.Free(start, size_in_bytes); 1732 int wasted = free_list_.Free(start, size_in_bytes);
(...skipping 11 matching lines...) Expand all
1716 Page::FromAddress(top) == Page::FromAddress(limit - 1)); 1744 Page::FromAddress(top) == Page::FromAddress(limit - 1));
1717 MemoryChunk::UpdateHighWaterMark(allocation_info_.top); 1745 MemoryChunk::UpdateHighWaterMark(allocation_info_.top);
1718 allocation_info_.top = top; 1746 allocation_info_.top = top;
1719 allocation_info_.limit = limit; 1747 allocation_info_.limit = limit;
1720 } 1748 }
1721 1749
1722 void Allocate(int bytes) { 1750 void Allocate(int bytes) {
1723 accounting_stats_.AllocateBytes(bytes); 1751 accounting_stats_.AllocateBytes(bytes);
1724 } 1752 }
1725 1753
1754 void AllocatePretenure(int bytes) {
1755 accounting_stats_.AllocatePretenureBytes(bytes);
1756 }
1757
1726 void IncreaseCapacity(int size) { 1758 void IncreaseCapacity(int size) {
1727 accounting_stats_.ExpandSpace(size); 1759 accounting_stats_.ExpandSpace(size);
1728 } 1760 }
1729 1761
1730 // Releases an unused page and shrinks the space. 1762 // Releases an unused page and shrinks the space.
1731 void ReleasePage(Page* page, bool unlink); 1763 void ReleasePage(Page* page, bool unlink);
1732 1764
1733 // The dummy page that anchors the linked list of pages. 1765 // The dummy page that anchors the linked list of pages.
1734 Page* anchor() { return &anchor_; } 1766 Page* anchor() { return &anchor_; }
1735 1767
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
1862 // Expands the space by allocating a fixed number of pages. Returns false if 1894 // Expands the space by allocating a fixed number of pages. Returns false if
1863 // it cannot allocate requested number of pages from OS, or if the hard heap 1895 // it cannot allocate requested number of pages from OS, or if the hard heap
1864 // size limit has been hit. 1896 // size limit has been hit.
1865 bool Expand(); 1897 bool Expand();
1866 1898
1867 // Generic fast case allocation function that tries linear allocation at the 1899 // Generic fast case allocation function that tries linear allocation at the
1868 // address denoted by top in allocation_info_. 1900 // address denoted by top in allocation_info_.
1869 inline HeapObject* AllocateLinearly(int size_in_bytes); 1901 inline HeapObject* AllocateLinearly(int size_in_bytes);
1870 1902
1871 // Slow path of AllocateRaw. This function is space-dependent. 1903 // Slow path of AllocateRaw. This function is space-dependent.
1872 MUST_USE_RESULT virtual HeapObject* SlowAllocateRaw(int size_in_bytes); 1904 template<FreeList::AllocationStrategy strategy>
1905 MUST_USE_RESULT HeapObject* SlowAllocateRaw(int size_in_bytes);
1873 1906
1874 friend class PageIterator; 1907 friend class PageIterator;
1875 friend class SweeperThread; 1908 friend class SweeperThread;
1876 }; 1909 };
1877 1910
1878 1911
1879 class NumberAndSizeInfo BASE_EMBEDDED { 1912 class NumberAndSizeInfo BASE_EMBEDDED {
1880 public: 1913 public:
1881 NumberAndSizeInfo() : number_(0), bytes_(0) {} 1914 NumberAndSizeInfo() : number_(0), bytes_(0) {}
1882 1915
(...skipping 962 matching lines...) Expand 10 before | Expand all | Expand 10 after
2845 } 2878 }
2846 // Must be small, since an iteration is used for lookup. 2879 // Must be small, since an iteration is used for lookup.
2847 static const int kMaxComments = 64; 2880 static const int kMaxComments = 64;
2848 }; 2881 };
2849 #endif 2882 #endif
2850 2883
2851 2884
2852 } } // namespace v8::internal 2885 } } // namespace v8::internal
2853 2886
2854 #endif // V8_SPACES_H_ 2887 #endif // V8_SPACES_H_
OLDNEW
« no previous file with comments | « src/runtime.cc ('k') | src/spaces.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698