| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent f68f572 commit 1c0ae10
5 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1814,7 +1814,11 @@ void Heap::Scavenge() { | |||
| 1814 | 1814 | ArrayBufferTracker::FreeDeadInNewSpace(this); | |
| 1815 | 1815 | ||
| 1816 | 1816 | RememberedSet<OLD_TO_NEW>::IterateMemoryChunks(this, [](MemoryChunk* chunk) { | |
| 1817 | - RememberedSet<OLD_TO_NEW>::PreFreeEmptyBuckets(chunk); | ||
| 1817 | + if (chunk->SweepingDone()) { | ||
| 1818 | + RememberedSet<OLD_TO_NEW>::FreeEmptyBuckets(chunk); | ||
| 1819 | + } else { | ||
| 1820 | + RememberedSet<OLD_TO_NEW>::PreFreeEmptyBuckets(chunk); | ||
| 1821 | + } | ||
| 1818 | 1822 | }); | |
| 1819 | 1823 | ||
| 1820 | 1824 | // Update how much has survived scavenge. | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -150,6 +150,19 @@ class RememberedSet : public AllStatic { | |||
| 150 | 150 | } | |
| 151 | 151 | } | |
| 152 | 152 | ||
| 153 | + static int NumberOfPreFreedEmptyBuckets(MemoryChunk* chunk) { | ||
| 154 | + DCHECK(type == OLD_TO_NEW); | ||
| 155 | + int result = 0; | ||
| 156 | + SlotSet* slots = chunk->slot_set<type>(); | ||
| 157 | + if (slots != nullptr) { | ||
| 158 | + size_t pages = (chunk->size() + Page::kPageSize - 1) / Page::kPageSize; | ||
| 159 | + for (size_t page = 0; page < pages; page++) { | ||
| 160 | + result += slots[page].NumberOfPreFreedEmptyBuckets(); | ||
| 161 | + } | ||
| 162 | + } | ||
| 163 | + return result; | ||
| 164 | + } | ||
| 165 | + | ||
| 153 | 166 | static void PreFreeEmptyBuckets(MemoryChunk* chunk) { | |
| 154 | 167 | DCHECK(type == OLD_TO_NEW); | |
| 155 | 168 | SlotSet* slots = chunk->slot_set<type>(); | |
@@ -161,6 +174,18 @@ class RememberedSet : public AllStatic { | |||
| 161 | 174 | } | |
| 162 | 175 | } | |
| 163 | 176 | ||
| 177 | + static void FreeEmptyBuckets(MemoryChunk* chunk) { | ||
| 178 | + DCHECK(type == OLD_TO_NEW); | ||
| 179 | + SlotSet* slots = chunk->slot_set<type>(); | ||
| 180 | + if (slots != nullptr) { | ||
| 181 | + size_t pages = (chunk->size() + Page::kPageSize - 1) / Page::kPageSize; | ||
| 182 | + for (size_t page = 0; page < pages; page++) { | ||
| 183 | + slots[page].FreeEmptyBuckets(); | ||
| 184 | + slots[page].FreeToBeFreedBuckets(); | ||
| 185 | + } | ||
| 186 | + } | ||
| 187 | + } | ||
| 188 | + | ||
| 164 | 189 | // Given a page and a typed slot in that page, this function adds the slot | |
| 165 | 190 | // to the remembered set. | |
| 166 | 191 | static void InsertTyped(Page* page, Address host_addr, SlotType slot_type, | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -225,32 +225,41 @@ class SlotSet : public Malloced { | |||
| 225 | 225 | return new_count; | |
| 226 | 226 | } | |
| 227 | 227 | ||
| 228 | + int NumberOfPreFreedEmptyBuckets() { | ||
| 229 | + base::LockGuard<base::Mutex> guard(&to_be_freed_buckets_mutex_); | ||
| 230 | + return static_cast<int>(to_be_freed_buckets_.size()); | ||
| 231 | + } | ||
| 232 | + | ||
| 228 | 233 | void PreFreeEmptyBuckets() { | |
| 229 | 234 | for (int bucket_index = 0; bucket_index < kBuckets; bucket_index++) { | |
| 230 | 235 | Bucket bucket = LoadBucket(&buckets_[bucket_index]); | |
| 231 | 236 | if (bucket != nullptr) { | |
| 232 | - bool found_non_empty_cell = false; | ||
| 233 | - int cell_offset = bucket_index * kBitsPerBucket; | ||
| 234 | - for (int i = 0; i < kCellsPerBucket; i++, cell_offset += kBitsPerCell) { | ||
| 235 | - if (LoadCell(&bucket[i])) { | ||
| 236 | - found_non_empty_cell = true; | ||
| 237 | - break; | ||
| 238 | - } | ||
| 239 | - } | ||
| 240 | - if (!found_non_empty_cell) { | ||
| 237 | + if (IsEmptyBucket(bucket)) { | ||
| 241 | 238 | PreFreeEmptyBucket(bucket_index); | |
| 242 | 239 | } | |
| 243 | 240 | } | |
| 244 | 241 | } | |
| 245 | 242 | } | |
| 246 | 243 | ||
| 244 | + void FreeEmptyBuckets() { | ||
| 245 | + for (int bucket_index = 0; bucket_index < kBuckets; bucket_index++) { | ||
| 246 | + Bucket bucket = LoadBucket(&buckets_[bucket_index]); | ||
| 247 | + if (bucket != nullptr) { | ||
| 248 | + if (IsEmptyBucket(bucket)) { | ||
| 249 | + ReleaseBucket(bucket_index); | ||
| 250 | + } | ||
| 251 | + } | ||
| 252 | + } | ||
| 253 | + } | ||
| 254 | + | ||
| 247 | 255 | void FreeToBeFreedBuckets() { | |
| 248 | 256 | base::LockGuard<base::Mutex> guard(&to_be_freed_buckets_mutex_); | |
| 249 | 257 | while (!to_be_freed_buckets_.empty()) { | |
| 250 | 258 | Bucket top = to_be_freed_buckets_.top(); | |
| 251 | 259 | to_be_freed_buckets_.pop(); | |
| 252 | 260 | DeleteArray<uint32_t>(top); | |
| 253 | 261 | } | |
| 262 | + DCHECK_EQ(0u, to_be_freed_buckets_.size()); | ||
| 254 | 263 | } | |
| 255 | 264 | ||
| 256 | 265 | private: | |
@@ -313,6 +322,15 @@ class SlotSet : public Malloced { | |||
| 313 | 322 | } | |
| 314 | 323 | } | |
| 315 | 324 | ||
| 325 | + bool IsEmptyBucket(Bucket bucket) { | ||
| 326 | + for (int i = 0; i < kCellsPerBucket; i++) { | ||
| 327 | + if (LoadCell(&bucket[i])) { | ||
| 328 | + return false; | ||
| 329 | + } | ||
| 330 | + } | ||
| 331 | + return true; | ||
| 332 | + } | ||
| 333 | + | ||
| 316 | 334 | template <AccessMode access_mode = AccessMode::ATOMIC> | |
| 317 | 335 | bool SwapInNewBucket(Bucket* bucket, Bucket value) { | |
| 318 | 336 | if (access_mode == AccessMode::ATOMIC) { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -3308,6 +3308,7 @@ void LargeObjectSpace::ClearMarkingStateOfLiveObjects() { | |||
| 3308 | 3308 | Marking::MarkWhite( | |
| 3309 | 3309 | ObjectMarking::MarkBitFrom(obj, MarkingState::Internal(obj))); | |
| 3310 | 3310 | MemoryChunk* chunk = MemoryChunk::FromAddress(obj->address()); | |
| 3311 | + RememberedSet<OLD_TO_NEW>::FreeEmptyBuckets(chunk); | ||
| 3311 | 3312 | chunk->ResetProgressBar(); | |
| 3312 | 3313 | MarkingState::Internal(chunk).SetLiveBytes(0); | |
| 3313 | 3314 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -6237,6 +6237,53 @@ HEAP_TEST(Regress5831) { | |||
| 6237 | 6237 | CHECK(chunk->NeverEvacuate()); | |
| 6238 | 6238 | } | |
| 6239 | 6239 | ||
| 6240 | + TEST(Regress6800) { | ||
| 6241 | + CcTest::InitializeVM(); | ||
| 6242 | + Isolate* isolate = CcTest::i_isolate(); | ||
| 6243 | + HandleScope handle_scope(isolate); | ||
| 6244 | + | ||
| 6245 | + const int kRootLength = 1000; | ||
| 6246 | + Handle<FixedArray> root = | ||
| 6247 | + isolate->factory()->NewFixedArray(kRootLength, TENURED); | ||
| 6248 | + { | ||
| 6249 | + HandleScope inner_scope(isolate); | ||
| 6250 | + Handle<FixedArray> new_space_array = isolate->factory()->NewFixedArray(1); | ||
| 6251 | + for (int i = 0; i < kRootLength; i++) { | ||
| 6252 | + root->set(i, *new_space_array); | ||
| 6253 | + } | ||
| 6254 | + for (int i = 0; i < kRootLength; i++) { | ||
| 6255 | + root->set(i, CcTest::heap()->undefined_value()); | ||
| 6256 | + } | ||
| 6257 | + } | ||
| 6258 | + CcTest::CollectGarbage(NEW_SPACE); | ||
| 6259 | + CHECK_EQ(0, RememberedSet<OLD_TO_NEW>::NumberOfPreFreedEmptyBuckets( | ||
| 6260 | + MemoryChunk::FromAddress(root->address()))); | ||
| 6261 | + } | ||
| 6262 | + | ||
| 6263 | + TEST(Regress6800LargeObject) { | ||
| 6264 | + CcTest::InitializeVM(); | ||
| 6265 | + Isolate* isolate = CcTest::i_isolate(); | ||
| 6266 | + HandleScope handle_scope(isolate); | ||
| 6267 | + | ||
| 6268 | + const int kRootLength = i::kMaxRegularHeapObjectSize / kPointerSize; | ||
| 6269 | + Handle<FixedArray> root = | ||
| 6270 | + isolate->factory()->NewFixedArray(kRootLength, TENURED); | ||
| 6271 | + CcTest::heap()->lo_space()->Contains(*root); | ||
| 6272 | + { | ||
| 6273 | + HandleScope inner_scope(isolate); | ||
| 6274 | + Handle<FixedArray> new_space_array = isolate->factory()->NewFixedArray(1); | ||
| 6275 | + for (int i = 0; i < kRootLength; i++) { | ||
| 6276 | + root->set(i, *new_space_array); | ||
| 6277 | + } | ||
| 6278 | + for (int i = 0; i < kRootLength; i++) { | ||
| 6279 | + root->set(i, CcTest::heap()->undefined_value()); | ||
| 6280 | + } | ||
| 6281 | + } | ||
| 6282 | + CcTest::CollectGarbage(OLD_SPACE); | ||
| 6283 | + CHECK_EQ(0, RememberedSet<OLD_TO_NEW>::NumberOfPreFreedEmptyBuckets( | ||
| 6284 | + MemoryChunk::FromAddress(root->address()))); | ||
| 6285 | + } | ||
| 6286 | + | ||
| 6240 | 6287 | HEAP_TEST(RegressMissingWriteBarrierInAllocate) { | |
| 6241 | 6288 | if (!FLAG_incremental_marking) return; | |
| 6242 | 6289 | FLAG_black_allocation = true; | |
| Back | FazBrowse Home | New Git URL |
0 commit comments