• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
PushBlack(HeapObject * obj)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 
UnshiftBlack(HeapObject * obj)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 
MarkObject(HeapObject * obj,MarkBit mark_bit)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 
SetMark(HeapObject * obj,MarkBit mark_bit)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 
IsMarked(Object * obj)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 
RecordSlot(HeapObject * object,Object ** slot,Object * target)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 
ForceRecordSlot(HeapObject * object,Object ** slot,Object * target)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 
AddCandidate(SharedFunctionInfo * shared_info)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 
AddCandidate(JSFunction * function)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 
GetNextCandidateSlot(JSFunction * candidate)102 JSFunction** CodeFlusher::GetNextCandidateSlot(JSFunction* candidate) {
103   return reinterpret_cast<JSFunction**>(
104       HeapObject::RawField(candidate, JSFunction::kNextFunctionLinkOffset));
105 }
106 
107 
GetNextCandidate(JSFunction * candidate)108 JSFunction* CodeFlusher::GetNextCandidate(JSFunction* candidate) {
109   Object* next_candidate = candidate->next_function_link();
110   return reinterpret_cast<JSFunction*>(next_candidate);
111 }
112 
113 
SetNextCandidate(JSFunction * candidate,JSFunction * next_candidate)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 
ClearNextCandidate(JSFunction * candidate,Object * undefined)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 
GetNextCandidate(SharedFunctionInfo * candidate)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 
SetNextCandidate(SharedFunctionInfo * candidate,SharedFunctionInfo * next_candidate)133 void CodeFlusher::SetNextCandidate(SharedFunctionInfo* candidate,
134                                    SharedFunctionInfo* next_candidate) {
135   candidate->code()->set_gc_metadata(next_candidate);
136 }
137 
138 
ClearNextCandidate(SharedFunctionInfo * candidate)139 void CodeFlusher::ClearNextCandidate(SharedFunctionInfo* candidate) {
140   candidate->code()->set_gc_metadata(NULL, SKIP_WRITE_BARRIER);
141 }
142 
143 
144 template <LiveObjectIterationMode T>
Next()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