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/mark-compact.h" | 5 #include "src/heap/mark-compact.h" |
6 | 6 |
7 #include "src/base/atomicops.h" | 7 #include "src/base/atomicops.h" |
8 #include "src/base/bits.h" | 8 #include "src/base/bits.h" |
9 #include "src/base/sys-info.h" | 9 #include "src/base/sys-info.h" |
10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
(...skipping 2097 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2108 } | 2108 } |
2109 | 2109 |
2110 void MarkingDeque::SetUp() { | 2110 void MarkingDeque::SetUp() { |
2111 backing_store_ = new base::VirtualMemory(kMaxSize); | 2111 backing_store_ = new base::VirtualMemory(kMaxSize); |
2112 backing_store_committed_size_ = 0; | 2112 backing_store_committed_size_ = 0; |
2113 if (backing_store_ == nullptr) { | 2113 if (backing_store_ == nullptr) { |
2114 V8::FatalProcessOutOfMemory("MarkingDeque::SetUp"); | 2114 V8::FatalProcessOutOfMemory("MarkingDeque::SetUp"); |
2115 } | 2115 } |
2116 } | 2116 } |
2117 | 2117 |
2118 void MarkingDeque::TearDown() { delete backing_store_; } | 2118 void MarkingDeque::TearDown() { |
2119 WaitForUncommitTask(); | |
Michael Lippautz
2016/10/24 08:43:23
Maybe for future: Afaik, background tasks provide
ulan
2016/10/24 13:14:09
I made the task cancelable.
| |
2120 delete backing_store_; | |
2121 } | |
2119 | 2122 |
2120 void MarkingDeque::StartUsing() { | 2123 void MarkingDeque::StartUsing() { |
2124 base::LockGuard<base::Mutex> guard(&mutex_); | |
2121 if (in_use_) { | 2125 if (in_use_) { |
2122 // This can happen in mark-compact GC if the incremental marker already | 2126 // This can happen in mark-compact GC if the incremental marker already |
2123 // started using the marking deque. | 2127 // started using the marking deque. |
2124 return; | 2128 return; |
2125 } | 2129 } |
2126 in_use_ = true; | 2130 in_use_ = true; |
2127 EnsureCommitted(); | 2131 EnsureCommitted(); |
2128 array_ = reinterpret_cast<HeapObject**>(backing_store_->address()); | 2132 array_ = reinterpret_cast<HeapObject**>(backing_store_->address()); |
2129 size_t size = FLAG_force_marking_deque_overflows | 2133 size_t size = FLAG_force_marking_deque_overflows |
2130 ? 64 * kPointerSize | 2134 ? 64 * kPointerSize |
2131 : backing_store_committed_size_; | 2135 : backing_store_committed_size_; |
2132 DCHECK( | 2136 DCHECK( |
2133 base::bits::IsPowerOfTwo32(static_cast<uint32_t>(size / kPointerSize))); | 2137 base::bits::IsPowerOfTwo32(static_cast<uint32_t>(size / kPointerSize))); |
2134 mask_ = static_cast<int>((size / kPointerSize) - 1); | 2138 mask_ = static_cast<int>((size / kPointerSize) - 1); |
2135 top_ = bottom_ = 0; | 2139 top_ = bottom_ = 0; |
2136 overflowed_ = false; | 2140 overflowed_ = false; |
2137 } | 2141 } |
2138 | 2142 |
2139 void MarkingDeque::StopUsing() { | 2143 void MarkingDeque::StopUsing() { |
2144 base::LockGuard<base::Mutex> guard(&mutex_); | |
2140 DCHECK(IsEmpty()); | 2145 DCHECK(IsEmpty()); |
2141 DCHECK(!overflowed_); | 2146 DCHECK(!overflowed_); |
2142 top_ = bottom_ = mask_ = 0; | 2147 top_ = bottom_ = mask_ = 0; |
2143 Uncommit(); | |
2144 in_use_ = false; | 2148 in_use_ = false; |
2149 if (FLAG_concurrent_sweeping) { | |
2150 StartUncommitTask(); | |
2151 } else { | |
2152 Uncommit(); | |
2153 } | |
2145 } | 2154 } |
2146 | 2155 |
2147 void MarkingDeque::Clear() { | 2156 void MarkingDeque::Clear() { |
2148 DCHECK(in_use_); | 2157 DCHECK(in_use_); |
2149 top_ = bottom_ = 0; | 2158 top_ = bottom_ = 0; |
2150 overflowed_ = false; | 2159 overflowed_ = false; |
2151 } | 2160 } |
2152 | 2161 |
2153 void MarkingDeque::Uncommit() { | 2162 void MarkingDeque::Uncommit() { |
2154 DCHECK(in_use_); | 2163 DCHECK(!in_use_); |
2155 bool success = backing_store_->Uncommit(backing_store_->address(), | 2164 bool success = backing_store_->Uncommit(backing_store_->address(), |
2156 backing_store_committed_size_); | 2165 backing_store_committed_size_); |
2157 backing_store_committed_size_ = 0; | 2166 backing_store_committed_size_ = 0; |
2158 CHECK(success); | 2167 CHECK(success); |
2159 } | 2168 } |
2160 | 2169 |
2161 void MarkingDeque::EnsureCommitted() { | 2170 void MarkingDeque::EnsureCommitted() { |
2162 DCHECK(in_use_); | 2171 DCHECK(in_use_); |
2163 if (backing_store_committed_size_ > 0) return; | 2172 if (backing_store_committed_size_ > 0) return; |
2164 | 2173 |
2165 for (size_t size = kMaxSize; size >= kMinSize; size /= 2) { | 2174 for (size_t size = kMaxSize; size >= kMinSize; size /= 2) { |
2166 if (backing_store_->Commit(backing_store_->address(), size, false)) { | 2175 if (backing_store_->Commit(backing_store_->address(), size, false)) { |
2167 backing_store_committed_size_ = size; | 2176 backing_store_committed_size_ = size; |
2168 break; | 2177 break; |
2169 } | 2178 } |
2170 } | 2179 } |
2171 if (backing_store_committed_size_ == 0) { | 2180 if (backing_store_committed_size_ == 0) { |
2172 V8::FatalProcessOutOfMemory("MarkingDeque::EnsureCommitted"); | 2181 V8::FatalProcessOutOfMemory("MarkingDeque::EnsureCommitted"); |
2173 } | 2182 } |
2174 } | 2183 } |
2175 | 2184 |
2185 void MarkingDeque::StartUncommitTask() { | |
2186 if (!uncommit_task_pending_) { | |
2187 uncommit_task_pending_ = true; | |
2188 V8::GetCurrentPlatform()->CallOnBackgroundThread( | |
2189 new UncommitTask(this), v8::Platform::kShortRunningTask); | |
2190 } | |
2191 } | |
2192 | |
2193 void MarkingDeque::WaitForUncommitTask() { | |
2194 base::LockGuard<base::Mutex> guard(&mutex_); | |
2195 while (uncommit_task_pending_) { | |
2196 uncommit_task_barrier_.Wait(&mutex_); | |
2197 } | |
2198 } | |
2199 | |
2176 class MarkCompactCollector::ObjectStatsVisitor | 2200 class MarkCompactCollector::ObjectStatsVisitor |
2177 : public MarkCompactCollector::HeapObjectVisitor { | 2201 : public MarkCompactCollector::HeapObjectVisitor { |
2178 public: | 2202 public: |
2179 ObjectStatsVisitor(Heap* heap, ObjectStats* live_stats, | 2203 ObjectStatsVisitor(Heap* heap, ObjectStats* live_stats, |
2180 ObjectStats* dead_stats) | 2204 ObjectStats* dead_stats) |
2181 : live_collector_(heap, live_stats), dead_collector_(heap, dead_stats) { | 2205 : live_collector_(heap, live_stats), dead_collector_(heap, dead_stats) { |
2182 DCHECK_NOT_NULL(live_stats); | 2206 DCHECK_NOT_NULL(live_stats); |
2183 DCHECK_NOT_NULL(dead_stats); | 2207 DCHECK_NOT_NULL(dead_stats); |
2184 // Global objects are roots and thus recorded as live. | 2208 // Global objects are roots and thus recorded as live. |
2185 live_collector_.CollectGlobalStatistics(); | 2209 live_collector_.CollectGlobalStatistics(); |
(...skipping 1706 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3892 // The target is always in old space, we don't have to record the slot in | 3916 // The target is always in old space, we don't have to record the slot in |
3893 // the old-to-new remembered set. | 3917 // the old-to-new remembered set. |
3894 DCHECK(!heap()->InNewSpace(target)); | 3918 DCHECK(!heap()->InNewSpace(target)); |
3895 RecordRelocSlot(host, &rinfo, target); | 3919 RecordRelocSlot(host, &rinfo, target); |
3896 } | 3920 } |
3897 } | 3921 } |
3898 } | 3922 } |
3899 | 3923 |
3900 } // namespace internal | 3924 } // namespace internal |
3901 } // namespace v8 | 3925 } // namespace v8 |
OLD | NEW |