| OLD | NEW |
| 1 // Copyright 2017 the V8 project authors. All rights reserved. | 1 // Copyright 2017 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/concurrent-marking.h" | 5 #include "src/heap/concurrent-marking.h" |
| 6 | 6 |
| 7 #include <stack> | 7 #include <stack> |
| 8 #include <unordered_map> | 8 #include <unordered_map> |
| 9 | 9 |
| 10 #include "src/heap/heap-inl.h" | 10 #include "src/heap/heap-inl.h" |
| 11 #include "src/heap/heap.h" | 11 #include "src/heap/heap.h" |
| 12 #include "src/heap/marking.h" | 12 #include "src/heap/marking.h" |
| 13 #include "src/isolate.h" | 13 #include "src/isolate.h" |
| 14 #include "src/locked-queue-inl.h" | 14 #include "src/locked-queue-inl.h" |
| 15 #include "src/utils-inl.h" |
| 16 #include "src/utils.h" |
| 15 #include "src/v8.h" | 17 #include "src/v8.h" |
| 16 | 18 |
| 17 namespace v8 { | 19 namespace v8 { |
| 18 namespace internal { | 20 namespace internal { |
| 19 | 21 |
| 20 class ConcurrentMarkingMarkbits { | 22 class ConcurrentMarkingMarkbits { |
| 21 public: | 23 public: |
| 22 ConcurrentMarkingMarkbits() {} | 24 ConcurrentMarkingMarkbits() {} |
| 23 ~ConcurrentMarkingMarkbits() { | 25 ~ConcurrentMarkingMarkbits() { |
| 24 for (auto chunk_bitmap : bitmap_) { | 26 for (auto chunk_bitmap : bitmap_) { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 43 } | 45 } |
| 44 | 46 |
| 45 void FreeBitmap(Bitmap* bitmap) { free(bitmap); } | 47 void FreeBitmap(Bitmap* bitmap) { free(bitmap); } |
| 46 | 48 |
| 47 private: | 49 private: |
| 48 std::unordered_map<MemoryChunk*, Bitmap*> bitmap_; | 50 std::unordered_map<MemoryChunk*, Bitmap*> bitmap_; |
| 49 }; | 51 }; |
| 50 | 52 |
| 51 class ConcurrentMarkingVisitor : public ObjectVisitor { | 53 class ConcurrentMarkingVisitor : public ObjectVisitor { |
| 52 public: | 54 public: |
| 53 ConcurrentMarkingVisitor() {} | 55 ConcurrentMarkingVisitor() : bytes_marked_(0) {} |
| 54 | 56 |
| 55 void VisitPointers(Object** start, Object** end) override { | 57 void VisitPointers(Object** start, Object** end) override { |
| 56 for (Object** p = start; p < end; p++) { | 58 for (Object** p = start; p < end; p++) { |
| 57 if (!(*p)->IsHeapObject()) continue; | 59 if (!(*p)->IsHeapObject()) continue; |
| 58 MarkObject(HeapObject::cast(*p)); | 60 MarkObject(HeapObject::cast(*p)); |
| 59 } | 61 } |
| 60 } | 62 } |
| 61 | 63 |
| 62 void MarkObject(HeapObject* obj) { | 64 void MarkObject(HeapObject* obj) { |
| 63 if (markbits_.Mark(obj)) { | 65 if (markbits_.Mark(obj)) { |
| 66 bytes_marked_ += obj->Size(); |
| 64 marking_stack_.push(obj); | 67 marking_stack_.push(obj); |
| 65 } | 68 } |
| 66 } | 69 } |
| 67 | 70 |
| 68 void MarkTransitively() { | 71 void MarkTransitively() { |
| 69 while (!marking_stack_.empty()) { | 72 while (!marking_stack_.empty()) { |
| 70 HeapObject* obj = marking_stack_.top(); | 73 HeapObject* obj = marking_stack_.top(); |
| 71 marking_stack_.pop(); | 74 marking_stack_.pop(); |
| 72 obj->Iterate(this); | 75 obj->Iterate(this); |
| 73 } | 76 } |
| 74 } | 77 } |
| 75 | 78 |
| 79 size_t bytes_marked() { return bytes_marked_; } |
| 80 |
| 76 private: | 81 private: |
| 82 size_t bytes_marked_; |
| 77 std::stack<HeapObject*> marking_stack_; | 83 std::stack<HeapObject*> marking_stack_; |
| 78 ConcurrentMarkingMarkbits markbits_; | 84 ConcurrentMarkingMarkbits markbits_; |
| 79 }; | 85 }; |
| 80 | 86 |
| 81 class ConcurrentMarking::Task : public CancelableTask { | 87 class ConcurrentMarking::Task : public CancelableTask { |
| 82 public: | 88 public: |
| 83 Task(Heap* heap, std::vector<HeapObject*>* root_set, | 89 Task(Heap* heap, std::vector<HeapObject*>* root_set, |
| 84 base::Semaphore* on_finish) | 90 base::Semaphore* on_finish) |
| 85 : CancelableTask(heap->isolate()), | 91 : CancelableTask(heap->isolate()), |
| 86 heap_(heap), | 92 heap_(heap), |
| 87 on_finish_(on_finish), | 93 on_finish_(on_finish), |
| 88 root_set_(root_set) {} | 94 root_set_(root_set) {} |
| 89 | 95 |
| 90 virtual ~Task() {} | 96 virtual ~Task() {} |
| 91 | 97 |
| 92 private: | 98 private: |
| 93 // v8::internal::CancelableTask overrides. | 99 // v8::internal::CancelableTask overrides. |
| 94 void RunInternal() override { | 100 void RunInternal() override { |
| 95 USE(heap_); | 101 double time_ms = heap_->MonotonicallyIncreasingTimeInMs(); |
| 96 for (HeapObject* obj : *root_set_) { | 102 { |
| 97 marking_visitor_.MarkObject(obj); | 103 TimedScope scope(&time_ms); |
| 104 for (HeapObject* obj : *root_set_) { |
| 105 marking_visitor_.MarkObject(obj); |
| 106 } |
| 107 marking_visitor_.MarkTransitively(); |
| 98 } | 108 } |
| 99 marking_visitor_.MarkTransitively(); | 109 if (FLAG_trace_concurrent_marking) { |
| 110 heap_->isolate()->PrintWithTimestamp( |
| 111 "concurrently marked %dKB in %.2fms\n", |
| 112 static_cast<int>(marking_visitor_.bytes_marked() / KB), time_ms); |
| 113 } |
| 100 on_finish_->Signal(); | 114 on_finish_->Signal(); |
| 101 } | 115 } |
| 102 | 116 |
| 103 Heap* heap_; | 117 Heap* heap_; |
| 104 base::Semaphore* on_finish_; | 118 base::Semaphore* on_finish_; |
| 105 ConcurrentMarkingVisitor marking_visitor_; | 119 ConcurrentMarkingVisitor marking_visitor_; |
| 106 std::vector<HeapObject*>* root_set_; | 120 std::vector<HeapObject*>* root_set_; |
| 107 DISALLOW_COPY_AND_ASSIGN(Task); | 121 DISALLOW_COPY_AND_ASSIGN(Task); |
| 108 }; | 122 }; |
| 109 | 123 |
| 110 ConcurrentMarking::ConcurrentMarking(Heap* heap) | 124 ConcurrentMarking::ConcurrentMarking(Heap* heap) |
| 111 : heap_(heap), pending_task_(0) {} | 125 : heap_(heap), pending_task_semaphore_(0), is_task_pending_(false) { |
| 126 // Concurrent marking does not work with double unboxing. |
| 127 STATIC_ASSERT(!(V8_CONCURRENT_MARKING && V8_DOUBLE_FIELDS_UNBOXING)); |
| 128 // The runtime flag should be set only if the compile time flag was set. |
| 129 CHECK(!FLAG_concurrent_marking || V8_CONCURRENT_MARKING); |
| 130 } |
| 112 | 131 |
| 113 ConcurrentMarking::~ConcurrentMarking() {} | 132 ConcurrentMarking::~ConcurrentMarking() {} |
| 114 | 133 |
| 115 void ConcurrentMarking::AddRoot(HeapObject* object) { | 134 void ConcurrentMarking::AddRoot(HeapObject* object) { |
| 116 root_set_.push_back(object); | 135 root_set_.push_back(object); |
| 117 } | 136 } |
| 118 | 137 |
| 119 void ConcurrentMarking::StartMarkingTask() { | 138 void ConcurrentMarking::StartTask() { |
| 120 if (!FLAG_concurrent_marking) return; | 139 if (!FLAG_concurrent_marking) return; |
| 140 is_task_pending_ = true; |
| 121 | 141 |
| 122 V8::GetCurrentPlatform()->CallOnBackgroundThread( | 142 V8::GetCurrentPlatform()->CallOnBackgroundThread( |
| 123 new Task(heap_, &root_set_, &pending_task_), | 143 new Task(heap_, &root_set_, &pending_task_semaphore_), |
| 124 v8::Platform::kShortRunningTask); | 144 v8::Platform::kShortRunningTask); |
| 125 } | 145 } |
| 126 | 146 |
| 127 void ConcurrentMarking::WaitForTaskToComplete() { | 147 void ConcurrentMarking::WaitForTaskToComplete() { |
| 128 if (!FLAG_concurrent_marking) return; | 148 if (!FLAG_concurrent_marking) return; |
| 129 pending_task_.Wait(); | 149 pending_task_semaphore_.Wait(); |
| 150 is_task_pending_ = false; |
| 151 root_set_.clear(); |
| 152 } |
| 153 |
| 154 void ConcurrentMarking::EnsureTaskCompleted() { |
| 155 if (IsTaskPending()) { |
| 156 WaitForTaskToComplete(); |
| 157 } |
| 130 } | 158 } |
| 131 | 159 |
| 132 } // namespace internal | 160 } // namespace internal |
| 133 } // namespace v8 | 161 } // namespace v8 |
| OLD | NEW |