| 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/concurrent-marking-deque.h" | 10 #include "src/heap/concurrent-marking-deque.h" |
| (...skipping 12 matching lines...) Expand all Loading... |
| 23 namespace internal { | 23 namespace internal { |
| 24 | 24 |
| 25 class ConcurrentMarkingVisitor final | 25 class ConcurrentMarkingVisitor final |
| 26 : public HeapVisitor<int, ConcurrentMarkingVisitor> { | 26 : public HeapVisitor<int, ConcurrentMarkingVisitor> { |
| 27 public: | 27 public: |
| 28 using BaseClass = HeapVisitor<int, ConcurrentMarkingVisitor>; | 28 using BaseClass = HeapVisitor<int, ConcurrentMarkingVisitor>; |
| 29 | 29 |
| 30 explicit ConcurrentMarkingVisitor(ConcurrentMarkingDeque* deque) | 30 explicit ConcurrentMarkingVisitor(ConcurrentMarkingDeque* deque) |
| 31 : deque_(deque) {} | 31 : deque_(deque) {} |
| 32 | 32 |
| 33 bool ShouldVisit(HeapObject* object) override { |
| 34 return ObjectMarking::GreyToBlack<MarkBit::AccessMode::ATOMIC>( |
| 35 object, marking_state(object)); |
| 36 } |
| 37 |
| 33 void VisitPointers(HeapObject* host, Object** start, Object** end) override { | 38 void VisitPointers(HeapObject* host, Object** start, Object** end) override { |
| 34 for (Object** p = start; p < end; p++) { | 39 for (Object** p = start; p < end; p++) { |
| 35 if (!(*p)->IsHeapObject()) continue; | 40 if (!(*p)->IsHeapObject()) continue; |
| 36 MarkObject(HeapObject::cast(*p)); | 41 MarkObject(HeapObject::cast(*p)); |
| 37 } | 42 } |
| 38 } | 43 } |
| 39 | 44 |
| 40 // =========================================================================== | 45 // =========================================================================== |
| 41 // JS object ================================================================= | 46 // JS object ================================================================= |
| 42 // =========================================================================== | 47 // =========================================================================== |
| (...skipping 18 matching lines...) Expand all Loading... |
| 61 int VisitFixedArray(Map* map, FixedArray* object) override { | 66 int VisitFixedArray(Map* map, FixedArray* object) override { |
| 62 // TODO(ulan): implement iteration with prefetched length. | 67 // TODO(ulan): implement iteration with prefetched length. |
| 63 return BaseClass::VisitFixedArray(map, object); | 68 return BaseClass::VisitFixedArray(map, object); |
| 64 } | 69 } |
| 65 | 70 |
| 66 // =========================================================================== | 71 // =========================================================================== |
| 67 // Code object =============================================================== | 72 // Code object =============================================================== |
| 68 // =========================================================================== | 73 // =========================================================================== |
| 69 | 74 |
| 70 int VisitCode(Map* map, Code* object) override { | 75 int VisitCode(Map* map, Code* object) override { |
| 71 // TODO(ulan): push the object to the bail-out deque. | 76 deque_->Push(object, MarkingThread::kConcurrent, TargetDeque::kBailout); |
| 72 return 0; | 77 return 0; |
| 73 } | 78 } |
| 74 | 79 |
| 75 // =========================================================================== | 80 // =========================================================================== |
| 76 // Objects with weak fields and/or side-effectiful visitation. | 81 // Objects with weak fields and/or side-effectiful visitation. |
| 77 // =========================================================================== | 82 // =========================================================================== |
| 78 | 83 |
| 79 int VisitBytecodeArray(Map* map, BytecodeArray* object) override { | 84 int VisitBytecodeArray(Map* map, BytecodeArray* object) override { |
| 80 // TODO(ulan): implement iteration of strong fields and push the object to | 85 // TODO(ulan): implement iteration of strong fields. |
| 81 // the bailout deque. | 86 deque_->Push(object, MarkingThread::kConcurrent, TargetDeque::kBailout); |
| 82 return 0; | 87 return 0; |
| 83 } | 88 } |
| 84 | 89 |
| 85 int VisitJSFunction(Map* map, JSFunction* object) override { | 90 int VisitJSFunction(Map* map, JSFunction* object) override { |
| 86 // TODO(ulan): implement iteration of strong fields and push the object to | 91 // TODO(ulan): implement iteration of strong fields. |
| 87 // the bailout deque. | 92 deque_->Push(object, MarkingThread::kConcurrent, TargetDeque::kBailout); |
| 88 return 0; | 93 return 0; |
| 89 } | 94 } |
| 90 | 95 |
| 91 int VisitMap(Map* map, Map* object) override { | 96 int VisitMap(Map* map, Map* object) override { |
| 92 // TODO(ulan): implement iteration of strong fields and push the object to | 97 // TODO(ulan): implement iteration of strong fields. |
| 93 // the bailout deque. | 98 deque_->Push(object, MarkingThread::kConcurrent, TargetDeque::kBailout); |
| 94 return 0; | 99 return 0; |
| 95 } | 100 } |
| 96 | 101 |
| 97 int VisitNativeContext(Map* map, Context* object) override { | 102 int VisitNativeContext(Map* map, Context* object) override { |
| 98 // TODO(ulan): implement iteration of strong fields and push the object to | 103 // TODO(ulan): implement iteration of strong fields. |
| 99 // the bailout deque. | 104 deque_->Push(object, MarkingThread::kConcurrent, TargetDeque::kBailout); |
| 100 return 0; | 105 return 0; |
| 101 } | 106 } |
| 102 | 107 |
| 103 int VisitSharedFunctionInfo(Map* map, SharedFunctionInfo* object) override { | 108 int VisitSharedFunctionInfo(Map* map, SharedFunctionInfo* object) override { |
| 104 // TODO(ulan): implement iteration of strong fields and push the object to | 109 // TODO(ulan): implement iteration of strong fields. |
| 105 // the bailout deque. | 110 deque_->Push(object, MarkingThread::kConcurrent, TargetDeque::kBailout); |
| 106 return 0; | 111 return 0; |
| 107 } | 112 } |
| 108 | 113 |
| 109 int VisitTransitionArray(Map* map, TransitionArray* object) override { | 114 int VisitTransitionArray(Map* map, TransitionArray* object) override { |
| 110 // TODO(ulan): implement iteration of strong fields and push the object to | 115 // TODO(ulan): implement iteration of strong fields. |
| 111 // the bailout deque. | 116 deque_->Push(object, MarkingThread::kConcurrent, TargetDeque::kBailout); |
| 112 return 0; | 117 return 0; |
| 113 } | 118 } |
| 114 | 119 |
| 115 int VisitWeakCell(Map* map, WeakCell* object) override { | 120 int VisitWeakCell(Map* map, WeakCell* object) override { |
| 116 // TODO(ulan): implement iteration of strong fields and push the object to | 121 // TODO(ulan): implement iteration of strong fields. |
| 117 // the bailout deque. | 122 deque_->Push(object, MarkingThread::kConcurrent, TargetDeque::kBailout); |
| 118 return 0; | 123 return 0; |
| 119 } | 124 } |
| 120 | 125 |
| 121 int VisitJSWeakCollection(Map* map, JSWeakCollection* object) override { | 126 int VisitJSWeakCollection(Map* map, JSWeakCollection* object) override { |
| 122 // TODO(ulan): implement iteration of strong fields and push the object to | 127 // TODO(ulan): implement iteration of strong fields. |
| 123 // the bailout deque. | 128 deque_->Push(object, MarkingThread::kConcurrent, TargetDeque::kBailout); |
| 124 return 0; | 129 return 0; |
| 125 } | 130 } |
| 126 | 131 |
| 127 void MarkObject(HeapObject* obj) { | 132 void MarkObject(HeapObject* object) { |
| 128 deque_->Push(obj, MarkingThread::kConcurrent, TargetDeque::kShared); | 133 if (ObjectMarking::WhiteToGrey<MarkBit::AccessMode::ATOMIC>( |
| 134 object, marking_state(object))) { |
| 135 deque_->Push(object, MarkingThread::kConcurrent, TargetDeque::kShared); |
| 136 } |
| 129 } | 137 } |
| 130 | 138 |
| 131 private: | 139 private: |
| 140 MarkingState marking_state(HeapObject* object) const { |
| 141 return MarkingState::Internal(object); |
| 142 } |
| 143 |
| 132 ConcurrentMarkingDeque* deque_; | 144 ConcurrentMarkingDeque* deque_; |
| 133 }; | 145 }; |
| 134 | 146 |
| 135 class ConcurrentMarking::Task : public CancelableTask { | 147 class ConcurrentMarking::Task : public CancelableTask { |
| 136 public: | 148 public: |
| 137 Task(Isolate* isolate, ConcurrentMarking* concurrent_marking, | 149 Task(Isolate* isolate, ConcurrentMarking* concurrent_marking, |
| 138 base::Semaphore* on_finish) | 150 base::Semaphore* on_finish) |
| 139 : CancelableTask(isolate), | 151 : CancelableTask(isolate), |
| 140 concurrent_marking_(concurrent_marking), | 152 concurrent_marking_(concurrent_marking), |
| 141 on_finish_(on_finish) {} | 153 on_finish_(on_finish) {} |
| (...skipping 26 matching lines...) Expand all Loading... |
| 168 | 180 |
| 169 ConcurrentMarking::~ConcurrentMarking() { delete visitor_; } | 181 ConcurrentMarking::~ConcurrentMarking() { delete visitor_; } |
| 170 | 182 |
| 171 void ConcurrentMarking::Run() { | 183 void ConcurrentMarking::Run() { |
| 172 double time_ms = heap_->MonotonicallyIncreasingTimeInMs(); | 184 double time_ms = heap_->MonotonicallyIncreasingTimeInMs(); |
| 173 size_t bytes_marked = 0; | 185 size_t bytes_marked = 0; |
| 174 { | 186 { |
| 175 TimedScope scope(&time_ms); | 187 TimedScope scope(&time_ms); |
| 176 HeapObject* object; | 188 HeapObject* object; |
| 177 while ((object = deque_->Pop(MarkingThread::kConcurrent)) != nullptr) { | 189 while ((object = deque_->Pop(MarkingThread::kConcurrent)) != nullptr) { |
| 178 bytes_marked += visitor_->IterateBody(object); | 190 bytes_marked += visitor_->Visit(object); |
| 179 } | 191 } |
| 180 } | 192 } |
| 181 if (FLAG_trace_concurrent_marking) { | 193 if (FLAG_trace_concurrent_marking) { |
| 182 heap_->isolate()->PrintWithTimestamp("concurrently marked %dKB in %.2fms\n", | 194 heap_->isolate()->PrintWithTimestamp("concurrently marked %dKB in %.2fms\n", |
| 183 static_cast<int>(bytes_marked / KB), | 195 static_cast<int>(bytes_marked / KB), |
| 184 time_ms); | 196 time_ms); |
| 185 } | 197 } |
| 186 } | 198 } |
| 187 | 199 |
| 188 void ConcurrentMarking::StartTask() { | 200 void ConcurrentMarking::StartTask() { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 200 } | 212 } |
| 201 | 213 |
| 202 void ConcurrentMarking::EnsureTaskCompleted() { | 214 void ConcurrentMarking::EnsureTaskCompleted() { |
| 203 if (IsTaskPending()) { | 215 if (IsTaskPending()) { |
| 204 WaitForTaskToComplete(); | 216 WaitForTaskToComplete(); |
| 205 } | 217 } |
| 206 } | 218 } |
| 207 | 219 |
| 208 } // namespace internal | 220 } // namespace internal |
| 209 } // namespace v8 | 221 } // namespace v8 |
| OLD | NEW |