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/remembered-set.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   Page* source_page = Page::FromAddress(reinterpret_cast<Address>(object));
     63   if (target_page->IsEvacuationCandidate() &&
     64       !ShouldSkipEvacuationSlotRecording(object)) {
     65     DCHECK(Marking::IsBlackOrGrey(Marking::MarkBitFrom(object)));
     66     RememberedSet<OLD_TO_OLD>::Insert(source_page,
     67                                       reinterpret_cast<Address>(slot));
     68   }
     69 }
     70 
     71 
     72 void CodeFlusher::AddCandidate(SharedFunctionInfo* shared_info) {
     73   if (GetNextCandidate(shared_info) == nullptr) {
     74     SetNextCandidate(shared_info, shared_function_info_candidates_head_);
     75     shared_function_info_candidates_head_ = shared_info;
     76   }
     77 }
     78 
     79 
     80 void CodeFlusher::AddCandidate(JSFunction* function) {
     81   DCHECK(function->code() == function->shared()->code());
     82   if (function->next_function_link()->IsUndefined(isolate_)) {
     83     SetNextCandidate(function, jsfunction_candidates_head_);
     84     jsfunction_candidates_head_ = function;
     85   }
     86 }
     87 
     88 
     89 JSFunction** CodeFlusher::GetNextCandidateSlot(JSFunction* candidate) {
     90   return reinterpret_cast<JSFunction**>(
     91       HeapObject::RawField(candidate, JSFunction::kNextFunctionLinkOffset));
     92 }
     93 
     94 
     95 JSFunction* CodeFlusher::GetNextCandidate(JSFunction* candidate) {
     96   Object* next_candidate = candidate->next_function_link();
     97   return reinterpret_cast<JSFunction*>(next_candidate);
     98 }
     99 
    100 
    101 void CodeFlusher::SetNextCandidate(JSFunction* candidate,
    102                                    JSFunction* next_candidate) {
    103   candidate->set_next_function_link(next_candidate, UPDATE_WEAK_WRITE_BARRIER);
    104 }
    105 
    106 
    107 void CodeFlusher::ClearNextCandidate(JSFunction* candidate, Object* undefined) {
    108   DCHECK(undefined->IsUndefined(candidate->GetIsolate()));
    109   candidate->set_next_function_link(undefined, SKIP_WRITE_BARRIER);
    110 }
    111 
    112 
    113 SharedFunctionInfo* CodeFlusher::GetNextCandidate(
    114     SharedFunctionInfo* candidate) {
    115   Object* next_candidate = candidate->code()->gc_metadata();
    116   return reinterpret_cast<SharedFunctionInfo*>(next_candidate);
    117 }
    118 
    119 
    120 void CodeFlusher::SetNextCandidate(SharedFunctionInfo* candidate,
    121                                    SharedFunctionInfo* next_candidate) {
    122   candidate->code()->set_gc_metadata(next_candidate);
    123 }
    124 
    125 
    126 void CodeFlusher::ClearNextCandidate(SharedFunctionInfo* candidate) {
    127   candidate->code()->set_gc_metadata(NULL, SKIP_WRITE_BARRIER);
    128 }
    129 
    130 
    131 template <LiveObjectIterationMode T>
    132 HeapObject* LiveObjectIterator<T>::Next() {
    133   while (!it_.Done()) {
    134     HeapObject* object = nullptr;
    135     while (current_cell_ != 0) {
    136       uint32_t trailing_zeros = base::bits::CountTrailingZeros32(current_cell_);
    137       Address addr = cell_base_ + trailing_zeros * kPointerSize;
    138 
    139       // Clear the first bit of the found object..
    140       current_cell_ &= ~(1u << trailing_zeros);
    141 
    142       uint32_t second_bit_index = 0;
    143       if (trailing_zeros < Bitmap::kBitIndexMask) {
    144         second_bit_index = 1u << (trailing_zeros + 1);
    145       } else {
    146         second_bit_index = 0x1;
    147         // The overlapping case; there has to exist a cell after the current
    148         // cell.
    149         DCHECK(!it_.Done());
    150         it_.Advance();
    151         cell_base_ = it_.CurrentCellBase();
    152         current_cell_ = *it_.CurrentCell();
    153       }
    154       if (T == kBlackObjects && (current_cell_ & second_bit_index)) {
    155         object = HeapObject::FromAddress(addr);
    156       } else if (T == kGreyObjects && !(current_cell_ & second_bit_index)) {
    157         object = HeapObject::FromAddress(addr);
    158       } else if (T == kAllLiveObjects) {
    159         object = HeapObject::FromAddress(addr);
    160       }
    161 
    162       // Clear the second bit of the found object.
    163       current_cell_ &= ~second_bit_index;
    164 
    165       // We found a live object.
    166       if (object != nullptr) break;
    167     }
    168     if (current_cell_ == 0) {
    169       if (!it_.Done()) {
    170         it_.Advance();
    171         cell_base_ = it_.CurrentCellBase();
    172         current_cell_ = *it_.CurrentCell();
    173       }
    174     }
    175     if (object != nullptr) return object;
    176   }
    177   return nullptr;
    178 }
    179 
    180 }  // namespace internal
    181 }  // namespace v8
    182 
    183 #endif  // V8_HEAP_MARK_COMPACT_INL_H_
    184