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 #ifndef V8_HEAP_SPACES_H_ | 5 #ifndef V8_HEAP_SPACES_H_ |
6 #define V8_HEAP_SPACES_H_ | 6 #define V8_HEAP_SPACES_H_ |
7 | 7 |
8 #include "src/allocation.h" | 8 #include "src/allocation.h" |
9 #include "src/atomic-utils.h" | 9 #include "src/atomic-utils.h" |
10 #include "src/base/atomicops.h" | 10 #include "src/base/atomicops.h" |
(...skipping 1454 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1465 | 1465 |
1466 | 1466 |
1467 // ----------------------------------------------------------------------------- | 1467 // ----------------------------------------------------------------------------- |
1468 // A space has a circular list of pages. The next page can be accessed via | 1468 // A space has a circular list of pages. The next page can be accessed via |
1469 // Page::next_page() call. | 1469 // Page::next_page() call. |
1470 | 1470 |
1471 // An abstraction of allocation and relocation pointers in a page-structured | 1471 // An abstraction of allocation and relocation pointers in a page-structured |
1472 // space. | 1472 // space. |
1473 class AllocationInfo { | 1473 class AllocationInfo { |
1474 public: | 1474 public: |
1475 AllocationInfo() : top_(NULL), limit_(NULL) {} | 1475 AllocationInfo() : top_(nullptr), limit_(nullptr) {} |
| 1476 AllocationInfo(Address top, Address limit) : top_(top), limit_(limit) {} |
| 1477 |
| 1478 void Reset(Address top, Address limit) { |
| 1479 set_top(top); |
| 1480 set_limit(limit); |
| 1481 } |
1476 | 1482 |
1477 INLINE(void set_top(Address top)) { | 1483 INLINE(void set_top(Address top)) { |
1478 SLOW_DCHECK(top == NULL || | 1484 SLOW_DCHECK(top == NULL || |
1479 (reinterpret_cast<intptr_t>(top) & kHeapObjectTagMask) == 0); | 1485 (reinterpret_cast<intptr_t>(top) & kHeapObjectTagMask) == 0); |
1480 top_ = top; | 1486 top_ = top; |
1481 } | 1487 } |
1482 | 1488 |
1483 INLINE(Address top()) const { | 1489 INLINE(Address top()) const { |
1484 SLOW_DCHECK(top_ == NULL || | 1490 SLOW_DCHECK(top_ == NULL || |
1485 (reinterpret_cast<intptr_t>(top_) & kHeapObjectTagMask) == 0); | 1491 (reinterpret_cast<intptr_t>(top_) & kHeapObjectTagMask) == 0); |
(...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1862 explicit AllocationResult(AllocationSpace space) | 1868 explicit AllocationResult(AllocationSpace space) |
1863 : object_(Smi::FromInt(static_cast<int>(space))) {} | 1869 : object_(Smi::FromInt(static_cast<int>(space))) {} |
1864 | 1870 |
1865 Object* object_; | 1871 Object* object_; |
1866 }; | 1872 }; |
1867 | 1873 |
1868 | 1874 |
1869 STATIC_ASSERT(sizeof(AllocationResult) == kPointerSize); | 1875 STATIC_ASSERT(sizeof(AllocationResult) == kPointerSize); |
1870 | 1876 |
1871 | 1877 |
| 1878 // LocalAllocationBuffer represents a linear allocation area that is created |
| 1879 // from a given {AllocationResult} and can be used to allocate memory without |
| 1880 // synchronization. |
| 1881 // |
| 1882 // The buffer is properly closed upon destruction and reassignment. |
| 1883 // Example: |
| 1884 // { |
| 1885 // AllocationResult result = ...; |
| 1886 // LocalAllocationBuffer a(heap, result, size); |
| 1887 // LocalAllocationBuffer b = a; |
| 1888 // CHECK(!a.IsValid()); |
| 1889 // CHECK(b.IsValid()); |
| 1890 // // {a} is invalid now and cannot be used for further allocations. |
| 1891 // } |
| 1892 // // Since {b} went out of scope, the LAB is closed, resulting in creating a |
| 1893 // // filler object for the remaining area. |
| 1894 class LocalAllocationBuffer { |
| 1895 public: |
| 1896 // Indicates that a buffer cannot be used for allocations anymore. Can result |
| 1897 // from either reassigning a buffer, or trying to construct it from an |
| 1898 // invalid {AllocationResult}. |
| 1899 static inline LocalAllocationBuffer InvalidBuffer(); |
| 1900 |
| 1901 // Creates a new LAB from a given {AllocationResult}. Results in |
| 1902 // InvalidBuffer if the result indicates a retry. |
| 1903 static inline LocalAllocationBuffer FromResult(Heap* heap, |
| 1904 AllocationResult result, |
| 1905 intptr_t size); |
| 1906 |
| 1907 ~LocalAllocationBuffer() { Close(); } |
| 1908 |
| 1909 // Convert to C++11 move-semantics once allowed by the style guide. |
| 1910 LocalAllocationBuffer(const LocalAllocationBuffer& other); |
| 1911 LocalAllocationBuffer& operator=(const LocalAllocationBuffer& other); |
| 1912 |
| 1913 MUST_USE_RESULT inline AllocationResult AllocateRawAligned( |
| 1914 int size_in_bytes, AllocationAlignment alignment); |
| 1915 |
| 1916 inline bool IsValid() { return allocation_info_.top() != nullptr; } |
| 1917 |
| 1918 // Try to merge LABs, which is only possible when they are adjacent in memory. |
| 1919 // Returns true if the merge was successful, false otherwise. |
| 1920 inline bool TryMerge(LocalAllocationBuffer* other); |
| 1921 |
| 1922 private: |
| 1923 LocalAllocationBuffer(Heap* heap, AllocationInfo allocation_info); |
| 1924 |
| 1925 void Close(); |
| 1926 |
| 1927 Heap* heap_; |
| 1928 AllocationInfo allocation_info_; |
| 1929 }; |
| 1930 |
| 1931 |
1872 class PagedSpace : public Space { | 1932 class PagedSpace : public Space { |
1873 public: | 1933 public: |
1874 static const intptr_t kCompactionMemoryWanted = 500 * KB; | 1934 static const intptr_t kCompactionMemoryWanted = 500 * KB; |
1875 | 1935 |
1876 // Creates a space with an id. | 1936 // Creates a space with an id. |
1877 PagedSpace(Heap* heap, AllocationSpace id, Executability executable); | 1937 PagedSpace(Heap* heap, AllocationSpace id, Executability executable); |
1878 | 1938 |
1879 ~PagedSpace() override { TearDown(); } | 1939 ~PagedSpace() override { TearDown(); } |
1880 | 1940 |
1881 // Set up the space using the given address range of virtual memory (from | 1941 // Set up the space using the given address range of virtual memory (from |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1992 return size_in_bytes - wasted; | 2052 return size_in_bytes - wasted; |
1993 } | 2053 } |
1994 | 2054 |
1995 void ResetFreeList() { free_list_.Reset(); } | 2055 void ResetFreeList() { free_list_.Reset(); } |
1996 | 2056 |
1997 // Set space allocation info. | 2057 // Set space allocation info. |
1998 void SetTopAndLimit(Address top, Address limit) { | 2058 void SetTopAndLimit(Address top, Address limit) { |
1999 DCHECK(top == limit || | 2059 DCHECK(top == limit || |
2000 Page::FromAddress(top) == Page::FromAddress(limit - 1)); | 2060 Page::FromAddress(top) == Page::FromAddress(limit - 1)); |
2001 MemoryChunk::UpdateHighWaterMark(allocation_info_.top()); | 2061 MemoryChunk::UpdateHighWaterMark(allocation_info_.top()); |
2002 allocation_info_.set_top(top); | 2062 allocation_info_.Reset(top, limit); |
2003 allocation_info_.set_limit(limit); | |
2004 } | 2063 } |
2005 | 2064 |
2006 // Empty space allocation info, returning unused area to free list. | 2065 // Empty space allocation info, returning unused area to free list. |
2007 void EmptyAllocationInfo() { | 2066 void EmptyAllocationInfo() { |
2008 // Mark the old linear allocation area with a free space map so it can be | 2067 // Mark the old linear allocation area with a free space map so it can be |
2009 // skipped when scanning the heap. | 2068 // skipped when scanning the heap. |
2010 int old_linear_size = static_cast<int>(limit() - top()); | 2069 int old_linear_size = static_cast<int>(limit() - top()); |
2011 Free(top(), old_linear_size); | 2070 Free(top(), old_linear_size); |
2012 SetTopAndLimit(NULL, NULL); | 2071 SetTopAndLimit(NULL, NULL); |
2013 } | 2072 } |
(...skipping 720 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2734 | 2793 |
2735 MUST_USE_RESULT INLINE(AllocationResult AllocateRawAligned( | 2794 MUST_USE_RESULT INLINE(AllocationResult AllocateRawAligned( |
2736 int size_in_bytes, AllocationAlignment alignment)); | 2795 int size_in_bytes, AllocationAlignment alignment)); |
2737 | 2796 |
2738 MUST_USE_RESULT INLINE( | 2797 MUST_USE_RESULT INLINE( |
2739 AllocationResult AllocateRawUnaligned(int size_in_bytes)); | 2798 AllocationResult AllocateRawUnaligned(int size_in_bytes)); |
2740 | 2799 |
2741 MUST_USE_RESULT INLINE(AllocationResult AllocateRaw( | 2800 MUST_USE_RESULT INLINE(AllocationResult AllocateRaw( |
2742 int size_in_bytes, AllocationAlignment alignment)); | 2801 int size_in_bytes, AllocationAlignment alignment)); |
2743 | 2802 |
| 2803 MUST_USE_RESULT inline AllocationResult AllocateRawSynchronized( |
| 2804 int size_in_bytes, AllocationAlignment alignment); |
| 2805 |
2744 // Reset the allocation pointer to the beginning of the active semispace. | 2806 // Reset the allocation pointer to the beginning of the active semispace. |
2745 void ResetAllocationInfo(); | 2807 void ResetAllocationInfo(); |
2746 | 2808 |
2747 void UpdateInlineAllocationLimit(int size_in_bytes); | 2809 void UpdateInlineAllocationLimit(int size_in_bytes); |
2748 | 2810 |
2749 // Allows observation of inline allocation. The observer->Step() method gets | 2811 // Allows observation of inline allocation. The observer->Step() method gets |
2750 // called after every step_size bytes have been allocated (approximately). | 2812 // called after every step_size bytes have been allocated (approximately). |
2751 // This works by adjusting the allocation limit to a lower value and adjusting | 2813 // This works by adjusting the allocation limit to a lower value and adjusting |
2752 // it after each step. | 2814 // it after each step. |
2753 void AddInlineAllocationObserver(InlineAllocationObserver* observer); | 2815 void AddInlineAllocationObserver(InlineAllocationObserver* observer); |
(...skipping 29 matching lines...) Expand all Loading... |
2783 // respective semispace (not necessarily below the allocation pointer of the | 2845 // respective semispace (not necessarily below the allocation pointer of the |
2784 // semispace). | 2846 // semispace). |
2785 inline bool ToSpaceContains(Object* o) { return to_space_.Contains(o); } | 2847 inline bool ToSpaceContains(Object* o) { return to_space_.Contains(o); } |
2786 inline bool FromSpaceContains(Object* o) { return from_space_.Contains(o); } | 2848 inline bool FromSpaceContains(Object* o) { return from_space_.Contains(o); } |
2787 | 2849 |
2788 // Try to switch the active semispace to a new, empty, page. | 2850 // Try to switch the active semispace to a new, empty, page. |
2789 // Returns false if this isn't possible or reasonable (i.e., there | 2851 // Returns false if this isn't possible or reasonable (i.e., there |
2790 // are no pages, or the current page is already empty), or true | 2852 // are no pages, or the current page is already empty), or true |
2791 // if successful. | 2853 // if successful. |
2792 bool AddFreshPage(); | 2854 bool AddFreshPage(); |
| 2855 bool AddFreshPageSynchronized(); |
2793 | 2856 |
2794 #ifdef VERIFY_HEAP | 2857 #ifdef VERIFY_HEAP |
2795 // Verify the active semispace. | 2858 // Verify the active semispace. |
2796 virtual void Verify(); | 2859 virtual void Verify(); |
2797 #endif | 2860 #endif |
2798 | 2861 |
2799 #ifdef DEBUG | 2862 #ifdef DEBUG |
2800 // Print the active semispace. | 2863 // Print the active semispace. |
2801 void Print() override { to_space_.Print(); } | 2864 void Print() override { to_space_.Print(); } |
2802 #endif | 2865 #endif |
(...skipping 23 matching lines...) Expand all Loading... |
2826 } | 2889 } |
2827 | 2890 |
2828 bool IsFromSpaceCommitted() { return from_space_.is_committed(); } | 2891 bool IsFromSpaceCommitted() { return from_space_.is_committed(); } |
2829 | 2892 |
2830 SemiSpace* active_space() { return &to_space_; } | 2893 SemiSpace* active_space() { return &to_space_; } |
2831 | 2894 |
2832 private: | 2895 private: |
2833 // Update allocation info to match the current to-space page. | 2896 // Update allocation info to match the current to-space page. |
2834 void UpdateAllocationInfo(); | 2897 void UpdateAllocationInfo(); |
2835 | 2898 |
| 2899 base::Mutex mutex_; |
| 2900 |
2836 Address chunk_base_; | 2901 Address chunk_base_; |
2837 uintptr_t chunk_size_; | 2902 uintptr_t chunk_size_; |
2838 | 2903 |
2839 // The semispaces. | 2904 // The semispaces. |
2840 SemiSpace to_space_; | 2905 SemiSpace to_space_; |
2841 SemiSpace from_space_; | 2906 SemiSpace from_space_; |
2842 base::VirtualMemory reservation_; | 2907 base::VirtualMemory reservation_; |
2843 int pages_used_; | 2908 int pages_used_; |
2844 | 2909 |
2845 // Start address and bit mask for containment testing. | 2910 // Start address and bit mask for containment testing. |
(...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3155 count = 0; | 3220 count = 0; |
3156 } | 3221 } |
3157 // Must be small, since an iteration is used for lookup. | 3222 // Must be small, since an iteration is used for lookup. |
3158 static const int kMaxComments = 64; | 3223 static const int kMaxComments = 64; |
3159 }; | 3224 }; |
3160 #endif | 3225 #endif |
3161 } // namespace internal | 3226 } // namespace internal |
3162 } // namespace v8 | 3227 } // namespace v8 |
3163 | 3228 |
3164 #endif // V8_HEAP_SPACES_H_ | 3229 #endif // V8_HEAP_SPACES_H_ |
OLD | NEW |