Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 53 // ------------------------------------------------------------------------- | 53 // ------------------------------------------------------------------------- |
| 54 // MarkCompactCollector | 54 // MarkCompactCollector |
| 55 | 55 |
| 56 MarkCompactCollector::MarkCompactCollector() : // NOLINT | 56 MarkCompactCollector::MarkCompactCollector() : // NOLINT |
| 57 #ifdef DEBUG | 57 #ifdef DEBUG |
| 58 state_(IDLE), | 58 state_(IDLE), |
| 59 #endif | 59 #endif |
| 60 sweep_precisely_(false), | 60 sweep_precisely_(false), |
| 61 compacting_(false), | 61 compacting_(false), |
| 62 tracer_(NULL), | 62 tracer_(NULL), |
| 63 migration_slots_buffer_(NULL), | |
| 63 #ifdef DEBUG | 64 #ifdef DEBUG |
| 64 live_young_objects_size_(0), | 65 live_young_objects_size_(0), |
| 65 live_old_pointer_objects_size_(0), | 66 live_old_pointer_objects_size_(0), |
| 66 live_old_data_objects_size_(0), | 67 live_old_data_objects_size_(0), |
| 67 live_code_objects_size_(0), | 68 live_code_objects_size_(0), |
| 68 live_map_objects_size_(0), | 69 live_map_objects_size_(0), |
| 69 live_cell_objects_size_(0), | 70 live_cell_objects_size_(0), |
| 70 live_lo_objects_size_(0), | 71 live_lo_objects_size_(0), |
| 71 live_bytes_(0), | 72 live_bytes_(0), |
| 72 #endif | 73 #endif |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 225 evacuation_candidates_.Add(p); | 226 evacuation_candidates_.Add(p); |
| 226 } | 227 } |
| 227 | 228 |
| 228 | 229 |
| 229 bool MarkCompactCollector::StartCompaction() { | 230 bool MarkCompactCollector::StartCompaction() { |
| 230 // Don't start compaction if we are in the middle of incremental | 231 // Don't start compaction if we are in the middle of incremental |
| 231 // marking cycle. We did not collect any slots. | 232 // marking cycle. We did not collect any slots. |
| 232 if (!compacting_ && !heap_->incremental_marking()->IsMarking()) { | 233 if (!compacting_ && !heap_->incremental_marking()->IsMarking()) { |
| 233 ASSERT(evacuation_candidates_.length() == 0); | 234 ASSERT(evacuation_candidates_.length() == 0); |
| 234 | 235 |
| 235 // TODO(gc) Shrink slots buffer when we receive low memory notification. | |
| 236 slots_buffer_.Clear(); | |
| 237 | |
| 238 CollectEvacuationCandidates(heap()->old_pointer_space()); | 236 CollectEvacuationCandidates(heap()->old_pointer_space()); |
| 239 CollectEvacuationCandidates(heap()->old_data_space()); | 237 CollectEvacuationCandidates(heap()->old_data_space()); |
| 240 | 238 |
| 241 heap()->old_pointer_space()->EvictEvacuationCandidatesFromFreeLists(); | 239 heap()->old_pointer_space()->EvictEvacuationCandidatesFromFreeLists(); |
| 242 heap()->old_data_space()->EvictEvacuationCandidatesFromFreeLists(); | 240 heap()->old_data_space()->EvictEvacuationCandidatesFromFreeLists(); |
| 243 | 241 |
| 244 compacting_ = evacuation_candidates_.length() > 0; | 242 compacting_ = evacuation_candidates_.length() > 0; |
| 245 } | 243 } |
| 246 | 244 |
| 247 return compacting_; | 245 return compacting_; |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 377 new_mark_bit.Set(); | 375 new_mark_bit.Set(); |
| 378 return true; | 376 return true; |
| 379 } | 377 } |
| 380 | 378 |
| 381 | 379 |
| 382 void MarkCompactCollector::CollectEvacuationCandidates(PagedSpace* space) { | 380 void MarkCompactCollector::CollectEvacuationCandidates(PagedSpace* space) { |
| 383 ASSERT(space->identity() == OLD_POINTER_SPACE || | 381 ASSERT(space->identity() == OLD_POINTER_SPACE || |
| 384 space->identity() == OLD_DATA_SPACE); | 382 space->identity() == OLD_DATA_SPACE); |
| 385 | 383 |
| 386 PageIterator it(space); | 384 PageIterator it(space); |
| 385 if (it.has_next()) it.next(); // Never compact the first page. | |
| 387 while (it.has_next()) { | 386 while (it.has_next()) { |
| 388 Page* p = it.next(); | 387 Page* p = it.next(); |
| 389 if (space->IsFragmented(p)) { | 388 if (space->IsFragmented(p)) { |
| 390 AddEvacuationCandidate(p); | 389 AddEvacuationCandidate(p); |
| 391 } else { | 390 } else { |
| 392 p->ClearEvacuationCandidate(); | 391 p->ClearEvacuationCandidate(); |
| 393 } | 392 } |
| 394 } | 393 } |
| 395 } | 394 } |
| 396 | 395 |
| (...skipping 1659 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2056 | 2055 |
| 2057 for (int remaining = size / kPointerSize; remaining > 0; remaining--) { | 2056 for (int remaining = size / kPointerSize; remaining > 0; remaining--) { |
| 2058 Object* value = Memory::Object_at(src_slot); | 2057 Object* value = Memory::Object_at(src_slot); |
| 2059 | 2058 |
| 2060 Memory::Object_at(dst_slot) = value; | 2059 Memory::Object_at(dst_slot) = value; |
| 2061 | 2060 |
| 2062 if (heap_->InNewSpace(value)) { | 2061 if (heap_->InNewSpace(value)) { |
| 2063 heap_->store_buffer()->Mark(dst_slot); | 2062 heap_->store_buffer()->Mark(dst_slot); |
| 2064 } else if (value->IsHeapObject() && | 2063 } else if (value->IsHeapObject() && |
| 2065 MarkCompactCollector::IsOnEvacuationCandidate(value)) { | 2064 MarkCompactCollector::IsOnEvacuationCandidate(value)) { |
| 2066 slots_buffer_.Add(reinterpret_cast<Object**>(dst_slot)); | 2065 SlotsBuffer::AddTo(&slots_buffer_allocator_, |
| 2066 &migration_slots_buffer_, | |
| 2067 reinterpret_cast<Object**>(dst_slot), | |
| 2068 SlotsBuffer::IGNORE_OVERFLOW); | |
| 2067 } | 2069 } |
| 2068 | 2070 |
| 2069 src_slot += kPointerSize; | 2071 src_slot += kPointerSize; |
| 2070 dst_slot += kPointerSize; | 2072 dst_slot += kPointerSize; |
| 2071 } | 2073 } |
| 2072 } else { | 2074 } else { |
| 2073 heap_->CopyBlock(dst, src, size); | 2075 heap_->CopyBlock(dst, src, size); |
| 2074 } | 2076 } |
| 2075 Memory::Address_at(src) = dst; | 2077 Memory::Address_at(src) = dst; |
| 2076 } | 2078 } |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2261 } | 2263 } |
| 2262 | 2264 |
| 2263 heap_->IncrementYoungSurvivorsCounter(survivors_size); | 2265 heap_->IncrementYoungSurvivorsCounter(survivors_size); |
| 2264 new_space->set_age_mark(new_space->top()); | 2266 new_space->set_age_mark(new_space->top()); |
| 2265 } | 2267 } |
| 2266 | 2268 |
| 2267 | 2269 |
| 2268 void MarkCompactCollector::EvacuateLiveObjectsFromPage(Page* p) { | 2270 void MarkCompactCollector::EvacuateLiveObjectsFromPage(Page* p) { |
| 2269 AlwaysAllocateScope always_allocate; | 2271 AlwaysAllocateScope always_allocate; |
| 2270 | 2272 |
| 2271 ASSERT(p->IsEvacuationCandidate() && !p->WasEvacuated()); | 2273 ASSERT(p->IsEvacuationCandidate() && !p->WasSwept()); |
| 2272 | 2274 |
| 2273 PagedSpace* space = static_cast<PagedSpace*>(p->owner()); | 2275 PagedSpace* space = static_cast<PagedSpace*>(p->owner()); |
| 2274 | 2276 |
| 2275 MarkBit::CellType* cells = p->markbits()->cells(); | 2277 MarkBit::CellType* cells = p->markbits()->cells(); |
| 2276 | 2278 |
| 2277 int last_cell_index = | 2279 int last_cell_index = |
| 2278 Bitmap::IndexToCell( | 2280 Bitmap::IndexToCell( |
| 2279 Bitmap::CellAlignIndex( | 2281 Bitmap::CellAlignIndex( |
| 2280 p->AddressToMarkbitIndex(p->ObjectAreaEnd()))); | 2282 p->AddressToMarkbitIndex(p->ObjectAreaEnd()))); |
| 2281 | 2283 |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 2310 ASSERT(object->map_word().IsForwardingAddress()); | 2312 ASSERT(object->map_word().IsForwardingAddress()); |
| 2311 } | 2313 } |
| 2312 } | 2314 } |
| 2313 } | 2315 } |
| 2314 | 2316 |
| 2315 | 2317 |
| 2316 void MarkCompactCollector::EvacuatePages() { | 2318 void MarkCompactCollector::EvacuatePages() { |
| 2317 int npages = evacuation_candidates_.length(); | 2319 int npages = evacuation_candidates_.length(); |
| 2318 for (int i = 0; i < npages; i++) { | 2320 for (int i = 0; i < npages; i++) { |
| 2319 Page* p = evacuation_candidates_[i]; | 2321 Page* p = evacuation_candidates_[i]; |
| 2320 EvacuateLiveObjectsFromPage(p); | 2322 ASSERT(p->IsEvacuationCandidate() || |
| 2323 p->IsFlagSet(Page::RESCAN_ON_EVACUATION)); | |
| 2324 if (p->IsEvacuationCandidate()) { | |
| 2325 EvacuateLiveObjectsFromPage(p); | |
| 2326 } | |
| 2321 } | 2327 } |
| 2322 } | 2328 } |
| 2323 | 2329 |
| 2324 | 2330 |
| 2325 class EvacuationWeakObjectRetainer : public WeakObjectRetainer { | 2331 class EvacuationWeakObjectRetainer : public WeakObjectRetainer { |
| 2326 public: | 2332 public: |
| 2327 virtual Object* RetainAs(Object* object) { | 2333 virtual Object* RetainAs(Object* object) { |
| 2328 if (object->IsHeapObject()) { | 2334 if (object->IsHeapObject()) { |
| 2329 HeapObject* heap_object = HeapObject::cast(object); | 2335 HeapObject* heap_object = HeapObject::cast(object); |
| 2330 MapWord map_word = heap_object->map_word(); | 2336 MapWord map_word = heap_object->map_word(); |
| 2331 if (map_word.IsForwardingAddress()) { | 2337 if (map_word.IsForwardingAddress()) { |
| 2332 return map_word.ToForwardingAddress(); | 2338 return map_word.ToForwardingAddress(); |
| 2333 } | 2339 } |
| 2334 } | 2340 } |
| 2335 return object; | 2341 return object; |
| 2336 } | 2342 } |
| 2337 }; | 2343 }; |
| 2338 | 2344 |
| 2339 | 2345 |
| 2346 static inline void UpdateSlot(Object** slot) { | |
| 2347 Object* obj = *slot; | |
| 2348 if (!obj->IsHeapObject()) return; | |
| 2349 | |
| 2350 HeapObject* heap_obj = HeapObject::cast(obj); | |
| 2351 | |
| 2352 MapWord map_word = heap_obj->map_word(); | |
| 2353 if (map_word.IsForwardingAddress()) { | |
| 2354 ASSERT(MarkCompactCollector::IsOnEvacuationCandidate(*slot)); | |
| 2355 *slot = map_word.ToForwardingAddress(); | |
| 2356 ASSERT(!MarkCompactCollector::IsOnEvacuationCandidate(*slot)); | |
| 2357 } | |
| 2358 } | |
| 2359 | |
| 2360 | |
| 2361 static inline void UpdateSlotsInRange(Object** start, Object** end) { | |
| 2362 for (Object** slot = start; | |
| 2363 slot < end; | |
| 2364 slot++) { | |
| 2365 Object* obj = *slot; | |
| 2366 if (obj->IsHeapObject() && | |
| 2367 MarkCompactCollector::IsOnEvacuationCandidate(obj)) { | |
| 2368 MapWord map_word = HeapObject::cast(obj)->map_word(); | |
| 2369 if (map_word.IsForwardingAddress()) { | |
| 2370 *slot = map_word.ToForwardingAddress(); | |
| 2371 ASSERT(!MarkCompactCollector::IsOnEvacuationCandidate(*slot)); | |
| 2372 } | |
| 2373 } | |
| 2374 } | |
| 2375 } | |
| 2376 | |
| 2377 | |
| 2378 static void UpdateSlotsOnPage(Page* p, ObjectVisitor* visitor) { | |
| 2379 // TODO(gc) this is basically clone of SweepPrecisely | |
| 2380 PagedSpace* space = static_cast<PagedSpace*>(p->owner()); | |
| 2381 MarkBit::CellType* cells = p->markbits()->cells(); | |
| 2382 | |
| 2383 p->ClearFlag(MemoryChunk::WAS_SWEPT_CONSERVATIVELY); | |
| 2384 p->ClearFlag(MemoryChunk::RESCAN_ON_EVACUATION); | |
| 2385 p->MarkSwept(); | |
| 2386 | |
| 2387 int last_cell_index = | |
| 2388 Bitmap::IndexToCell( | |
| 2389 Bitmap::CellAlignIndex( | |
| 2390 p->AddressToMarkbitIndex(p->ObjectAreaEnd()))); | |
| 2391 | |
| 2392 int cell_index = Page::kFirstUsedCell; | |
| 2393 Address free_start = p->ObjectAreaStart(); | |
| 2394 ASSERT(reinterpret_cast<intptr_t>(free_start) % (32 * kPointerSize) == 0); | |
| 2395 Address object_address = p->ObjectAreaStart(); | |
| 2396 int offsets[16]; | |
| 2397 | |
| 2398 for (cell_index = Page::kFirstUsedCell; | |
| 2399 cell_index < last_cell_index; | |
| 2400 cell_index++, object_address += 32 * kPointerSize) { | |
| 2401 ASSERT((unsigned)cell_index == | |
| 2402 Bitmap::IndexToCell( | |
| 2403 Bitmap::CellAlignIndex( | |
| 2404 p->AddressToMarkbitIndex(object_address)))); | |
| 2405 int live_objects = MarkWordToObjectStarts(cells[cell_index], offsets); | |
| 2406 int live_index = 0; | |
| 2407 for ( ; live_objects != 0; live_objects--) { | |
| 2408 Address free_end = object_address + offsets[live_index++] * kPointerSize; | |
| 2409 if (free_end != free_start) { | |
| 2410 space->Free(free_start, free_end - free_start); | |
| 2411 } | |
| 2412 HeapObject* live_object = HeapObject::FromAddress(free_end); | |
| 2413 ASSERT(Marking::IsBlack(Marking::MarkBitFrom(live_object))); | |
| 2414 int size = live_object->Size(); | |
| 2415 UpdateSlotsInRange(HeapObject::RawField(live_object, kPointerSize), | |
| 2416 HeapObject::RawField(live_object, size)); | |
| 2417 free_start = free_end + size; | |
| 2418 } | |
| 2419 } | |
| 2420 if (free_start != p->ObjectAreaEnd()) { | |
| 2421 space->Free(free_start, p->ObjectAreaEnd() - free_start); | |
| 2422 } | |
| 2423 } | |
| 2424 | |
| 2425 | |
| 2340 void MarkCompactCollector::EvacuateNewSpaceAndCandidates() { | 2426 void MarkCompactCollector::EvacuateNewSpaceAndCandidates() { |
| 2341 EvacuateNewSpace(); | 2427 EvacuateNewSpace(); |
| 2342 EvacuatePages(); | 2428 EvacuatePages(); |
| 2343 | 2429 |
| 2344 // Second pass: find pointers to new space and update them. | 2430 // Second pass: find pointers to new space and update them. |
| 2345 PointersUpdatingVisitor updating_visitor(heap()); | 2431 PointersUpdatingVisitor updating_visitor(heap()); |
| 2346 | 2432 |
| 2347 // Update pointers in to space. | 2433 // Update pointers in to space. |
| 2348 SemiSpaceIterator to_it(heap()->new_space()->bottom(), | 2434 SemiSpaceIterator to_it(heap()->new_space()->bottom(), |
| 2349 heap()->new_space()->top()); | 2435 heap()->new_space()->top()); |
| 2350 for (HeapObject* object = to_it.Next(); | 2436 for (HeapObject* object = to_it.Next(); |
| 2351 object != NULL; | 2437 object != NULL; |
| 2352 object = to_it.Next()) { | 2438 object = to_it.Next()) { |
| 2353 Map* map = object->map(); | 2439 Map* map = object->map(); |
| 2354 object->IterateBody(map->instance_type(), | 2440 object->IterateBody(map->instance_type(), |
| 2355 object->SizeFromMap(map), | 2441 object->SizeFromMap(map), |
| 2356 &updating_visitor); | 2442 &updating_visitor); |
| 2357 } | 2443 } |
| 2358 | 2444 |
| 2359 // Update roots. | 2445 // Update roots. |
| 2360 heap_->IterateRoots(&updating_visitor, VISIT_ALL_IN_SWEEP_NEWSPACE); | 2446 heap_->IterateRoots(&updating_visitor, VISIT_ALL_IN_SWEEP_NEWSPACE); |
| 2361 LiveObjectList::IterateElements(&updating_visitor); | 2447 LiveObjectList::IterateElements(&updating_visitor); |
| 2362 | 2448 |
| 2363 { | 2449 { |
| 2364 StoreBufferRebuildScope scope(heap_, | 2450 StoreBufferRebuildScope scope(heap_, |
| 2365 heap_->store_buffer(), | 2451 heap_->store_buffer(), |
| 2366 &Heap::ScavengeStoreBufferCallback); | 2452 &Heap::ScavengeStoreBufferCallback); |
| 2367 heap_->store_buffer()->IteratePointersToNewSpace(&UpdatePointer); | 2453 heap_->store_buffer()->IteratePointersToNewSpace(&UpdatePointer); |
| 2368 } | 2454 } |
| 2369 slots_buffer_.Update(); | 2455 |
| 2456 SlotsBuffer::UpdateSlotsRecordedIn(migration_slots_buffer_); | |
| 2457 if (FLAG_trace_fragmentation) { | |
| 2458 PrintF(" migration slots buffer: %d\n", | |
| 2459 SlotsBuffer::SizeOfChain(migration_slots_buffer_)); | |
| 2460 } | |
| 2461 | |
| 2462 int npages = evacuation_candidates_.length(); | |
| 2463 for (int i = 0; i < npages; i++) { | |
| 2464 Page* p = evacuation_candidates_[i]; | |
| 2465 ASSERT(p->IsEvacuationCandidate() || | |
| 2466 p->IsFlagSet(Page::RESCAN_ON_EVACUATION)); | |
| 2467 | |
| 2468 if (p->IsEvacuationCandidate()) { | |
| 2469 SlotsBuffer::UpdateSlotsRecordedIn(p->slots_buffer()); | |
| 2470 if (FLAG_trace_fragmentation) { | |
| 2471 PrintF(" page %p slots buffer: %d\n", | |
| 2472 reinterpret_cast<void*>(p), | |
| 2473 SlotsBuffer::SizeOfChain(p->slots_buffer())); | |
| 2474 } | |
| 2475 } else { | |
| 2476 UpdateSlotsOnPage(p, &updating_visitor); | |
| 2477 } | |
| 2478 } | |
| 2370 | 2479 |
| 2371 // Update pointers from cells. | 2480 // Update pointers from cells. |
| 2372 HeapObjectIterator cell_iterator(heap_->cell_space()); | 2481 HeapObjectIterator cell_iterator(heap_->cell_space()); |
| 2373 for (HeapObject* cell = cell_iterator.Next(); | 2482 for (HeapObject* cell = cell_iterator.Next(); |
| 2374 cell != NULL; | 2483 cell != NULL; |
| 2375 cell = cell_iterator.Next()) { | 2484 cell = cell_iterator.Next()) { |
| 2376 if (cell->IsJSGlobalPropertyCell()) { | 2485 if (cell->IsJSGlobalPropertyCell()) { |
| 2377 Address value_address = | 2486 Address value_address = |
| 2378 reinterpret_cast<Address>(cell) + | 2487 reinterpret_cast<Address>(cell) + |
| 2379 (JSGlobalPropertyCell::kValueOffset - kHeapObjectTag); | 2488 (JSGlobalPropertyCell::kValueOffset - kHeapObjectTag); |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 2395 | 2504 |
| 2396 EvacuationWeakObjectRetainer evacuation_object_retainer; | 2505 EvacuationWeakObjectRetainer evacuation_object_retainer; |
| 2397 heap()->ProcessWeakReferences(&evacuation_object_retainer); | 2506 heap()->ProcessWeakReferences(&evacuation_object_retainer); |
| 2398 | 2507 |
| 2399 #ifdef DEBUG | 2508 #ifdef DEBUG |
| 2400 if (FLAG_verify_heap) { | 2509 if (FLAG_verify_heap) { |
| 2401 VerifyEvacuation(heap_); | 2510 VerifyEvacuation(heap_); |
| 2402 } | 2511 } |
| 2403 #endif | 2512 #endif |
| 2404 | 2513 |
| 2405 int npages = evacuation_candidates_.length(); | 2514 slots_buffer_allocator_.DeallocateChain(&migration_slots_buffer_); |
| 2406 ASSERT(compacting_ == (npages > 0)); | 2515 ASSERT(migration_slots_buffer_ == NULL); |
| 2407 for (int i = 0; i < npages; i++) { | 2516 for (int i = 0; i < npages; i++) { |
| 2408 Page* p = evacuation_candidates_[i]; | 2517 Page* p = evacuation_candidates_[i]; |
| 2409 ASSERT(p->IsEvacuationCandidate() && !p->WasEvacuated()); | 2518 if (!p->IsEvacuationCandidate()) continue; |
| 2410 PagedSpace* space = static_cast<PagedSpace*>(p->owner()); | 2519 PagedSpace* space = static_cast<PagedSpace*>(p->owner()); |
| 2411 space->Free(p->ObjectAreaStart(), Page::kObjectAreaSize); | 2520 space->Free(p->ObjectAreaStart(), Page::kObjectAreaSize); |
| 2412 p->set_scan_on_scavenge(false); | 2521 p->set_scan_on_scavenge(false); |
| 2522 slots_buffer_allocator_.DeallocateChain(p->slots_buffer_address()); | |
| 2413 p->ClearEvacuationCandidate(); | 2523 p->ClearEvacuationCandidate(); |
| 2414 p->SetFlag(MemoryChunk::EVACUATED); | 2524 p->MarkSwept(); |
| 2415 p->ClearFlag(MemoryChunk::WAS_SWEPT_CONSERVATIVELY); | 2525 p->ClearFlag(MemoryChunk::WAS_SWEPT_CONSERVATIVELY); |
| 2416 } | 2526 } |
| 2417 evacuation_candidates_.Rewind(0); | 2527 evacuation_candidates_.Rewind(0); |
| 2418 compacting_ = false; | 2528 compacting_ = false; |
| 2419 } | 2529 } |
| 2420 | 2530 |
| 2421 | 2531 |
| 2422 INLINE(static uint32_t SweepFree(PagedSpace* space, | 2532 INLINE(static uint32_t SweepFree(PagedSpace* space, |
| 2423 Page* p, | 2533 Page* p, |
| 2424 uint32_t free_start, | 2534 uint32_t free_start, |
| (...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2736 | 2846 |
| 2737 | 2847 |
| 2738 // Sweeps a space conservatively. After this has been done the larger free | 2848 // Sweeps a space conservatively. After this has been done the larger free |
| 2739 // spaces have been put on the free list and the smaller ones have been | 2849 // spaces have been put on the free list and the smaller ones have been |
| 2740 // ignored and left untouched. A free space is always either ignored or put | 2850 // ignored and left untouched. A free space is always either ignored or put |
| 2741 // on the free list, never split up into two parts. This is important | 2851 // on the free list, never split up into two parts. This is important |
| 2742 // because it means that any FreeSpace maps left actually describe a region of | 2852 // because it means that any FreeSpace maps left actually describe a region of |
| 2743 // memory that can be ignored when scanning. Dead objects other than free | 2853 // memory that can be ignored when scanning. Dead objects other than free |
| 2744 // spaces will not contain the free space map. | 2854 // spaces will not contain the free space map. |
| 2745 int MarkCompactCollector::SweepConservatively(PagedSpace* space, Page* p) { | 2855 int MarkCompactCollector::SweepConservatively(PagedSpace* space, Page* p) { |
| 2746 ASSERT(!p->IsEvacuationCandidate() && !p->WasEvacuated()); | 2856 ASSERT(!p->IsEvacuationCandidate() && !p->WasSwept()); |
| 2747 | 2857 |
| 2748 int freed_bytes = 0; | 2858 int freed_bytes = 0; |
| 2749 | 2859 |
| 2750 MarkBit::CellType* cells = p->markbits()->cells(); | 2860 MarkBit::CellType* cells = p->markbits()->cells(); |
| 2751 | 2861 |
| 2752 p->SetFlag(MemoryChunk::WAS_SWEPT_CONSERVATIVELY); | 2862 p->SetFlag(MemoryChunk::WAS_SWEPT_CONSERVATIVELY); |
| 2753 | 2863 |
| 2754 // This is the start of the 32 word block that we are currently looking at. | 2864 // This is the start of the 32 word block that we are currently looking at. |
| 2755 Address block_address = p->ObjectAreaStart(); | 2865 Address block_address = p->ObjectAreaStart(); |
| 2756 | 2866 |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2824 return freed_bytes; | 2934 return freed_bytes; |
| 2825 } | 2935 } |
| 2826 | 2936 |
| 2827 | 2937 |
| 2828 // Sweep a space precisely. After this has been done the space can | 2938 // Sweep a space precisely. After this has been done the space can |
| 2829 // be iterated precisely, hitting only the live objects. Code space | 2939 // be iterated precisely, hitting only the live objects. Code space |
| 2830 // is always swept precisely because we want to be able to iterate | 2940 // is always swept precisely because we want to be able to iterate |
| 2831 // over it. Map space is swept precisely, because it is not compacted. | 2941 // over it. Map space is swept precisely, because it is not compacted. |
| 2832 static void SweepPrecisely(PagedSpace* space, | 2942 static void SweepPrecisely(PagedSpace* space, |
| 2833 Page* p) { | 2943 Page* p) { |
| 2834 ASSERT(!p->IsEvacuationCandidate() && !p->WasEvacuated()); | 2944 ASSERT(!p->IsEvacuationCandidate() && !p->WasSwept()); |
| 2835 MarkBit::CellType* cells = p->markbits()->cells(); | 2945 MarkBit::CellType* cells = p->markbits()->cells(); |
| 2836 | 2946 |
| 2837 p->ClearFlag(MemoryChunk::WAS_SWEPT_CONSERVATIVELY); | 2947 p->ClearFlag(MemoryChunk::WAS_SWEPT_CONSERVATIVELY); |
| 2838 | 2948 |
| 2839 int last_cell_index = | 2949 int last_cell_index = |
| 2840 Bitmap::IndexToCell( | 2950 Bitmap::IndexToCell( |
| 2841 Bitmap::CellAlignIndex( | 2951 Bitmap::CellAlignIndex( |
| 2842 p->AddressToMarkbitIndex(p->ObjectAreaEnd()))); | 2952 p->AddressToMarkbitIndex(p->ObjectAreaEnd()))); |
| 2843 | 2953 |
| 2844 int cell_index = Page::kFirstUsedCell; | 2954 int cell_index = Page::kFirstUsedCell; |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2885 int newspace_size = space->heap()->new_space()->Size(); | 2995 int newspace_size = space->heap()->new_space()->Size(); |
| 2886 | 2996 |
| 2887 while (it.has_next()) { | 2997 while (it.has_next()) { |
| 2888 Page* p = it.next(); | 2998 Page* p = it.next(); |
| 2889 | 2999 |
| 2890 if (p->IsEvacuationCandidate()) { | 3000 if (p->IsEvacuationCandidate()) { |
| 2891 ASSERT(evacuation_candidates_.length() > 0); | 3001 ASSERT(evacuation_candidates_.length() > 0); |
| 2892 continue; | 3002 continue; |
| 2893 } | 3003 } |
| 2894 | 3004 |
| 3005 if (p->IsFlagSet(Page::RESCAN_ON_EVACUATION)) { | |
| 3006 // Will be processed in EvacuateNewSpaceAndCandidates. | |
| 3007 continue; | |
| 3008 } | |
| 3009 | |
| 2895 switch (sweeper) { | 3010 switch (sweeper) { |
| 2896 case CONSERVATIVE: { | 3011 case CONSERVATIVE: { |
| 2897 SweepConservatively(space, p); | 3012 SweepConservatively(space, p); |
| 2898 break; | 3013 break; |
| 2899 } | 3014 } |
| 2900 case LAZY_CONSERVATIVE: { | 3015 case LAZY_CONSERVATIVE: { |
| 2901 Page* next_page = p->next_page(); | 3016 Page* next_page = p->next_page(); |
| 2902 freed_bytes += SweepConservatively(space, p); | 3017 freed_bytes += SweepConservatively(space, p); |
| 2903 // TODO(gc): tweak the heuristic. | 3018 // TODO(gc): tweak the heuristic. |
| 2904 if (freed_bytes >= newspace_size && p != space->LastPage()) { | 3019 if (freed_bytes >= newspace_size && p != space->LastPage()) { |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3045 } | 3160 } |
| 3046 #endif | 3161 #endif |
| 3047 } | 3162 } |
| 3048 | 3163 |
| 3049 | 3164 |
| 3050 void MarkCompactCollector::Initialize() { | 3165 void MarkCompactCollector::Initialize() { |
| 3051 StaticMarkingVisitor::Initialize(); | 3166 StaticMarkingVisitor::Initialize(); |
| 3052 } | 3167 } |
| 3053 | 3168 |
| 3054 | 3169 |
| 3055 SlotsBuffer::SlotsBuffer() | 3170 void SlotsBuffer::UpdateSlots() { |
| 3056 : buffers_(0), | 3171 ObjectSlot* slots = AsArray(); |
| 3057 buffer_(NULL), | 3172 for (int slot_idx = 0; slot_idx < idx_; ++slot_idx) { |
| 3058 idx_(kBufferSize), | 3173 UpdateSlot(slots[slot_idx]); |
| 3059 buffer_idx_(-1) { | |
| 3060 } | |
| 3061 | |
| 3062 | |
| 3063 SlotsBuffer::~SlotsBuffer() { | |
| 3064 for (int buffer_index = 0; buffer_index < buffers_.length(); ++buffer_index) { | |
| 3065 delete buffers_[buffer_index]; | |
| 3066 } | 3174 } |
| 3067 } | 3175 } |
| 3068 | 3176 |
| 3069 | 3177 |
| 3070 void SlotsBuffer::Clear() { | 3178 SlotsBuffer* SlotsBufferAllocator::AllocateBuffer(SlotsBuffer* next_buffer) { |
| 3071 idx_ = kBufferSize; | 3179 // TODO(gc) Consider maintaining local cache of buffers. |
| 3072 buffer_idx_ = -1; | 3180 SlotsBuffer* buffer = reinterpret_cast<SlotsBuffer*>( |
|
Erik Corry
2011/07/08 13:02:38
This could just be new SlotsBuffer().
| |
| 3181 malloc(SlotsBuffer::kSizeWords * kPointerSize)); | |
| 3182 buffer->Initialize(next_buffer); | |
| 3183 return buffer; | |
| 3073 } | 3184 } |
| 3074 | 3185 |
| 3075 | 3186 |
| 3076 void SlotsBuffer::Add(Object** slot) { | 3187 void SlotsBufferAllocator::DeallocateBuffer(SlotsBuffer* buffer) { |
| 3077 if (idx_ == kBufferSize) { | 3188 free(buffer); |
| 3078 idx_ = 0; | |
| 3079 buffer_idx_++; | |
| 3080 if (buffer_idx_ == buffers_.length()) { | |
| 3081 buffers_.Add(new ObjectSlot[kBufferSize]); | |
| 3082 } | |
| 3083 buffer_ = buffers_[buffer_idx_]; | |
| 3084 } | |
| 3085 | |
| 3086 buffer_[idx_++] = slot; | |
| 3087 } | 3189 } |
| 3088 | 3190 |
| 3089 | 3191 |
| 3090 static inline void UpdateSlot(Object** slot) { | 3192 void SlotsBufferAllocator::DeallocateChain(SlotsBuffer** buffer_address) { |
| 3091 Object* obj = *slot; | 3193 SlotsBuffer* buffer = *buffer_address; |
| 3092 if (!obj->IsHeapObject()) return; | 3194 while (buffer != NULL) { |
| 3093 | 3195 SlotsBuffer* next_buffer = buffer->next(); |
| 3094 HeapObject* heap_obj = HeapObject::cast(obj); | 3196 DeallocateBuffer(buffer); |
| 3095 | 3197 buffer = next_buffer; |
| 3096 MapWord map_word = heap_obj->map_word(); | |
| 3097 if (map_word.IsForwardingAddress()) { | |
| 3098 ASSERT(MarkCompactCollector::IsOnEvacuationCandidate(*slot)); | |
| 3099 *slot = map_word.ToForwardingAddress(); | |
| 3100 ASSERT(!MarkCompactCollector::IsOnEvacuationCandidate(*slot)); | |
| 3101 } | 3198 } |
| 3199 *buffer_address = NULL; | |
| 3102 } | 3200 } |
| 3103 | 3201 |
| 3104 | 3202 |
| 3105 void SlotsBuffer::Update() { | |
| 3106 if (buffer_idx_ < 0) return; | |
| 3107 | |
| 3108 for (int buffer_index = 0; buffer_index < buffer_idx_; ++buffer_index) { | |
| 3109 ObjectSlot* buffer = buffers_[buffer_index]; | |
| 3110 for (int slot_idx = 0; slot_idx < kBufferSize; ++slot_idx) { | |
| 3111 UpdateSlot(buffer[slot_idx]); | |
| 3112 } | |
| 3113 } | |
| 3114 | |
| 3115 ObjectSlot* last_buffer = buffers_[buffer_idx_]; | |
| 3116 for (int slot_idx = 0; slot_idx < idx_; ++slot_idx) { | |
| 3117 UpdateSlot(last_buffer[slot_idx]); | |
| 3118 } | |
| 3119 } | |
| 3120 | |
| 3121 | |
| 3122 void SlotsBuffer::Report() { | |
| 3123 } | |
| 3124 | |
| 3125 | |
| 3126 } } // namespace v8::internal | 3203 } } // namespace v8::internal |
| OLD | NEW |