Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(59)

Side by Side Diff: src/mark-compact.cc

Issue 7639020: Perform TODO(gc) cleanup for TODO-lockdown. (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/gc
Patch Set: Created 9 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/mark-compact.h ('k') | src/objects.h » ('j') | src/spaces.h » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 345 matching lines...) Expand 10 before | Expand all | Expand 10 after
356 #endif 356 #endif
357 if (Marking::IsBlack(old_mark_bit)) { 357 if (Marking::IsBlack(old_mark_bit)) {
358 Marking::MarkBlack(new_mark_bit); 358 Marking::MarkBlack(new_mark_bit);
359 old_mark_bit.Clear(); 359 old_mark_bit.Clear();
360 return true; 360 return true;
361 } else if (Marking::IsGrey(old_mark_bit)) { 361 } else if (Marking::IsGrey(old_mark_bit)) {
362 old_mark_bit.Next().Clear(); 362 old_mark_bit.Next().Clear();
363 heap_->incremental_marking()->WhiteToGreyAndPush( 363 heap_->incremental_marking()->WhiteToGreyAndPush(
364 HeapObject::FromAddress(new_start), new_mark_bit); 364 HeapObject::FromAddress(new_start), new_mark_bit);
365 heap_->incremental_marking()->RestartIfNotMarking(); 365 heap_->incremental_marking()->RestartIfNotMarking();
366 // TODO(gc): if we shift huge array in the loop we might end up pushing
367 // too much into the marking deque. Maybe we should check one or two
368 // elements on top/bottom of the marking deque to see whether they are
369 // equal to old_start.
370 } 366 }
371 367
372 #ifdef DEBUG 368 #ifdef DEBUG
373 ObjectColor new_color = Color(new_mark_bit); 369 ObjectColor new_color = Color(new_mark_bit);
374 ASSERT(new_color == old_color); 370 ASSERT(new_color == old_color);
375 #endif 371 #endif
376 return false; 372 return false;
377 } 373 }
378 MarkBit old_mark_bit = MarkBitFrom(old_start); 374 MarkBit old_mark_bit = MarkBitFrom(old_start);
379 if (!old_mark_bit.Get()) { 375 if (!old_mark_bit.Get()) {
(...skipping 15 matching lines...) Expand all
395 if (space->IsFragmented(p)) { 391 if (space->IsFragmented(p)) {
396 AddEvacuationCandidate(p); 392 AddEvacuationCandidate(p);
397 } else { 393 } else {
398 p->ClearEvacuationCandidate(); 394 p->ClearEvacuationCandidate();
399 } 395 }
400 } 396 }
401 } 397 }
402 398
403 399
404 void MarkCompactCollector::Prepare(GCTracer* tracer) { 400 void MarkCompactCollector::Prepare(GCTracer* tracer) {
405 // TODO(gc) re-enable code flushing.
406 FLAG_flush_code = false; 401 FLAG_flush_code = false;
407 FLAG_always_compact = false; 402 FLAG_always_compact = false;
408 403
409 // Disable collection of maps if incremental marking is enabled. 404 // Disable collection of maps if incremental marking is enabled.
410 // TODO(gc) improve maps collection algorithm to work with incremental 405 // Map collection algorithm relies on a special map transition tree traversal
411 // marking. 406 // order which is not implemented for incremental marking.
Erik Corry 2011/08/16 11:17:20 Do we have a bug number for map collection?
412 // TODO(gc) consider oscillating collect_maps_ on and off when possible. This
413 // will allow map transition trees to die from both root and leaves.
414 collect_maps_ = FLAG_collect_maps && 407 collect_maps_ = FLAG_collect_maps &&
415 !heap()->incremental_marking()->IsMarking(); 408 !heap()->incremental_marking()->IsMarking();
416 409
417 // Rather than passing the tracer around we stash it in a static member 410 // Rather than passing the tracer around we stash it in a static member
418 // variable. 411 // variable.
419 tracer_ = tracer; 412 tracer_ = tracer;
420 413
421 #ifdef DEBUG 414 #ifdef DEBUG
422 ASSERT(state_ == IDLE); 415 ASSERT(state_ == IDLE);
423 state_ = PREPARE_GC; 416 state_ = PREPARE_GC;
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after
647 640
648 Object* second = reinterpret_cast<ConsString*>(object)->unchecked_second(); 641 Object* second = reinterpret_cast<ConsString*>(object)->unchecked_second();
649 Heap* heap = map->GetHeap(); 642 Heap* heap = map->GetHeap();
650 if (second != heap->empty_string()) { 643 if (second != heap->empty_string()) {
651 return object; 644 return object;
652 } 645 }
653 646
654 // Since we don't have the object's start, it is impossible to update the 647 // Since we don't have the object's start, it is impossible to update the
655 // page dirty marks. Therefore, we only replace the string with its left 648 // page dirty marks. Therefore, we only replace the string with its left
656 // substring when page dirty marks do not change. 649 // substring when page dirty marks do not change.
657 // TODO(gc): Seems like we could relax this restriction with store buffers.
658 Object* first = reinterpret_cast<ConsString*>(object)->unchecked_first(); 650 Object* first = reinterpret_cast<ConsString*>(object)->unchecked_first();
659 if (!heap->InNewSpace(object) && heap->InNewSpace(first)) return object; 651 if (!heap->InNewSpace(object) && heap->InNewSpace(first)) return object;
660 652
661 *p = first; 653 *p = first;
662 return HeapObject::cast(first); 654 return HeapObject::cast(first);
663 } 655 }
664 656
665 657
666 class StaticMarkingVisitor : public StaticVisitorBase { 658 class StaticMarkingVisitor : public StaticVisitorBase {
667 public: 659 public:
(...skipping 1498 matching lines...) Expand 10 before | Expand all | Expand 10 after
2166 // Fill slots that became free with undefined value. 2158 // Fill slots that became free with undefined value.
2167 Object* undefined = heap()->undefined_value(); 2159 Object* undefined = heap()->undefined_value();
2168 for (int i = new_number_of_transitions * step; 2160 for (int i = new_number_of_transitions * step;
2169 i < number_of_transitions * step; 2161 i < number_of_transitions * step;
2170 i++) { 2162 i++) {
2171 prototype_transitions->set_unchecked(heap_, 2163 prototype_transitions->set_unchecked(heap_,
2172 header + i, 2164 header + i,
2173 undefined, 2165 undefined,
2174 SKIP_WRITE_BARRIER); 2166 SKIP_WRITE_BARRIER);
2175 2167
2176 // TODO(gc) we should not evacuate first page of data space.
2177 // but we are doing it now to increase coverage.
2178 Object** undefined_slot = 2168 Object** undefined_slot =
2179 prototype_transitions->data_start() + i; 2169 prototype_transitions->data_start() + i;
2180 RecordSlot(undefined_slot, undefined_slot, undefined); 2170 RecordSlot(undefined_slot, undefined_slot, undefined);
2181 } 2171 }
2182 map->SetNumberOfProtoTransitions(new_number_of_transitions); 2172 map->SetNumberOfProtoTransitions(new_number_of_transitions);
2183 } 2173 }
2184 2174
2185 // Follow the chain of back pointers to find the prototype. 2175 // Follow the chain of back pointers to find the prototype.
2186 Map* current = map; 2176 Map* current = map;
2187 while (current->IsMap()) { 2177 while (current->IsMap()) {
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after
2394 return String::cast(*p); 2384 return String::cast(*p);
2395 } 2385 }
2396 2386
2397 2387
2398 bool MarkCompactCollector::TryPromoteObject(HeapObject* object, 2388 bool MarkCompactCollector::TryPromoteObject(HeapObject* object,
2399 int object_size) { 2389 int object_size) {
2400 Object* result; 2390 Object* result;
2401 2391
2402 if (object_size > heap()->MaxObjectSizeInPagedSpace()) { 2392 if (object_size > heap()->MaxObjectSizeInPagedSpace()) {
2403 MaybeObject* maybe_result = 2393 MaybeObject* maybe_result =
2404 heap()->lo_space()->AllocateRawFixedArray(object_size); 2394 heap()->lo_space()->AllocateRaw(object_size, NOT_EXECUTABLE);
2405 if (maybe_result->ToObject(&result)) { 2395 if (maybe_result->ToObject(&result)) {
2406 HeapObject* target = HeapObject::cast(result); 2396 HeapObject* target = HeapObject::cast(result);
2407 MigrateObject(target->address(), 2397 MigrateObject(target->address(),
2408 object->address(), 2398 object->address(),
2409 object_size, 2399 object_size,
2410 LO_SPACE); 2400 LO_SPACE);
2411 heap()->mark_compact_collector()->tracer()-> 2401 heap()->mark_compact_collector()->tracer()->
2412 increment_promoted_objects_size(object_size); 2402 increment_promoted_objects_size(object_size);
2413 return true; 2403 return true;
2414 } 2404 }
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
2604 if (map_word.IsForwardingAddress()) { 2594 if (map_word.IsForwardingAddress()) {
2605 *slot = map_word.ToForwardingAddress(); 2595 *slot = map_word.ToForwardingAddress();
2606 ASSERT(!MarkCompactCollector::IsOnEvacuationCandidate(*slot)); 2596 ASSERT(!MarkCompactCollector::IsOnEvacuationCandidate(*slot));
2607 } 2597 }
2608 } 2598 }
2609 } 2599 }
2610 } 2600 }
2611 2601
2612 2602
2613 static void UpdateSlotsOnPage(Page* p, ObjectVisitor* visitor) { 2603 static void UpdateSlotsOnPage(Page* p, ObjectVisitor* visitor) {
2614 // TODO(gc) this is basically clone of SweepPrecisely
2615 PagedSpace* space = static_cast<PagedSpace*>(p->owner()); 2604 PagedSpace* space = static_cast<PagedSpace*>(p->owner());
2616 MarkBit::CellType* cells = p->markbits()->cells(); 2605 MarkBit::CellType* cells = p->markbits()->cells();
2617 2606
2618 p->ClearFlag(MemoryChunk::WAS_SWEPT_CONSERVATIVELY); 2607 p->ClearFlag(MemoryChunk::WAS_SWEPT_CONSERVATIVELY);
2619 p->ClearFlag(MemoryChunk::RESCAN_ON_EVACUATION); 2608 p->ClearFlag(MemoryChunk::RESCAN_ON_EVACUATION);
2620 p->MarkSwept(); 2609 p->MarkSwept();
2621 2610
2622 int last_cell_index = 2611 int last_cell_index =
2623 Bitmap::IndexToCell( 2612 Bitmap::IndexToCell(
2624 Bitmap::CellAlignIndex( 2613 Bitmap::CellAlignIndex(
(...skipping 622 matching lines...) Expand 10 before | Expand all | Expand 10 after
3247 } 3236 }
3248 3237
3249 switch (sweeper) { 3238 switch (sweeper) {
3250 case CONSERVATIVE: { 3239 case CONSERVATIVE: {
3251 SweepConservatively(space, p); 3240 SweepConservatively(space, p);
3252 break; 3241 break;
3253 } 3242 }
3254 case LAZY_CONSERVATIVE: { 3243 case LAZY_CONSERVATIVE: {
3255 Page* next_page = p->next_page(); 3244 Page* next_page = p->next_page();
3256 freed_bytes += SweepConservatively(space, p); 3245 freed_bytes += SweepConservatively(space, p);
3257 // TODO(gc): tweak the heuristic.
3258 if (freed_bytes >= newspace_size && p != space->LastPage()) { 3246 if (freed_bytes >= newspace_size && p != space->LastPage()) {
3259 space->SetPagesToSweep(next_page, space->LastPage()); 3247 space->SetPagesToSweep(next_page, space->LastPage());
3260 return; 3248 return;
3261 } 3249 }
3262 break; 3250 break;
3263 } 3251 }
3264 case PRECISE: { 3252 case PRECISE: {
3265 SweepPrecisely(space, p); 3253 SweepPrecisely(space, p);
3266 break; 3254 break;
3267 } 3255 }
3268 default: { 3256 default: {
3269 UNREACHABLE(); 3257 UNREACHABLE();
3270 } 3258 }
3271 } 3259 }
3272 } 3260 }
3273
3274 // TODO(gc): set up allocation top and limit using the free list.
3275 } 3261 }
3276 3262
3277 3263
3278 void MarkCompactCollector::SweepSpaces() { 3264 void MarkCompactCollector::SweepSpaces() {
3279 GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_SWEEP); 3265 GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_SWEEP);
3280 #ifdef DEBUG 3266 #ifdef DEBUG
3281 state_ = SWEEP_SPACES; 3267 state_ = SWEEP_SPACES;
3282 #endif 3268 #endif
3283 SweeperType how_to_sweep = 3269 SweeperType how_to_sweep =
3284 FLAG_lazy_sweeping ? LAZY_CONSERVATIVE : CONSERVATIVE; 3270 FLAG_lazy_sweeping ? LAZY_CONSERVATIVE : CONSERVATIVE;
3285 if (sweep_precisely_) how_to_sweep = PRECISE; 3271 if (sweep_precisely_) how_to_sweep = PRECISE;
3286 // Noncompacting collections simply sweep the spaces to clear the mark 3272 // Noncompacting collections simply sweep the spaces to clear the mark
3287 // bits and free the nonlive blocks (for old and map spaces). We sweep 3273 // bits and free the nonlive blocks (for old and map spaces). We sweep
3288 // the map space last because freeing non-live maps overwrites them and 3274 // the map space last because freeing non-live maps overwrites them and
3289 // the other spaces rely on possibly non-live maps to get the sizes for 3275 // the other spaces rely on possibly non-live maps to get the sizes for
3290 // non-live objects. 3276 // non-live objects.
3291 SweepSpace(heap()->old_pointer_space(), how_to_sweep); 3277 SweepSpace(heap()->old_pointer_space(), how_to_sweep);
3292 SweepSpace(heap()->old_data_space(), how_to_sweep); 3278 SweepSpace(heap()->old_data_space(), how_to_sweep);
3293 SweepSpace(heap()->code_space(), PRECISE); 3279 SweepSpace(heap()->code_space(), PRECISE);
3294 // TODO(gc): implement specialized sweeper for cell space.
3295 SweepSpace(heap()->cell_space(), PRECISE); 3280 SweepSpace(heap()->cell_space(), PRECISE);
3296 { GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_SWEEP_NEWSPACE); 3281 { GCTracer::Scope gc_scope(tracer_, GCTracer::Scope::MC_SWEEP_NEWSPACE);
3297 EvacuateNewSpaceAndCandidates(); 3282 EvacuateNewSpaceAndCandidates();
3298 } 3283 }
3299 // TODO(gc): ClearNonLiveTransitions depends on precise sweeping of 3284 // ClearNonLiveTransitions depends on precise sweeping of map space to
3300 // map space to detect whether unmarked map became dead in this 3285 // detect whether unmarked map became dead in this collection or in one
3301 // collection or in one of the previous ones. 3286 // of the previous ones.
3302 // TODO(gc): Implement specialized sweeper for map space.
3303 SweepSpace(heap()->map_space(), PRECISE); 3287 SweepSpace(heap()->map_space(), PRECISE);
3304 3288
3305 ASSERT(live_map_objects_size_ <= heap()->map_space()->Size()); 3289 ASSERT(live_map_objects_size_ <= heap()->map_space()->Size());
3306 3290
3307 // Deallocate unmarked objects and clear marked bits for marked objects. 3291 // Deallocate unmarked objects and clear marked bits for marked objects.
3308 heap_->lo_space()->FreeUnmarkedObjects(); 3292 heap_->lo_space()->FreeUnmarkedObjects();
3309 } 3293 }
3310 3294
3311 3295
3312 // Iterate the live objects in a range of addresses (eg, a page or a 3296 // TODO(1466) ReportDeleteIfNeeded is not called currently.
3313 // semispace). The live regions of the range have been linked into a list.
3314 // The first live region is [first_live_start, first_live_end), and the last
3315 // address in the range is top. The callback function is used to get the
3316 // size of each live object.
3317 int MarkCompactCollector::IterateLiveObjectsInRange(
3318 Address start,
3319 Address end,
3320 LiveObjectCallback size_func) {
3321 int live_objects_size = 0;
3322 Address current = start;
3323 while (current < end) {
3324 uint32_t encoded_map = Memory::uint32_at(current);
3325 if (encoded_map == kSingleFreeEncoding) {
3326 current += kPointerSize;
3327 } else if (encoded_map == kMultiFreeEncoding) {
3328 current += Memory::int_at(current + kIntSize);
3329 } else {
3330 int size = (this->*size_func)(HeapObject::FromAddress(current));
3331 current += size;
3332 live_objects_size += size;
3333 }
3334 }
3335 return live_objects_size;
3336 }
3337
3338
3339 int MarkCompactCollector::IterateLiveObjects(
3340 NewSpace* space, LiveObjectCallback size_f) {
3341 ASSERT(MARK_LIVE_OBJECTS < state_ && state_ <= RELOCATE_OBJECTS);
3342 int accumulator = 0;
3343 Address end = space->top();
3344 NewSpacePageIterator it(space->bottom(), end);
3345 // The bottom is at the start of its page.
3346 ASSERT_EQ(space->bottom(),
3347 NewSpacePage::FromAddress(space->bottom())->body());
3348 while (it.has_next()) {
3349 NewSpacePage* page = it.next();
3350 Address start = page->body();
3351 Address limit = it.has_next() ? page->body_limit() : end;
3352 accumulator += IterateLiveObjectsInRange(start, limit, size_f);
3353 }
3354 return accumulator;
3355 }
3356
3357
3358 int MarkCompactCollector::IterateLiveObjects(
3359 PagedSpace* space, LiveObjectCallback size_f) {
3360 ASSERT(MARK_LIVE_OBJECTS < state_ && state_ <= RELOCATE_OBJECTS);
3361 // TODO(gc): Do a mark-sweep first with precise sweeping.
3362 int total = 0;
3363 PageIterator it(space);
3364 while (it.has_next()) {
3365 Page* p = it.next();
3366 total += IterateLiveObjectsInRange(p->ObjectAreaStart(),
3367 p->ObjectAreaEnd(),
3368 size_f);
3369 }
3370 return total;
3371 }
3372
3373
3374 // TODO(gc) ReportDeleteIfNeeded is not called currently.
3375 // Our profiling tools do not expect intersections between 3297 // Our profiling tools do not expect intersections between
3376 // code objects. We should either reenable it or change our tools. 3298 // code objects. We should either reenable it or change our tools.
3377 void MarkCompactCollector::EnableCodeFlushing(bool enable) { 3299 void MarkCompactCollector::EnableCodeFlushing(bool enable) {
3378 if (enable) { 3300 if (enable) {
3379 if (code_flusher_ != NULL) return; 3301 if (code_flusher_ != NULL) return;
3380 code_flusher_ = new CodeFlusher(heap()->isolate()); 3302 code_flusher_ = new CodeFlusher(heap()->isolate());
3381 } else { 3303 } else {
3382 if (code_flusher_ == NULL) return; 3304 if (code_flusher_ == NULL) return;
3383 delete code_flusher_; 3305 delete code_flusher_;
3384 code_flusher_ = NULL; 3306 code_flusher_ = NULL;
(...skipping 20 matching lines...) Expand all
3405 3327
3406 3328
3407 void SlotsBuffer::UpdateSlots() { 3329 void SlotsBuffer::UpdateSlots() {
3408 for (int slot_idx = 0; slot_idx < idx_; ++slot_idx) { 3330 for (int slot_idx = 0; slot_idx < idx_; ++slot_idx) {
3409 UpdateSlot(slots_[slot_idx]); 3331 UpdateSlot(slots_[slot_idx]);
3410 } 3332 }
3411 } 3333 }
3412 3334
3413 3335
3414 SlotsBuffer* SlotsBufferAllocator::AllocateBuffer(SlotsBuffer* next_buffer) { 3336 SlotsBuffer* SlotsBufferAllocator::AllocateBuffer(SlotsBuffer* next_buffer) {
3415 // TODO(gc) Consider maintaining local cache of buffers.
3416 return new SlotsBuffer(next_buffer); 3337 return new SlotsBuffer(next_buffer);
3417 } 3338 }
3418 3339
3419 3340
3420 void SlotsBufferAllocator::DeallocateBuffer(SlotsBuffer* buffer) { 3341 void SlotsBufferAllocator::DeallocateBuffer(SlotsBuffer* buffer) {
3421 delete buffer; 3342 delete buffer;
3422 } 3343 }
3423 3344
3424 3345
3425 void SlotsBufferAllocator::DeallocateChain(SlotsBuffer** buffer_address) { 3346 void SlotsBufferAllocator::DeallocateChain(SlotsBuffer** buffer_address) {
3426 SlotsBuffer* buffer = *buffer_address; 3347 SlotsBuffer* buffer = *buffer_address;
3427 while (buffer != NULL) { 3348 while (buffer != NULL) {
3428 SlotsBuffer* next_buffer = buffer->next(); 3349 SlotsBuffer* next_buffer = buffer->next();
3429 DeallocateBuffer(buffer); 3350 DeallocateBuffer(buffer);
3430 buffer = next_buffer; 3351 buffer = next_buffer;
3431 } 3352 }
3432 *buffer_address = NULL; 3353 *buffer_address = NULL;
3433 } 3354 }
3434 3355
3435 3356
3436 } } // namespace v8::internal 3357 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/mark-compact.h ('k') | src/objects.h » ('j') | src/spaces.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698