1b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved.
2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file.
4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifndef V8_HEAP_MARK_COMPACT_INL_H_
6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define V8_HEAP_MARK_COMPACT_INL_H_
7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/heap/mark-compact.h"
91b268ca467c924004286c97bac133db489cf43d0Ben Murdoch#include "src/heap/remembered-set.h"
10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/isolate.h"
11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace v8 {
13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace internal {
14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
15014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MarkCompactCollector::PushBlack(HeapObject* obj) {
16014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(Marking::IsBlack(Marking::MarkBitFrom(obj)));
17014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (marking_deque_.Push(obj)) {
18014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    MemoryChunk::IncrementLiveBytesFromGC(obj, obj->Size());
19014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
20014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Marking::BlackToGrey(obj);
21014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
22b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
23b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
25014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MarkCompactCollector::UnshiftBlack(HeapObject* obj) {
26014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(Marking::IsBlack(Marking::MarkBitFrom(obj)));
27014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (!marking_deque_.Unshift(obj)) {
28014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    MemoryChunk::IncrementLiveBytesFromGC(obj, -obj->Size());
29014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Marking::BlackToGrey(obj);
30014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MarkCompactCollector::MarkObject(HeapObject* obj, MarkBit mark_bit) {
35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(Marking::MarkBitFrom(obj) == mark_bit);
36014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (Marking::IsWhite(mark_bit)) {
37014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Marking::WhiteToBlack(mark_bit);
38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(obj->GetIsolate()->heap()->Contains(obj));
39014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    PushBlack(obj);
40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid MarkCompactCollector::SetMark(HeapObject* obj, MarkBit mark_bit) {
45014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(Marking::IsWhite(mark_bit));
46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(Marking::MarkBitFrom(obj) == mark_bit);
47014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Marking::WhiteToBlack(mark_bit);
48014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  MemoryChunk::IncrementLiveBytesFromGC(obj, obj->Size());
49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool MarkCompactCollector::IsMarked(Object* obj) {
53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(obj->IsHeapObject());
54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HeapObject* heap_object = HeapObject::cast(obj);
55014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return Marking::IsBlackOrGrey(Marking::MarkBitFrom(heap_object));
56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
59014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid MarkCompactCollector::RecordSlot(HeapObject* object, Object** slot,
60014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                      Object* target) {
61014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Page* target_page = Page::FromAddress(reinterpret_cast<Address>(target));
621b268ca467c924004286c97bac133db489cf43d0Ben Murdoch  Page* source_page = Page::FromAddress(reinterpret_cast<Address>(object));
63014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (target_page->IsEvacuationCandidate() &&
64014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      !ShouldSkipEvacuationSlotRecording(object)) {
651b268ca467c924004286c97bac133db489cf43d0Ben Murdoch    DCHECK(Marking::IsBlackOrGrey(Marking::MarkBitFrom(object)));
661b268ca467c924004286c97bac133db489cf43d0Ben Murdoch    RememberedSet<OLD_TO_OLD>::Insert(source_page,
671b268ca467c924004286c97bac133db489cf43d0Ben Murdoch                                      reinterpret_cast<Address>(slot));
68014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
69014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
70014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
71014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
72014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid CodeFlusher::AddCandidate(SharedFunctionInfo* shared_info) {
73342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch  if (GetNextCandidate(shared_info) == nullptr) {
74014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    SetNextCandidate(shared_info, shared_function_info_candidates_head_);
75014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    shared_function_info_candidates_head_ = shared_info;
76014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
77014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
78014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
79014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
80014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid CodeFlusher::AddCandidate(JSFunction* function) {
81014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK(function->code() == function->shared()->code());
8221efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  if (function->next_function_link()->IsUndefined(isolate_)) {
83014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    SetNextCandidate(function, jsfunction_candidates_head_);
84014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    jsfunction_candidates_head_ = function;
85014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
87014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
88014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
89014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochJSFunction** CodeFlusher::GetNextCandidateSlot(JSFunction* candidate) {
90014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return reinterpret_cast<JSFunction**>(
91014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      HeapObject::RawField(candidate, JSFunction::kNextFunctionLinkOffset));
92014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
93014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
94014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
95014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochJSFunction* CodeFlusher::GetNextCandidate(JSFunction* candidate) {
96014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Object* next_candidate = candidate->next_function_link();
97014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return reinterpret_cast<JSFunction*>(next_candidate);
98014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
99014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
100014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
101014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid CodeFlusher::SetNextCandidate(JSFunction* candidate,
102014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                   JSFunction* next_candidate) {
103014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  candidate->set_next_function_link(next_candidate, UPDATE_WEAK_WRITE_BARRIER);
104014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
105014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
106014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
107014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid CodeFlusher::ClearNextCandidate(JSFunction* candidate, Object* undefined) {
10821efce637eb329c94f1323b6a2334a1c977e1a9dBen Murdoch  DCHECK(undefined->IsUndefined(candidate->GetIsolate()));
109014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  candidate->set_next_function_link(undefined, SKIP_WRITE_BARRIER);
110014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
111014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
112014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
113014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochSharedFunctionInfo* CodeFlusher::GetNextCandidate(
114014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    SharedFunctionInfo* candidate) {
115014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Object* next_candidate = candidate->code()->gc_metadata();
116014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return reinterpret_cast<SharedFunctionInfo*>(next_candidate);
117014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
118014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
119014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
120014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid CodeFlusher::SetNextCandidate(SharedFunctionInfo* candidate,
121014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                   SharedFunctionInfo* next_candidate) {
122014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  candidate->code()->set_gc_metadata(next_candidate);
123014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
124014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
125014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
126014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid CodeFlusher::ClearNextCandidate(SharedFunctionInfo* candidate) {
127014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  candidate->code()->set_gc_metadata(NULL, SKIP_WRITE_BARRIER);
128014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
129014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
130014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
131014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochtemplate <LiveObjectIterationMode T>
132014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochHeapObject* LiveObjectIterator<T>::Next() {
133014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  while (!it_.Done()) {
134014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    HeapObject* object = nullptr;
135014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    while (current_cell_ != 0) {
136014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      uint32_t trailing_zeros = base::bits::CountTrailingZeros32(current_cell_);
137014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Address addr = cell_base_ + trailing_zeros * kPointerSize;
138014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
139014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // Clear the first bit of the found object..
140014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      current_cell_ &= ~(1u << trailing_zeros);
141014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
142014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      uint32_t second_bit_index = 0;
143014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (trailing_zeros < Bitmap::kBitIndexMask) {
144014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        second_bit_index = 1u << (trailing_zeros + 1);
145014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      } else {
146014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        second_bit_index = 0x1;
147014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // The overlapping case; there has to exist a cell after the current
148014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        // cell.
149014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        DCHECK(!it_.Done());
150014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        it_.Advance();
151014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        cell_base_ = it_.CurrentCellBase();
152014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        current_cell_ = *it_.CurrentCell();
153014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
154014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (T == kBlackObjects && (current_cell_ & second_bit_index)) {
155014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        object = HeapObject::FromAddress(addr);
156014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      } else if (T == kGreyObjects && !(current_cell_ & second_bit_index)) {
157014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        object = HeapObject::FromAddress(addr);
158014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      } else if (T == kAllLiveObjects) {
159014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        object = HeapObject::FromAddress(addr);
160014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
1611b268ca467c924004286c97bac133db489cf43d0Ben Murdoch
162014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // Clear the second bit of the found object.
163014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      current_cell_ &= ~second_bit_index;
164014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
165014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // We found a live object.
166014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (object != nullptr) break;
167014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
168014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (current_cell_ == 0) {
169014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      if (!it_.Done()) {
170014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        it_.Advance();
171014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        cell_base_ = it_.CurrentCellBase();
172014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        current_cell_ = *it_.CurrentCell();
173014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
174014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
175014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (object != nullptr) return object;
176014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
177014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return nullptr;
178014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
179014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
180014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace internal
181014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace v8
182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif  // V8_HEAP_MARK_COMPACT_INL_H_
184