Home | History | Annotate | Download | only in heap
      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
      3 // found in the LICENSE file.
      4 
      5 #ifndef V8_HEAP_MARK_COMPACT_INL_H_
      6 #define V8_HEAP_MARK_COMPACT_INL_H_
      7 
      8 #include "src/heap/mark-compact.h"
      9 #include "src/heap/slots-buffer.h"
     10 #include "src/isolate.h"
     11 
     12 namespace v8 {
     13 namespace internal {
     14 
     15 void MarkCompactCollector::PushBlack(HeapObject* obj) {
     16   DCHECK(Marking::IsBlack(Marking::MarkBitFrom(obj)));
     17   if (marking_deque_.Push(obj)) {
     18     MemoryChunk::IncrementLiveBytesFromGC(obj, obj->Size());
     19   } else {
     20     Marking::BlackToGrey(obj);
     21   }
     22 }
     23 
     24 
     25 void MarkCompactCollector::UnshiftBlack(HeapObject* obj) {
     26   DCHECK(Marking::IsBlack(Marking::MarkBitFrom(obj)));
     27   if (!marking_deque_.Unshift(obj)) {
     28     MemoryChunk::IncrementLiveBytesFromGC(obj, -obj->Size());
     29     Marking::BlackToGrey(obj);
     30   }
     31 }
     32 
     33 
     34 void MarkCompactCollector::MarkObject(HeapObject* obj, MarkBit mark_bit) {
     35   DCHECK(Marking::MarkBitFrom(obj) == mark_bit);
     36   if (Marking::IsWhite(mark_bit)) {
     37     Marking::WhiteToBlack(mark_bit);
     38     DCHECK(obj->GetIsolate()->heap()->Contains(obj));
     39     PushBlack(obj);
     40   }
     41 }
     42 
     43 
     44 void MarkCompactCollector::SetMark(HeapObject* obj, MarkBit mark_bit) {
     45   DCHECK(Marking::IsWhite(mark_bit));
     46   DCHECK(Marking::MarkBitFrom(obj) == mark_bit);
     47   Marking::WhiteToBlack(mark_bit);
     48   MemoryChunk::IncrementLiveBytesFromGC(obj, obj->Size());
     49 }
     50 
     51 
     52 bool MarkCompactCollector::IsMarked(Object* obj) {
     53   DCHECK(obj->IsHeapObject());
     54   HeapObject* heap_object = HeapObject::cast(obj);
     55   return Marking::IsBlackOrGrey(Marking::MarkBitFrom(heap_object));
     56 }
     57 
     58 
     59 void MarkCompactCollector::RecordSlot(HeapObject* object, Object** slot,
     60                                       Object* target) {
     61   Page* target_page = Page::FromAddress(reinterpret_cast<Address>(target));
     62   if (target_page->IsEvacuationCandidate() &&
     63       !ShouldSkipEvacuationSlotRecording(object)) {
     64     if (!SlotsBuffer::AddTo(slots_buffer_allocator_,
     65                             target_page->slots_buffer_address(), slot,
     66                             SlotsBuffer::FAIL_ON_OVERFLOW)) {
     67       EvictPopularEvacuationCandidate(target_page);
     68     }
     69   }
     70 }
     71 
     72 
     73 void MarkCompactCollector::ForceRecordSlot(HeapObject* object, Object** slot,
     74                                            Object* target) {
     75   Page* target_page = Page::FromAddress(reinterpret_cast<Address>(target));
     76   if (target_page->IsEvacuationCandidate() &&
     77       !ShouldSkipEvacuationSlotRecording(object)) {
     78     CHECK(SlotsBuffer::AddTo(slots_buffer_allocator_,
     79                              target_page->slots_buffer_address(), slot,
     80                              SlotsBuffer::IGNORE_OVERFLOW));
     81   }
     82 }
     83 
     84 
     85 void CodeFlusher::AddCandidate(SharedFunctionInfo* shared_info) {
     86   if (GetNextCandidate(shared_info) == NULL) {
     87     SetNextCandidate(shared_info, shared_function_info_candidates_head_);
     88     shared_function_info_candidates_head_ = shared_info;
     89   }
     90 }
     91 
     92 
     93 void CodeFlusher::AddCandidate(JSFunction* function) {
     94   DCHECK(function->code() == function->shared()->code());
     95   if (GetNextCandidate(function)->IsUndefined()) {
     96     SetNextCandidate(function, jsfunction_candidates_head_);
     97     jsfunction_candidates_head_ = function;
     98   }
     99 }
    100 
    101 
    102 JSFunction** CodeFlusher::GetNextCandidateSlot(JSFunction* candidate) {
    103   return reinterpret_cast<JSFunction**>(
    104       HeapObject::RawField(candidate, JSFunction::kNextFunctionLinkOffset));
    105 }
    106 
    107 
    108 JSFunction* CodeFlusher::GetNextCandidate(JSFunction* candidate) {
    109   Object* next_candidate = candidate->next_function_link();
    110   return reinterpret_cast<JSFunction*>(next_candidate);
    111 }
    112 
    113 
    114 void CodeFlusher::SetNextCandidate(JSFunction* candidate,
    115                                    JSFunction* next_candidate) {
    116   candidate->set_next_function_link(next_candidate, UPDATE_WEAK_WRITE_BARRIER);
    117 }
    118 
    119 
    120 void CodeFlusher::ClearNextCandidate(JSFunction* candidate, Object* undefined) {
    121   DCHECK(undefined->IsUndefined());
    122   candidate->set_next_function_link(undefined, SKIP_WRITE_BARRIER);
    123 }
    124 
    125 
    126 SharedFunctionInfo* CodeFlusher::GetNextCandidate(
    127     SharedFunctionInfo* candidate) {
    128   Object* next_candidate = candidate->code()->gc_metadata();
    129   return reinterpret_cast<SharedFunctionInfo*>(next_candidate);
    130 }
    131 
    132 
    133 void CodeFlusher::SetNextCandidate(SharedFunctionInfo* candidate,
    134                                    SharedFunctionInfo* next_candidate) {
    135   candidate->code()->set_gc_metadata(next_candidate);
    136 }
    137 
    138 
    139 void CodeFlusher::ClearNextCandidate(SharedFunctionInfo* candidate) {
    140   candidate->code()->set_gc_metadata(NULL, SKIP_WRITE_BARRIER);
    141 }
    142 
    143 
    144 template <LiveObjectIterationMode T>
    145 HeapObject* LiveObjectIterator<T>::Next() {
    146   while (!it_.Done()) {
    147     HeapObject* object = nullptr;
    148     while (current_cell_ != 0) {
    149       uint32_t trailing_zeros = base::bits::CountTrailingZeros32(current_cell_);
    150       Address addr = cell_base_ + trailing_zeros * kPointerSize;
    151 
    152       // Clear the first bit of the found object..
    153       current_cell_ &= ~(1u << trailing_zeros);
    154 
    155       uint32_t second_bit_index = 0;
    156       if (trailing_zeros < Bitmap::kBitIndexMask) {
    157         second_bit_index = 1u << (trailing_zeros + 1);
    158       } else {
    159         second_bit_index = 0x1;
    160         // The overlapping case; there has to exist a cell after the current
    161         // cell.
    162         DCHECK(!it_.Done());
    163         it_.Advance();
    164         cell_base_ = it_.CurrentCellBase();
    165         current_cell_ = *it_.CurrentCell();
    166       }
    167       if (T == kBlackObjects && (current_cell_ & second_bit_index)) {
    168         object = HeapObject::FromAddress(addr);
    169       } else if (T == kGreyObjects && !(current_cell_ & second_bit_index)) {
    170         object = HeapObject::FromAddress(addr);
    171       } else if (T == kAllLiveObjects) {
    172         object = HeapObject::FromAddress(addr);
    173       }
    174       // Clear the second bit of the found object.
    175       current_cell_ &= ~second_bit_index;
    176 
    177       // We found a live object.
    178       if (object != nullptr) break;
    179     }
    180     if (current_cell_ == 0) {
    181       if (!it_.Done()) {
    182         it_.Advance();
    183         cell_base_ = it_.CurrentCellBase();
    184         current_cell_ = *it_.CurrentCell();
    185       }
    186     }
    187     if (object != nullptr) return object;
    188   }
    189   return nullptr;
    190 }
    191 
    192 }  // namespace internal
    193 }  // namespace v8
    194 
    195 #endif  // V8_HEAP_MARK_COMPACT_INL_H_
    196