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

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

Issue 1260463002: Remove slot buffer entries in deoptimized code objects after marking. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 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
« no previous file with comments | « src/heap/mark-compact.h ('k') | test/cctest/test-heap.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/v8.h" 5 #include "src/v8.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/code-stubs.h" 9 #include "src/code-stubs.h"
10 #include "src/compilation-cache.h" 10 #include "src/compilation-cache.h"
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after
285 while (it.has_next()) { 285 while (it.has_next()) {
286 Page* p = it.next(); 286 Page* p = it.next();
287 SlotsBuffer::RemoveInvalidSlots(heap_, p->slots_buffer()); 287 SlotsBuffer::RemoveInvalidSlots(heap_, p->slots_buffer());
288 } 288 }
289 } 289 }
290 290
291 291
292 void MarkCompactCollector::ClearInvalidStoreAndSlotsBufferEntries() { 292 void MarkCompactCollector::ClearInvalidStoreAndSlotsBufferEntries() {
293 heap_->store_buffer()->ClearInvalidStoreBufferEntries(); 293 heap_->store_buffer()->ClearInvalidStoreBufferEntries();
294 294
295 RemoveDeoptimizedCodeSlots();
296
295 ClearInvalidSlotsBufferEntries(heap_->old_space()); 297 ClearInvalidSlotsBufferEntries(heap_->old_space());
296 ClearInvalidSlotsBufferEntries(heap_->code_space()); 298 ClearInvalidSlotsBufferEntries(heap_->code_space());
297 ClearInvalidSlotsBufferEntries(heap_->map_space()); 299 ClearInvalidSlotsBufferEntries(heap_->map_space());
298 300
299 LargeObjectIterator it(heap_->lo_space()); 301 LargeObjectIterator it(heap_->lo_space());
300 for (HeapObject* object = it.Next(); object != NULL; object = it.Next()) { 302 for (HeapObject* object = it.Next(); object != NULL; object = it.Next()) {
301 MemoryChunk* chunk = MemoryChunk::FromAddress(object->address()); 303 MemoryChunk* chunk = MemoryChunk::FromAddress(object->address());
302 SlotsBuffer::RemoveInvalidSlots(heap_, chunk->slots_buffer()); 304 SlotsBuffer::RemoveInvalidSlots(heap_, chunk->slots_buffer());
303 } 305 }
304 } 306 }
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after
550 // to only refill them for the old space. 552 // to only refill them for the old space.
551 return; 553 return;
552 } 554 }
553 555
554 intptr_t freed_bytes = space->free_list()->Concatenate(free_list); 556 intptr_t freed_bytes = space->free_list()->Concatenate(free_list);
555 space->AddToAccountingStats(freed_bytes); 557 space->AddToAccountingStats(freed_bytes);
556 space->DecrementUnsweptFreeBytes(freed_bytes); 558 space->DecrementUnsweptFreeBytes(freed_bytes);
557 } 559 }
558 560
559 561
560 void Marking::SetAllMarkBitsInRange(MarkBit start, MarkBit end) {
561 MarkBit::CellType* start_cell = start.cell();
562 MarkBit::CellType* end_cell = end.cell();
563 MarkBit::CellType start_mask = ~(start.mask() - 1);
564 MarkBit::CellType end_mask = (end.mask() << 1) - 1;
565
566 if (start_cell == end_cell) {
567 *start_cell |= start_mask & end_mask;
568 } else {
569 *start_cell |= start_mask;
570 for (MarkBit::CellType* cell = start_cell + 1; cell < end_cell; cell++) {
571 *cell = ~0;
572 }
573 *end_cell |= end_mask;
574 }
575 }
576
577
578 void Marking::ClearAllMarkBitsOfCellsContainedInRange(MarkBit start,
579 MarkBit end) {
580 MarkBit::CellType* start_cell = start.cell();
581 MarkBit::CellType* end_cell = end.cell();
582 for (MarkBit::CellType* cell = start_cell; cell <= end_cell; cell++) {
583 *cell = 0;
584 }
585 }
586
587
588 void Marking::TransferMark(Address old_start, Address new_start) { 562 void Marking::TransferMark(Address old_start, Address new_start) {
589 // This is only used when resizing an object. 563 // This is only used when resizing an object.
590 DCHECK(MemoryChunk::FromAddress(old_start) == 564 DCHECK(MemoryChunk::FromAddress(old_start) ==
591 MemoryChunk::FromAddress(new_start)); 565 MemoryChunk::FromAddress(new_start));
592 566
593 if (!heap_->incremental_marking()->IsMarking()) return; 567 if (!heap_->incremental_marking()->IsMarking()) return;
594 568
595 // If the mark doesn't move, we don't check the color of the object. 569 // If the mark doesn't move, we don't check the color of the object.
596 // It doesn't matter whether the object is black, since it hasn't changed 570 // It doesn't matter whether the object is black, since it hasn't changed
597 // size, so the adjustment to the live data count will be zero anyway. 571 // size, so the adjustment to the live data count will be zero anyway.
(...skipping 2966 matching lines...) Expand 10 before | Expand all | Expand 10 after
3564 // When concurrent sweeping is active, the page will be marked after 3538 // When concurrent sweeping is active, the page will be marked after
3565 // sweeping by the main thread. 3539 // sweeping by the main thread.
3566 p->set_parallel_sweeping(MemoryChunk::SWEEPING_FINALIZE); 3540 p->set_parallel_sweeping(MemoryChunk::SWEEPING_FINALIZE);
3567 } else { 3541 } else {
3568 p->SetWasSwept(); 3542 p->SetWasSwept();
3569 } 3543 }
3570 return FreeList::GuaranteedAllocatable(static_cast<int>(max_freed_bytes)); 3544 return FreeList::GuaranteedAllocatable(static_cast<int>(max_freed_bytes));
3571 } 3545 }
3572 3546
3573 3547
3574 static bool SetMarkBitsUnderInvalidatedCode(Code* code, bool value) {
3575 Page* p = Page::FromAddress(code->address());
3576
3577 if (p->IsEvacuationCandidate() || p->IsFlagSet(Page::RESCAN_ON_EVACUATION)) {
3578 return false;
3579 }
3580
3581 Address code_start = code->address();
3582 Address code_end = code_start + code->Size();
3583
3584 uint32_t start_index = MemoryChunk::FastAddressToMarkbitIndex(code_start);
3585 uint32_t end_index =
3586 MemoryChunk::FastAddressToMarkbitIndex(code_end - kPointerSize);
3587
3588 // TODO(hpayer): Filter out invalidated code in
3589 // ClearInvalidSlotsBufferEntries.
3590 Bitmap* b = p->markbits();
3591
3592 MarkBit start_mark_bit = b->MarkBitFromIndex(start_index);
3593 MarkBit end_mark_bit = b->MarkBitFromIndex(end_index);
3594
3595 if (value) {
3596 Marking::SetAllMarkBitsInRange(start_mark_bit, end_mark_bit);
3597 } else {
3598 Marking::ClearAllMarkBitsOfCellsContainedInRange(start_mark_bit,
3599 end_mark_bit);
3600 }
3601
3602 return true;
3603 }
3604
3605
3606 static bool IsOnInvalidatedCodeObject(Address addr) { 3548 static bool IsOnInvalidatedCodeObject(Address addr) {
3607 // We did not record any slots in large objects thus 3549 // We did not record any slots in large objects thus
3608 // we can safely go to the page from the slot address. 3550 // we can safely go to the page from the slot address.
3609 Page* p = Page::FromAddress(addr); 3551 Page* p = Page::FromAddress(addr);
3610 3552
3611 // First check owner's identity because old space is swept concurrently or 3553 // First check owner's identity because old space is swept concurrently or
3612 // lazily and might still have non-zero mark-bits on some pages. 3554 // lazily and might still have non-zero mark-bits on some pages.
3613 if (p->owner()->identity() != CODE_SPACE) return false; 3555 if (p->owner()->identity() != CODE_SPACE) return false;
3614 3556
3615 // In code space only bits on evacuation candidates (but we don't record 3557 // In code space only bits on evacuation candidates (but we don't record
(...skipping 18 matching lines...) Expand all
3634 } 3576 }
3635 } 3577 }
3636 3578
3637 3579
3638 // Return true if the given code is deoptimized or will be deoptimized. 3580 // Return true if the given code is deoptimized or will be deoptimized.
3639 bool MarkCompactCollector::WillBeDeoptimized(Code* code) { 3581 bool MarkCompactCollector::WillBeDeoptimized(Code* code) {
3640 return code->is_optimized_code() && code->marked_for_deoptimization(); 3582 return code->is_optimized_code() && code->marked_for_deoptimization();
3641 } 3583 }
3642 3584
3643 3585
3644 bool MarkCompactCollector::MarkInvalidatedCode() { 3586 void MarkCompactCollector::RemoveDeoptimizedCodeSlots() {
3645 bool code_marked = false;
3646
3647 int length = invalidated_code_.length(); 3587 int length = invalidated_code_.length();
3648 for (int i = 0; i < length; i++) { 3588 for (int i = 0; i < length; i++) {
3649 Code* code = invalidated_code_[i]; 3589 Code* code = invalidated_code_[i];
3650 3590 Page* p = Page::FromAddress(code->address());
3651 if (SetMarkBitsUnderInvalidatedCode(code, true)) { 3591 if (!p->IsEvacuationCandidate() &&
3652 code_marked = true; 3592 !p->IsFlagSet(Page::RESCAN_ON_EVACUATION)) {
3593 // Ignore all slots that might have been recorded in the body of the
3594 // deoptimized code object.
3595 RemoveObjectSlots(code->instruction_start(),
3596 code->address() + code->Size());
3653 } 3597 }
3654 } 3598 }
3655
3656 return code_marked;
3657 } 3599 }
3658 3600
3659 3601
3660 void MarkCompactCollector::RemoveDeadInvalidatedCode() { 3602 void MarkCompactCollector::RemoveDeadInvalidatedCode() {
3661 int length = invalidated_code_.length(); 3603 int length = invalidated_code_.length();
3662 for (int i = 0; i < length; i++) { 3604 for (int i = 0; i < length; i++) {
3663 if (!IsMarked(invalidated_code_[i])) invalidated_code_[i] = NULL; 3605 if (!IsMarked(invalidated_code_[i])) invalidated_code_[i] = NULL;
3664 } 3606 }
3665 } 3607 }
3666 3608
3667 3609
3668 void MarkCompactCollector::ProcessInvalidatedCode(ObjectVisitor* visitor) { 3610 void MarkCompactCollector::ProcessInvalidatedCode(ObjectVisitor* visitor) {
3669 int length = invalidated_code_.length(); 3611 int length = invalidated_code_.length();
3670 for (int i = 0; i < length; i++) { 3612 for (int i = 0; i < length; i++) {
3671 Code* code = invalidated_code_[i]; 3613 Code* code = invalidated_code_[i];
3672 if (code != NULL) { 3614 if (code != NULL) {
3673 code->Iterate(visitor); 3615 code->Iterate(visitor);
3674 SetMarkBitsUnderInvalidatedCode(code, false);
3675 } 3616 }
3676 } 3617 }
3677 invalidated_code_.Rewind(0); 3618 invalidated_code_.Rewind(0);
3678 } 3619 }
3679 3620
3680 3621
3622 void MarkCompactCollector::RemoveObjectSlots(Address start_slot,
3623 Address end_slot) {
3624 // Remove entries by replacing them with an old-space slot containing a smi
3625 // that is located in an unmovable page.
3626 int npages = evacuation_candidates_.length();
3627 for (int i = 0; i < npages; i++) {
3628 Page* p = evacuation_candidates_[i];
3629 DCHECK(p->IsEvacuationCandidate() ||
3630 p->IsFlagSet(Page::RESCAN_ON_EVACUATION));
3631 if (p->IsEvacuationCandidate()) {
3632 SlotsBuffer::RemoveObjectSlots(heap_, p->slots_buffer(), start_slot,
3633 end_slot);
3634 }
3635 }
3636 }
3637
3638
3681 void MarkCompactCollector::EvacuateNewSpaceAndCandidates() { 3639 void MarkCompactCollector::EvacuateNewSpaceAndCandidates() {
3682 Heap::RelocationLock relocation_lock(heap()); 3640 Heap::RelocationLock relocation_lock(heap());
3683 3641
3684 bool code_slots_filtering_required;
3685 { 3642 {
3686 GCTracer::Scope gc_scope(heap()->tracer(), 3643 GCTracer::Scope gc_scope(heap()->tracer(),
3687 GCTracer::Scope::MC_SWEEP_NEWSPACE); 3644 GCTracer::Scope::MC_SWEEP_NEWSPACE);
3688 code_slots_filtering_required = MarkInvalidatedCode();
3689 EvacuationScope evacuation_scope(this); 3645 EvacuationScope evacuation_scope(this);
3690 EvacuateNewSpace(); 3646 EvacuateNewSpace();
3691 } 3647 }
3692 3648
3693 { 3649 {
3694 GCTracer::Scope gc_scope(heap()->tracer(), 3650 GCTracer::Scope gc_scope(heap()->tracer(),
3695 GCTracer::Scope::MC_EVACUATE_PAGES); 3651 GCTracer::Scope::MC_EVACUATE_PAGES);
3696 EvacuationScope evacuation_scope(this); 3652 EvacuationScope evacuation_scope(this);
3697 EvacuatePages(); 3653 EvacuatePages();
3698 } 3654 }
(...skipping 26 matching lines...) Expand all
3725 GCTracer::Scope gc_scope(heap()->tracer(), 3681 GCTracer::Scope gc_scope(heap()->tracer(),
3726 GCTracer::Scope::MC_UPDATE_OLD_TO_NEW_POINTERS); 3682 GCTracer::Scope::MC_UPDATE_OLD_TO_NEW_POINTERS);
3727 StoreBufferRebuildScope scope(heap_, heap_->store_buffer(), 3683 StoreBufferRebuildScope scope(heap_, heap_->store_buffer(),
3728 &Heap::ScavengeStoreBufferCallback); 3684 &Heap::ScavengeStoreBufferCallback);
3729 heap_->store_buffer()->IteratePointersToNewSpace(&UpdatePointer); 3685 heap_->store_buffer()->IteratePointersToNewSpace(&UpdatePointer);
3730 } 3686 }
3731 3687
3732 { 3688 {
3733 GCTracer::Scope gc_scope(heap()->tracer(), 3689 GCTracer::Scope gc_scope(heap()->tracer(),
3734 GCTracer::Scope::MC_UPDATE_POINTERS_TO_EVACUATED); 3690 GCTracer::Scope::MC_UPDATE_POINTERS_TO_EVACUATED);
3735 SlotsBuffer::UpdateSlotsRecordedIn(heap_, migration_slots_buffer_, 3691 SlotsBuffer::UpdateSlotsRecordedIn(heap_, migration_slots_buffer_);
3736 code_slots_filtering_required);
3737 if (FLAG_trace_fragmentation_verbose) { 3692 if (FLAG_trace_fragmentation_verbose) {
3738 PrintF(" migration slots buffer: %d\n", 3693 PrintF(" migration slots buffer: %d\n",
3739 SlotsBuffer::SizeOfChain(migration_slots_buffer_)); 3694 SlotsBuffer::SizeOfChain(migration_slots_buffer_));
3740 } 3695 }
3741 3696
3742 if (compacting_ && was_marked_incrementally_) { 3697 if (compacting_ && was_marked_incrementally_) {
3743 // It's difficult to filter out slots recorded for large objects. 3698 // It's difficult to filter out slots recorded for large objects.
3744 LargeObjectIterator it(heap_->lo_space()); 3699 LargeObjectIterator it(heap_->lo_space());
3745 for (HeapObject* obj = it.Next(); obj != NULL; obj = it.Next()) { 3700 for (HeapObject* obj = it.Next(); obj != NULL; obj = it.Next()) {
3746 // LargeObjectSpace is not swept yet thus we have to skip 3701 // LargeObjectSpace is not swept yet thus we have to skip
(...skipping 13 matching lines...) Expand all
3760 { 3715 {
3761 GCTracer::Scope gc_scope( 3716 GCTracer::Scope gc_scope(
3762 heap()->tracer(), 3717 heap()->tracer(),
3763 GCTracer::Scope::MC_UPDATE_POINTERS_BETWEEN_EVACUATED); 3718 GCTracer::Scope::MC_UPDATE_POINTERS_BETWEEN_EVACUATED);
3764 for (int i = 0; i < npages; i++) { 3719 for (int i = 0; i < npages; i++) {
3765 Page* p = evacuation_candidates_[i]; 3720 Page* p = evacuation_candidates_[i];
3766 DCHECK(p->IsEvacuationCandidate() || 3721 DCHECK(p->IsEvacuationCandidate() ||
3767 p->IsFlagSet(Page::RESCAN_ON_EVACUATION)); 3722 p->IsFlagSet(Page::RESCAN_ON_EVACUATION));
3768 3723
3769 if (p->IsEvacuationCandidate()) { 3724 if (p->IsEvacuationCandidate()) {
3770 SlotsBuffer::UpdateSlotsRecordedIn(heap_, p->slots_buffer(), 3725 SlotsBuffer::UpdateSlotsRecordedIn(heap_, p->slots_buffer());
3771 code_slots_filtering_required);
3772 if (FLAG_trace_fragmentation_verbose) { 3726 if (FLAG_trace_fragmentation_verbose) {
3773 PrintF(" page %p slots buffer: %d\n", reinterpret_cast<void*>(p), 3727 PrintF(" page %p slots buffer: %d\n", reinterpret_cast<void*>(p),
3774 SlotsBuffer::SizeOfChain(p->slots_buffer())); 3728 SlotsBuffer::SizeOfChain(p->slots_buffer()));
3775 } 3729 }
3776 3730
3777 // Important: skip list should be cleared only after roots were updated 3731 // Important: skip list should be cleared only after roots were updated
3778 // because root iteration traverses the stack and might have to find 3732 // because root iteration traverses the stack and might have to find
3779 // code objects from non-updated pc pointing into evacuation candidate. 3733 // code objects from non-updated pc pointing into evacuation candidate.
3780 SkipList* list = p->skip_list(); 3734 SkipList* list = p->skip_list();
3781 if (list != NULL) list->Clear(); 3735 if (list != NULL) list->Clear();
(...skipping 793 matching lines...) Expand 10 before | Expand all | Expand 10 after
4575 } else { 4529 } else {
4576 ++slot_idx; 4530 ++slot_idx;
4577 DCHECK(slot_idx < slots_count); 4531 DCHECK(slot_idx < slots_count);
4578 } 4532 }
4579 } 4533 }
4580 buffer = buffer->next(); 4534 buffer = buffer->next();
4581 } 4535 }
4582 } 4536 }
4583 4537
4584 4538
4539 void SlotsBuffer::RemoveObjectSlots(Heap* heap, SlotsBuffer* buffer,
4540 Address start_slot, Address end_slot) {
4541 // Remove entries by replacing them with an old-space slot containing a smi
4542 // that is located in an unmovable page.
4543 const ObjectSlot kRemovedEntry = HeapObject::RawField(
4544 heap->empty_fixed_array(), FixedArrayBase::kLengthOffset);
4545 DCHECK(Page::FromAddress(reinterpret_cast<Address>(kRemovedEntry))
4546 ->NeverEvacuate());
4547
4548 while (buffer != NULL) {
4549 SlotsBuffer::ObjectSlot* slots = buffer->slots_;
4550 intptr_t slots_count = buffer->idx_;
4551 bool is_typed_slot = false;
4552
4553 for (int slot_idx = 0; slot_idx < slots_count; ++slot_idx) {
4554 ObjectSlot slot = slots[slot_idx];
4555 if (!IsTypedSlot(slot)) {
4556 Address slot_address = reinterpret_cast<Address>(slot);
4557 if (slot_address >= start_slot && slot_address < end_slot) {
4558 slots[slot_idx] = kRemovedEntry;
4559 if (is_typed_slot) {
4560 slots[slot_idx - 1] = kRemovedEntry;
4561 }
4562 }
4563 is_typed_slot = false;
4564 } else {
4565 is_typed_slot = true;
4566 DCHECK(slot_idx < slots_count);
4567 }
4568 }
4569 buffer = buffer->next();
4570 }
4571 }
4572
4573
4585 void SlotsBuffer::VerifySlots(Heap* heap, SlotsBuffer* buffer) { 4574 void SlotsBuffer::VerifySlots(Heap* heap, SlotsBuffer* buffer) {
4586 while (buffer != NULL) { 4575 while (buffer != NULL) {
4587 SlotsBuffer::ObjectSlot* slots = buffer->slots_; 4576 SlotsBuffer::ObjectSlot* slots = buffer->slots_;
4588 intptr_t slots_count = buffer->idx_; 4577 intptr_t slots_count = buffer->idx_;
4589 4578
4590 for (int slot_idx = 0; slot_idx < slots_count; ++slot_idx) { 4579 for (int slot_idx = 0; slot_idx < slots_count; ++slot_idx) {
4591 ObjectSlot slot = slots[slot_idx]; 4580 ObjectSlot slot = slots[slot_idx];
4592 if (!IsTypedSlot(slot)) { 4581 if (!IsTypedSlot(slot)) {
4593 Object* object = *slot; 4582 Object* object = *slot;
4594 if (object->IsHeapObject()) { 4583 if (object->IsHeapObject()) {
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
4759 SlotsBuffer* buffer = *buffer_address; 4748 SlotsBuffer* buffer = *buffer_address;
4760 while (buffer != NULL) { 4749 while (buffer != NULL) {
4761 SlotsBuffer* next_buffer = buffer->next(); 4750 SlotsBuffer* next_buffer = buffer->next();
4762 DeallocateBuffer(buffer); 4751 DeallocateBuffer(buffer);
4763 buffer = next_buffer; 4752 buffer = next_buffer;
4764 } 4753 }
4765 *buffer_address = NULL; 4754 *buffer_address = NULL;
4766 } 4755 }
4767 } // namespace internal 4756 } // namespace internal
4768 } // namespace v8 4757 } // namespace v8
OLDNEW
« no previous file with comments | « src/heap/mark-compact.h ('k') | test/cctest/test-heap.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698