13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved.
2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without
3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are
4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met:
5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions of source code must retain the above copyright
7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       notice, this list of conditions and the following disclaimer.
8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions in binary form must reproduce the above
9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       copyright notice, this list of conditions and the following
10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       disclaimer in the documentation and/or other materials provided
11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       with the distribution.
12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Neither the name of Google Inc. nor the names of its
13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       contributors may be used to endorse or promote products derived
14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       from this software without specific prior written permission.
15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifndef V8_MARK_COMPACT_H_
29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define V8_MARK_COMPACT_H_
30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#include "compiler-intrinsics.h"
3244f0eee88ff00398ff7f715fab053374d808c90dSteve Block#include "spaces.h"
3344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 {
35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal {
36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Callback function, returns whether an object is alive. The heap size
38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// of the object is returned in size. It optionally updates the offset
39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// to the first live object in the page (only used for old and map objects).
40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocktypedef bool (*IsAliveFunction)(HeapObject* obj, int* size, int* offset);
41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Forward declarations.
4344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockclass CodeFlusher;
4444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockclass GCTracer;
45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass MarkingVisitor;
4644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockclass RootMarkingVisitor;
4744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
4844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochclass Marking {
503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch public:
513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  explicit Marking(Heap* heap)
523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      : heap_(heap) {
533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static inline MarkBit MarkBitFrom(Address addr);
563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static inline MarkBit MarkBitFrom(HeapObject* obj) {
583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return MarkBitFrom(reinterpret_cast<Address>(obj));
593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Impossible markbits: 01
623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static const char* kImpossibleBitPattern;
633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static inline bool IsImpossible(MarkBit mark_bit) {
643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return !mark_bit.Get() && mark_bit.Next().Get();
653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Black markbits: 10 - this is required by the sweeper.
683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static const char* kBlackBitPattern;
693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static inline bool IsBlack(MarkBit mark_bit) {
703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return mark_bit.Get() && !mark_bit.Next().Get();
713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // White markbits: 00 - this is required by the mark bit clearer.
743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static const char* kWhiteBitPattern;
753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static inline bool IsWhite(MarkBit mark_bit) {
763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return !mark_bit.Get();
773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Grey markbits: 11
803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static const char* kGreyBitPattern;
813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static inline bool IsGrey(MarkBit mark_bit) {
823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return mark_bit.Get() && mark_bit.Next().Get();
833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static inline void MarkBlack(MarkBit mark_bit) {
863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    mark_bit.Set();
873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    mark_bit.Next().Clear();
883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static inline void BlackToGrey(MarkBit markbit) {
913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    markbit.Next().Set();
923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static inline void WhiteToGrey(MarkBit markbit) {
953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    markbit.Set();
963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    markbit.Next().Set();
973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static inline void GreyToBlack(MarkBit markbit) {
1003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    markbit.Next().Clear();
1013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static inline void BlackToGrey(HeapObject* obj) {
1043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    BlackToGrey(MarkBitFrom(obj));
1053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static inline void AnyToGrey(MarkBit markbit) {
1083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    markbit.Set();
1093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    markbit.Next().Set();
1103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Returns true if the the object whose mark is transferred is marked black.
1133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool TransferMark(Address old_start, Address new_start);
1143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifdef DEBUG
1163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  enum ObjectColor {
1173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    BLACK_OBJECT,
1183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    WHITE_OBJECT,
1193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    GREY_OBJECT,
1203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    IMPOSSIBLE_COLOR
1213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  };
1223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static const char* ColorName(ObjectColor color) {
1243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    switch (color) {
1253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case BLACK_OBJECT: return "black";
1263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case WHITE_OBJECT: return "white";
1273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case GREY_OBJECT: return "grey";
1283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case IMPOSSIBLE_COLOR: return "impossible";
1293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
1303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return "error";
1313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static ObjectColor Color(HeapObject* obj) {
1343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return Color(Marking::MarkBitFrom(obj));
1353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static ObjectColor Color(MarkBit mark_bit) {
1383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (IsBlack(mark_bit)) return BLACK_OBJECT;
1393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (IsWhite(mark_bit)) return WHITE_OBJECT;
1403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (IsGrey(mark_bit)) return GREY_OBJECT;
1413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    UNREACHABLE();
1423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return IMPOSSIBLE_COLOR;
1433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif
1453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Returns true if the transferred color is black.
1473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  INLINE(static bool TransferColor(HeapObject* from,
1483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                   HeapObject* to)) {
1493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MarkBit from_mark_bit = MarkBitFrom(from);
1503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MarkBit to_mark_bit = MarkBitFrom(to);
1513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bool is_black = false;
1523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (from_mark_bit.Get()) {
1533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      to_mark_bit.Set();
1543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      is_black = true;  // Looks black so far.
1553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
1563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (from_mark_bit.Next().Get()) {
1573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      to_mark_bit.Next().Set();
1583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      is_black = false;  // Was actually gray.
1593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
1603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return is_black;
1613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch private:
1643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Heap* heap_;
1653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch};
1663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
16744f0eee88ff00398ff7f715fab053374d808c90dSteve Block// ----------------------------------------------------------------------------
1683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Marking deque for tracing live objects.
16944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochclass MarkingDeque {
17144f0eee88ff00398ff7f715fab053374d808c90dSteve Block public:
1723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  MarkingDeque()
1733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      : array_(NULL), top_(0), bottom_(0), mask_(0), overflowed_(false) { }
17444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
17544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void Initialize(Address low, Address high) {
1763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    HeapObject** obj_low = reinterpret_cast<HeapObject**>(low);
1773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    HeapObject** obj_high = reinterpret_cast<HeapObject**>(high);
1783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    array_ = obj_low;
1793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    mask_ = RoundDownToPowerOf2(static_cast<int>(obj_high - obj_low)) - 1;
1803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    top_ = bottom_ = 0;
18144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    overflowed_ = false;
18244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
18344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  inline bool IsFull() { return ((top_ + 1) & mask_) == bottom_; }
18544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  inline bool IsEmpty() { return top_ == bottom_; }
18744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
18844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  bool overflowed() const { return overflowed_; }
18944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
1903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void ClearOverflowed() { overflowed_ = false; }
1913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void SetOverflowed() { overflowed_ = true; }
19344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
19444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Push the (marked) object on the marking stack if there is room,
19544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // otherwise mark the object as overflowed and wait for a rescan of the
19644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // heap.
1973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  inline void PushBlack(HeapObject* object) {
1983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(object->IsHeapObject());
1993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (IsFull()) {
2003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Marking::BlackToGrey(object);
2013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      MemoryChunk::IncrementLiveBytesFromGC(object->address(), -object->Size());
2023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      SetOverflowed();
20344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    } else {
2043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      array_[top_] = object;
2053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      top_ = ((top_ + 1) & mask_);
20644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
20744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
20844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
2093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  inline void PushGrey(HeapObject* object) {
2103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(object->IsHeapObject());
2113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (IsFull()) {
2123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      SetOverflowed();
2133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
2143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      array_[top_] = object;
2153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      top_ = ((top_ + 1) & mask_);
2163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
2173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  inline HeapObject* Pop() {
2203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(!IsEmpty());
2213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    top_ = ((top_ - 1) & mask_);
2223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    HeapObject* object = array_[top_];
2233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(object->IsHeapObject());
22444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    return object;
22544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
22644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
2273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  inline void UnshiftGrey(HeapObject* object) {
2283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(object->IsHeapObject());
2293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (IsFull()) {
2303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      SetOverflowed();
2313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
2323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      bottom_ = ((bottom_ - 1) & mask_);
2333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      array_[bottom_] = object;
2343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
2353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HeapObject** array() { return array_; }
2383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int bottom() { return bottom_; }
2393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int top() { return top_; }
2403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int mask() { return mask_; }
2413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void set_top(int top) { top_ = top; }
2423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
24344f0eee88ff00398ff7f715fab053374d808c90dSteve Block private:
2443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HeapObject** array_;
2453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // array_[(top - 1) & mask_] is the top element in the deque.  The Deque is
2463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // empty when top_ == bottom_.  It is full when top_ + 1 == bottom
2473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // (mod mask + 1).
2483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int top_;
2493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int bottom_;
2503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int mask_;
25144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  bool overflowed_;
25244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
2533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DISALLOW_COPY_AND_ASSIGN(MarkingDeque);
2543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch};
2553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochclass SlotsBufferAllocator {
2583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch public:
2593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  SlotsBuffer* AllocateBuffer(SlotsBuffer* next_buffer);
2603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void DeallocateBuffer(SlotsBuffer* buffer);
2613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void DeallocateChain(SlotsBuffer** buffer_address);
2633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch};
2643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// SlotsBuffer records a sequence of slots that has to be updated
2673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// after live objects were relocated from evacuation candidates.
2683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// All slots are either untyped or typed:
2693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//    - Untyped slots are expected to contain a tagged object pointer.
2703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//      They are recorded by an address.
2713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//    - Typed slots are expected to contain an encoded pointer to a heap
2723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//      object where the way of encoding depends on the type of the slot.
2733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//      They are recorded as a pair (SlotType, slot address).
2743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// We assume that zero-page is never mapped this allows us to distinguish
2753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// untyped slots from typed slots during iteration by a simple comparison:
2763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// if element of slots buffer is less than NUMBER_OF_SLOT_TYPES then it
2773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// is the first element of typed slot's pair.
2783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochclass SlotsBuffer {
2793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch public:
2803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  typedef Object** ObjectSlot;
2813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  explicit SlotsBuffer(SlotsBuffer* next_buffer)
2833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      : idx_(0), chain_length_(1), next_(next_buffer) {
2843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (next_ != NULL) {
2853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      chain_length_ = next_->chain_length_ + 1;
2863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
2873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ~SlotsBuffer() {
2903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void Add(ObjectSlot slot) {
2933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(0 <= idx_ && idx_ < kNumberOfElements);
2943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    slots_[idx_++] = slot;
2953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  enum SlotType {
2983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    EMBEDDED_OBJECT_SLOT,
2993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    RELOCATED_CODE_OBJECT,
3003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CODE_TARGET_SLOT,
3013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CODE_ENTRY_SLOT,
3023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    DEBUG_TARGET_SLOT,
3033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    JS_RETURN_SLOT,
3043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    NUMBER_OF_SLOT_TYPES
3053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  };
3063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void UpdateSlots(Heap* heap);
3083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void UpdateSlotsWithFilter(Heap* heap);
3103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  SlotsBuffer* next() { return next_; }
3123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static int SizeOfChain(SlotsBuffer* buffer) {
3143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (buffer == NULL) return 0;
3153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return static_cast<int>(buffer->idx_ +
3163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                            (buffer->chain_length_ - 1) * kNumberOfElements);
3173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  inline bool IsFull() {
3203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return idx_ == kNumberOfElements;
3213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  inline bool HasSpaceForTypedSlot() {
3243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return idx_ < kNumberOfElements - 1;
3253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static void UpdateSlotsRecordedIn(Heap* heap,
3283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    SlotsBuffer* buffer,
3293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    bool code_slots_filtering_required) {
3303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    while (buffer != NULL) {
3313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (code_slots_filtering_required) {
3323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        buffer->UpdateSlotsWithFilter(heap);
3333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
3343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        buffer->UpdateSlots(heap);
3353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
3363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      buffer = buffer->next();
3373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
3383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  enum AdditionMode {
3413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FAIL_ON_OVERFLOW,
3423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    IGNORE_OVERFLOW
3433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  };
3443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static bool ChainLengthThresholdReached(SlotsBuffer* buffer) {
3463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return buffer != NULL && buffer->chain_length_ >= kChainLengthThreshold;
3473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static bool AddTo(SlotsBufferAllocator* allocator,
3503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                    SlotsBuffer** buffer_address,
3513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                    ObjectSlot slot,
3523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                    AdditionMode mode) {
3533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    SlotsBuffer* buffer = *buffer_address;
3543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (buffer == NULL || buffer->IsFull()) {
3553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (mode == FAIL_ON_OVERFLOW && ChainLengthThresholdReached(buffer)) {
3563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        allocator->DeallocateChain(buffer_address);
3573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        return false;
3583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
3593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      buffer = allocator->AllocateBuffer(buffer);
3603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      *buffer_address = buffer;
3613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
3623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    buffer->Add(slot);
3633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return true;
3643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static bool IsTypedSlot(ObjectSlot slot);
3673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static bool AddTo(SlotsBufferAllocator* allocator,
3693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                    SlotsBuffer** buffer_address,
3703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                    SlotType type,
3713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                    Address addr,
3723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                    AdditionMode mode);
3733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static const int kNumberOfElements = 1021;
3753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch private:
3773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static const int kChainLengthThreshold = 15;
3783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  intptr_t idx_;
3803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  intptr_t chain_length_;
3813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  SlotsBuffer* next_;
3823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ObjectSlot slots_[kNumberOfElements];
38344f0eee88ff00398ff7f715fab053374d808c90dSteve Block};
384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
386692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch// Defined in isolate.h.
387692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdochclass ThreadLocalTop;
388692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch
389692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch
390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// -------------------------------------------------------------------------
391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Mark-Compact collector
39244f0eee88ff00398ff7f715fab053374d808c90dSteve Blockclass MarkCompactCollector {
393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Type of functions to compute forwarding addresses of objects in
395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // compacted spaces.  Given an object and its size, return a (non-failure)
396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Object* that will be the object after forwarding.  There is a separate
397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // allocation function for each (compactable) space based on the location
398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // of the object before compaction.
39944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  typedef MaybeObject* (*AllocationFunction)(Heap* heap,
40044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                             HeapObject* object,
4015913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck                                             int object_size);
402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Type of functions to encode the forwarding address for an object.
404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Given the object, its size, and the new (non-failure) object it will be
405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // forwarded to, encode the forwarding address.  For paged spaces, the
406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // 'offset' input/output parameter contains the offset of the forwarded
407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // object from the forwarding address of the previous live object in the
408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // page as input, and is updated to contain the offset to be used for the
409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // next live object in the same page.  For spaces using a different
4103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // encoding (i.e., contiguous spaces), the offset parameter is ignored.
41144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  typedef void (*EncodingFunction)(Heap* heap,
41244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                   HeapObject* old_object,
413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                   int object_size,
414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                   Object* new_object,
415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                   int* offset);
416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Type of functions to process non-live objects.
4188b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  typedef void (*ProcessNonLiveFunction)(HeapObject* object, Isolate* isolate);
419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
42044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Pointer to member function, used in IterateLiveObjects.
42144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  typedef int (MarkCompactCollector::*LiveObjectCallback)(HeapObject* obj);
42244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
4233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set the global flags, it must be called before Prepare to take effect.
4243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  inline void SetFlags(int flags);
425592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
42685b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  static void Initialize();
427592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
4283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void CollectEvacuationCandidates(PagedSpace* space);
4293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void AddEvacuationCandidate(Page* p);
4313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Prepares for GC by resetting relocation info in old and map spaces and
433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // choosing spaces to compact.
43444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void Prepare(GCTracer* tracer);
435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Performs a global garbage collection.
43744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void CollectGarbage();
438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  enum CompactionMode {
4403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    INCREMENTAL_COMPACTION,
4413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    NON_INCREMENTAL_COMPACTION
4423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  };
4435d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
4443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool StartCompaction(CompactionMode mode);
445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void AbortCompaction();
447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // During a full GC, there is a stack-allocated GCTracer that is used for
449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // bookkeeping information.  Return a pointer to that tracer.
45044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  GCTracer* tracer() { return tracer_; }
451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Checks whether performing mark-compact collection.
45444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  bool in_use() { return state_ > PREPARE_GC; }
45544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  bool are_map_pointers_encoded() { return state_ == UPDATE_POINTERS; }
456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
458d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Determine type of object and emit deletion log event.
4598b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  static void ReportDeleteIfNeeded(HeapObject* obj, Isolate* isolate);
4608a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
46180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Distinguishable invalid map encodings (for single word and multiple words)
46280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // that indicate free regions.
46380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  static const uint32_t kSingleFreeEncoding = 0;
46480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  static const uint32_t kMultiFreeEncoding = 1;
46580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
4663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static inline bool IsMarked(Object* obj);
4673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
46844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  inline Heap* heap() const { return heap_; }
46944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
47044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CodeFlusher* code_flusher() { return code_flusher_; }
47144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  inline bool is_code_flushing_enabled() const { return code_flusher_ != NULL; }
47244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void EnableCodeFlushing(bool enable);
47344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
4743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  enum SweeperType {
4753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    CONSERVATIVE,
4763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    LAZY_CONSERVATIVE,
4773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    PRECISE
4783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  };
4793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifdef DEBUG
4813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void VerifyMarkbitsAreClean();
4823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static void VerifyMarkbitsAreClean(PagedSpace* space);
4833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static void VerifyMarkbitsAreClean(NewSpace* space);
4843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif
4853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Sweep a single page from the given space conservatively.
4873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Return a number of reclaimed bytes.
4883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static intptr_t SweepConservatively(PagedSpace* space, Page* p);
4893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  INLINE(static bool ShouldSkipEvacuationSlotRecording(Object** anchor)) {
4913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return Page::FromAddress(reinterpret_cast<Address>(anchor))->
4923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ShouldSkipEvacuationSlotRecording();
4933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  INLINE(static bool ShouldSkipEvacuationSlotRecording(Object* host)) {
4963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return Page::FromAddress(reinterpret_cast<Address>(host))->
4973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ShouldSkipEvacuationSlotRecording();
4983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  INLINE(static bool IsOnEvacuationCandidate(Object* obj)) {
5013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return Page::FromAddress(reinterpret_cast<Address>(obj))->
5023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        IsEvacuationCandidate();
5033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
5043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void EvictEvacuationCandidate(Page* page) {
5063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (FLAG_trace_fragmentation) {
5073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      PrintF("Page %p is too popular. Disabling evacuation.\n",
5083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch             reinterpret_cast<void*>(page));
5093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
5103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // TODO(gc) If all evacuation candidates are too popular we
5123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // should stop slots recording entirely.
5133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    page->ClearEvacuationCandidate();
5143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // We were not collecting slots on this page that point
5163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // to other evacuation candidates thus we have to
5173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // rescan the page after evacuation to discover and update all
5183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // pointers to evacuated objects.
5193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (page->owner()->identity() == OLD_DATA_SPACE) {
5203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      evacuation_candidates_.RemoveElement(page);
5213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
5223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      page->SetFlag(Page::RESCAN_ON_EVACUATION);
5233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
5243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
5253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void RecordRelocSlot(RelocInfo* rinfo, Object* target);
5273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void RecordCodeEntrySlot(Address slot, Code* target);
5283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  INLINE(void RecordSlot(Object** anchor_slot, Object** slot, Object* object));
5303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void MigrateObject(Address dst,
5323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     Address src,
5333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     int size,
5343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                     AllocationSpace to_old_space);
5353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool TryPromoteObject(HeapObject* object, int object_size);
5373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
53869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  inline Object* encountered_weak_maps() { return encountered_weak_maps_; }
53969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  inline void set_encountered_weak_maps(Object* weak_map) {
54069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    encountered_weak_maps_ = weak_map;
54169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
54269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
5433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void InvalidateCode(Code* code);
5443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void ClearMarkbits();
5463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
54844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  MarkCompactCollector();
54944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ~MarkCompactCollector();
55044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
5513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool MarkInvalidatedCode();
5523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void RemoveDeadInvalidatedCode();
5533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void ProcessInvalidatedCode(ObjectVisitor* visitor);
5543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  enum CollectorState {
558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    IDLE,
559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    PREPARE_GC,
560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    MARK_LIVE_OBJECTS,
561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    SWEEP_SPACES,
562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ENCODE_FORWARDING_ADDRESSES,
563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    UPDATE_POINTERS,
5647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    RELOCATE_OBJECTS
565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  };
566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The current stage of the collector.
56844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CollectorState state_;
569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Global flag that forces sweeping to be precise, so we can traverse the
5723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // heap.
5733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool sweep_precisely_;
5743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool reduce_memory_footprint_;
5763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool abort_incremental_marking_;
5783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // True if we are collecting slots to perform evacuation from evacuation
5803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // candidates.
5813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool compacting_;
582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool was_marked_incrementally_;
584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool collect_maps_;
586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool flush_monomorphic_ics_;
588c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // A pointer to the current stack-allocated GC tracer object during a full
590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // collection (NULL before and after).
59144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  GCTracer* tracer_;
592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  SlotsBufferAllocator slots_buffer_allocator_;
5943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  SlotsBuffer* migration_slots_buffer_;
5963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Finishes GC, performs heap verification if enabled.
59844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void Finish();
599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------------------------------------------
601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Phase 1: Marking live objects.
602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  Before: The heap has been prepared for garbage collection by
604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //          MarkCompactCollector::Prepare() and is otherwise in its
605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //          normal state.
606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //   After: Live objects are marked and non-live objects are unmarked.
608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  friend class RootMarkingVisitor;
611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  friend class MarkingVisitor;
612756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  friend class StaticMarkingVisitor;
613756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  friend class CodeMarkingVisitor;
614756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  friend class SharedFunctionInfoMarkingVisitor;
615756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick
616692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch  // Mark non-optimize code for functions inlined into the given optimized
617692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch  // code. This will prevent it from being flushed.
618692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch  void MarkInlinedFunctionsCode(Code* code);
619692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch
620692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch  // Mark code objects that are active on the stack to prevent them
621692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch  // from being flushed.
622692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch  void PrepareThreadForCodeFlushing(Isolate* isolate, ThreadLocalTop* top);
623692be65d6b06edd9ff4cfc4c308555b7c99c1191Ben Murdoch
62444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void PrepareForCodeFlushing();
625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Marking operations for objects reachable from roots.
62744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void MarkLiveObjects();
628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void AfterMarking();
630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Marks the object black and pushes it on the marking stack.
6323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // This is for non-incremental marking.
6333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  INLINE(void MarkObject(HeapObject* obj, MarkBit mark_bit));
634592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
6353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  INLINE(bool MarkObjectWithoutPush(HeapObject* object));
6363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  INLINE(void MarkObjectAndPush(HeapObject* value));
6373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Marks the object black.  This is for non-incremental marking.
6393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  INLINE(void SetMark(HeapObject* obj, MarkBit mark_bit));
6403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void ProcessNewlyMarkedObject(HeapObject* obj);
642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Creates back pointers for all map transitions, stores them in
644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the prototype field.  The original prototype pointers are restored
645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // in ClearNonLiveTransitions().  All JSObject maps
646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // connected by map transitions have the same prototype object, which
647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // is why we can use this field temporarily for back pointers.
64844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void CreateBackPointers();
649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Mark a Map and its DescriptorArray together, skipping transitions.
65144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void MarkMapContents(Map* map);
6523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void MarkAccessorPairSlot(HeapObject* accessors, int offset);
65344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void MarkDescriptorArray(DescriptorArray* descriptors);
654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Mark the heap roots and all objects reachable from them.
65644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void MarkRoots(RootMarkingVisitor* visitor);
657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Mark the symbol table specially.  References to symbols from the
659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // symbol table are weak.
66044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void MarkSymbolTable();
661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Mark objects in object groups that have at least one object in the
663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // group marked.
66444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void MarkObjectGroups();
66544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
66644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Mark objects in implicit references groups if their parent object
66744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // is marked.
66844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void MarkImplicitRefGroups();
669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
67044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Mark all objects which are reachable due to host application
67144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // logic like object groups or implicit references' groups.
67244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void ProcessExternalMarking();
673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Mark objects reachable (transitively) from objects in the marking stack
675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // or overflowed in the heap.
6763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void ProcessMarkingDeque();
677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Mark objects reachable (transitively) from objects in the marking
679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // stack.  This function empties the marking stack, but may leave
680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // overflowed objects in the heap, in which case the marking stack's
681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // overflow flag will be set.
6823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void EmptyMarkingDeque();
683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Refill the marking stack with overflowed objects from the heap.  This
685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // function either leaves the marking stack full or clears the overflow
686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // flag on the marking stack.
6873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void RefillMarkingDeque();
688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // After reachable maps have been marked process per context object
6903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // literal map caches removing unmarked entries.
6913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void ProcessMapCaches();
6923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Callback function for telling whether the object *p is an unmarked
694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // heap object.
695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static bool IsUnmarkedHeapObject(Object** p);
696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Map transitions from a live map to a dead map must be killed.
698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // We replace them with a null descriptor, with the same key.
69944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void ClearNonLiveTransitions();
7003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void ClearNonLivePrototypeTransitions(Map* map);
7013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void ClearNonLiveMapTransitions(Map* map, MarkBit map_mark);
7023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Marking detaches initial maps from SharedFunctionInfo objects
7043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // to make this reference weak. We need to reattach initial maps
7053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // back after collection. This is either done during
7063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // ClearNonLiveTransitions pass or by calling this function.
7073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void ReattachInitialMaps();
708592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
70969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Mark all values associated with reachable keys in weak maps encountered
71069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // so far.  This might push new object or even new weak maps onto the
71169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // marking stack.
71269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  void ProcessWeakMaps();
71369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
71469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // After all reachable objects have been marked those weak map entries
71569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // with an unreachable key are removed from all encountered weak maps.
71669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // The linked list of all encountered weak maps is destroyed.
71769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  void ClearWeakMaps();
71869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // -----------------------------------------------------------------------
720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Phase 2: Sweeping to clear mark bits and free non-live objects for
7213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // a non-compacting collection.
722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //  Before: Live objects are marked and non-live objects are unmarked.
724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
7253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //   After: Live objects are unmarked, non-live regions have been added to
7263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //          their space's free list. Active eden semispace is compacted by
7273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  //          evacuation.
728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  //
729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If we are not compacting the heap, we simply sweep the spaces except
731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // for the large object space, clearing mark bits and adding unmarked
732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // regions to each space's free list.
73344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void SweepSpaces();
734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void EvacuateNewSpace();
736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void EvacuateLiveObjectsFromPage(Page* p);
738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void EvacuatePages();
740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void EvacuateNewSpaceAndCandidates();
742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void SweepSpace(PagedSpace* space, SweeperType sweeper);
744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  friend class MarkObjectVisitor;
747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static void VisitObject(HeapObject* obj);
748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  friend class UnmarkObjectVisitor;
750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static void UnmarkObject(HeapObject* obj);
751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
75244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
75344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Heap* heap_;
7543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  MarkingDeque marking_deque_;
75544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  CodeFlusher* code_flusher_;
75669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Object* encountered_weak_maps_;
75744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
7583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  List<Page*> evacuation_candidates_;
7593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  List<Code*> invalidated_code_;
7603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
76144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  friend class Heap;
762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochconst char* AllocationSpaceName(AllocationSpace space);
7663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} }  // namespace v8::internal
768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif  // V8_MARK_COMPACT_H_
770