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
12namespace v8 {
13namespace internal {
14
15void 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
25void 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
34void 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
44void 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
52bool 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
59void 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
72void 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
80void 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
89JSFunction** CodeFlusher::GetNextCandidateSlot(JSFunction* candidate) {
90  return reinterpret_cast<JSFunction**>(
91      HeapObject::RawField(candidate, JSFunction::kNextFunctionLinkOffset));
92}
93
94
95JSFunction* CodeFlusher::GetNextCandidate(JSFunction* candidate) {
96  Object* next_candidate = candidate->next_function_link();
97  return reinterpret_cast<JSFunction*>(next_candidate);
98}
99
100
101void CodeFlusher::SetNextCandidate(JSFunction* candidate,
102                                   JSFunction* next_candidate) {
103  candidate->set_next_function_link(next_candidate, UPDATE_WEAK_WRITE_BARRIER);
104}
105
106
107void 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
113SharedFunctionInfo* CodeFlusher::GetNextCandidate(
114    SharedFunctionInfo* candidate) {
115  Object* next_candidate = candidate->code()->gc_metadata();
116  return reinterpret_cast<SharedFunctionInfo*>(next_candidate);
117}
118
119
120void CodeFlusher::SetNextCandidate(SharedFunctionInfo* candidate,
121                                   SharedFunctionInfo* next_candidate) {
122  candidate->code()->set_gc_metadata(next_candidate);
123}
124
125
126void CodeFlusher::ClearNextCandidate(SharedFunctionInfo* candidate) {
127  candidate->code()->set_gc_metadata(NULL, SKIP_WRITE_BARRIER);
128}
129
130
131template <LiveObjectIterationMode T>
132HeapObject* 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