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 |