| 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 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 50 const char* Marking::kImpossibleBitPattern = "01"; | 50 const char* Marking::kImpossibleBitPattern = "01"; |
| 51 | 51 |
| 52 | 52 |
| 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), |
| 61 compacting_(false), |
| 60 tracer_(NULL), | 62 tracer_(NULL), |
| 61 #ifdef DEBUG | 63 #ifdef DEBUG |
| 62 live_young_objects_size_(0), | 64 live_young_objects_size_(0), |
| 63 live_old_pointer_objects_size_(0), | 65 live_old_pointer_objects_size_(0), |
| 64 live_old_data_objects_size_(0), | 66 live_old_data_objects_size_(0), |
| 65 live_code_objects_size_(0), | 67 live_code_objects_size_(0), |
| 66 live_map_objects_size_(0), | 68 live_map_objects_size_(0), |
| 67 live_cell_objects_size_(0), | 69 live_cell_objects_size_(0), |
| 68 live_lo_objects_size_(0), | 70 live_lo_objects_size_(0), |
| 69 live_bytes_(0), | 71 live_bytes_(0), |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 147 } | 149 } |
| 148 | 150 |
| 149 | 151 |
| 150 class VerifyEvacuationVisitor: public ObjectVisitor { | 152 class VerifyEvacuationVisitor: public ObjectVisitor { |
| 151 public: | 153 public: |
| 152 void VisitPointers(Object** start, Object** end) { | 154 void VisitPointers(Object** start, Object** end) { |
| 153 for (Object** current = start; current < end; current++) { | 155 for (Object** current = start; current < end; current++) { |
| 154 if ((*current)->IsHeapObject()) { | 156 if ((*current)->IsHeapObject()) { |
| 155 HeapObject* object = HeapObject::cast(*current); | 157 HeapObject* object = HeapObject::cast(*current); |
| 156 if (MarkCompactCollector::IsOnEvacuationCandidate(object)) { | 158 if (MarkCompactCollector::IsOnEvacuationCandidate(object)) { |
| 157 HEAP->TracePathToObject(source_); | |
| 158 CHECK(false); | 159 CHECK(false); |
| 159 } | 160 } |
| 160 } | 161 } |
| 161 } | 162 } |
| 162 } | 163 } |
| 163 | 164 |
| 164 HeapObject* source_; | 165 HeapObject* source_; |
| 165 }; | 166 }; |
| 166 | 167 |
| 167 | 168 |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 218 } | 219 } |
| 219 #endif | 220 #endif |
| 220 | 221 |
| 221 | 222 |
| 222 void MarkCompactCollector::AddEvacuationCandidate(Page* p) { | 223 void MarkCompactCollector::AddEvacuationCandidate(Page* p) { |
| 223 p->MarkEvacuationCandidate(); | 224 p->MarkEvacuationCandidate(); |
| 224 evacuation_candidates_.Add(p); | 225 evacuation_candidates_.Add(p); |
| 225 } | 226 } |
| 226 | 227 |
| 227 | 228 |
| 229 bool MarkCompactCollector::StartCompaction() { |
| 230 // Don't start compaction if we are in the middle of incremental |
| 231 // marking cycle. We did not collect any slots. |
| 232 if (!compacting_ && !heap_->incremental_marking()->IsMarking()) { |
| 233 ASSERT(evacuation_candidates_.length() == 0); |
| 234 |
| 235 // TODO(gc) Shrink slots buffer when we receive low memory notification. |
| 236 slots_buffer_.Clear(); |
| 237 |
| 238 CollectEvacuationCandidates(heap()->old_pointer_space()); |
| 239 CollectEvacuationCandidates(heap()->old_data_space()); |
| 240 |
| 241 heap()->old_pointer_space()->EvictEvacuationCandidatesFromFreeLists(); |
| 242 heap()->old_data_space()->EvictEvacuationCandidatesFromFreeLists(); |
| 243 |
| 244 compacting_ = evacuation_candidates_.length() > 0; |
| 245 } |
| 246 |
| 247 return compacting_; |
| 248 } |
| 249 |
| 250 |
| 228 void MarkCompactCollector::CollectGarbage() { | 251 void MarkCompactCollector::CollectGarbage() { |
| 229 // Make sure that Prepare() has been called. The individual steps below will | 252 // Make sure that Prepare() has been called. The individual steps below will |
| 230 // update the state as they proceed. | 253 // update the state as they proceed. |
| 231 ASSERT(state_ == PREPARE_GC); | 254 ASSERT(state_ == PREPARE_GC); |
| 232 | 255 |
| 233 MarkLiveObjects(); | 256 MarkLiveObjects(); |
| 234 ASSERT(heap_->incremental_marking()->IsStopped()); | 257 ASSERT(heap_->incremental_marking()->IsStopped()); |
| 235 | 258 |
| 236 if (FLAG_collect_maps) ClearNonLiveTransitions(); | 259 if (FLAG_collect_maps) ClearNonLiveTransitions(); |
| 237 | 260 |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 363 Page* p = it.next(); | 386 Page* p = it.next(); |
| 364 if (space->IsFragmented(p)) { | 387 if (space->IsFragmented(p)) { |
| 365 AddEvacuationCandidate(p); | 388 AddEvacuationCandidate(p); |
| 366 } else { | 389 } else { |
| 367 p->ClearEvacuationCandidate(); | 390 p->ClearEvacuationCandidate(); |
| 368 } | 391 } |
| 369 } | 392 } |
| 370 } | 393 } |
| 371 | 394 |
| 372 | 395 |
| 373 static void ClearEvacuationCandidates(PagedSpace* space) { | |
| 374 ASSERT(space->identity() == OLD_POINTER_SPACE || | |
| 375 space->identity() == OLD_DATA_SPACE); | |
| 376 | |
| 377 PageIterator it(space); | |
| 378 while (it.has_next()) { | |
| 379 Page* p = it.next(); | |
| 380 p->ClearEvacuationCandidate(); | |
| 381 } | |
| 382 } | |
| 383 | |
| 384 | |
| 385 void MarkCompactCollector::Prepare(GCTracer* tracer) { | 396 void MarkCompactCollector::Prepare(GCTracer* tracer) { |
| 386 // TODO(gc) re-enable code flushing. | 397 // TODO(gc) re-enable code flushing. |
| 387 FLAG_flush_code = false; | 398 FLAG_flush_code = false; |
| 388 FLAG_always_compact = false; | 399 FLAG_always_compact = false; |
| 389 | 400 |
| 390 // Disable collection of maps if incremental marking is enabled. | 401 // Disable collection of maps if incremental marking is enabled. |
| 391 // TODO(gc) improve maps collection algorithm to work with incremental | 402 // TODO(gc) improve maps collection algorithm to work with incremental |
| 392 // marking. | 403 // marking. |
| 393 if (FLAG_incremental_marking) FLAG_collect_maps = false; | 404 if (FLAG_incremental_marking) FLAG_collect_maps = false; |
| 394 | 405 |
| 395 // Rather than passing the tracer around we stash it in a static member | 406 // Rather than passing the tracer around we stash it in a static member |
| 396 // variable. | 407 // variable. |
| 397 tracer_ = tracer; | 408 tracer_ = tracer; |
| 398 | 409 |
| 399 #ifdef DEBUG | 410 #ifdef DEBUG |
| 400 ASSERT(state_ == IDLE); | 411 ASSERT(state_ == IDLE); |
| 401 state_ = PREPARE_GC; | 412 state_ = PREPARE_GC; |
| 402 #endif | 413 #endif |
| 403 ASSERT(!FLAG_always_compact || !FLAG_never_compact); | 414 ASSERT(!FLAG_always_compact || !FLAG_never_compact); |
| 404 | 415 |
| 405 if (FLAG_collect_maps) CreateBackPointers(); | 416 if (FLAG_collect_maps) CreateBackPointers(); |
| 406 #ifdef ENABLE_GDB_JIT_INTERFACE | 417 #ifdef ENABLE_GDB_JIT_INTERFACE |
| 407 if (FLAG_gdbjit) { | 418 if (FLAG_gdbjit) { |
| 408 // If GDBJIT interface is active disable compaction. | 419 // If GDBJIT interface is active disable compaction. |
| 409 compacting_collection_ = false; | 420 compacting_collection_ = false; |
| 410 } | 421 } |
| 411 #endif | 422 #endif |
| 412 | 423 |
| 413 if (!FLAG_never_compact) { | 424 if (!FLAG_never_compact) StartCompaction(); |
| 414 slots_buffer_.Clear(); | |
| 415 evacuation_candidates_.Rewind(0); | |
| 416 | |
| 417 if (!heap()->incremental_marking()->IsMarking()) { | |
| 418 CollectEvacuationCandidates(heap()->old_pointer_space()); | |
| 419 CollectEvacuationCandidates(heap()->old_data_space()); | |
| 420 } else { | |
| 421 ClearEvacuationCandidates(heap()->old_pointer_space()); | |
| 422 ClearEvacuationCandidates(heap()->old_data_space()); | |
| 423 } | |
| 424 } | |
| 425 | 425 |
| 426 PagedSpaces spaces; | 426 PagedSpaces spaces; |
| 427 for (PagedSpace* space = spaces.next(); | 427 for (PagedSpace* space = spaces.next(); |
| 428 space != NULL; | 428 space != NULL; |
| 429 space = spaces.next()) { | 429 space = spaces.next()) { |
| 430 space->PrepareForMarkCompact(); | 430 space->PrepareForMarkCompact(); |
| 431 } | 431 } |
| 432 | 432 |
| 433 if (!heap()->incremental_marking()->IsMarking()) { | 433 if (!heap()->incremental_marking()->IsMarking()) { |
| 434 ClearMarkbits(heap_); | 434 ClearMarkbits(heap_); |
| (...skipping 1820 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2255 } | 2255 } |
| 2256 | 2256 |
| 2257 heap_->IncrementYoungSurvivorsCounter(survivors_size); | 2257 heap_->IncrementYoungSurvivorsCounter(survivors_size); |
| 2258 new_space->set_age_mark(new_space->top()); | 2258 new_space->set_age_mark(new_space->top()); |
| 2259 } | 2259 } |
| 2260 | 2260 |
| 2261 | 2261 |
| 2262 void MarkCompactCollector::EvacuateLiveObjectsFromPage(Page* p) { | 2262 void MarkCompactCollector::EvacuateLiveObjectsFromPage(Page* p) { |
| 2263 AlwaysAllocateScope always_allocate; | 2263 AlwaysAllocateScope always_allocate; |
| 2264 | 2264 |
| 2265 ASSERT(p->IsEvacuationCandidate() && !p->WasEvacuated()); |
| 2266 |
| 2265 PagedSpace* space = static_cast<PagedSpace*>(p->owner()); | 2267 PagedSpace* space = static_cast<PagedSpace*>(p->owner()); |
| 2266 | 2268 |
| 2267 MarkBit::CellType* cells = p->markbits()->cells(); | 2269 MarkBit::CellType* cells = p->markbits()->cells(); |
| 2268 | 2270 |
| 2269 int last_cell_index = | 2271 int last_cell_index = |
| 2270 Bitmap::IndexToCell( | 2272 Bitmap::IndexToCell( |
| 2271 Bitmap::CellAlignIndex( | 2273 Bitmap::CellAlignIndex( |
| 2272 p->AddressToMarkbitIndex(p->ObjectAreaEnd()))); | 2274 p->AddressToMarkbitIndex(p->ObjectAreaEnd()))); |
| 2273 | 2275 |
| 2274 int cell_index = Page::kFirstUsedCell; | 2276 int cell_index = Page::kFirstUsedCell; |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2307 | 2309 |
| 2308 void MarkCompactCollector::EvacuatePages() { | 2310 void MarkCompactCollector::EvacuatePages() { |
| 2309 int npages = evacuation_candidates_.length(); | 2311 int npages = evacuation_candidates_.length(); |
| 2310 for (int i = 0; i < npages; i++) { | 2312 for (int i = 0; i < npages; i++) { |
| 2311 Page* p = evacuation_candidates_[i]; | 2313 Page* p = evacuation_candidates_[i]; |
| 2312 EvacuateLiveObjectsFromPage(p); | 2314 EvacuateLiveObjectsFromPage(p); |
| 2313 } | 2315 } |
| 2314 } | 2316 } |
| 2315 | 2317 |
| 2316 | 2318 |
| 2319 class EvacuationWeakObjectRetainer : public WeakObjectRetainer { |
| 2320 public: |
| 2321 virtual Object* RetainAs(Object* object) { |
| 2322 if (object->IsHeapObject()) { |
| 2323 HeapObject* heap_object = HeapObject::cast(object); |
| 2324 MapWord map_word = heap_object->map_word(); |
| 2325 if (map_word.IsForwardingAddress()) { |
| 2326 return map_word.ToForwardingAddress(); |
| 2327 } |
| 2328 } |
| 2329 return object; |
| 2330 } |
| 2331 }; |
| 2332 |
| 2333 |
| 2317 void MarkCompactCollector::EvacuateNewSpaceAndCandidates() { | 2334 void MarkCompactCollector::EvacuateNewSpaceAndCandidates() { |
| 2318 EvacuateNewSpace(); | 2335 EvacuateNewSpace(); |
| 2319 EvacuatePages(); | 2336 EvacuatePages(); |
| 2320 | 2337 |
| 2321 // Second pass: find pointers to new space and update them. | 2338 // Second pass: find pointers to new space and update them. |
| 2322 PointersUpdatingVisitor updating_visitor(heap()); | 2339 PointersUpdatingVisitor updating_visitor(heap()); |
| 2323 | 2340 |
| 2324 // Update pointers in to space. | 2341 // Update pointers in to space. |
| 2325 SemiSpaceIterator to_it(heap()->new_space()->bottom(), | 2342 SemiSpaceIterator to_it(heap()->new_space()->bottom(), |
| 2326 heap()->new_space()->top()); | 2343 heap()->new_space()->top()); |
| 2327 for (HeapObject* object = to_it.Next(); | 2344 for (HeapObject* object = to_it.Next(); |
| 2328 object != NULL; | 2345 object != NULL; |
| 2329 object = to_it.Next()) { | 2346 object = to_it.Next()) { |
| 2330 Map* map = object->map(); | 2347 Map* map = object->map(); |
| 2331 object->IterateBody(map->instance_type(), | 2348 object->IterateBody(map->instance_type(), |
| 2332 object->SizeFromMap(map), | 2349 object->SizeFromMap(map), |
| 2333 &updating_visitor); | 2350 &updating_visitor); |
| 2334 } | 2351 } |
| 2335 | 2352 |
| 2336 // Update roots. | 2353 // Update roots. |
| 2337 heap_->IterateRoots(&updating_visitor, VISIT_ALL_IN_SWEEP_NEWSPACE); | 2354 heap_->IterateRoots(&updating_visitor, VISIT_ALL_IN_SWEEP_NEWSPACE); |
| 2338 LiveObjectList::IterateElements(&updating_visitor); | 2355 LiveObjectList::IterateElements(&updating_visitor); |
| 2339 | 2356 |
| 2340 { | 2357 { |
| 2341 StoreBufferRebuildScope scope(heap_, | 2358 StoreBufferRebuildScope scope(heap_, |
| 2342 heap_->store_buffer(), | 2359 heap_->store_buffer(), |
| 2343 &Heap::ScavengeStoreBufferCallback); | 2360 &Heap::ScavengeStoreBufferCallback); |
| 2344 heap_->store_buffer()->IteratePointersToNewSpace(&UpdatePointer); | 2361 heap_->store_buffer()->IteratePointersToNewSpace(&UpdatePointer); |
| 2345 } | 2362 } |
| 2346 slots_buffer_.Iterate(&updating_visitor); | 2363 slots_buffer_.Update(); |
| 2347 | 2364 |
| 2348 // Update pointers from cells. | 2365 // Update pointers from cells. |
| 2349 HeapObjectIterator cell_iterator(heap_->cell_space()); | 2366 HeapObjectIterator cell_iterator(heap_->cell_space()); |
| 2350 for (HeapObject* cell = cell_iterator.Next(); | 2367 for (HeapObject* cell = cell_iterator.Next(); |
| 2351 cell != NULL; | 2368 cell != NULL; |
| 2352 cell = cell_iterator.Next()) { | 2369 cell = cell_iterator.Next()) { |
| 2353 if (cell->IsJSGlobalPropertyCell()) { | 2370 if (cell->IsJSGlobalPropertyCell()) { |
| 2354 Address value_address = | 2371 Address value_address = |
| 2355 reinterpret_cast<Address>(cell) + | 2372 reinterpret_cast<Address>(cell) + |
| 2356 (JSGlobalPropertyCell::kValueOffset - kHeapObjectTag); | 2373 (JSGlobalPropertyCell::kValueOffset - kHeapObjectTag); |
| 2357 updating_visitor.VisitPointer(reinterpret_cast<Object**>(value_address)); | 2374 updating_visitor.VisitPointer(reinterpret_cast<Object**>(value_address)); |
| 2358 } | 2375 } |
| 2359 } | 2376 } |
| 2360 | 2377 |
| 2361 // Update pointer from the global contexts list. | 2378 // Update pointer from the global contexts list. |
| 2362 updating_visitor.VisitPointer(heap_->global_contexts_list_address()); | 2379 updating_visitor.VisitPointer(heap_->global_contexts_list_address()); |
| 2363 | 2380 |
| 2364 heap_->symbol_table()->Iterate(&updating_visitor); | 2381 heap_->symbol_table()->Iterate(&updating_visitor); |
| 2365 | 2382 |
| 2366 // Update pointers from external string table. | 2383 // Update pointers from external string table. |
| 2367 heap_->UpdateReferencesInExternalStringTable( | 2384 heap_->UpdateReferencesInExternalStringTable( |
| 2368 &UpdateReferenceInExternalStringTableEntry); | 2385 &UpdateReferenceInExternalStringTableEntry); |
| 2369 | 2386 |
| 2370 // Update JSFunction pointers from the runtime profiler. | 2387 // Update JSFunction pointers from the runtime profiler. |
| 2371 heap_->isolate()->runtime_profiler()->UpdateSamplesAfterScavenge(); | 2388 heap_->isolate()->runtime_profiler()->UpdateSamplesAfterScavenge(); |
| 2372 | 2389 |
| 2390 EvacuationWeakObjectRetainer evacuation_object_retainer; |
| 2391 heap()->ProcessWeakReferences(&evacuation_object_retainer); |
| 2392 |
| 2373 #ifdef DEBUG | 2393 #ifdef DEBUG |
| 2374 if (FLAG_verify_heap) { | 2394 if (FLAG_verify_heap) { |
| 2375 VerifyEvacuation(heap_); | 2395 VerifyEvacuation(heap_); |
| 2376 } | 2396 } |
| 2377 #endif | 2397 #endif |
| 2378 | 2398 |
| 2379 int npages = evacuation_candidates_.length(); | 2399 int npages = evacuation_candidates_.length(); |
| 2400 ASSERT(compacting_ == (npages > 0)); |
| 2380 for (int i = 0; i < npages; i++) { | 2401 for (int i = 0; i < npages; i++) { |
| 2381 Page* p = evacuation_candidates_[i]; | 2402 Page* p = evacuation_candidates_[i]; |
| 2403 ASSERT(p->IsEvacuationCandidate() && !p->WasEvacuated()); |
| 2382 PagedSpace* space = static_cast<PagedSpace*>(p->owner()); | 2404 PagedSpace* space = static_cast<PagedSpace*>(p->owner()); |
| 2383 space->Free(p->ObjectAreaStart(), Page::kObjectAreaSize); | 2405 space->Free(p->ObjectAreaStart(), Page::kObjectAreaSize); |
| 2384 p->set_scan_on_scavenge(false); | 2406 p->set_scan_on_scavenge(false); |
| 2385 | 2407 p->ClearEvacuationCandidate(); |
| 2386 // We are not clearing evacuation candidate flag here | 2408 p->SetFlag(MemoryChunk::EVACUATED); |
| 2387 // because it is required to notify lazy sweeper to skip | 2409 p->ClearFlag(MemoryChunk::WAS_SWEPT_CONSERVATIVELY); |
| 2388 // these pages. | |
| 2389 } | 2410 } |
| 2411 evacuation_candidates_.Rewind(0); |
| 2412 compacting_ = false; |
| 2390 } | 2413 } |
| 2391 | 2414 |
| 2392 | 2415 |
| 2393 INLINE(static uint32_t SweepFree(PagedSpace* space, | 2416 INLINE(static uint32_t SweepFree(PagedSpace* space, |
| 2394 Page* p, | 2417 Page* p, |
| 2395 uint32_t free_start, | 2418 uint32_t free_start, |
| 2396 uint32_t region_end, | 2419 uint32_t region_end, |
| 2397 uint32_t* cells)); | 2420 uint32_t* cells)); |
| 2398 | 2421 |
| 2399 | 2422 |
| (...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2707 | 2730 |
| 2708 | 2731 |
| 2709 // Sweeps a space conservatively. After this has been done the larger free | 2732 // Sweeps a space conservatively. After this has been done the larger free |
| 2710 // spaces have been put on the free list and the smaller ones have been | 2733 // spaces have been put on the free list and the smaller ones have been |
| 2711 // ignored and left untouched. A free space is always either ignored or put | 2734 // ignored and left untouched. A free space is always either ignored or put |
| 2712 // on the free list, never split up into two parts. This is important | 2735 // on the free list, never split up into two parts. This is important |
| 2713 // because it means that any FreeSpace maps left actually describe a region of | 2736 // because it means that any FreeSpace maps left actually describe a region of |
| 2714 // memory that can be ignored when scanning. Dead objects other than free | 2737 // memory that can be ignored when scanning. Dead objects other than free |
| 2715 // spaces will not contain the free space map. | 2738 // spaces will not contain the free space map. |
| 2716 int MarkCompactCollector::SweepConservatively(PagedSpace* space, Page* p) { | 2739 int MarkCompactCollector::SweepConservatively(PagedSpace* space, Page* p) { |
| 2717 // We might start advancing sweeper before evacuation happened. | 2740 ASSERT(!p->IsEvacuationCandidate() && !p->WasEvacuated()); |
| 2718 if (p->IsEvacuationCandidate()) return 0; | |
| 2719 | 2741 |
| 2720 int freed_bytes = 0; | 2742 int freed_bytes = 0; |
| 2721 | 2743 |
| 2722 MarkBit::CellType* cells = p->markbits()->cells(); | 2744 MarkBit::CellType* cells = p->markbits()->cells(); |
| 2723 | 2745 |
| 2724 p->SetFlag(MemoryChunk::WAS_SWEPT_CONSERVATIVELY); | 2746 p->SetFlag(MemoryChunk::WAS_SWEPT_CONSERVATIVELY); |
| 2725 | 2747 |
| 2726 // This is the start of the 32 word block that we are currently looking at. | 2748 // This is the start of the 32 word block that we are currently looking at. |
| 2727 Address block_address = p->ObjectAreaStart(); | 2749 Address block_address = p->ObjectAreaStart(); |
| 2728 | 2750 |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2796 return freed_bytes; | 2818 return freed_bytes; |
| 2797 } | 2819 } |
| 2798 | 2820 |
| 2799 | 2821 |
| 2800 // Sweep a space precisely. After this has been done the space can | 2822 // Sweep a space precisely. After this has been done the space can |
| 2801 // be iterated precisely, hitting only the live objects. Code space | 2823 // be iterated precisely, hitting only the live objects. Code space |
| 2802 // is always swept precisely because we want to be able to iterate | 2824 // is always swept precisely because we want to be able to iterate |
| 2803 // over it. Map space is swept precisely, because it is not compacted. | 2825 // over it. Map space is swept precisely, because it is not compacted. |
| 2804 static void SweepPrecisely(PagedSpace* space, | 2826 static void SweepPrecisely(PagedSpace* space, |
| 2805 Page* p) { | 2827 Page* p) { |
| 2828 ASSERT(!p->IsEvacuationCandidate() && !p->WasEvacuated()); |
| 2806 MarkBit::CellType* cells = p->markbits()->cells(); | 2829 MarkBit::CellType* cells = p->markbits()->cells(); |
| 2807 | 2830 |
| 2808 p->ClearFlag(MemoryChunk::WAS_SWEPT_CONSERVATIVELY); | 2831 p->ClearFlag(MemoryChunk::WAS_SWEPT_CONSERVATIVELY); |
| 2809 | 2832 |
| 2810 int last_cell_index = | 2833 int last_cell_index = |
| 2811 Bitmap::IndexToCell( | 2834 Bitmap::IndexToCell( |
| 2812 Bitmap::CellAlignIndex( | 2835 Bitmap::CellAlignIndex( |
| 2813 p->AddressToMarkbitIndex(p->ObjectAreaEnd()))); | 2836 p->AddressToMarkbitIndex(p->ObjectAreaEnd()))); |
| 2814 | 2837 |
| 2815 int cell_index = Page::kFirstUsedCell; | 2838 int cell_index = Page::kFirstUsedCell; |
| (...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3051 if (buffer_idx_ == buffers_.length()) { | 3074 if (buffer_idx_ == buffers_.length()) { |
| 3052 buffers_.Add(new ObjectSlot[kBufferSize]); | 3075 buffers_.Add(new ObjectSlot[kBufferSize]); |
| 3053 } | 3076 } |
| 3054 buffer_ = buffers_[buffer_idx_]; | 3077 buffer_ = buffers_[buffer_idx_]; |
| 3055 } | 3078 } |
| 3056 | 3079 |
| 3057 buffer_[idx_++] = slot; | 3080 buffer_[idx_++] = slot; |
| 3058 } | 3081 } |
| 3059 | 3082 |
| 3060 | 3083 |
| 3061 void SlotsBuffer::Iterate(ObjectVisitor* visitor) { | 3084 static inline void UpdateSlot(Object** slot) { |
| 3085 Object* obj = *slot; |
| 3086 if (!obj->IsHeapObject()) return; |
| 3087 |
| 3088 HeapObject* heap_obj = HeapObject::cast(obj); |
| 3089 |
| 3090 MapWord map_word = heap_obj->map_word(); |
| 3091 if (map_word.IsForwardingAddress()) { |
| 3092 ASSERT(MarkCompactCollector::IsOnEvacuationCandidate(*slot)); |
| 3093 *slot = map_word.ToForwardingAddress(); |
| 3094 ASSERT(!MarkCompactCollector::IsOnEvacuationCandidate(*slot)); |
| 3095 } |
| 3096 } |
| 3097 |
| 3098 |
| 3099 void SlotsBuffer::Update() { |
| 3062 if (buffer_idx_ < 0) return; | 3100 if (buffer_idx_ < 0) return; |
| 3063 | 3101 |
| 3064 for (int buffer_index = 0; buffer_index < buffer_idx_; ++buffer_index) { | 3102 for (int buffer_index = 0; buffer_index < buffer_idx_; ++buffer_index) { |
| 3065 ObjectSlot* buffer = buffers_[buffer_index]; | 3103 ObjectSlot* buffer = buffers_[buffer_index]; |
| 3066 for (int slot_idx = 0; slot_idx < kBufferSize; ++slot_idx) { | 3104 for (int slot_idx = 0; slot_idx < kBufferSize; ++slot_idx) { |
| 3067 visitor->VisitPointer(buffer[slot_idx]); | 3105 UpdateSlot(buffer[slot_idx]); |
| 3068 } | 3106 } |
| 3069 } | 3107 } |
| 3070 | 3108 |
| 3071 ObjectSlot* last_buffer = buffers_[buffer_idx_]; | 3109 ObjectSlot* last_buffer = buffers_[buffer_idx_]; |
| 3072 for (int slot_idx = 0; slot_idx < idx_; ++slot_idx) { | 3110 for (int slot_idx = 0; slot_idx < idx_; ++slot_idx) { |
| 3073 visitor->VisitPointer(last_buffer[slot_idx]); | 3111 UpdateSlot(last_buffer[slot_idx]); |
| 3074 } | 3112 } |
| 3075 } | 3113 } |
| 3076 | 3114 |
| 3077 | 3115 |
| 3078 void SlotsBuffer::Report() { | 3116 void SlotsBuffer::Report() { |
| 3079 } | 3117 } |
| 3080 | 3118 |
| 3081 | 3119 |
| 3082 } } // namespace v8::internal | 3120 } } // namespace v8::internal |
| OLD | NEW |