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 401 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
412 NEW_SPACE_BELOW_AGE_MARK, | 412 NEW_SPACE_BELOW_AGE_MARK, |
413 EVACUATION_CANDIDATE, | 413 EVACUATION_CANDIDATE, |
414 NEVER_EVACUATE, // May contain immortal immutables. | 414 NEVER_EVACUATE, // May contain immortal immutables. |
415 | 415 |
416 // Large objects can have a progress bar in their page header. These object | 416 // Large objects can have a progress bar in their page header. These object |
417 // are scanned in increments and will be kept black while being scanned. | 417 // are scanned in increments and will be kept black while being scanned. |
418 // Even if the mutator writes to them they will be kept black and a white | 418 // Even if the mutator writes to them they will be kept black and a white |
419 // to grey transition is performed in the value. | 419 // to grey transition is performed in the value. |
420 HAS_PROGRESS_BAR, | 420 HAS_PROGRESS_BAR, |
421 | 421 |
422 // A fast evacuation page has been moved from new space to old space during | |
423 // evacuation. | |
424 FAST_NEW_OLD_EVACUATION, | |
Hannes Payer (out of office)
2016/04/18 12:12:23
Keep this page flag in sync with the regular flags
Michael Lippautz
2016/04/18 12:57:38
Done.
| |
425 | |
422 // A black page has all mark bits set to 1 (black). A black page currently | 426 // A black page has all mark bits set to 1 (black). A black page currently |
423 // cannot be iterated because it is not swept. Moreover live bytes are also | 427 // cannot be iterated because it is not swept. Moreover live bytes are also |
424 // not updated. | 428 // not updated. |
425 BLACK_PAGE, | 429 BLACK_PAGE, |
426 | 430 |
427 // This flag is intended to be used for testing. Works only when both | 431 // This flag is intended to be used for testing. Works only when both |
428 // FLAG_stress_compaction and FLAG_manual_evacuation_candidates_selection | 432 // FLAG_stress_compaction and FLAG_manual_evacuation_candidates_selection |
429 // are set. It forces the page to become an evacuation candidate at next | 433 // are set. It forces the page to become an evacuation candidate at next |
430 // candidates selection cycle. | 434 // candidates selection cycle. |
431 FORCE_EVACUATION_CANDIDATE_FOR_TESTING, | 435 FORCE_EVACUATION_CANDIDATE_FOR_TESTING, |
(...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
813 }; | 817 }; |
814 | 818 |
815 // ----------------------------------------------------------------------------- | 819 // ----------------------------------------------------------------------------- |
816 // A page is a memory chunk of a size 1MB. Large object pages may be larger. | 820 // A page is a memory chunk of a size 1MB. Large object pages may be larger. |
817 // | 821 // |
818 // The only way to get a page pointer is by calling factory methods: | 822 // The only way to get a page pointer is by calling factory methods: |
819 // Page* p = Page::FromAddress(addr); or | 823 // Page* p = Page::FromAddress(addr); or |
820 // Page* p = Page::FromAllocationTop(top); | 824 // Page* p = Page::FromAllocationTop(top); |
821 class Page : public MemoryChunk { | 825 class Page : public MemoryChunk { |
822 public: | 826 public: |
827 static inline Page* Convert(NewSpacePage* old_page, PagedSpace* new_owner); | |
828 | |
823 // Returns the page containing a given address. The address ranges | 829 // Returns the page containing a given address. The address ranges |
824 // from [page_addr .. page_addr + kPageSize[ | 830 // from [page_addr .. page_addr + kPageSize[ |
825 // This only works if the object is in fact in a page. See also MemoryChunk:: | 831 // This only works if the object is in fact in a page. See also MemoryChunk:: |
826 // FromAddress() and FromAnyAddress(). | 832 // FromAddress() and FromAnyAddress(). |
827 INLINE(static Page* FromAddress(Address a)) { | 833 INLINE(static Page* FromAddress(Address a)) { |
828 return reinterpret_cast<Page*>(OffsetFrom(a) & ~kPageAlignmentMask); | 834 return reinterpret_cast<Page*>(OffsetFrom(a) & ~kPageAlignmentMask); |
829 } | 835 } |
830 | 836 |
831 // Only works for addresses in pointer spaces, not code space. | 837 // Only works for addresses in pointer spaces, not code space. |
832 inline static Page* FromAnyPointerAddress(Heap* heap, Address addr); | 838 inline static Page* FromAnyPointerAddress(Heap* heap, Address addr); |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
927 | 933 |
928 #ifdef DEBUG | 934 #ifdef DEBUG |
929 void Print(); | 935 void Print(); |
930 #endif // DEBUG | 936 #endif // DEBUG |
931 | 937 |
932 inline void MarkNeverAllocateForTesting(); | 938 inline void MarkNeverAllocateForTesting(); |
933 inline void MarkEvacuationCandidate(); | 939 inline void MarkEvacuationCandidate(); |
934 inline void ClearEvacuationCandidate(); | 940 inline void ClearEvacuationCandidate(); |
935 | 941 |
936 private: | 942 private: |
943 enum InitializationMode { kFreeMemory, kDoNotFreeMemory }; | |
944 | |
945 template <InitializationMode mode = kFreeMemory> | |
937 static inline Page* Initialize(Heap* heap, MemoryChunk* chunk, | 946 static inline Page* Initialize(Heap* heap, MemoryChunk* chunk, |
938 Executability executable, PagedSpace* owner); | 947 Executability executable, PagedSpace* owner); |
939 | 948 |
940 inline void InitializeFreeListCategories(); | 949 inline void InitializeFreeListCategories(); |
941 | 950 |
942 friend class MemoryAllocator; | 951 friend class MemoryAllocator; |
943 }; | 952 }; |
944 | 953 |
945 | 954 |
946 class LargePage : public MemoryChunk { | 955 class LargePage : public MemoryChunk { |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1030 virtual intptr_t Available() = 0; | 1039 virtual intptr_t Available() = 0; |
1031 | 1040 |
1032 virtual int RoundSizeDownToObjectAlignment(int size) { | 1041 virtual int RoundSizeDownToObjectAlignment(int size) { |
1033 if (id_ == CODE_SPACE) { | 1042 if (id_ == CODE_SPACE) { |
1034 return RoundDown(size, kCodeAlignment); | 1043 return RoundDown(size, kCodeAlignment); |
1035 } else { | 1044 } else { |
1036 return RoundDown(size, kPointerSize); | 1045 return RoundDown(size, kPointerSize); |
1037 } | 1046 } |
1038 } | 1047 } |
1039 | 1048 |
1040 #ifdef DEBUG | |
1041 virtual void Print() = 0; | |
1042 #endif | |
1043 | |
1044 protected: | |
1045 void AccountCommitted(intptr_t bytes) { | 1049 void AccountCommitted(intptr_t bytes) { |
1046 DCHECK_GE(bytes, 0); | 1050 DCHECK_GE(bytes, 0); |
1047 committed_ += bytes; | 1051 committed_ += bytes; |
1048 if (committed_ > max_committed_) { | 1052 if (committed_ > max_committed_) { |
1049 max_committed_ = committed_; | 1053 max_committed_ = committed_; |
1050 } | 1054 } |
1051 } | 1055 } |
1052 | 1056 |
1053 void AccountUncommitted(intptr_t bytes) { | 1057 void AccountUncommitted(intptr_t bytes) { |
1054 DCHECK_GE(bytes, 0); | 1058 DCHECK_GE(bytes, 0); |
1055 committed_ -= bytes; | 1059 committed_ -= bytes; |
1056 DCHECK_GE(committed_, 0); | 1060 DCHECK_GE(committed_, 0); |
1057 } | 1061 } |
1058 | 1062 |
1063 #ifdef DEBUG | |
1064 virtual void Print() = 0; | |
1065 #endif | |
1066 | |
1067 protected: | |
1059 v8::base::SmartPointer<List<AllocationObserver*>> allocation_observers_; | 1068 v8::base::SmartPointer<List<AllocationObserver*>> allocation_observers_; |
1060 bool allocation_observers_paused_; | 1069 bool allocation_observers_paused_; |
1061 | 1070 |
1062 private: | 1071 private: |
1063 Heap* heap_; | 1072 Heap* heap_; |
1064 AllocationSpace id_; | 1073 AllocationSpace id_; |
1065 Executability executable_; | 1074 Executability executable_; |
1066 | 1075 |
1067 // Keeps track of committed memory in a space. | 1076 // Keeps track of committed memory in a space. |
1068 intptr_t committed_; | 1077 intptr_t committed_; |
(...skipping 1275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2344 static inline NewSpacePage* Initialize(Heap* heap, MemoryChunk* chunk, | 2353 static inline NewSpacePage* Initialize(Heap* heap, MemoryChunk* chunk, |
2345 Executability executable, | 2354 Executability executable, |
2346 SemiSpace* owner); | 2355 SemiSpace* owner); |
2347 | 2356 |
2348 // GC related flags copied from from-space to to-space when | 2357 // GC related flags copied from from-space to to-space when |
2349 // flipping semispaces. | 2358 // flipping semispaces. |
2350 static const intptr_t kCopyOnFlipFlagsMask = | 2359 static const intptr_t kCopyOnFlipFlagsMask = |
2351 (1 << MemoryChunk::POINTERS_TO_HERE_ARE_INTERESTING) | | 2360 (1 << MemoryChunk::POINTERS_TO_HERE_ARE_INTERESTING) | |
2352 (1 << MemoryChunk::POINTERS_FROM_HERE_ARE_INTERESTING); | 2361 (1 << MemoryChunk::POINTERS_FROM_HERE_ARE_INTERESTING); |
2353 | 2362 |
2363 static const intptr_t kCopyAllFlags = ~0; | |
2364 | |
2354 // Create a NewSpacePage object that is only used as anchor | 2365 // Create a NewSpacePage object that is only used as anchor |
2355 // for the doubly-linked list of real pages. | 2366 // for the doubly-linked list of real pages. |
2356 explicit NewSpacePage(SemiSpace* owner) { InitializeAsAnchor(owner); } | 2367 explicit NewSpacePage(SemiSpace* owner) { InitializeAsAnchor(owner); } |
2357 | 2368 |
2358 // Intialize a fake NewSpacePage used as sentinel at the ends | 2369 // Intialize a fake NewSpacePage used as sentinel at the ends |
2359 // of a doubly-linked list of real NewSpacePages. | 2370 // of a doubly-linked list of real NewSpacePages. |
2360 // Only uses the prev/next links, and sets flags to not be in new-space. | 2371 // Only uses the prev/next links, and sets flags to not be in new-space. |
2361 void InitializeAsAnchor(SemiSpace* owner); | 2372 void InitializeAsAnchor(SemiSpace* owner); |
2362 | 2373 |
2363 friend class MemoryAllocator; | 2374 friend class MemoryAllocator; |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2429 bool AdvancePage() { | 2440 bool AdvancePage() { |
2430 NewSpacePage* next_page = current_page_->next_page(); | 2441 NewSpacePage* next_page = current_page_->next_page(); |
2431 if (next_page == anchor()) return false; | 2442 if (next_page == anchor()) return false; |
2432 current_page_ = next_page; | 2443 current_page_ = next_page; |
2433 return true; | 2444 return true; |
2434 } | 2445 } |
2435 | 2446 |
2436 // Resets the space to using the first page. | 2447 // Resets the space to using the first page. |
2437 void Reset(); | 2448 void Reset(); |
2438 | 2449 |
2450 void ReplaceWithEmptyPage(NewSpacePage* page); | |
2451 | |
2439 // Age mark accessors. | 2452 // Age mark accessors. |
2440 Address age_mark() { return age_mark_; } | 2453 Address age_mark() { return age_mark_; } |
2441 void set_age_mark(Address mark); | 2454 void set_age_mark(Address mark); |
2442 | 2455 |
2443 // Returns the current capacity of the semispace. | 2456 // Returns the current capacity of the semispace. |
2444 int current_capacity() { return current_capacity_; } | 2457 int current_capacity() { return current_capacity_; } |
2445 | 2458 |
2446 // Returns the maximum capacity of the semispace. | 2459 // Returns the maximum capacity of the semispace. |
2447 int maximum_capacity() { return maximum_capacity_; } | 2460 int maximum_capacity() { return maximum_capacity_; } |
2448 | 2461 |
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2646 return from_space_.MaximumCommittedMemory() + | 2659 return from_space_.MaximumCommittedMemory() + |
2647 to_space_.MaximumCommittedMemory(); | 2660 to_space_.MaximumCommittedMemory(); |
2648 } | 2661 } |
2649 | 2662 |
2650 // Approximate amount of physical memory committed for this space. | 2663 // Approximate amount of physical memory committed for this space. |
2651 size_t CommittedPhysicalMemory() override; | 2664 size_t CommittedPhysicalMemory() override; |
2652 | 2665 |
2653 // Return the available bytes without growing. | 2666 // Return the available bytes without growing. |
2654 intptr_t Available() override { return Capacity() - Size(); } | 2667 intptr_t Available() override { return Capacity() - Size(); } |
2655 | 2668 |
2669 void ReplaceWithEmptyPage(NewSpacePage* page) { | |
2670 // This method is called after flipping the semispace. | |
2671 DCHECK(page->InFromSpace()); | |
2672 from_space_.ReplaceWithEmptyPage(page); | |
2673 } | |
2674 | |
2656 size_t AllocatedSinceLastGC() { | 2675 size_t AllocatedSinceLastGC() { |
2657 bool seen_age_mark = false; | 2676 bool seen_age_mark = false; |
2658 Address age_mark = to_space_.age_mark(); | 2677 Address age_mark = to_space_.age_mark(); |
2659 NewSpacePage* current_page = to_space_.first_page(); | 2678 NewSpacePage* current_page = to_space_.first_page(); |
2660 NewSpacePage* age_mark_page = NewSpacePage::FromAddress(age_mark); | 2679 NewSpacePage* age_mark_page = NewSpacePage::FromAddress(age_mark); |
2661 NewSpacePage* last_page = NewSpacePage::FromAddress(top() - kPointerSize); | 2680 NewSpacePage* last_page = NewSpacePage::FromAddress(top() - kPointerSize); |
2662 if (age_mark_page == last_page) { | 2681 if (age_mark_page == last_page) { |
2663 if (top() - age_mark >= 0) { | 2682 if (top() - age_mark >= 0) { |
2664 return top() - age_mark; | 2683 return top() - age_mark; |
2665 } | 2684 } |
(...skipping 449 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3115 count = 0; | 3134 count = 0; |
3116 } | 3135 } |
3117 // Must be small, since an iteration is used for lookup. | 3136 // Must be small, since an iteration is used for lookup. |
3118 static const int kMaxComments = 64; | 3137 static const int kMaxComments = 64; |
3119 }; | 3138 }; |
3120 #endif | 3139 #endif |
3121 } // namespace internal | 3140 } // namespace internal |
3122 } // namespace v8 | 3141 } // namespace v8 |
3123 | 3142 |
3124 #endif // V8_HEAP_SPACES_H_ | 3143 #endif // V8_HEAP_SPACES_H_ |
OLD | NEW |