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
8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/base/bits.h"
9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/heap/spaces.h"
10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace v8 {
12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace internal {
13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Callback function, returns whether an object is alive. The heap size
15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// of the object is returned in size. It optionally updates the offset
16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// to the first live object in the page (only used for old and map objects).
17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtypedef bool (*IsAliveFunction)(HeapObject* obj, int* size, int* offset);
18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Forward declarations.
20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass CodeFlusher;
21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass MarkCompactCollector;
22b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass MarkingVisitor;
23b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass RootMarkingVisitor;
24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass Marking {
27b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  explicit Marking(Heap* heap) : heap_(heap) {}
29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  INLINE(static MarkBit MarkBitFrom(Address addr));
31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  INLINE(static MarkBit MarkBitFrom(HeapObject* obj)) {
33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return MarkBitFrom(reinterpret_cast<Address>(obj));
34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Impossible markbits: 01
37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static const char* kImpossibleBitPattern;
38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  INLINE(static bool IsImpossible(MarkBit mark_bit)) {
39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return !mark_bit.Get() && mark_bit.Next().Get();
40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Black markbits: 10 - this is required by the sweeper.
43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static const char* kBlackBitPattern;
44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  INLINE(static bool IsBlack(MarkBit mark_bit)) {
45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return mark_bit.Get() && !mark_bit.Next().Get();
46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // White markbits: 00 - this is required by the mark bit clearer.
49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static const char* kWhiteBitPattern;
50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  INLINE(static bool IsWhite(MarkBit mark_bit)) { return !mark_bit.Get(); }
51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Grey markbits: 11
53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static const char* kGreyBitPattern;
54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  INLINE(static bool IsGrey(MarkBit mark_bit)) {
55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return mark_bit.Get() && mark_bit.Next().Get();
56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  INLINE(static void MarkBlack(MarkBit mark_bit)) {
59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mark_bit.Set();
60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mark_bit.Next().Clear();
61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  INLINE(static void BlackToGrey(MarkBit markbit)) { markbit.Next().Set(); }
64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  INLINE(static void WhiteToGrey(MarkBit markbit)) {
66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    markbit.Set();
67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    markbit.Next().Set();
68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  INLINE(static void GreyToBlack(MarkBit markbit)) { markbit.Next().Clear(); }
71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  INLINE(static void BlackToGrey(HeapObject* obj)) {
73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    BlackToGrey(MarkBitFrom(obj));
74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  INLINE(static void AnyToGrey(MarkBit markbit)) {
77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    markbit.Set();
78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    markbit.Next().Set();
79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void TransferMark(Address old_start, Address new_start);
82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
83b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG
84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  enum ObjectColor {
85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    BLACK_OBJECT,
86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    WHITE_OBJECT,
87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    GREY_OBJECT,
88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    IMPOSSIBLE_COLOR
89b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  };
90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static const char* ColorName(ObjectColor color) {
92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    switch (color) {
93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case BLACK_OBJECT:
94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return "black";
95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case WHITE_OBJECT:
96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return "white";
97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case GREY_OBJECT:
98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return "grey";
99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case IMPOSSIBLE_COLOR:
100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return "impossible";
101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return "error";
103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static ObjectColor Color(HeapObject* obj) {
106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return Color(Marking::MarkBitFrom(obj));
107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static ObjectColor Color(MarkBit mark_bit) {
110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (IsBlack(mark_bit)) return BLACK_OBJECT;
111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (IsWhite(mark_bit)) return WHITE_OBJECT;
112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (IsGrey(mark_bit)) return GREY_OBJECT;
113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    UNREACHABLE();
114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return IMPOSSIBLE_COLOR;
115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Returns true if the transferred color is black.
119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  INLINE(static bool TransferColor(HeapObject* from, HeapObject* to)) {
120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MarkBit from_mark_bit = MarkBitFrom(from);
121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MarkBit to_mark_bit = MarkBitFrom(to);
122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    bool is_black = false;
123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (from_mark_bit.Get()) {
124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      to_mark_bit.Set();
125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      is_black = true;  // Looks black so far.
126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (from_mark_bit.Next().Get()) {
128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      to_mark_bit.Next().Set();
129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      is_black = false;  // Was actually gray.
130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return is_black;
132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private:
135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Heap* heap_;
136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// ----------------------------------------------------------------------------
139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Marking deque for tracing live objects.
140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass MarkingDeque {
141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MarkingDeque()
143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : array_(NULL), top_(0), bottom_(0), mask_(0), overflowed_(false) {}
144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Initialize(Address low, Address high) {
146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    HeapObject** obj_low = reinterpret_cast<HeapObject**>(low);
147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    HeapObject** obj_high = reinterpret_cast<HeapObject**>(high);
148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    array_ = obj_low;
149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    mask_ = base::bits::RoundDownToPowerOfTwo32(
150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                static_cast<uint32_t>(obj_high - obj_low)) -
151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            1;
152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    top_ = bottom_ = 0;
153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    overflowed_ = false;
154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inline bool IsFull() { return ((top_ + 1) & mask_) == bottom_; }
157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inline bool IsEmpty() { return top_ == bottom_; }
159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool overflowed() const { return overflowed_; }
161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void ClearOverflowed() { overflowed_ = false; }
163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void SetOverflowed() { overflowed_ = true; }
165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Push the (marked) object on the marking stack if there is room,
167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // otherwise mark the object as overflowed and wait for a rescan of the
168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // heap.
169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  INLINE(void PushBlack(HeapObject* object)) {
170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(object->IsHeapObject());
171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (IsFull()) {
172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Marking::BlackToGrey(object);
173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      MemoryChunk::IncrementLiveBytesFromGC(object->address(), -object->Size());
174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SetOverflowed();
175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      array_[top_] = object;
177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      top_ = ((top_ + 1) & mask_);
178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  INLINE(void PushGrey(HeapObject* object)) {
182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(object->IsHeapObject());
183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (IsFull()) {
184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SetOverflowed();
185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      array_[top_] = object;
187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      top_ = ((top_ + 1) & mask_);
188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  INLINE(HeapObject* Pop()) {
192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(!IsEmpty());
193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    top_ = ((top_ - 1) & mask_);
194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    HeapObject* object = array_[top_];
195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(object->IsHeapObject());
196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return object;
197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  INLINE(void UnshiftGrey(HeapObject* object)) {
200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(object->IsHeapObject());
201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (IsFull()) {
202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SetOverflowed();
203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      bottom_ = ((bottom_ - 1) & mask_);
205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      array_[bottom_] = object;
206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HeapObject** array() { return array_; }
210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int bottom() { return bottom_; }
211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int top() { return top_; }
212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int mask() { return mask_; }
213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void set_top(int top) { top_ = top; }
214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private:
216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HeapObject** array_;
217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // array_[(top - 1) & mask_] is the top element in the deque.  The Deque is
218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // empty when top_ == bottom_.  It is full when top_ + 1 == bottom
219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // (mod mask + 1).
220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int top_;
221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int bottom_;
222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int mask_;
223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool overflowed_;
224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DISALLOW_COPY_AND_ASSIGN(MarkingDeque);
226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass SlotsBufferAllocator {
230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SlotsBuffer* AllocateBuffer(SlotsBuffer* next_buffer);
232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void DeallocateBuffer(SlotsBuffer* buffer);
233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void DeallocateChain(SlotsBuffer** buffer_address);
235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// SlotsBuffer records a sequence of slots that has to be updated
239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// after live objects were relocated from evacuation candidates.
240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// All slots are either untyped or typed:
241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//    - Untyped slots are expected to contain a tagged object pointer.
242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//      They are recorded by an address.
243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//    - Typed slots are expected to contain an encoded pointer to a heap
244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//      object where the way of encoding depends on the type of the slot.
245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//      They are recorded as a pair (SlotType, slot address).
246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// We assume that zero-page is never mapped this allows us to distinguish
247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// untyped slots from typed slots during iteration by a simple comparison:
248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// if element of slots buffer is less than NUMBER_OF_SLOT_TYPES then it
249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// is the first element of typed slot's pair.
250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass SlotsBuffer {
251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  typedef Object** ObjectSlot;
253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  explicit SlotsBuffer(SlotsBuffer* next_buffer)
255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : idx_(0), chain_length_(1), next_(next_buffer) {
256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (next_ != NULL) {
257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      chain_length_ = next_->chain_length_ + 1;
258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ~SlotsBuffer() {}
262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Add(ObjectSlot slot) {
264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(0 <= idx_ && idx_ < kNumberOfElements);
265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    slots_[idx_++] = slot;
266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  enum SlotType {
269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    EMBEDDED_OBJECT_SLOT,
270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    RELOCATED_CODE_OBJECT,
271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CODE_TARGET_SLOT,
272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CODE_ENTRY_SLOT,
273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DEBUG_TARGET_SLOT,
274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    JS_RETURN_SLOT,
275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    NUMBER_OF_SLOT_TYPES
276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  };
277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static const char* SlotTypeToString(SlotType type) {
279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    switch (type) {
280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case EMBEDDED_OBJECT_SLOT:
281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return "EMBEDDED_OBJECT_SLOT";
282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case RELOCATED_CODE_OBJECT:
283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return "RELOCATED_CODE_OBJECT";
284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case CODE_TARGET_SLOT:
285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return "CODE_TARGET_SLOT";
286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case CODE_ENTRY_SLOT:
287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return "CODE_ENTRY_SLOT";
288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case DEBUG_TARGET_SLOT:
289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return "DEBUG_TARGET_SLOT";
290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case JS_RETURN_SLOT:
291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return "JS_RETURN_SLOT";
292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      case NUMBER_OF_SLOT_TYPES:
293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return "NUMBER_OF_SLOT_TYPES";
294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return "UNKNOWN SlotType";
296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void UpdateSlots(Heap* heap);
299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void UpdateSlotsWithFilter(Heap* heap);
301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SlotsBuffer* next() { return next_; }
303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static int SizeOfChain(SlotsBuffer* buffer) {
305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (buffer == NULL) return 0;
306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return static_cast<int>(buffer->idx_ +
307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                            (buffer->chain_length_ - 1) * kNumberOfElements);
308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inline bool IsFull() { return idx_ == kNumberOfElements; }
311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inline bool HasSpaceForTypedSlot() { return idx_ < kNumberOfElements - 1; }
313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static void UpdateSlotsRecordedIn(Heap* heap, SlotsBuffer* buffer,
315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                    bool code_slots_filtering_required) {
316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    while (buffer != NULL) {
317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (code_slots_filtering_required) {
318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        buffer->UpdateSlotsWithFilter(heap);
319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      } else {
320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        buffer->UpdateSlots(heap);
321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      buffer = buffer->next();
323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  enum AdditionMode { FAIL_ON_OVERFLOW, IGNORE_OVERFLOW };
327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static bool ChainLengthThresholdReached(SlotsBuffer* buffer) {
329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return buffer != NULL && buffer->chain_length_ >= kChainLengthThreshold;
330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  INLINE(static bool AddTo(SlotsBufferAllocator* allocator,
333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           SlotsBuffer** buffer_address, ObjectSlot slot,
334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           AdditionMode mode)) {
335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SlotsBuffer* buffer = *buffer_address;
336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (buffer == NULL || buffer->IsFull()) {
337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      if (mode == FAIL_ON_OVERFLOW && ChainLengthThresholdReached(buffer)) {
338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        allocator->DeallocateChain(buffer_address);
339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        return false;
340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      }
341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      buffer = allocator->AllocateBuffer(buffer);
342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      *buffer_address = buffer;
343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    buffer->Add(slot);
345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return true;
346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static bool IsTypedSlot(ObjectSlot slot);
349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static bool AddTo(SlotsBufferAllocator* allocator,
351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                    SlotsBuffer** buffer_address, SlotType type, Address addr,
352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                    AdditionMode mode);
353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static const int kNumberOfElements = 1021;
355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private:
357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static const int kChainLengthThreshold = 15;
358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  intptr_t idx_;
360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  intptr_t chain_length_;
361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SlotsBuffer* next_;
362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ObjectSlot slots_[kNumberOfElements];
363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// CodeFlusher collects candidates for code flushing during marking and
367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// processes those candidates after marking has completed in order to
368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// reset those functions referencing code objects that would otherwise
369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// be unreachable. Code objects can be referenced in three ways:
370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//    - SharedFunctionInfo references unoptimized code.
371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//    - JSFunction references either unoptimized or optimized code.
372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch//    - OptimizedCodeMap references optimized code.
373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// We are not allowed to flush unoptimized code for functions that got
374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// optimized or inlined into optimized code, because we might bailout
375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// into the unoptimized code again during deoptimization.
376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass CodeFlusher {
377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  explicit CodeFlusher(Isolate* isolate)
379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : isolate_(isolate),
380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        jsfunction_candidates_head_(NULL),
381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        shared_function_info_candidates_head_(NULL),
382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        optimized_code_map_holder_head_(NULL) {}
383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void AddCandidate(SharedFunctionInfo* shared_info) {
385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (GetNextCandidate(shared_info) == NULL) {
386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SetNextCandidate(shared_info, shared_function_info_candidates_head_);
387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      shared_function_info_candidates_head_ = shared_info;
388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void AddCandidate(JSFunction* function) {
392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(function->code() == function->shared()->code());
393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (GetNextCandidate(function)->IsUndefined()) {
394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SetNextCandidate(function, jsfunction_candidates_head_);
395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      jsfunction_candidates_head_ = function;
396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void AddOptimizedCodeMap(SharedFunctionInfo* code_map_holder) {
400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (GetNextCodeMap(code_map_holder)->IsUndefined()) {
401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SetNextCodeMap(code_map_holder, optimized_code_map_holder_head_);
402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      optimized_code_map_holder_head_ = code_map_holder;
403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void EvictOptimizedCodeMap(SharedFunctionInfo* code_map_holder);
407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void EvictCandidate(SharedFunctionInfo* shared_info);
408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void EvictCandidate(JSFunction* function);
409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void ProcessCandidates() {
411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ProcessOptimizedCodeMaps();
412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ProcessSharedFunctionInfoCandidates();
413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ProcessJSFunctionCandidates();
414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void EvictAllCandidates() {
417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    EvictOptimizedCodeMaps();
418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    EvictJSFunctionCandidates();
419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    EvictSharedFunctionInfoCandidates();
420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void IteratePointersToFromSpace(ObjectVisitor* v);
423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private:
425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void ProcessOptimizedCodeMaps();
426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void ProcessJSFunctionCandidates();
427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void ProcessSharedFunctionInfoCandidates();
428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void EvictOptimizedCodeMaps();
429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void EvictJSFunctionCandidates();
430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void EvictSharedFunctionInfoCandidates();
431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static JSFunction** GetNextCandidateSlot(JSFunction* candidate) {
433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return reinterpret_cast<JSFunction**>(
434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        HeapObject::RawField(candidate, JSFunction::kNextFunctionLinkOffset));
435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static JSFunction* GetNextCandidate(JSFunction* candidate) {
438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Object* next_candidate = candidate->next_function_link();
439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return reinterpret_cast<JSFunction*>(next_candidate);
440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static void SetNextCandidate(JSFunction* candidate,
443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               JSFunction* next_candidate) {
444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    candidate->set_next_function_link(next_candidate);
445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static void ClearNextCandidate(JSFunction* candidate, Object* undefined) {
448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(undefined->IsUndefined());
449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    candidate->set_next_function_link(undefined, SKIP_WRITE_BARRIER);
450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static SharedFunctionInfo* GetNextCandidate(SharedFunctionInfo* candidate) {
453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Object* next_candidate = candidate->code()->gc_metadata();
454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return reinterpret_cast<SharedFunctionInfo*>(next_candidate);
455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static void SetNextCandidate(SharedFunctionInfo* candidate,
458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               SharedFunctionInfo* next_candidate) {
459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    candidate->code()->set_gc_metadata(next_candidate);
460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static void ClearNextCandidate(SharedFunctionInfo* candidate) {
463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    candidate->code()->set_gc_metadata(NULL, SKIP_WRITE_BARRIER);
464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static SharedFunctionInfo* GetNextCodeMap(SharedFunctionInfo* holder) {
467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    FixedArray* code_map = FixedArray::cast(holder->optimized_code_map());
468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Object* next_map = code_map->get(SharedFunctionInfo::kNextMapIndex);
469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return reinterpret_cast<SharedFunctionInfo*>(next_map);
470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static void SetNextCodeMap(SharedFunctionInfo* holder,
473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             SharedFunctionInfo* next_holder) {
474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    FixedArray* code_map = FixedArray::cast(holder->optimized_code_map());
475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    code_map->set(SharedFunctionInfo::kNextMapIndex, next_holder);
476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static void ClearNextCodeMap(SharedFunctionInfo* holder) {
479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    FixedArray* code_map = FixedArray::cast(holder->optimized_code_map());
480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    code_map->set_undefined(SharedFunctionInfo::kNextMapIndex);
481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Isolate* isolate_;
484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  JSFunction* jsfunction_candidates_head_;
485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SharedFunctionInfo* shared_function_info_candidates_head_;
486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SharedFunctionInfo* optimized_code_map_holder_head_;
487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DISALLOW_COPY_AND_ASSIGN(CodeFlusher);
489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Defined in isolate.h.
493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass ThreadLocalTop;
494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// -------------------------------------------------------------------------
497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Mark-Compact collector
498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass MarkCompactCollector {
499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Set the global flags, it must be called before Prepare to take effect.
501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inline void SetFlags(int flags);
502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static void Initialize();
504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void SetUp();
506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void TearDown();
508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void CollectEvacuationCandidates(PagedSpace* space);
510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void AddEvacuationCandidate(Page* p);
512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Prepares for GC by resetting relocation info in old and map spaces and
514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // choosing spaces to compact.
515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Prepare();
516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Performs a global garbage collection.
518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void CollectGarbage();
519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  enum CompactionMode { INCREMENTAL_COMPACTION, NON_INCREMENTAL_COMPACTION };
521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool StartCompaction(CompactionMode mode);
523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void AbortCompaction();
525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG
527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Checks whether performing mark-compact collection.
528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool in_use() { return state_ > PREPARE_GC; }
529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool are_map_pointers_encoded() { return state_ == UPDATE_POINTERS; }
530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Determine type of object and emit deletion log event.
533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static void ReportDeleteIfNeeded(HeapObject* obj, Isolate* isolate);
534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Distinguishable invalid map encodings (for single word and multiple words)
536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // that indicate free regions.
537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static const uint32_t kSingleFreeEncoding = 0;
538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static const uint32_t kMultiFreeEncoding = 1;
539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static inline bool IsMarked(Object* obj);
541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inline Heap* heap() const { return heap_; }
543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inline Isolate* isolate() const;
544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CodeFlusher* code_flusher() { return code_flusher_; }
546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inline bool is_code_flushing_enabled() const { return code_flusher_ != NULL; }
547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void EnableCodeFlushing(bool enable);
548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  enum SweeperType {
550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PARALLEL_SWEEPING,
551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CONCURRENT_SWEEPING,
552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SEQUENTIAL_SWEEPING
553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  };
554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  enum SweepingParallelism { SWEEP_ON_MAIN_THREAD, SWEEP_IN_PARALLEL };
556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef VERIFY_HEAP
558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void VerifyMarkbitsAreClean();
559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static void VerifyMarkbitsAreClean(PagedSpace* space);
560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static void VerifyMarkbitsAreClean(NewSpace* space);
561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void VerifyWeakEmbeddedObjectsInCode();
562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void VerifyOmittedMapChecks();
563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  INLINE(static bool ShouldSkipEvacuationSlotRecording(Object** anchor)) {
566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return Page::FromAddress(reinterpret_cast<Address>(anchor))
567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ->ShouldSkipEvacuationSlotRecording();
568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  INLINE(static bool ShouldSkipEvacuationSlotRecording(Object* host)) {
571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return Page::FromAddress(reinterpret_cast<Address>(host))
572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ->ShouldSkipEvacuationSlotRecording();
573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  INLINE(static bool IsOnEvacuationCandidate(Object* obj)) {
576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return Page::FromAddress(reinterpret_cast<Address>(obj))
577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ->IsEvacuationCandidate();
578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  INLINE(void EvictEvacuationCandidate(Page* page)) {
581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (FLAG_trace_fragmentation) {
582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      PrintF("Page %p is too popular. Disabling evacuation.\n",
583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch             reinterpret_cast<void*>(page));
584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // TODO(gc) If all evacuation candidates are too popular we
587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // should stop slots recording entirely.
588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    page->ClearEvacuationCandidate();
589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // We were not collecting slots on this page that point
591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // to other evacuation candidates thus we have to
592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // rescan the page after evacuation to discover and update all
593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // pointers to evacuated objects.
594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (page->owner()->identity() == OLD_DATA_SPACE) {
595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      evacuation_candidates_.RemoveElement(page);
596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      page->SetFlag(Page::RESCAN_ON_EVACUATION);
598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void RecordRelocSlot(RelocInfo* rinfo, Object* target);
602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void RecordCodeEntrySlot(Address slot, Code* target);
603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void RecordCodeTargetPatch(Address pc, Code* target);
604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  INLINE(void RecordSlot(
606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      Object** anchor_slot, Object** slot, Object* object,
607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      SlotsBuffer::AdditionMode mode = SlotsBuffer::FAIL_ON_OVERFLOW));
608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void MigrateObject(HeapObject* dst, HeapObject* src, int size,
610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                     AllocationSpace to_old_space);
611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool TryPromoteObject(HeapObject* object, int object_size);
613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void InvalidateCode(Code* code);
615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void ClearMarkbits();
617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool abort_incremental_marking() const { return abort_incremental_marking_; }
619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool is_compacting() const { return compacting_; }
621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MarkingParity marking_parity() { return marking_parity_; }
623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Concurrent and parallel sweeping support. If required_freed_bytes was set
625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // to a value larger than 0, then sweeping returns after a block of at least
626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // required_freed_bytes was freed. If required_freed_bytes was set to zero
627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // then the whole given space is swept. It returns the size of the maximum
628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // continuous freed memory chunk.
629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int SweepInParallel(PagedSpace* space, int required_freed_bytes);
630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Sweeps a given page concurrently to the sweeper threads. It returns the
632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // size of the maximum continuous freed memory chunk.
633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int SweepInParallel(Page* page, PagedSpace* space);
634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void EnsureSweepingCompleted();
636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // If sweeper threads are not active this method will return true. If
638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // this is a latency issue we should be smarter here. Otherwise, it will
639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // return true if the sweeper threads are done processing the pages.
640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool IsSweepingCompleted();
641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void RefillFreeList(PagedSpace* space);
643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool AreSweeperThreadsActivated();
645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Checks if sweeping is in progress right now on any space.
647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool sweeping_in_progress() { return sweeping_in_progress_; }
648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void set_sequential_sweeping(bool sequential_sweeping) {
650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    sequential_sweeping_ = sequential_sweeping;
651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool sequential_sweeping() const { return sequential_sweeping_; }
654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Mark the global table which maps weak objects to dependent code without
656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // marking its contents.
657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void MarkWeakObjectToCodeTable();
658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Special case for processing weak references in a full collection. We need
660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // to artificially keep AllocationSites alive for a time.
661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void MarkAllocationSite(AllocationSite* site);
662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private:
664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  class SweeperTask;
665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  explicit MarkCompactCollector(Heap* heap);
667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ~MarkCompactCollector();
668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool MarkInvalidatedCode();
670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool WillBeDeoptimized(Code* code);
671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void RemoveDeadInvalidatedCode();
672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void ProcessInvalidatedCode(ObjectVisitor* visitor);
673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void StartSweeperThreads();
675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG
677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  enum CollectorState {
678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    IDLE,
679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    PREPARE_GC,
680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MARK_LIVE_OBJECTS,
681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SWEEP_SPACES,
682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ENCODE_FORWARDING_ADDRESSES,
683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    UPDATE_POINTERS,
684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    RELOCATE_OBJECTS
685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  };
686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The current stage of the collector.
688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CollectorState state_;
689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool reduce_memory_footprint_;
692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool abort_incremental_marking_;
694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MarkingParity marking_parity_;
696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // True if we are collecting slots to perform evacuation from evacuation
698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // candidates.
699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool compacting_;
700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool was_marked_incrementally_;
702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // True if concurrent or parallel sweeping is currently in progress.
704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool sweeping_in_progress_;
705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  base::Semaphore pending_sweeper_jobs_semaphore_;
707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool sequential_sweeping_;
709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SlotsBufferAllocator slots_buffer_allocator_;
711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SlotsBuffer* migration_slots_buffer_;
713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Finishes GC, performs heap verification if enabled.
715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void Finish();
716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // -----------------------------------------------------------------------
718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Phase 1: Marking live objects.
719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //
720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  Before: The heap has been prepared for garbage collection by
721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //          MarkCompactCollector::Prepare() and is otherwise in its
722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //          normal state.
723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //
724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //   After: Live objects are marked and non-live objects are unmarked.
725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  friend class RootMarkingVisitor;
727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  friend class MarkingVisitor;
728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  friend class MarkCompactMarkingVisitor;
729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  friend class CodeMarkingVisitor;
730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  friend class SharedFunctionInfoMarkingVisitor;
731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Mark code objects that are active on the stack to prevent them
733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // from being flushed.
734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void PrepareThreadForCodeFlushing(Isolate* isolate, ThreadLocalTop* top);
735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void PrepareForCodeFlushing();
737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Marking operations for objects reachable from roots.
739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void MarkLiveObjects();
740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void AfterMarking();
742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Marks the object black and pushes it on the marking stack.
744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // This is for non-incremental marking only.
745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  INLINE(void MarkObject(HeapObject* obj, MarkBit mark_bit));
746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Marks the object black assuming that it is not yet marked.
748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // This is for non-incremental marking only.
749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  INLINE(void SetMark(HeapObject* obj, MarkBit mark_bit));
750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Mark the heap roots and all objects reachable from them.
752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void MarkRoots(RootMarkingVisitor* visitor);
753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Mark the string table specially.  References to internalized strings from
755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // the string table are weak.
756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void MarkStringTable(RootMarkingVisitor* visitor);
757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Mark objects in implicit references groups if their parent object
759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // is marked.
760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void MarkImplicitRefGroups();
761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Mark objects reachable (transitively) from objects in the marking stack
763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // or overflowed in the heap.
764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void ProcessMarkingDeque();
765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Mark objects reachable (transitively) from objects in the marking stack
767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // or overflowed in the heap.  This respects references only considered in
768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // the final atomic marking pause including the following:
769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //    - Processing of objects reachable through Harmony WeakMaps.
770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //    - Objects reachable due to host application logic like object groups
771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //      or implicit references' groups.
772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void ProcessEphemeralMarking(ObjectVisitor* visitor);
773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // If the call-site of the top optimized code was not prepared for
775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // deoptimization, then treat the maps in the code as strong pointers,
776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // otherwise a map can die and deoptimize the code.
777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void ProcessTopOptimizedFrame(ObjectVisitor* visitor);
778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Mark objects reachable (transitively) from objects in the marking
780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // stack.  This function empties the marking stack, but may leave
781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // overflowed objects in the heap, in which case the marking stack's
782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // overflow flag will be set.
783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void EmptyMarkingDeque();
784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Refill the marking stack with overflowed objects from the heap.  This
786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // function either leaves the marking stack full or clears the overflow
787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // flag on the marking stack.
788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void RefillMarkingDeque();
789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // After reachable maps have been marked process per context object
791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // literal map caches removing unmarked entries.
792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void ProcessMapCaches();
793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Callback function for telling whether the object *p is an unmarked
795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // heap object.
796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static bool IsUnmarkedHeapObject(Object** p);
797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static bool IsUnmarkedHeapObjectWithHeap(Heap* heap, Object** p);
798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Map transitions from a live map to a dead map must be killed.
800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // We replace them with a null descriptor, with the same key.
801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void ClearNonLiveReferences();
802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void ClearNonLivePrototypeTransitions(Map* map);
803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void ClearNonLiveMapTransitions(Map* map, MarkBit map_mark);
804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void ClearMapTransitions(Map* map);
805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool ClearMapBackPointer(Map* map);
806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void TrimDescriptorArray(Map* map, DescriptorArray* descriptors,
807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                           int number_of_own_descriptors);
808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void TrimEnumCache(Map* map, DescriptorArray* descriptors);
809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void ClearDependentCode(DependentCode* dependent_code);
811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void ClearDependentICList(Object* head);
812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void ClearNonLiveDependentCode(DependentCode* dependent_code);
813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int ClearNonLiveDependentCodeInGroup(DependentCode* dependent_code, int group,
814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                       int start, int end, int new_start);
815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Mark all values associated with reachable keys in weak collections
817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // encountered so far.  This might push new object or even new weak maps onto
818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // the marking stack.
819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void ProcessWeakCollections();
820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // After all reachable objects have been marked those weak map entries
822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // with an unreachable key are removed from all encountered weak maps.
823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The linked list of all encountered weak maps is destroyed.
824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void ClearWeakCollections();
825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // We have to remove all encountered weak maps from the list of weak
827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // collections when incremental marking is aborted.
828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void AbortWeakCollections();
829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // -----------------------------------------------------------------------
831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Phase 2: Sweeping to clear mark bits and free non-live objects for
832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // a non-compacting collection.
833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //
834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //  Before: Live objects are marked and non-live objects are unmarked.
835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //
836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //   After: Live objects are unmarked, non-live regions have been added to
837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //          their space's free list. Active eden semispace is compacted by
838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //          evacuation.
839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  //
840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // If we are not compacting the heap, we simply sweep the spaces except
842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // for the large object space, clearing mark bits and adding unmarked
843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // regions to each space's free list.
844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void SweepSpaces();
845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int DiscoverAndEvacuateBlackObjectsOnPage(NewSpace* new_space,
847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                            NewSpacePage* p);
848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void EvacuateNewSpace();
850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void EvacuateLiveObjectsFromPage(Page* p);
852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void EvacuatePages();
854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void EvacuateNewSpaceAndCandidates();
856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void ReleaseEvacuationCandidates();
858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Moves the pages of the evacuation_candidates_ list to the end of their
860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // corresponding space pages list.
861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void MoveEvacuationCandidatesToEndOfPagesList();
862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void SweepSpace(PagedSpace* space, SweeperType sweeper);
864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Finalizes the parallel sweeping phase. Marks all the pages that were
866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // swept in parallel.
867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void ParallelSweepSpacesComplete();
868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void ParallelSweepSpaceComplete(PagedSpace* space);
870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Updates store buffer and slot buffer for a pointer in a migrating object.
872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void RecordMigratedSlot(Object* value, Address slot);
873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG
875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  friend class MarkObjectVisitor;
876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static void VisitObject(HeapObject* obj);
877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  friend class UnmarkObjectVisitor;
879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static void UnmarkObject(HeapObject* obj);
880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Heap* heap_;
883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MarkingDeque marking_deque_;
884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CodeFlusher* code_flusher_;
885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool have_code_to_deoptimize_;
886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  List<Page*> evacuation_candidates_;
888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  List<Code*> invalidated_code_;
889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SmartPointer<FreeList> free_list_old_data_space_;
891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SmartPointer<FreeList> free_list_old_pointer_space_;
892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  friend class Heap;
894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass MarkBitCellIterator BASE_EMBEDDED {
898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  explicit MarkBitCellIterator(MemoryChunk* chunk) : chunk_(chunk) {
900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    last_cell_index_ = Bitmap::IndexToCell(Bitmap::CellAlignIndex(
901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        chunk_->AddressToMarkbitIndex(chunk_->area_end())));
902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cell_base_ = chunk_->area_start();
903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cell_index_ = Bitmap::IndexToCell(
904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        Bitmap::CellAlignIndex(chunk_->AddressToMarkbitIndex(cell_base_)));
905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cells_ = chunk_->markbits()->cells();
906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inline bool Done() { return cell_index_ == last_cell_index_; }
909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inline bool HasNext() { return cell_index_ < last_cell_index_ - 1; }
911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inline MarkBit::CellType* CurrentCell() {
913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(cell_index_ == Bitmap::IndexToCell(Bitmap::CellAlignIndex(
914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              chunk_->AddressToMarkbitIndex(cell_base_))));
915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return &cells_[cell_index_];
916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inline Address CurrentCellBase() {
919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(cell_index_ == Bitmap::IndexToCell(Bitmap::CellAlignIndex(
920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                              chunk_->AddressToMarkbitIndex(cell_base_))));
921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return cell_base_;
922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inline void Advance() {
925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cell_index_++;
926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    cell_base_ += 32 * kPointerSize;
927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private:
930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MemoryChunk* chunk_;
931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MarkBit::CellType* cells_;
932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  unsigned int last_cell_index_;
933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  unsigned int cell_index_;
934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Address cell_base_;
935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass SequentialSweepingScope BASE_EMBEDDED {
939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public:
940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  explicit SequentialSweepingScope(MarkCompactCollector* collector)
941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : collector_(collector) {
942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    collector_->set_sequential_sweeping(true);
943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ~SequentialSweepingScope() { collector_->set_sequential_sweeping(false); }
946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private:
948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MarkCompactCollector* collector_;
949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst char* AllocationSpaceName(AllocationSpace space);
953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}  // namespace v8::internal
955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif  // V8_HEAP_MARK_COMPACT_H_
957