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/atomic-utils.h" |
| 10 #include "src/base/atomicops.h" | 10 #include "src/base/atomicops.h" |
| (...skipping 399 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 410 // The start offset of the object area in a page. Aligned to both maps and | 410 // The start offset of the object area in a page. Aligned to both maps and |
| 411 // code alignment to be suitable for both. Also aligned to 32 words because | 411 // code alignment to be suitable for both. Also aligned to 32 words because |
| 412 // the marking bitmap is arranged in 32 bit chunks. | 412 // the marking bitmap is arranged in 32 bit chunks. |
| 413 static const int kObjectStartAlignment = 32 * kPointerSize; | 413 static const int kObjectStartAlignment = 32 * kPointerSize; |
| 414 static const int kObjectStartOffset = | 414 static const int kObjectStartOffset = |
| 415 kBodyOffset - 1 + | 415 kBodyOffset - 1 + |
| 416 (kObjectStartAlignment - (kBodyOffset - 1) % kObjectStartAlignment); | 416 (kObjectStartAlignment - (kBodyOffset - 1) % kObjectStartAlignment); |
| 417 | 417 |
| 418 static const int kFlagsOffset = kPointerSize; | 418 static const int kFlagsOffset = kPointerSize; |
| 419 | 419 |
| 420 // Page size in bytes. This must be a multiple of the OS page size. | |
| 421 static const int kPageSize = 1 << kPageSizeBits; | |
| 422 static const intptr_t kPageAlignmentMask = (1 << kPageSizeBits) - 1; | |
| 423 | |
| 424 static const int kAllocatableMemory = kPageSize - kObjectStartOffset; | |
| 425 | |
| 420 static inline void IncrementLiveBytesFromMutator(HeapObject* object, int by); | 426 static inline void IncrementLiveBytesFromMutator(HeapObject* object, int by); |
| 421 static inline void IncrementLiveBytesFromGC(HeapObject* object, int by); | 427 static inline void IncrementLiveBytesFromGC(HeapObject* object, int by); |
| 422 | 428 |
| 423 // Only works if the pointer is in the first kPageSize of the MemoryChunk. | 429 // Only works if the pointer is in the first kPageSize of the MemoryChunk. |
| 424 static MemoryChunk* FromAddress(Address a) { | 430 static MemoryChunk* FromAddress(Address a) { |
| 425 return reinterpret_cast<MemoryChunk*>(OffsetFrom(a) & ~kAlignmentMask); | 431 return reinterpret_cast<MemoryChunk*>(OffsetFrom(a) & ~kAlignmentMask); |
| 426 } | 432 } |
| 427 | 433 |
| 428 static inline MemoryChunk* FromAnyPointerAddress(Heap* heap, Address addr); | 434 static inline MemoryChunk* FromAnyPointerAddress(Heap* heap, Address addr); |
| 429 | 435 |
| (...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 771 } | 777 } |
| 772 | 778 |
| 773 // Returns the address for a given offset to the this page. | 779 // Returns the address for a given offset to the this page. |
| 774 Address OffsetToAddress(int offset) { | 780 Address OffsetToAddress(int offset) { |
| 775 DCHECK_PAGE_OFFSET(offset); | 781 DCHECK_PAGE_OFFSET(offset); |
| 776 return address() + offset; | 782 return address() + offset; |
| 777 } | 783 } |
| 778 | 784 |
| 779 // --------------------------------------------------------------------- | 785 // --------------------------------------------------------------------- |
| 780 | 786 |
| 781 // Page size in bytes. This must be a multiple of the OS page size. | |
| 782 static const int kPageSize = 1 << kPageSizeBits; | |
| 783 | |
| 784 // Maximum object size that gets allocated into regular pages. Objects larger | 787 // Maximum object size that gets allocated into regular pages. Objects larger |
| 785 // than that size are allocated in large object space and are never moved in | 788 // than that size are allocated in large object space and are never moved in |
| 786 // memory. This also applies to new space allocation, since objects are never | 789 // memory. This also applies to new space allocation, since objects are never |
| 787 // migrated from new space to large object space. Takes double alignment into | 790 // migrated from new space to large object space. Takes double alignment into |
| 788 // account. | 791 // account. |
| 789 // TODO(hpayer): This limit should be way smaller but we currently have | 792 // TODO(hpayer): This limit should be way smaller but we currently have |
| 790 // short living objects >256K. | 793 // short living objects >256K. |
| 791 static const int kMaxRegularHeapObjectSize = 600 * KB; | 794 static const int kMaxRegularHeapObjectSize = 600 * KB; |
| 792 | 795 |
| 793 static const int kAllocatableMemory = kPageSize - kObjectStartOffset; | |
| 794 | |
| 795 // Page size mask. | |
| 796 static const intptr_t kPageAlignmentMask = (1 << kPageSizeBits) - 1; | |
| 797 | |
| 798 inline void ClearGCFields(); | 796 inline void ClearGCFields(); |
| 799 | 797 |
| 800 static inline Page* Initialize(Heap* heap, MemoryChunk* chunk, | 798 static inline Page* Initialize(Heap* heap, MemoryChunk* chunk, |
| 801 Executability executable, PagedSpace* owner); | 799 Executability executable, PagedSpace* owner); |
| 802 | 800 |
| 803 void InitializeAsAnchor(PagedSpace* owner); | 801 void InitializeAsAnchor(PagedSpace* owner); |
| 804 | 802 |
| 805 // WaitUntilSweepingCompleted only works when concurrent sweeping is in | 803 // WaitUntilSweepingCompleted only works when concurrent sweeping is in |
| 806 // progress. In particular, when we know that right before this call a | 804 // progress. In particular, when we know that right before this call a |
| 807 // sweeper thread was sweeping this page. | 805 // sweeper thread was sweeping this page. |
| (...skipping 1383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2191 private: | 2189 private: |
| 2192 const char* name_; | 2190 const char* name_; |
| 2193 }; | 2191 }; |
| 2194 | 2192 |
| 2195 | 2193 |
| 2196 enum SemiSpaceId { kFromSpace = 0, kToSpace = 1 }; | 2194 enum SemiSpaceId { kFromSpace = 0, kToSpace = 1 }; |
| 2197 | 2195 |
| 2198 | 2196 |
| 2199 class NewSpacePage : public MemoryChunk { | 2197 class NewSpacePage : public MemoryChunk { |
| 2200 public: | 2198 public: |
| 2201 // GC related flags copied from from-space to to-space when | |
| 2202 // flipping semispaces. | |
| 2203 static const intptr_t kCopyOnFlipFlagsMask = | |
| 2204 (1 << MemoryChunk::POINTERS_TO_HERE_ARE_INTERESTING) | | |
| 2205 (1 << MemoryChunk::POINTERS_FROM_HERE_ARE_INTERESTING); | |
| 2206 | |
| 2207 static const int kAreaSize = Page::kAllocatableMemory; | |
|
Michael Lippautz
2016/03/17 10:13:43
Now available on MemoryChunk since the allocatable
| |
| 2208 | |
| 2209 inline NewSpacePage* next_page() { | |
| 2210 return static_cast<NewSpacePage*>(next_chunk()); | |
| 2211 } | |
| 2212 | |
| 2213 inline void set_next_page(NewSpacePage* page) { set_next_chunk(page); } | |
| 2214 | |
| 2215 inline NewSpacePage* prev_page() { | |
| 2216 return static_cast<NewSpacePage*>(prev_chunk()); | |
| 2217 } | |
| 2218 | |
| 2219 inline void set_prev_page(NewSpacePage* page) { set_prev_chunk(page); } | |
| 2220 | |
| 2221 SemiSpace* semi_space() { return reinterpret_cast<SemiSpace*>(owner()); } | |
| 2222 | |
| 2223 bool is_anchor() { return !this->InNewSpace(); } | |
| 2224 | |
| 2225 static bool IsAtStart(Address addr) { | 2199 static bool IsAtStart(Address addr) { |
| 2226 return (reinterpret_cast<intptr_t>(addr) & Page::kPageAlignmentMask) == | 2200 return (reinterpret_cast<intptr_t>(addr) & Page::kPageAlignmentMask) == |
| 2227 kObjectStartOffset; | 2201 kObjectStartOffset; |
| 2228 } | 2202 } |
| 2229 | 2203 |
| 2230 static bool IsAtEnd(Address addr) { | 2204 static bool IsAtEnd(Address addr) { |
| 2231 return (reinterpret_cast<intptr_t>(addr) & Page::kPageAlignmentMask) == 0; | 2205 return (reinterpret_cast<intptr_t>(addr) & Page::kPageAlignmentMask) == 0; |
| 2232 } | 2206 } |
| 2233 | 2207 |
| 2234 Address address() { return reinterpret_cast<Address>(this); } | |
|
Michael Lippautz
2016/03/17 10:13:43
dead code
| |
| 2235 | |
| 2236 // Finds the NewSpacePage containing the given address. | 2208 // Finds the NewSpacePage containing the given address. |
| 2237 static inline NewSpacePage* FromAddress(Address address_in_page) { | 2209 static inline NewSpacePage* FromAddress(Address address_in_page) { |
| 2238 Address page_start = | 2210 Address page_start = |
| 2239 reinterpret_cast<Address>(reinterpret_cast<uintptr_t>(address_in_page) & | 2211 reinterpret_cast<Address>(reinterpret_cast<uintptr_t>(address_in_page) & |
| 2240 ~Page::kPageAlignmentMask); | 2212 ~Page::kPageAlignmentMask); |
| 2241 NewSpacePage* page = reinterpret_cast<NewSpacePage*>(page_start); | 2213 NewSpacePage* page = reinterpret_cast<NewSpacePage*>(page_start); |
| 2242 return page; | 2214 return page; |
| 2243 } | 2215 } |
| 2244 | 2216 |
| 2245 // Find the page for a limit address. A limit address is either an address | 2217 // Find the page for a limit address. A limit address is either an address |
| 2246 // inside a page, or the address right after the last byte of a page. | 2218 // inside a page, or the address right after the last byte of a page. |
| 2247 static inline NewSpacePage* FromLimit(Address address_limit) { | 2219 static inline NewSpacePage* FromLimit(Address address_limit) { |
| 2248 return NewSpacePage::FromAddress(address_limit - 1); | 2220 return NewSpacePage::FromAddress(address_limit - 1); |
| 2249 } | 2221 } |
| 2250 | 2222 |
| 2251 // Checks if address1 and address2 are on the same new space page. | 2223 // Checks if address1 and address2 are on the same new space page. |
| 2252 static inline bool OnSamePage(Address address1, Address address2) { | 2224 static inline bool OnSamePage(Address address1, Address address2) { |
| 2253 return NewSpacePage::FromAddress(address1) == | 2225 return NewSpacePage::FromAddress(address1) == |
| 2254 NewSpacePage::FromAddress(address2); | 2226 NewSpacePage::FromAddress(address2); |
| 2255 } | 2227 } |
| 2256 | 2228 |
| 2229 inline NewSpacePage* next_page() { | |
| 2230 return static_cast<NewSpacePage*>(next_chunk()); | |
| 2231 } | |
| 2232 | |
| 2233 inline void set_next_page(NewSpacePage* page) { set_next_chunk(page); } | |
| 2234 | |
| 2235 inline NewSpacePage* prev_page() { | |
| 2236 return static_cast<NewSpacePage*>(prev_chunk()); | |
| 2237 } | |
| 2238 | |
| 2239 inline void set_prev_page(NewSpacePage* page) { set_prev_chunk(page); } | |
| 2240 | |
| 2241 SemiSpace* semi_space() { return reinterpret_cast<SemiSpace*>(owner()); } | |
| 2242 | |
| 2243 bool is_anchor() { return !this->InNewSpace(); } | |
| 2244 | |
| 2257 private: | 2245 private: |
| 2246 // GC related flags copied from from-space to to-space when | |
| 2247 // flipping semispaces. | |
| 2248 static const intptr_t kCopyOnFlipFlagsMask = | |
| 2249 (1 << MemoryChunk::POINTERS_TO_HERE_ARE_INTERESTING) | | |
| 2250 (1 << MemoryChunk::POINTERS_FROM_HERE_ARE_INTERESTING); | |
| 2251 | |
| 2258 // Create a NewSpacePage object that is only used as anchor | 2252 // Create a NewSpacePage object that is only used as anchor |
| 2259 // for the doubly-linked list of real pages. | 2253 // for the doubly-linked list of real pages. |
| 2260 explicit NewSpacePage(SemiSpace* owner) { InitializeAsAnchor(owner); } | 2254 explicit NewSpacePage(SemiSpace* owner) { InitializeAsAnchor(owner); } |
| 2261 | 2255 |
| 2262 static NewSpacePage* Initialize(Heap* heap, Address start, | 2256 static NewSpacePage* Initialize(Heap* heap, Address start, |
| 2263 SemiSpace* semi_space); | 2257 SemiSpace* semi_space); |
| 2264 | 2258 |
| 2265 // Intialize a fake NewSpacePage used as sentinel at the ends | 2259 // Intialize a fake NewSpacePage used as sentinel at the ends |
| 2266 // of a doubly-linked list of real NewSpacePages. | 2260 // of a doubly-linked list of real NewSpacePages. |
| 2267 // Only uses the prev/next links, and sets flags to not be in new-space. | 2261 // Only uses the prev/next links, and sets flags to not be in new-space. |
| (...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2524 | 2518 |
| 2525 // Grow the capacity of the semispaces. Assumes that they are not at | 2519 // Grow the capacity of the semispaces. Assumes that they are not at |
| 2526 // their maximum capacity. | 2520 // their maximum capacity. |
| 2527 void Grow(); | 2521 void Grow(); |
| 2528 | 2522 |
| 2529 // Shrink the capacity of the semispaces. | 2523 // Shrink the capacity of the semispaces. |
| 2530 void Shrink(); | 2524 void Shrink(); |
| 2531 | 2525 |
| 2532 // Return the allocated bytes in the active semispace. | 2526 // Return the allocated bytes in the active semispace. |
| 2533 intptr_t Size() override { | 2527 intptr_t Size() override { |
| 2534 return pages_used_ * NewSpacePage::kAreaSize + | 2528 return pages_used_ * NewSpacePage::kAllocatableMemory + |
| 2535 static_cast<int>(top() - to_space_.page_low()); | 2529 static_cast<int>(top() - to_space_.page_low()); |
| 2536 } | 2530 } |
| 2537 | 2531 |
| 2538 // The same, but returning an int. We have to have the one that returns | 2532 // The same, but returning an int. We have to have the one that returns |
| 2539 // intptr_t because it is inherited, but if we know we are dealing with the | 2533 // intptr_t because it is inherited, but if we know we are dealing with the |
| 2540 // new space, which can't get as big as the other spaces then this is useful: | 2534 // new space, which can't get as big as the other spaces then this is useful: |
| 2541 int SizeAsInt() { return static_cast<int>(Size()); } | 2535 int SizeAsInt() { return static_cast<int>(Size()); } |
| 2542 | 2536 |
| 2543 // Return the allocatable capacity of a semispace. | 2537 // Return the allocatable capacity of a semispace. |
| 2544 intptr_t Capacity() { | 2538 intptr_t Capacity() { |
| 2545 SLOW_DCHECK(to_space_.current_capacity() == from_space_.current_capacity()); | 2539 SLOW_DCHECK(to_space_.current_capacity() == from_space_.current_capacity()); |
| 2546 return (to_space_.current_capacity() / Page::kPageSize) * | 2540 return (to_space_.current_capacity() / Page::kPageSize) * |
| 2547 NewSpacePage::kAreaSize; | 2541 NewSpacePage::kAllocatableMemory; |
| 2548 } | 2542 } |
| 2549 | 2543 |
| 2550 // Return the current size of a semispace, allocatable and non-allocatable | 2544 // Return the current size of a semispace, allocatable and non-allocatable |
| 2551 // memory. | 2545 // memory. |
| 2552 intptr_t TotalCapacity() { | 2546 intptr_t TotalCapacity() { |
| 2553 DCHECK(to_space_.current_capacity() == from_space_.current_capacity()); | 2547 DCHECK(to_space_.current_capacity() == from_space_.current_capacity()); |
| 2554 return to_space_.current_capacity(); | 2548 return to_space_.current_capacity(); |
| 2555 } | 2549 } |
| 2556 | 2550 |
| 2557 // Committed memory for NewSpace is the committed memory of both semi-spaces | 2551 // Committed memory for NewSpace is the committed memory of both semi-spaces |
| (...skipping 469 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3027 count = 0; | 3021 count = 0; |
| 3028 } | 3022 } |
| 3029 // Must be small, since an iteration is used for lookup. | 3023 // Must be small, since an iteration is used for lookup. |
| 3030 static const int kMaxComments = 64; | 3024 static const int kMaxComments = 64; |
| 3031 }; | 3025 }; |
| 3032 #endif | 3026 #endif |
| 3033 } // namespace internal | 3027 } // namespace internal |
| 3034 } // namespace v8 | 3028 } // namespace v8 |
| 3035 | 3029 |
| 3036 #endif // V8_HEAP_SPACES_H_ | 3030 #endif // V8_HEAP_SPACES_H_ |
| OLD | NEW |