Chromium Code Reviews| 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/base/atomicops.h" | 10 #include "src/base/atomicops.h" |
| 10 #include "src/base/bits.h" | 11 #include "src/base/bits.h" |
| 11 #include "src/base/platform/mutex.h" | 12 #include "src/base/platform/mutex.h" |
| 12 #include "src/flags.h" | 13 #include "src/flags.h" |
| 13 #include "src/hashmap.h" | 14 #include "src/hashmap.h" |
| 14 #include "src/list.h" | 15 #include "src/list.h" |
| 15 #include "src/objects.h" | 16 #include "src/objects.h" |
| 16 #include "src/utils.h" | 17 #include "src/utils.h" |
| 17 | 18 |
| 18 namespace v8 { | 19 namespace v8 { |
| (...skipping 534 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 553 | 554 |
| 554 static const size_t kSlotsBufferOffset = | 555 static const size_t kSlotsBufferOffset = |
| 555 kLiveBytesOffset + kIntSize; // int live_byte_count_ | 556 kLiveBytesOffset + kIntSize; // int live_byte_count_ |
| 556 | 557 |
| 557 static const size_t kWriteBarrierCounterOffset = | 558 static const size_t kWriteBarrierCounterOffset = |
| 558 kSlotsBufferOffset + kPointerSize // SlotsBuffer* slots_buffer_; | 559 kSlotsBufferOffset + kPointerSize // SlotsBuffer* slots_buffer_; |
| 559 + kPointerSize; // SkipList* skip_list_; | 560 + kPointerSize; // SkipList* skip_list_; |
| 560 | 561 |
| 561 static const size_t kMinHeaderSize = | 562 static const size_t kMinHeaderSize = |
| 562 kWriteBarrierCounterOffset + | 563 kWriteBarrierCounterOffset + |
| 563 kIntptrSize // intptr_t write_barrier_counter_ | 564 kIntptrSize // intptr_t write_barrier_counter_ |
| 564 + kIntSize // int progress_bar_ | 565 + kIntSize // int progress_bar_ |
| 565 + kIntSize // int high_water_mark_ | 566 + kPointerSize // AtomicValue high_water_mark_ |
| 566 + kPointerSize // base::Mutex* mutex_ | 567 + kPointerSize // base::Mutex* mutex_ |
| 567 + kPointerSize // base::AtomicWord parallel_sweeping_ | 568 + kPointerSize // base::AtomicWord parallel_sweeping_ |
| 568 + 5 * kIntSize // int free-list statistics | 569 + 5 * kPointerSize // AtomicNumber free-list statistics |
| 569 + kPointerSize // base::AtomicWord next_chunk_ | 570 + kPointerSize // base::AtomicWord next_chunk_ |
| 570 + kPointerSize; // base::AtomicWord prev_chunk_ | 571 + kPointerSize; // base::AtomicWord prev_chunk_ |
| 571 | 572 |
| 572 // We add some more space to the computed header size to amount for missing | 573 // We add some more space to the computed header size to amount for missing |
| 573 // alignment requirements in our computation. | 574 // alignment requirements in our computation. |
| 574 // Try to get kHeaderSize properly aligned on 32-bit and 64-bit machines. | 575 // Try to get kHeaderSize properly aligned on 32-bit and 64-bit machines. |
| 575 static const size_t kHeaderSize = kMinHeaderSize + kIntSize; | 576 static const size_t kHeaderSize = kMinHeaderSize + kIntSize; |
| 576 | 577 |
| 577 static const int kBodyOffset = | 578 static const int kBodyOffset = |
| 578 CODE_POINTER_ALIGN(kHeaderSize + Bitmap::kSize); | 579 CODE_POINTER_ALIGN(kHeaderSize + Bitmap::kSize); |
| 579 | 580 |
| 580 // The start offset of the object area in a page. Aligned to both maps and | 581 // The start offset of the object area in a page. Aligned to both maps and |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 667 DCHECK(slots_buffer_ == NULL); | 668 DCHECK(slots_buffer_ == NULL); |
| 668 ClearFlag(EVACUATION_CANDIDATE); | 669 ClearFlag(EVACUATION_CANDIDATE); |
| 669 } | 670 } |
| 670 | 671 |
| 671 Address area_start() { return area_start_; } | 672 Address area_start() { return area_start_; } |
| 672 Address area_end() { return area_end_; } | 673 Address area_end() { return area_end_; } |
| 673 int area_size() { return static_cast<int>(area_end() - area_start()); } | 674 int area_size() { return static_cast<int>(area_end() - area_start()); } |
| 674 bool CommitArea(size_t requested); | 675 bool CommitArea(size_t requested); |
| 675 | 676 |
| 676 // Approximate amount of physical memory committed for this chunk. | 677 // Approximate amount of physical memory committed for this chunk. |
| 677 size_t CommittedPhysicalMemory() { return high_water_mark_; } | 678 size_t CommittedPhysicalMemory() { return high_water_mark_.Value(); } |
| 678 | 679 |
| 679 // Should be called when memory chunk is about to be freed. | 680 // Should be called when memory chunk is about to be freed. |
| 680 void ReleaseAllocatedMemory(); | 681 void ReleaseAllocatedMemory(); |
| 681 | 682 |
| 682 static inline void UpdateHighWaterMark(Address mark) { | 683 static inline void UpdateHighWaterMark(Address mark) { |
| 683 if (mark == NULL) return; | 684 if (mark == nullptr) return; |
| 684 // Need to subtract one from the mark because when a chunk is full the | 685 // Need to subtract one from the mark because when a chunk is full the |
| 685 // top points to the next address after the chunk, which effectively belongs | 686 // top points to the next address after the chunk, which effectively belongs |
| 686 // to another chunk. See the comment to Page::FromAllocationTop. | 687 // to another chunk. See the comment to Page::FromAllocationTop. |
| 687 MemoryChunk* chunk = MemoryChunk::FromAddress(mark - 1); | 688 MemoryChunk* chunk = MemoryChunk::FromAddress(mark - 1); |
| 688 int new_mark = static_cast<int>(mark - chunk->address()); | 689 intptr_t new_mark = static_cast<intptr_t>(mark - chunk->address()); |
| 689 if (new_mark > chunk->high_water_mark_) { | 690 intptr_t old_mark = 0; |
| 690 chunk->high_water_mark_ = new_mark; | 691 do { |
| 691 } | 692 old_mark = chunk->high_water_mark_.Value(); |
| 693 } while ((new_mark > old_mark) && | |
| 694 !chunk->high_water_mark_.TrySetValue(old_mark, new_mark)); | |
| 692 } | 695 } |
| 693 | 696 |
| 694 protected: | 697 protected: |
| 695 size_t size_; | 698 size_t size_; |
| 696 intptr_t flags_; | 699 intptr_t flags_; |
| 697 | 700 |
| 698 // Start and end of allocatable memory on this chunk. | 701 // Start and end of allocatable memory on this chunk. |
| 699 Address area_start_; | 702 Address area_start_; |
| 700 Address area_end_; | 703 Address area_end_; |
| 701 | 704 |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 712 // Count of bytes marked black on page. | 715 // Count of bytes marked black on page. |
| 713 int live_byte_count_; | 716 int live_byte_count_; |
| 714 SlotsBuffer* slots_buffer_; | 717 SlotsBuffer* slots_buffer_; |
| 715 SkipList* skip_list_; | 718 SkipList* skip_list_; |
| 716 intptr_t write_barrier_counter_; | 719 intptr_t write_barrier_counter_; |
| 717 // Used by the incremental marker to keep track of the scanning progress in | 720 // Used by the incremental marker to keep track of the scanning progress in |
| 718 // large objects that have a progress bar and are scanned in increments. | 721 // large objects that have a progress bar and are scanned in increments. |
| 719 int progress_bar_; | 722 int progress_bar_; |
| 720 // Assuming the initial allocation on a page is sequential, | 723 // Assuming the initial allocation on a page is sequential, |
| 721 // count highest number of bytes ever allocated on the page. | 724 // count highest number of bytes ever allocated on the page. |
| 722 int high_water_mark_; | 725 AtomicValue<intptr_t> high_water_mark_; |
| 723 | 726 |
| 724 base::Mutex* mutex_; | 727 base::Mutex* mutex_; |
| 725 base::AtomicWord parallel_sweeping_; | 728 base::AtomicWord parallel_sweeping_; |
| 726 | 729 |
| 727 // PagedSpace free-list statistics. | 730 // PagedSpace free-list statistics. |
| 728 int available_in_small_free_list_; | 731 AtomicNumber<intptr_t> available_in_small_free_list_; |
| 729 int available_in_medium_free_list_; | 732 AtomicNumber<intptr_t> available_in_medium_free_list_; |
| 730 int available_in_large_free_list_; | 733 AtomicNumber<intptr_t> available_in_large_free_list_; |
| 731 int available_in_huge_free_list_; | 734 AtomicNumber<intptr_t> available_in_huge_free_list_; |
| 732 int non_available_small_blocks_; | 735 AtomicNumber<intptr_t> non_available_small_blocks_; |
| 733 | 736 |
| 734 // next_chunk_ holds a pointer of type MemoryChunk | 737 // next_chunk_ holds a pointer of type MemoryChunk |
| 735 base::AtomicWord next_chunk_; | 738 base::AtomicWord next_chunk_; |
| 736 // prev_chunk_ holds a pointer of type MemoryChunk | 739 // prev_chunk_ holds a pointer of type MemoryChunk |
| 737 base::AtomicWord prev_chunk_; | 740 base::AtomicWord prev_chunk_; |
| 738 | 741 |
| 739 static MemoryChunk* Initialize(Heap* heap, Address base, size_t size, | 742 static MemoryChunk* Initialize(Heap* heap, Address base, size_t size, |
| 740 Address area_start, Address area_end, | 743 Address area_start, Address area_end, |
| 741 Executability executable, Space* owner); | 744 Executability executable, Space* owner); |
| 742 | 745 |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 821 | 824 |
| 822 void InitializeAsAnchor(PagedSpace* owner); | 825 void InitializeAsAnchor(PagedSpace* owner); |
| 823 | 826 |
| 824 bool WasSwept() { return IsFlagSet(WAS_SWEPT); } | 827 bool WasSwept() { return IsFlagSet(WAS_SWEPT); } |
| 825 void SetWasSwept() { SetFlag(WAS_SWEPT); } | 828 void SetWasSwept() { SetFlag(WAS_SWEPT); } |
| 826 void ClearWasSwept() { ClearFlag(WAS_SWEPT); } | 829 void ClearWasSwept() { ClearFlag(WAS_SWEPT); } |
| 827 | 830 |
| 828 void ResetFreeListStatistics(); | 831 void ResetFreeListStatistics(); |
| 829 | 832 |
| 830 int LiveBytesFromFreeList() { | 833 int LiveBytesFromFreeList() { |
| 831 return area_size() - non_available_small_blocks_ - | 834 return static_cast<int>( |
| 832 available_in_small_free_list_ - available_in_medium_free_list_ - | 835 area_size() - non_available_small_blocks() - |
| 833 available_in_large_free_list_ - available_in_huge_free_list_; | 836 available_in_small_free_list() - available_in_medium_free_list() - |
| 837 available_in_large_free_list() - available_in_huge_free_list()); | |
| 834 } | 838 } |
| 835 | 839 |
| 836 #define FRAGMENTATION_STATS_ACCESSORS(type, name) \ | 840 #define FRAGMENTATION_STATS_ACCESSORS(type, name) \ |
| 837 type name() { return name##_; } \ | 841 type name() { return name##_.Value(); } \ |
| 838 void set_##name(type name) { name##_ = name; } \ | 842 void set_##name(type name) { name##_.SetValue(name); } \ |
| 839 void add_##name(type name) { name##_ += name; } | 843 void add_##name(type name) { name##_.Increment(name); } |
| 840 | 844 |
| 841 FRAGMENTATION_STATS_ACCESSORS(int, non_available_small_blocks) | 845 FRAGMENTATION_STATS_ACCESSORS(intptr_t, non_available_small_blocks) |
| 842 FRAGMENTATION_STATS_ACCESSORS(int, available_in_small_free_list) | 846 FRAGMENTATION_STATS_ACCESSORS(intptr_t, available_in_small_free_list) |
| 843 FRAGMENTATION_STATS_ACCESSORS(int, available_in_medium_free_list) | 847 FRAGMENTATION_STATS_ACCESSORS(intptr_t, available_in_medium_free_list) |
| 844 FRAGMENTATION_STATS_ACCESSORS(int, available_in_large_free_list) | 848 FRAGMENTATION_STATS_ACCESSORS(intptr_t, available_in_large_free_list) |
| 845 FRAGMENTATION_STATS_ACCESSORS(int, available_in_huge_free_list) | 849 FRAGMENTATION_STATS_ACCESSORS(intptr_t, available_in_huge_free_list) |
| 846 | 850 |
| 847 #undef FRAGMENTATION_STATS_ACCESSORS | 851 #undef FRAGMENTATION_STATS_ACCESSORS |
| 848 | 852 |
| 849 #ifdef DEBUG | 853 #ifdef DEBUG |
| 850 void Print(); | 854 void Print(); |
| 851 #endif // DEBUG | 855 #endif // DEBUG |
| 852 | 856 |
| 853 friend class MemoryAllocator; | 857 friend class MemoryAllocator; |
| 854 }; | 858 }; |
| 855 | 859 |
| (...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1143 // Returns allocated executable spaces in bytes. | 1147 // Returns allocated executable spaces in bytes. |
| 1144 intptr_t SizeExecutable() { return size_executable_; } | 1148 intptr_t SizeExecutable() { return size_executable_; } |
| 1145 | 1149 |
| 1146 // Returns maximum available bytes that the old space can have. | 1150 // Returns maximum available bytes that the old space can have. |
| 1147 intptr_t MaxAvailable() { | 1151 intptr_t MaxAvailable() { |
| 1148 return (Available() / Page::kPageSize) * Page::kMaxRegularHeapObjectSize; | 1152 return (Available() / Page::kPageSize) * Page::kMaxRegularHeapObjectSize; |
| 1149 } | 1153 } |
| 1150 | 1154 |
| 1151 // Returns an indication of whether a pointer is in a space that has | 1155 // Returns an indication of whether a pointer is in a space that has |
| 1152 // been allocated by this MemoryAllocator. | 1156 // been allocated by this MemoryAllocator. |
| 1153 V8_INLINE bool IsOutsideAllocatedSpace(const void* address) const { | 1157 V8_INLINE bool IsOutsideAllocatedSpace(const void* address) { |
| 1154 return address < lowest_ever_allocated_ || | 1158 return address < lowest_ever_allocated_.Value() || |
| 1155 address >= highest_ever_allocated_; | 1159 address >= highest_ever_allocated_.Value(); |
| 1156 } | 1160 } |
| 1157 | 1161 |
| 1158 #ifdef DEBUG | 1162 #ifdef DEBUG |
| 1159 // Reports statistic info of the space. | 1163 // Reports statistic info of the space. |
| 1160 void ReportStatistics(); | 1164 void ReportStatistics(); |
| 1161 #endif | 1165 #endif |
| 1162 | 1166 |
| 1163 // Returns a MemoryChunk in which the memory region from commit_area_size to | 1167 // Returns a MemoryChunk in which the memory region from commit_area_size to |
| 1164 // reserve_area_size of the chunk area is reserved but not committed, it | 1168 // reserve_area_size of the chunk area is reserved but not committed, it |
| 1165 // could be committed later by calling MemoryChunk::CommitArea. | 1169 // could be committed later by calling MemoryChunk::CommitArea. |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1239 // Allocated space size in bytes. | 1243 // Allocated space size in bytes. |
| 1240 size_t size_; | 1244 size_t size_; |
| 1241 // Allocated executable space size in bytes. | 1245 // Allocated executable space size in bytes. |
| 1242 size_t size_executable_; | 1246 size_t size_executable_; |
| 1243 | 1247 |
| 1244 // We keep the lowest and highest addresses allocated as a quick way | 1248 // We keep the lowest and highest addresses allocated as a quick way |
| 1245 // of determining that pointers are outside the heap. The estimate is | 1249 // of determining that pointers are outside the heap. The estimate is |
| 1246 // conservative, i.e. not all addrsses in 'allocated' space are allocated | 1250 // conservative, i.e. not all addrsses in 'allocated' space are allocated |
| 1247 // to our heap. The range is [lowest, highest[, inclusive on the low end | 1251 // to our heap. The range is [lowest, highest[, inclusive on the low end |
| 1248 // and exclusive on the high end. | 1252 // and exclusive on the high end. |
| 1249 void* lowest_ever_allocated_; | 1253 AtomicValue<void*> lowest_ever_allocated_; |
| 1250 void* highest_ever_allocated_; | 1254 AtomicValue<void*> highest_ever_allocated_; |
| 1251 | 1255 |
| 1252 struct MemoryAllocationCallbackRegistration { | 1256 struct MemoryAllocationCallbackRegistration { |
| 1253 MemoryAllocationCallbackRegistration(MemoryAllocationCallback callback, | 1257 MemoryAllocationCallbackRegistration(MemoryAllocationCallback callback, |
| 1254 ObjectSpace space, | 1258 ObjectSpace space, |
| 1255 AllocationAction action) | 1259 AllocationAction action) |
| 1256 : callback(callback), space(space), action(action) {} | 1260 : callback(callback), space(space), action(action) {} |
| 1257 MemoryAllocationCallback callback; | 1261 MemoryAllocationCallback callback; |
| 1258 ObjectSpace space; | 1262 ObjectSpace space; |
| 1259 AllocationAction action; | 1263 AllocationAction action; |
| 1260 }; | 1264 }; |
| 1261 | 1265 |
| 1262 // A List of callback that are triggered when memory is allocated or free'd | 1266 // A List of callback that are triggered when memory is allocated or free'd |
| 1263 List<MemoryAllocationCallbackRegistration> memory_allocation_callbacks_; | 1267 List<MemoryAllocationCallbackRegistration> memory_allocation_callbacks_; |
| 1264 | 1268 |
| 1265 // Initializes pages in a chunk. Returns the first page address. | 1269 // Initializes pages in a chunk. Returns the first page address. |
| 1266 // This function and GetChunkId() are provided for the mark-compact | 1270 // This function and GetChunkId() are provided for the mark-compact |
| 1267 // collector to rebuild page headers in the from space, which is | 1271 // collector to rebuild page headers in the from space, which is |
| 1268 // used as a marking stack and its page headers are destroyed. | 1272 // used as a marking stack and its page headers are destroyed. |
| 1269 Page* InitializePagesInChunk(int chunk_id, int pages_in_chunk, | 1273 Page* InitializePagesInChunk(int chunk_id, int pages_in_chunk, |
| 1270 PagedSpace* owner); | 1274 PagedSpace* owner); |
| 1271 | 1275 |
| 1272 void UpdateAllocatedSpaceLimits(void* low, void* high) { | 1276 void UpdateAllocatedSpaceLimits(void* low, void* high) { |
| 1273 lowest_ever_allocated_ = Min(lowest_ever_allocated_, low); | 1277 void* ptr = nullptr; |
| 1274 highest_ever_allocated_ = Max(highest_ever_allocated_, high); | 1278 do { |
| 1279 ptr = lowest_ever_allocated_.Value(); | |
|
Hannes Payer (out of office)
2015/09/15 09:55:36
Can this be a function on AtomicValue?
Michael Lippautz
2015/09/15 11:54:53
As discussed offline: While lamdas are supported,
| |
| 1280 } while ((low < ptr) && !lowest_ever_allocated_.TrySetValue(ptr, low)); | |
| 1281 do { | |
| 1282 ptr = highest_ever_allocated_.Value(); | |
| 1283 } while ((high > ptr) && !highest_ever_allocated_.TrySetValue(ptr, high)); | |
| 1275 } | 1284 } |
| 1276 | 1285 |
| 1277 DISALLOW_IMPLICIT_CONSTRUCTORS(MemoryAllocator); | 1286 DISALLOW_IMPLICIT_CONSTRUCTORS(MemoryAllocator); |
| 1278 }; | 1287 }; |
| 1279 | 1288 |
| 1280 | 1289 |
| 1281 // ----------------------------------------------------------------------------- | 1290 // ----------------------------------------------------------------------------- |
| 1282 // Interface for heap object iterator to be implemented by all object space | 1291 // Interface for heap object iterator to be implemented by all object space |
| 1283 // object iterators. | 1292 // object iterators. |
| 1284 // | 1293 // |
| (...skipping 1636 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2921 count = 0; | 2930 count = 0; |
| 2922 } | 2931 } |
| 2923 // Must be small, since an iteration is used for lookup. | 2932 // Must be small, since an iteration is used for lookup. |
| 2924 static const int kMaxComments = 64; | 2933 static const int kMaxComments = 64; |
| 2925 }; | 2934 }; |
| 2926 #endif | 2935 #endif |
| 2927 } | 2936 } |
| 2928 } // namespace v8::internal | 2937 } // namespace v8::internal |
| 2929 | 2938 |
| 2930 #endif // V8_HEAP_SPACES_H_ | 2939 #endif // V8_HEAP_SPACES_H_ |
| OLD | NEW |