OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 #include "src/heap/heap.h" | 5 #include "src/heap/heap.h" |
6 | 6 |
7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
8 #include "src/api.h" | 8 #include "src/api.h" |
9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" |
10 #include "src/base/once.h" | 10 #include "src/base/once.h" |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
128 old_generation_size_at_last_gc_(0), | 128 old_generation_size_at_last_gc_(0), |
129 gcs_since_last_deopt_(0), | 129 gcs_since_last_deopt_(0), |
130 allocation_sites_scratchpad_length_(0), | 130 allocation_sites_scratchpad_length_(0), |
131 ring_buffer_full_(false), | 131 ring_buffer_full_(false), |
132 ring_buffer_end_(0), | 132 ring_buffer_end_(0), |
133 promotion_queue_(this), | 133 promotion_queue_(this), |
134 configured_(false), | 134 configured_(false), |
135 current_gc_flags_(Heap::kNoGCFlags), | 135 current_gc_flags_(Heap::kNoGCFlags), |
136 external_string_table_(this), | 136 external_string_table_(this), |
137 chunks_queued_for_free_(NULL), | 137 chunks_queued_for_free_(NULL), |
| 138 pending_unmap_job_semaphore_(0), |
138 gc_callbacks_depth_(0), | 139 gc_callbacks_depth_(0), |
139 deserialization_complete_(false), | 140 deserialization_complete_(false), |
140 concurrent_sweeping_enabled_(false), | 141 concurrent_sweeping_enabled_(false), |
141 strong_roots_list_(NULL) { | 142 strong_roots_list_(NULL) { |
142 // Allow build-time customization of the max semispace size. Building | 143 // Allow build-time customization of the max semispace size. Building |
143 // V8 with snapshots and a non-default max semispace size is much | 144 // V8 with snapshots and a non-default max semispace size is much |
144 // easier if you can define it as part of the build environment. | 145 // easier if you can define it as part of the build environment. |
145 #if defined(V8_MAX_SEMISPACE_SIZE) | 146 #if defined(V8_MAX_SEMISPACE_SIZE) |
146 max_semi_space_size_ = reserved_semispace_size_ = V8_MAX_SEMISPACE_SIZE; | 147 max_semi_space_size_ = reserved_semispace_size_ = V8_MAX_SEMISPACE_SIZE; |
147 #endif | 148 #endif |
(...skipping 6407 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6555 heap_->FinalizeExternalString(ExternalString::cast(new_space_strings_[i])); | 6556 heap_->FinalizeExternalString(ExternalString::cast(new_space_strings_[i])); |
6556 } | 6557 } |
6557 new_space_strings_.Free(); | 6558 new_space_strings_.Free(); |
6558 for (int i = 0; i < old_space_strings_.length(); ++i) { | 6559 for (int i = 0; i < old_space_strings_.length(); ++i) { |
6559 heap_->FinalizeExternalString(ExternalString::cast(old_space_strings_[i])); | 6560 heap_->FinalizeExternalString(ExternalString::cast(old_space_strings_[i])); |
6560 } | 6561 } |
6561 old_space_strings_.Free(); | 6562 old_space_strings_.Free(); |
6562 } | 6563 } |
6563 | 6564 |
6564 | 6565 |
| 6566 class Heap::UnmapFreeMemoryTask : public v8::Task { |
| 6567 public: |
| 6568 UnmapFreeMemoryTask(Heap* heap, MemoryChunk* head) |
| 6569 : heap_(heap), head_(head) {} |
| 6570 virtual ~UnmapFreeMemoryTask() {} |
| 6571 |
| 6572 private: |
| 6573 // v8::Task overrides. |
| 6574 void Run() override { |
| 6575 heap_->FreeQueuedChunks(head_); |
| 6576 heap_->pending_unmap_job_semaphore_.Signal(); |
| 6577 } |
| 6578 |
| 6579 Heap* heap_; |
| 6580 MemoryChunk* head_; |
| 6581 |
| 6582 DISALLOW_COPY_AND_ASSIGN(UnmapFreeMemoryTask); |
| 6583 }; |
| 6584 |
| 6585 |
| 6586 void Heap::WaitUntilUnmappingOfFreeChunksCompleted() { |
| 6587 // We start an unmap job after sweeping and after compaction. |
| 6588 pending_unmap_job_semaphore_.Wait(); |
| 6589 pending_unmap_job_semaphore_.Wait(); |
| 6590 } |
| 6591 |
| 6592 |
6565 void Heap::QueueMemoryChunkForFree(MemoryChunk* chunk) { | 6593 void Heap::QueueMemoryChunkForFree(MemoryChunk* chunk) { |
6566 chunk->set_next_chunk(chunks_queued_for_free_); | 6594 chunk->set_next_chunk(chunks_queued_for_free_); |
6567 chunks_queued_for_free_ = chunk; | 6595 chunks_queued_for_free_ = chunk; |
6568 } | 6596 } |
6569 | 6597 |
6570 | 6598 |
6571 void Heap::FilterStoreBufferEntriesOnAboutToBeFreedPages() { | 6599 void Heap::FilterStoreBufferEntriesOnAboutToBeFreedPages() { |
6572 if (chunks_queued_for_free_ == NULL) return; | 6600 if (chunks_queued_for_free_ == NULL) return; |
6573 MemoryChunk* next; | 6601 MemoryChunk* next; |
6574 MemoryChunk* chunk; | 6602 MemoryChunk* chunk; |
6575 for (chunk = chunks_queued_for_free_; chunk != NULL; chunk = next) { | 6603 for (chunk = chunks_queued_for_free_; chunk != NULL; chunk = next) { |
6576 next = chunk->next_chunk(); | 6604 next = chunk->next_chunk(); |
6577 chunk->SetFlag(MemoryChunk::ABOUT_TO_BE_FREED); | 6605 chunk->SetFlag(MemoryChunk::ABOUT_TO_BE_FREED); |
6578 } | 6606 } |
6579 isolate_->heap()->store_buffer()->Compact(); | 6607 store_buffer()->Compact(); |
6580 isolate_->heap()->store_buffer()->Filter(MemoryChunk::ABOUT_TO_BE_FREED); | 6608 store_buffer()->Filter(MemoryChunk::ABOUT_TO_BE_FREED); |
6581 } | 6609 } |
6582 | 6610 |
6583 | 6611 |
6584 void Heap::FreeQueuedChunks() { | 6612 void Heap::FreeQueuedChunks() { |
| 6613 if (chunks_queued_for_free_ != NULL) { |
| 6614 V8::GetCurrentPlatform()->CallOnBackgroundThread( |
| 6615 new UnmapFreeMemoryTask(this, chunks_queued_for_free_), |
| 6616 v8::Platform::kShortRunningTask); |
| 6617 chunks_queued_for_free_ = NULL; |
| 6618 } else { |
| 6619 // If we do not have anything to unmap, we just signal the semaphore |
| 6620 // that we are done. |
| 6621 pending_unmap_job_semaphore_.Signal(); |
| 6622 } |
| 6623 } |
| 6624 |
| 6625 |
| 6626 void Heap::FreeQueuedChunks(MemoryChunk* list_head) { |
6585 MemoryChunk* next; | 6627 MemoryChunk* next; |
6586 MemoryChunk* chunk; | 6628 MemoryChunk* chunk; |
6587 for (chunk = chunks_queued_for_free_; chunk != NULL; chunk = next) { | 6629 for (chunk = list_head; chunk != NULL; chunk = next) { |
6588 next = chunk->next_chunk(); | 6630 next = chunk->next_chunk(); |
6589 isolate_->memory_allocator()->Free(chunk); | 6631 isolate_->memory_allocator()->Free(chunk); |
6590 } | 6632 } |
6591 chunks_queued_for_free_ = NULL; | |
6592 } | 6633 } |
6593 | 6634 |
6594 | 6635 |
6595 void Heap::RememberUnmappedPage(Address page, bool compacted) { | 6636 void Heap::RememberUnmappedPage(Address page, bool compacted) { |
6596 uintptr_t p = reinterpret_cast<uintptr_t>(page); | 6637 uintptr_t p = reinterpret_cast<uintptr_t>(page); |
6597 // Tag the page pointer to make it findable in the dump file. | 6638 // Tag the page pointer to make it findable in the dump file. |
6598 if (compacted) { | 6639 if (compacted) { |
6599 p ^= 0xc1ead & (Page::kPageSize - 1); // Cleared. | 6640 p ^= 0xc1ead & (Page::kPageSize - 1); // Cleared. |
6600 } else { | 6641 } else { |
6601 p ^= 0x1d1ed & (Page::kPageSize - 1); // I died. | 6642 p ^= 0x1d1ed & (Page::kPageSize - 1); // I died. |
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6785 *object_type = "CODE_TYPE"; \ | 6826 *object_type = "CODE_TYPE"; \ |
6786 *object_sub_type = "CODE_AGE/" #name; \ | 6827 *object_sub_type = "CODE_AGE/" #name; \ |
6787 return true; | 6828 return true; |
6788 CODE_AGE_LIST_COMPLETE(COMPARE_AND_RETURN_NAME) | 6829 CODE_AGE_LIST_COMPLETE(COMPARE_AND_RETURN_NAME) |
6789 #undef COMPARE_AND_RETURN_NAME | 6830 #undef COMPARE_AND_RETURN_NAME |
6790 } | 6831 } |
6791 return false; | 6832 return false; |
6792 } | 6833 } |
6793 } // namespace internal | 6834 } // namespace internal |
6794 } // namespace v8 | 6835 } // namespace v8 |
OLD | NEW |