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_H_
6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define V8_HEAP_MARK_COMPACT_H_
7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
8bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch#include <deque>
9bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/base/bits.h"
11c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch#include "src/base/platform/condition-variable.h"
12c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch#include "src/cancelable-task.h"
13f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include "src/heap/marking.h"
14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/heap/spaces.h"
15109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#include "src/heap/store-buffer.h"
16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace v8 {
18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace internal {
19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Callback function, returns whether an object is alive. The heap size
21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// of the object is returned in size. It optionally updates the offset
22b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// to the first live object in the page (only used for old and map objects).
23b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtypedef bool (*IsAliveFunction)(HeapObject* obj, int* size, int* offset);
24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
25014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Callback function to mark an object in a given heap.
26014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochtypedef void (*MarkObjectFunction)(Heap* heap, HeapObject* object);
27014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Forward declarations.
29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass CodeFlusher;
30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass MarkCompactCollector;
31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass MarkingVisitor;
32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass RootMarkingVisitor;
33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
34f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochclass ObjectMarking : public AllStatic {
35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
36014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  INLINE(static MarkBit MarkBitFrom(Address addr)) {
37014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    MemoryChunk* p = MemoryChunk::FromAddress(addr);
38014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return p->markbits()->MarkBitFromIndex(p->AddressToMarkbitIndex(addr));
39014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  INLINE(static MarkBit MarkBitFrom(HeapObject* obj)) {
42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return MarkBitFrom(reinterpret_cast<Address>(obj));
43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
45f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  static Marking::ObjectColor Color(HeapObject* obj) {
46f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return Marking::Color(ObjectMarking::MarkBitFrom(obj));
47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private:
50f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DISALLOW_IMPLICIT_CONSTRUCTORS(ObjectMarking);
51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// ----------------------------------------------------------------------------
54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Marking deque for tracing live objects.
55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass MarkingDeque {
56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
57c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  explicit MarkingDeque(Heap* heap)
58c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      : backing_store_(nullptr),
59c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        backing_store_committed_size_(0),
60c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        array_(nullptr),
61014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        top_(0),
62014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        bottom_(0),
63014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        mask_(0),
64014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        overflowed_(false),
65c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        in_use_(false),
66c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        uncommit_task_pending_(false),
67c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        heap_(heap) {}
68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
69c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  void SetUp();
70c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  void TearDown();
71c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
72c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // Ensures that the marking deque is committed and will stay committed until
73c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // StopUsing() is called.
74c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  void StartUsing();
75c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  void StopUsing();
76c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  void Clear();
77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inline bool IsFull() { return ((top_ + 1) & mask_) == bottom_; }
79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inline bool IsEmpty() { return top_ == bottom_; }
81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool overflowed() const { return overflowed_; }
83b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void ClearOverflowed() { overflowed_ = false; }
85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void SetOverflowed() { overflowed_ = true; }
87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
88014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Push the object on the marking stack if there is room, otherwise mark the
89014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // deque as overflowed and wait for a rescan of the heap.
90014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  INLINE(bool Push(HeapObject* object)) {
91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(object->IsHeapObject());
92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (IsFull()) {
93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SetOverflowed();
94014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return false;
95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      array_[top_] = object;
97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      top_ = ((top_ + 1) & mask_);
98014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return true;
99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  INLINE(HeapObject* Pop()) {
103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!IsEmpty());
104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    top_ = ((top_ - 1) & mask_);
105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    HeapObject* object = array_[top_];
106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(object->IsHeapObject());
107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return object;
108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
110014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Unshift the object into the marking stack if there is room, otherwise mark
111014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // the deque as overflowed and wait for a rescan of the heap.
112014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  INLINE(bool Unshift(HeapObject* object)) {
113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(object->IsHeapObject());
114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (IsFull()) {
115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SetOverflowed();
116014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return false;
117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      bottom_ = ((bottom_ - 1) & mask_);
119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      array_[bottom_] = object;
120014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      return true;
121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HeapObject** array() { return array_; }
125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int bottom() { return bottom_; }
126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int top() { return top_; }
127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int mask() { return mask_; }
128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void set_top(int top) { top_ = top; }
129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private:
131c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // This task uncommits the marking_deque backing store if
132c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // markin_deque->in_use_ is false.
133c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  class UncommitTask : public CancelableTask {
134c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch   public:
135c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    explicit UncommitTask(Isolate* isolate, MarkingDeque* marking_deque)
136c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        : CancelableTask(isolate), marking_deque_(marking_deque) {}
137c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
138c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch   private:
139c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    // CancelableTask override.
140c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    void RunInternal() override {
141c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      base::LockGuard<base::Mutex> guard(&marking_deque_->mutex_);
142c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      if (!marking_deque_->in_use_) {
143c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        marking_deque_->Uncommit();
144c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      }
145c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      marking_deque_->uncommit_task_pending_ = false;
146c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    }
147c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
148c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    MarkingDeque* marking_deque_;
149c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    DISALLOW_COPY_AND_ASSIGN(UncommitTask);
150c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  };
151c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
152c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  static const size_t kMaxSize = 4 * MB;
153c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  static const size_t kMinSize = 256 * KB;
154c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
155c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // Must be called with mutex lock.
156c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  void EnsureCommitted();
157c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
158c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // Must be called with mutex lock.
159c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  void Uncommit();
160c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
161c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // Must be called with mutex lock.
162c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  void StartUncommitTask();
163c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
164c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  base::Mutex mutex_;
165c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
166c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  base::VirtualMemory* backing_store_;
167c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  size_t backing_store_committed_size_;
168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HeapObject** array_;
169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // array_[(top - 1) & mask_] is the top element in the deque.  The Deque is
170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // empty when top_ == bottom_.  It is full when top_ + 1 == bottom
171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // (mod mask + 1).
172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int top_;
173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int bottom_;
174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int mask_;
175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool overflowed_;
176c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // in_use_ == true after taking mutex lock implies that the marking deque is
177c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // committed and will stay committed at least until in_use_ == false.
178014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool in_use_;
179c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  bool uncommit_task_pending_;
180c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Heap* heap_;
181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DISALLOW_COPY_AND_ASSIGN(MarkingDeque);
183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// CodeFlusher collects candidates for code flushing during marking and
187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// processes those candidates after marking has completed in order to
188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// reset those functions referencing code objects that would otherwise
189014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// be unreachable. Code objects can be referenced in two ways:
190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//    - SharedFunctionInfo references unoptimized code.
191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//    - JSFunction references either unoptimized or optimized code.
192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// We are not allowed to flush unoptimized code for functions that got
193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// optimized or inlined into optimized code, because we might bailout
194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// into the unoptimized code again during deoptimization.
195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass CodeFlusher {
196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  explicit CodeFlusher(Isolate* isolate)
198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : isolate_(isolate),
199014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        jsfunction_candidates_head_(nullptr),
200014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        shared_function_info_candidates_head_(nullptr) {}
201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
202014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline void AddCandidate(SharedFunctionInfo* shared_info);
203014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline void AddCandidate(JSFunction* function);
204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void EvictCandidate(SharedFunctionInfo* shared_info);
206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void EvictCandidate(JSFunction* function);
207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void ProcessCandidates() {
209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ProcessSharedFunctionInfoCandidates();
210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ProcessJSFunctionCandidates();
211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void IteratePointersToFromSpace(ObjectVisitor* v);
214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private:
216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void ProcessJSFunctionCandidates();
217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void ProcessSharedFunctionInfoCandidates();
218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
219014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static inline JSFunction** GetNextCandidateSlot(JSFunction* candidate);
220014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static inline JSFunction* GetNextCandidate(JSFunction* candidate);
221014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static inline void SetNextCandidate(JSFunction* candidate,
222014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                      JSFunction* next_candidate);
223014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static inline void ClearNextCandidate(JSFunction* candidate,
224014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                        Object* undefined);
225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
226014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static inline SharedFunctionInfo* GetNextCandidate(
227014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      SharedFunctionInfo* candidate);
228014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static inline void SetNextCandidate(SharedFunctionInfo* candidate,
229014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                      SharedFunctionInfo* next_candidate);
230014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static inline void ClearNextCandidate(SharedFunctionInfo* candidate);
231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Isolate* isolate_;
233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  JSFunction* jsfunction_candidates_head_;
234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SharedFunctionInfo* shared_function_info_candidates_head_;
235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DISALLOW_COPY_AND_ASSIGN(CodeFlusher);
237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Defined in isolate.h.
241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass ThreadLocalTop;
242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2433b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochclass MarkBitCellIterator BASE_EMBEDDED {
2443b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch public:
2453b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  explicit MarkBitCellIterator(MemoryChunk* chunk) : chunk_(chunk) {
2463b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    last_cell_index_ = Bitmap::IndexToCell(Bitmap::CellAlignIndex(
2473b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        chunk_->AddressToMarkbitIndex(chunk_->area_end())));
2483b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    cell_base_ = chunk_->area_start();
2493b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    cell_index_ = Bitmap::IndexToCell(
2503b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        Bitmap::CellAlignIndex(chunk_->AddressToMarkbitIndex(cell_base_)));
2513b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    cells_ = chunk_->markbits()->cells();
2523b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
2533b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
2543b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  inline bool Done() { return cell_index_ == last_cell_index_; }
2553b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
2563b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  inline bool HasNext() { return cell_index_ < last_cell_index_ - 1; }
2573b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
2583b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  inline MarkBit::CellType* CurrentCell() {
2593b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    DCHECK(cell_index_ == Bitmap::IndexToCell(Bitmap::CellAlignIndex(
2603b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                              chunk_->AddressToMarkbitIndex(cell_base_))));
2613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    return &cells_[cell_index_];
2623b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
2633b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
2643b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  inline Address CurrentCellBase() {
2653b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    DCHECK(cell_index_ == Bitmap::IndexToCell(Bitmap::CellAlignIndex(
2663b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                              chunk_->AddressToMarkbitIndex(cell_base_))));
2673b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    return cell_base_;
2683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
2693b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
2703b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  inline void Advance() {
2713b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    cell_index_++;
272f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    cell_base_ += Bitmap::kBitsPerCell * kPointerSize;
273f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
274f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
275f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  inline bool Advance(unsigned int new_cell_index) {
276f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    if (new_cell_index != cell_index_) {
277f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      DCHECK_GT(new_cell_index, cell_index_);
278f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      DCHECK_LE(new_cell_index, last_cell_index_);
279f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      unsigned int diff = new_cell_index - cell_index_;
280f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      cell_index_ = new_cell_index;
281f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      cell_base_ += diff * (Bitmap::kBitsPerCell * kPointerSize);
282f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      return true;
283f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    }
284f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return false;
2853b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
2863b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
2873b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Return the next mark bit cell. If there is no next it returns 0;
2883b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  inline MarkBit::CellType PeekNext() {
2893b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    if (HasNext()) {
2903b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      return cells_[cell_index_ + 1];
2913b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    }
2923b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    return 0;
2933b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
2943b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
2953b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch private:
2963b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  MemoryChunk* chunk_;
2973b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  MarkBit::CellType* cells_;
2983b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  unsigned int last_cell_index_;
2993b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  unsigned int cell_index_;
3003b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Address cell_base_;
3013b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch};
3023b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
3033b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch// Grey objects can happen on black pages when black objects transition to
3043b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch// grey e.g. when calling RecordWrites on them.
3053b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochenum LiveObjectIterationMode {
3063b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  kBlackObjects,
3073b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  kGreyObjects,
3083b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  kAllLiveObjects
3093b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch};
3103b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
3113b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochtemplate <LiveObjectIterationMode T>
3123b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochclass LiveObjectIterator BASE_EMBEDDED {
3133b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch public:
3143b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  explicit LiveObjectIterator(MemoryChunk* chunk)
3153b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      : chunk_(chunk),
3163b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        it_(chunk_),
3173b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        cell_base_(it_.CurrentCellBase()),
3183b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        current_cell_(*it_.CurrentCell()) {
3193b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
3203b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
3213b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  HeapObject* Next();
3223b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
3233b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch private:
324c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  inline Heap* heap() { return chunk_->heap(); }
325c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
3263b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  MemoryChunk* chunk_;
3273b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  MarkBitCellIterator it_;
3283b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Address cell_base_;
3293b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  MarkBit::CellType current_cell_;
3303b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch};
331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
332c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdochenum PageEvacuationMode { NEW_TO_NEW, NEW_TO_OLD };
333c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// -------------------------------------------------------------------------
335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Mark-Compact collector
336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass MarkCompactCollector {
337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
3383b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  class Evacuator;
3393b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
340bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  class Sweeper {
341bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch   public:
342bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    class SweeperTask;
343bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
34413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    enum FreeListRebuildingMode { REBUILD_FREE_LIST, IGNORE_FREE_LIST };
345bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    enum FreeSpaceTreatmentMode { IGNORE_FREE_SPACE, ZAP_FREE_SPACE };
346c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    enum ClearOldToNewSlotsMode {
347c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      DO_NOT_CLEAR,
348c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      CLEAR_REGULAR_SLOTS,
349c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      CLEAR_TYPED_SLOTS
350c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    };
351bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
352bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    typedef std::deque<Page*> SweepingList;
353bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    typedef List<Page*> SweptList;
354bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
355f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    static int RawSweep(Page* p, FreeListRebuildingMode free_list_mode,
356f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                        FreeSpaceTreatmentMode free_space_mode);
357bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
358bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    explicit Sweeper(Heap* heap)
359bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        : heap_(heap),
360bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          pending_sweeper_tasks_semaphore_(0),
361bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          sweeping_in_progress_(false),
362bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          num_sweeping_tasks_(0) {}
363bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
364bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    bool sweeping_in_progress() { return sweeping_in_progress_; }
365bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
366bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    void AddPage(AllocationSpace space, Page* page);
367bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
368bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    int ParallelSweepSpace(AllocationSpace identity, int required_freed_bytes,
369bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                           int max_pages = 0);
37013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    int ParallelSweepPage(Page* page, AllocationSpace identity);
371bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
372c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    // After calling this function sweeping is considered to be in progress
373c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    // and the main thread can sweep lazily, but the background sweeper tasks
374c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    // are not running yet.
375bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    void StartSweeping();
376c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    void StartSweeperTasks();
377bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    void EnsureCompleted();
37813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    void EnsureNewSpaceCompleted();
379c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    bool AreSweeperTasksRunning();
380c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    bool IsSweepingCompleted(AllocationSpace space);
381bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    void SweepOrWaitUntilSweepingCompleted(Page* page);
382bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
383bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    void AddSweptPageSafe(PagedSpace* space, Page* page);
384bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Page* GetSweptPageSafe(PagedSpace* space);
385bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
386bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch   private:
387bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    static const int kAllocationSpaces = LAST_PAGED_SPACE + 1;
388bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
389c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    static ClearOldToNewSlotsMode GetClearOldToNewSlotsMode(Page* p);
390c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
391bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    template <typename Callback>
392bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    void ForAllSweepingSpaces(Callback callback) {
393bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      for (int i = 0; i < kAllocationSpaces; i++) {
394bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        callback(static_cast<AllocationSpace>(i));
395bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      }
396bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    }
397bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
398bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Page* GetSweepingPageSafe(AllocationSpace space);
399bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    void AddSweepingPageSafe(AllocationSpace space, Page* page);
400bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
401bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    void PrepareToBeSweptPage(AllocationSpace space, Page* page);
402bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
403bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Heap* heap_;
404bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    base::Semaphore pending_sweeper_tasks_semaphore_;
405bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    base::Mutex mutex_;
406bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    SweptList swept_list_[kAllocationSpaces];
407bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    SweepingList sweeping_list_[kAllocationSpaces];
408bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    bool sweeping_in_progress_;
40913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    base::AtomicNumber<intptr_t> num_sweeping_tasks_;
410bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  };
411bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
412014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  enum IterationMode {
413014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    kKeepMarking,
414014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    kClearMarkbits,
415014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  };
416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static void Initialize();
418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void SetUp();
420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void TearDown();
422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void CollectEvacuationCandidates(PagedSpace* space);
424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void AddEvacuationCandidate(Page* p);
426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Prepares for GC by resetting relocation info in old and map spaces and
428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // choosing spaces to compact.
429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Prepare();
430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Performs a global garbage collection.
432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void CollectGarbage();
433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
434c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  bool StartCompaction();
435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void AbortCompaction();
437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG
439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Checks whether performing mark-compact collection.
440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool in_use() { return state_ > PREPARE_GC; }
441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool are_map_pointers_encoded() { return state_ == UPDATE_POINTERS; }
442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Determine type of object and emit deletion log event.
445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static void ReportDeleteIfNeeded(HeapObject* obj, Isolate* isolate);
446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Distinguishable invalid map encodings (for single word and multiple words)
448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // that indicate free regions.
449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static const uint32_t kSingleFreeEncoding = 0;
450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static const uint32_t kMultiFreeEncoding = 1;
451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static inline bool IsMarked(Object* obj);
453014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static bool IsUnmarkedHeapObjectWithHeap(Heap* heap, Object** p);
454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inline Heap* heap() const { return heap_; }
456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inline Isolate* isolate() const;
457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CodeFlusher* code_flusher() { return code_flusher_; }
459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inline bool is_code_flushing_enabled() const { return code_flusher_ != NULL; }
460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef VERIFY_HEAP
462014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void VerifyValidStoreAndSlotsBufferEntries();
463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void VerifyMarkbitsAreClean();
464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static void VerifyMarkbitsAreClean(PagedSpace* space);
465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static void VerifyMarkbitsAreClean(NewSpace* space);
466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void VerifyWeakEmbeddedObjectsInCode();
467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void VerifyOmittedMapChecks();
468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  INLINE(static bool ShouldSkipEvacuationSlotRecording(Object* host)) {
471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return Page::FromAddress(reinterpret_cast<Address>(host))
472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ->ShouldSkipEvacuationSlotRecording();
473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
475c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  static inline bool IsOnEvacuationCandidate(HeapObject* obj) {
476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return Page::FromAddress(reinterpret_cast<Address>(obj))
477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ->IsEvacuationCandidate();
478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
4803b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void RecordRelocSlot(Code* host, RelocInfo* rinfo, Object* target);
4813b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void RecordCodeEntrySlot(HeapObject* host, Address slot, Code* target);
482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void RecordCodeTargetPatch(Address pc, Code* target);
483014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  INLINE(void RecordSlot(HeapObject* object, Object** slot, Object* target));
484014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  INLINE(void ForceRecordSlot(HeapObject* object, Object** slot,
485014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                              Object* target));
486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
487014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void UpdateSlots(SlotsBuffer* buffer);
488014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void UpdateSlotsRecordedIn(SlotsBuffer* buffer);
489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void InvalidateCode(Code* code);
491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void ClearMarkbits();
493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool is_compacting() const { return compacting_; }
495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MarkingParity marking_parity() { return marking_parity_; }
497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
498014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Ensures that sweeping is finished.
499014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //
500014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Note: Can only be called safely from main thread.
501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void EnsureSweepingCompleted();
502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
503014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Help out in sweeping the corresponding space and refill memory that has
504014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // been regained.
505014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  //
506014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Note: Thread-safe.
507014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void SweepAndRefill(CompactionSpace* space);
508014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Checks if sweeping is in progress right now on any space.
510bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  bool sweeping_in_progress() { return sweeper().sweeping_in_progress(); }
511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
512958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void set_evacuation(bool evacuation) { evacuation_ = evacuation; }
513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
514958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bool evacuation() const { return evacuation_; }
515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Special case for processing weak references in a full collection. We need
517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // to artificially keep AllocationSites alive for a time.
518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void MarkAllocationSite(AllocationSite* site);
519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
520014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Mark objects in implicit references groups if their parent object
521014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // is marked.
522014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void MarkImplicitRefGroups(MarkObjectFunction mark_object);
523014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
524958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  MarkingDeque* marking_deque() { return &marking_deque_; }
525958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
526bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Sweeper& sweeper() { return sweeper_; }
527bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private:
529c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  template <PageEvacuationMode mode>
530bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  class EvacuateNewSpacePageVisitor;
531014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  class EvacuateNewSpaceVisitor;
532014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  class EvacuateOldSpaceVisitor;
533bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  class EvacuateRecordOnlyVisitor;
534014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  class EvacuateVisitorBase;
535014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  class HeapObjectVisitor;
536f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  class ObjectStatsVisitor;
537014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  explicit MarkCompactCollector(Heap* heap);
539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool WillBeDeoptimized(Code* code);
541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
542c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  void ComputeEvacuationHeuristics(size_t area_size,
543014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                   int* target_fragmentation_percent,
544c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                                   size_t* max_evacuated_bytes);
545014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
546f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  void VisitAllObjects(HeapObjectVisitor* visitor);
547f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
548f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  void RecordObjectStats();
549f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Finishes GC, performs heap verification if enabled.
551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Finish();
552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // -----------------------------------------------------------------------
554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Phase 1: Marking live objects.
555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //
556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  Before: The heap has been prepared for garbage collection by
557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //          MarkCompactCollector::Prepare() and is otherwise in its
558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //          normal state.
559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //
560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //   After: Live objects are marked and non-live objects are unmarked.
561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  friend class CodeMarkingVisitor;
563014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  friend class IncrementalMarkingMarkingVisitor;
564014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  friend class MarkCompactMarkingVisitor;
565014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  friend class MarkingVisitor;
566014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  friend class RecordMigratedSlotVisitor;
567014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  friend class RootMarkingVisitor;
568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  friend class SharedFunctionInfoMarkingVisitor;
569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Mark code objects that are active on the stack to prevent them
571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // from being flushed.
572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void PrepareThreadForCodeFlushing(Isolate* isolate, ThreadLocalTop* top);
573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void PrepareForCodeFlushing();
575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Marking operations for objects reachable from roots.
577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void MarkLiveObjects();
578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
579014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Pushes a black object onto the marking stack and accounts for live bytes.
580014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Note that this assumes live bytes have not yet been counted.
581014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  INLINE(void PushBlack(HeapObject* obj));
582014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
583014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Unshifts a black object into the marking stack and accounts for live bytes.
584014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Note that this assumes lives bytes have already been counted.
585014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  INLINE(void UnshiftBlack(HeapObject* obj));
586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Marks the object black and pushes it on the marking stack.
588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // This is for non-incremental marking only.
589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  INLINE(void MarkObject(HeapObject* obj, MarkBit mark_bit));
590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Marks the object black assuming that it is not yet marked.
592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // This is for non-incremental marking only.
593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  INLINE(void SetMark(HeapObject* obj, MarkBit mark_bit));
594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Mark the heap roots and all objects reachable from them.
596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void MarkRoots(RootMarkingVisitor* visitor);
597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Mark the string table specially.  References to internalized strings from
599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // the string table are weak.
600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void MarkStringTable(RootMarkingVisitor* visitor);
601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Mark objects reachable (transitively) from objects in the marking stack
603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // or overflowed in the heap.
604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void ProcessMarkingDeque();
605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Mark objects reachable (transitively) from objects in the marking stack
607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // or overflowed in the heap.  This respects references only considered in
608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // the final atomic marking pause including the following:
609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //    - Processing of objects reachable through Harmony WeakMaps.
610bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  //    - Objects reachable due to host application logic like object groups,
611bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  //      implicit references' groups, or embedder heap tracing.
612958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void ProcessEphemeralMarking(ObjectVisitor* visitor,
613958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                               bool only_process_harmony_weak_collections);
614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // If the call-site of the top optimized code was not prepared for
616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // deoptimization, then treat the maps in the code as strong pointers,
617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // otherwise a map can die and deoptimize the code.
618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void ProcessTopOptimizedFrame(ObjectVisitor* visitor);
619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
620014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Collects a list of dependent code from maps embedded in optimize code.
621014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DependentCode* DependentCodeListFromNonLiveMaps();
622014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Mark objects reachable (transitively) from objects in the marking
624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // stack.  This function empties the marking stack, but may leave
625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // overflowed objects in the heap, in which case the marking stack's
626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // overflow flag will be set.
627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void EmptyMarkingDeque();
628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Refill the marking stack with overflowed objects from the heap.  This
630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // function either leaves the marking stack full or clears the overflow
631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // flag on the marking stack.
632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void RefillMarkingDeque();
633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
634014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Helper methods for refilling the marking stack by discovering grey objects
635014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // on various pages of the heap. Used by {RefillMarkingDeque} only.
636014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  template <class T>
637014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void DiscoverGreyObjectsWithIterator(T* it);
638014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void DiscoverGreyObjectsOnPage(MemoryChunk* p);
639014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void DiscoverGreyObjectsInSpace(PagedSpace* space);
640014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void DiscoverGreyObjectsInNewSpace();
641014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Callback function for telling whether the object *p is an unmarked
643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // heap object.
644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static bool IsUnmarkedHeapObject(Object** p);
645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
646014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Clear non-live references in weak cells, transition and descriptor arrays,
647014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // and deoptimize dependent code of non-live maps.
648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void ClearNonLiveReferences();
649014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void MarkDependentCodeForDeoptimization(DependentCode* list);
650014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Find non-live targets of simple transitions in the given list. Clear
651014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // transitions to non-live targets and if needed trim descriptors arrays.
652014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void ClearSimpleMapTransitions(Object* non_live_map_list);
653014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void ClearSimpleMapTransition(Map* map, Map* dead_transition);
654014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Compact every array in the global list of transition arrays and
655014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // trim the corresponding descriptor array if a transition target is non-live.
656014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void ClearFullMapTransitions();
657014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool CompactTransitionArray(Map* map, TransitionArray* transitions,
658014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                              DescriptorArray* descriptors);
659014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void TrimDescriptorArray(Map* map, DescriptorArray* descriptors);
660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void TrimEnumCache(Map* map, DescriptorArray* descriptors);
661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Mark all values associated with reachable keys in weak collections
663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // encountered so far.  This might push new object or even new weak maps onto
664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // the marking stack.
665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void ProcessWeakCollections();
666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // After all reachable objects have been marked those weak map entries
668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // with an unreachable key are removed from all encountered weak maps.
669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The linked list of all encountered weak maps is destroyed.
670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void ClearWeakCollections();
671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // We have to remove all encountered weak maps from the list of weak
673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // collections when incremental marking is aborted.
674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void AbortWeakCollections();
675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
676014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void ClearWeakCells(Object** non_live_map_list,
677014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                      DependentCode** dependent_code_list);
678958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void AbortWeakCells();
679958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
680014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void AbortTransitionArrays();
681014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
682c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // Starts sweeping of spaces by contributing on the main thread and setting
683c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // up other pages for sweeping. Does not start sweeper tasks.
684c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  void StartSweepSpaces();
685c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  void StartSweepSpace(PagedSpace* space);
686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
687014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void EvacuateNewSpacePrologue();
688014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
689014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void EvacuatePagesInParallel();
690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
691014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // The number of parallel compaction tasks, including the main thread.
692109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  int NumberOfParallelCompactionTasks(int pages, intptr_t live_bytes);
693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void EvacuateNewSpaceAndCandidates();
695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
696014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void UpdatePointersAfterEvacuation();
697014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
698014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Iterates through all live objects on a page using marking information.
699014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Returns whether all objects have successfully been visited.
700bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  template <class Visitor>
701bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  bool VisitLiveObjects(MemoryChunk* page, Visitor* visitor,
702014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                        IterationMode mode);
703014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
704014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void RecomputeLiveBytes(MemoryChunk* page);
705014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void ReleaseEvacuationCandidates();
707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG
710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  friend class MarkObjectVisitor;
711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static void VisitObject(HeapObject* obj);
712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  friend class UnmarkObjectVisitor;
714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static void UnmarkObject(HeapObject* obj);
715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Heap* heap_;
718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
719bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  base::Semaphore page_parallel_job_semaphore_;
720bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
721bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch#ifdef DEBUG
722bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  enum CollectorState {
723bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    IDLE,
724bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    PREPARE_GC,
725bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    MARK_LIVE_OBJECTS,
726bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    SWEEP_SPACES,
727bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    ENCODE_FORWARDING_ADDRESSES,
728bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    UPDATE_POINTERS,
729bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    RELOCATE_OBJECTS
730bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  };
731bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
732bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // The current stage of the collector.
733bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  CollectorState state_;
734bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch#endif
735bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
736bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  MarkingParity marking_parity_;
737014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
738bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  bool was_marked_incrementally_;
739014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
740bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  bool evacuation_;
741109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
742014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // True if we are collecting slots to perform evacuation from evacuation
743014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // candidates.
744014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool compacting_;
745014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
746bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  bool black_allocation_;
747014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
748bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  bool have_code_to_deoptimize_;
749014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
750bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  MarkingDeque marking_deque_;
751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
752bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  CodeFlusher* code_flusher_;
753bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
754bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  List<Page*> evacuation_candidates_;
755bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  List<Page*> newspace_evacuation_candidates_;
756bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
757bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Sweeper sweeper_;
7583b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  friend class Heap;
760014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  friend class StoreBuffer;
761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
764958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierclass EvacuationScope BASE_EMBEDDED {
765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
766958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  explicit EvacuationScope(MarkCompactCollector* collector)
767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : collector_(collector) {
768958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    collector_->set_evacuation(true);
769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
771958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  ~EvacuationScope() { collector_->set_evacuation(false); }
772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private:
774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MarkCompactCollector* collector_;
775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
777f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben MurdochV8_EXPORT_PRIVATE const char* AllocationSpaceName(AllocationSpace space);
778014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace internal
779014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace v8
780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif  // V8_HEAP_MARK_COMPACT_H_
782