Home | History | Annotate | Download | only in src
      1 // Copyright 2011 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef V8_SPACES_H_
      6 #define V8_SPACES_H_
      7 
      8 #include "src/allocation.h"
      9 #include "src/base/atomicops.h"
     10 #include "src/hashmap.h"
     11 #include "src/list.h"
     12 #include "src/log.h"
     13 #include "src/platform/mutex.h"
     14 #include "src/utils.h"
     15 
     16 namespace v8 {
     17 namespace internal {
     18 
     19 class Isolate;
     20 
     21 // -----------------------------------------------------------------------------
     22 // Heap structures:
     23 //
     24 // A JS heap consists of a young generation, an old generation, and a large
     25 // object space. The young generation is divided into two semispaces. A
     26 // scavenger implements Cheney's copying algorithm. The old generation is
     27 // separated into a map space and an old object space. The map space contains
     28 // all (and only) map objects, the rest of old objects go into the old space.
     29 // The old generation is collected by a mark-sweep-compact collector.
     30 //
     31 // The semispaces of the young generation are contiguous.  The old and map
     32 // spaces consists of a list of pages. A page has a page header and an object
     33 // area.
     34 //
     35 // There is a separate large object space for objects larger than
     36 // Page::kMaxHeapObjectSize, so that they do not have to move during
     37 // collection. The large object space is paged. Pages in large object space
     38 // may be larger than the page size.
     39 //
     40 // A store-buffer based write barrier is used to keep track of intergenerational
     41 // references.  See store-buffer.h.
     42 //
     43 // During scavenges and mark-sweep collections we sometimes (after a store
     44 // buffer overflow) iterate intergenerational pointers without decoding heap
     45 // object maps so if the page belongs to old pointer space or large object
     46 // space it is essential to guarantee that the page does not contain any
     47 // garbage pointers to new space: every pointer aligned word which satisfies
     48 // the Heap::InNewSpace() predicate must be a pointer to a live heap object in
     49 // new space. Thus objects in old pointer and large object spaces should have a
     50 // special layout (e.g. no bare integer fields). This requirement does not
     51 // apply to map space which is iterated in a special fashion. However we still
     52 // require pointer fields of dead maps to be cleaned.
     53 //
     54 // To enable lazy cleaning of old space pages we can mark chunks of the page
     55 // as being garbage.  Garbage sections are marked with a special map.  These
     56 // sections are skipped when scanning the page, even if we are otherwise
     57 // scanning without regard for object boundaries.  Garbage sections are chained
     58 // together to form a free list after a GC.  Garbage sections created outside
     59 // of GCs by object trunctation etc. may not be in the free list chain.  Very
     60 // small free spaces are ignored, they need only be cleaned of bogus pointers
     61 // into new space.
     62 //
     63 // Each page may have up to one special garbage section.  The start of this
     64 // section is denoted by the top field in the space.  The end of the section
     65 // is denoted by the limit field in the space.  This special garbage section
     66 // is not marked with a free space map in the data.  The point of this section
     67 // is to enable linear allocation without having to constantly update the byte
     68 // array every time the top field is updated and a new object is created.  The
     69 // special garbage section is not in the chain of garbage sections.
     70 //
     71 // Since the top and limit fields are in the space, not the page, only one page
     72 // has a special garbage section, and if the top and limit are equal then there
     73 // is no special garbage section.
     74 
     75 // Some assertion macros used in the debugging mode.
     76 
     77 #define ASSERT_PAGE_ALIGNED(address)                                           \
     78   ASSERT((OffsetFrom(address) & Page::kPageAlignmentMask) == 0)
     79 
     80 #define ASSERT_OBJECT_ALIGNED(address)                                         \
     81   ASSERT((OffsetFrom(address) & kObjectAlignmentMask) == 0)
     82 
     83 #define ASSERT_OBJECT_SIZE(size)                                               \
     84   ASSERT((0 < size) && (size <= Page::kMaxRegularHeapObjectSize))
     85 
     86 #define ASSERT_PAGE_OFFSET(offset)                                             \
     87   ASSERT((Page::kObjectStartOffset <= offset)                                  \
     88       && (offset <= Page::kPageSize))
     89 
     90 #define ASSERT_MAP_PAGE_INDEX(index)                                           \
     91   ASSERT((0 <= index) && (index <= MapSpace::kMaxMapPageIndex))
     92 
     93 
     94 class PagedSpace;
     95 class MemoryAllocator;
     96 class AllocationInfo;
     97 class Space;
     98 class FreeList;
     99 class MemoryChunk;
    100 
    101 class MarkBit {
    102  public:
    103   typedef uint32_t CellType;
    104 
    105   inline MarkBit(CellType* cell, CellType mask, bool data_only)
    106       : cell_(cell), mask_(mask), data_only_(data_only) { }
    107 
    108   inline CellType* cell() { return cell_; }
    109   inline CellType mask() { return mask_; }
    110 
    111 #ifdef DEBUG
    112   bool operator==(const MarkBit& other) {
    113     return cell_ == other.cell_ && mask_ == other.mask_;
    114   }
    115 #endif
    116 
    117   inline void Set() { *cell_ |= mask_; }
    118   inline bool Get() { return (*cell_ & mask_) != 0; }
    119   inline void Clear() { *cell_ &= ~mask_; }
    120 
    121   inline bool data_only() { return data_only_; }
    122 
    123   inline MarkBit Next() {
    124     CellType new_mask = mask_ << 1;
    125     if (new_mask == 0) {
    126       return MarkBit(cell_ + 1, 1, data_only_);
    127     } else {
    128       return MarkBit(cell_, new_mask, data_only_);
    129     }
    130   }
    131 
    132  private:
    133   CellType* cell_;
    134   CellType mask_;
    135   // This boolean indicates that the object is in a data-only space with no
    136   // pointers.  This enables some optimizations when marking.
    137   // It is expected that this field is inlined and turned into control flow
    138   // at the place where the MarkBit object is created.
    139   bool data_only_;
    140 };
    141 
    142 
    143 // Bitmap is a sequence of cells each containing fixed number of bits.
    144 class Bitmap {
    145  public:
    146   static const uint32_t kBitsPerCell = 32;
    147   static const uint32_t kBitsPerCellLog2 = 5;
    148   static const uint32_t kBitIndexMask = kBitsPerCell - 1;
    149   static const uint32_t kBytesPerCell = kBitsPerCell / kBitsPerByte;
    150   static const uint32_t kBytesPerCellLog2 = kBitsPerCellLog2 - kBitsPerByteLog2;
    151 
    152   static const size_t kLength =
    153     (1 << kPageSizeBits) >> (kPointerSizeLog2);
    154 
    155   static const size_t kSize =
    156     (1 << kPageSizeBits) >> (kPointerSizeLog2 + kBitsPerByteLog2);
    157 
    158 
    159   static int CellsForLength(int length) {
    160     return (length + kBitsPerCell - 1) >> kBitsPerCellLog2;
    161   }
    162 
    163   int CellsCount() {
    164     return CellsForLength(kLength);
    165   }
    166 
    167   static int SizeFor(int cells_count) {
    168     return sizeof(MarkBit::CellType) * cells_count;
    169   }
    170 
    171   INLINE(static uint32_t IndexToCell(uint32_t index)) {
    172     return index >> kBitsPerCellLog2;
    173   }
    174 
    175   INLINE(static uint32_t CellToIndex(uint32_t index)) {
    176     return index << kBitsPerCellLog2;
    177   }
    178 
    179   INLINE(static uint32_t CellAlignIndex(uint32_t index)) {
    180     return (index + kBitIndexMask) & ~kBitIndexMask;
    181   }
    182 
    183   INLINE(MarkBit::CellType* cells()) {
    184     return reinterpret_cast<MarkBit::CellType*>(this);
    185   }
    186 
    187   INLINE(Address address()) {
    188     return reinterpret_cast<Address>(this);
    189   }
    190 
    191   INLINE(static Bitmap* FromAddress(Address addr)) {
    192     return reinterpret_cast<Bitmap*>(addr);
    193   }
    194 
    195   inline MarkBit MarkBitFromIndex(uint32_t index, bool data_only = false) {
    196     MarkBit::CellType mask = 1 << (index & kBitIndexMask);
    197     MarkBit::CellType* cell = this->cells() + (index >> kBitsPerCellLog2);
    198     return MarkBit(cell, mask, data_only);
    199   }
    200 
    201   static inline void Clear(MemoryChunk* chunk);
    202 
    203   static void PrintWord(uint32_t word, uint32_t himask = 0) {
    204     for (uint32_t mask = 1; mask != 0; mask <<= 1) {
    205       if ((mask & himask) != 0) PrintF("[");
    206       PrintF((mask & word) ? "1" : "0");
    207       if ((mask & himask) != 0) PrintF("]");
    208     }
    209   }
    210 
    211   class CellPrinter {
    212    public:
    213     CellPrinter() : seq_start(0), seq_type(0), seq_length(0) { }
    214 
    215     void Print(uint32_t pos, uint32_t cell) {
    216       if (cell == seq_type) {
    217         seq_length++;
    218         return;
    219       }
    220 
    221       Flush();
    222 
    223       if (IsSeq(cell)) {
    224         seq_start = pos;
    225         seq_length = 0;
    226         seq_type = cell;
    227         return;
    228       }
    229 
    230       PrintF("%d: ", pos);
    231       PrintWord(cell);
    232       PrintF("\n");
    233     }
    234 
    235     void Flush() {
    236       if (seq_length > 0) {
    237         PrintF("%d: %dx%d\n",
    238                seq_start,
    239                seq_type == 0 ? 0 : 1,
    240                seq_length * kBitsPerCell);
    241         seq_length = 0;
    242       }
    243     }
    244 
    245     static bool IsSeq(uint32_t cell) { return cell == 0 || cell == 0xFFFFFFFF; }
    246 
    247    private:
    248     uint32_t seq_start;
    249     uint32_t seq_type;
    250     uint32_t seq_length;
    251   };
    252 
    253   void Print() {
    254     CellPrinter printer;
    255     for (int i = 0; i < CellsCount(); i++) {
    256       printer.Print(i, cells()[i]);
    257     }
    258     printer.Flush();
    259     PrintF("\n");
    260   }
    261 
    262   bool IsClean() {
    263     for (int i = 0; i < CellsCount(); i++) {
    264       if (cells()[i] != 0) {
    265         return false;
    266       }
    267     }
    268     return true;
    269   }
    270 };
    271 
    272 
    273 class SkipList;
    274 class SlotsBuffer;
    275 
    276 // MemoryChunk represents a memory region owned by a specific space.
    277 // It is divided into the header and the body. Chunk start is always
    278 // 1MB aligned. Start of the body is aligned so it can accommodate
    279 // any heap object.
    280 class MemoryChunk {
    281  public:
    282   // Only works if the pointer is in the first kPageSize of the MemoryChunk.
    283   static MemoryChunk* FromAddress(Address a) {
    284     return reinterpret_cast<MemoryChunk*>(OffsetFrom(a) & ~kAlignmentMask);
    285   }
    286 
    287   // Only works for addresses in pointer spaces, not data or code spaces.
    288   static inline MemoryChunk* FromAnyPointerAddress(Heap* heap, Address addr);
    289 
    290   Address address() { return reinterpret_cast<Address>(this); }
    291 
    292   bool is_valid() { return address() != NULL; }
    293 
    294   MemoryChunk* next_chunk() const {
    295     return reinterpret_cast<MemoryChunk*>(base::Acquire_Load(&next_chunk_));
    296   }
    297 
    298   MemoryChunk* prev_chunk() const {
    299     return reinterpret_cast<MemoryChunk*>(base::Acquire_Load(&prev_chunk_));
    300   }
    301 
    302   void set_next_chunk(MemoryChunk* next) {
    303     base::Release_Store(&next_chunk_, reinterpret_cast<base::AtomicWord>(next));
    304   }
    305 
    306   void set_prev_chunk(MemoryChunk* prev) {
    307     base::Release_Store(&prev_chunk_, reinterpret_cast<base::AtomicWord>(prev));
    308   }
    309 
    310   Space* owner() const {
    311     if ((reinterpret_cast<intptr_t>(owner_) & kFailureTagMask) ==
    312         kFailureTag) {
    313       return reinterpret_cast<Space*>(reinterpret_cast<intptr_t>(owner_) -
    314                                       kFailureTag);
    315     } else {
    316       return NULL;
    317     }
    318   }
    319 
    320   void set_owner(Space* space) {
    321     ASSERT((reinterpret_cast<intptr_t>(space) & kFailureTagMask) == 0);
    322     owner_ = reinterpret_cast<Address>(space) + kFailureTag;
    323     ASSERT((reinterpret_cast<intptr_t>(owner_) & kFailureTagMask) ==
    324            kFailureTag);
    325   }
    326 
    327   VirtualMemory* reserved_memory() {
    328     return &reservation_;
    329   }
    330 
    331   void InitializeReservedMemory() {
    332     reservation_.Reset();
    333   }
    334 
    335   void set_reserved_memory(VirtualMemory* reservation) {
    336     ASSERT_NOT_NULL(reservation);
    337     reservation_.TakeControl(reservation);
    338   }
    339 
    340   bool scan_on_scavenge() { return IsFlagSet(SCAN_ON_SCAVENGE); }
    341   void initialize_scan_on_scavenge(bool scan) {
    342     if (scan) {
    343       SetFlag(SCAN_ON_SCAVENGE);
    344     } else {
    345       ClearFlag(SCAN_ON_SCAVENGE);
    346     }
    347   }
    348   inline void set_scan_on_scavenge(bool scan);
    349 
    350   int store_buffer_counter() { return store_buffer_counter_; }
    351   void set_store_buffer_counter(int counter) {
    352     store_buffer_counter_ = counter;
    353   }
    354 
    355   bool Contains(Address addr) {
    356     return addr >= area_start() && addr < area_end();
    357   }
    358 
    359   // Checks whether addr can be a limit of addresses in this page.
    360   // It's a limit if it's in the page, or if it's just after the
    361   // last byte of the page.
    362   bool ContainsLimit(Address addr) {
    363     return addr >= area_start() && addr <= area_end();
    364   }
    365 
    366   // Every n write barrier invocations we go to runtime even though
    367   // we could have handled it in generated code.  This lets us check
    368   // whether we have hit the limit and should do some more marking.
    369   static const int kWriteBarrierCounterGranularity = 500;
    370 
    371   enum MemoryChunkFlags {
    372     IS_EXECUTABLE,
    373     ABOUT_TO_BE_FREED,
    374     POINTERS_TO_HERE_ARE_INTERESTING,
    375     POINTERS_FROM_HERE_ARE_INTERESTING,
    376     SCAN_ON_SCAVENGE,
    377     IN_FROM_SPACE,  // Mutually exclusive with IN_TO_SPACE.
    378     IN_TO_SPACE,    // All pages in new space has one of these two set.
    379     NEW_SPACE_BELOW_AGE_MARK,
    380     CONTAINS_ONLY_DATA,
    381     EVACUATION_CANDIDATE,
    382     RESCAN_ON_EVACUATION,
    383 
    384     // Pages swept precisely can be iterated, hitting only the live objects.
    385     // Whereas those swept conservatively cannot be iterated over. Both flags
    386     // indicate that marking bits have been cleared by the sweeper, otherwise
    387     // marking bits are still intact.
    388     WAS_SWEPT_PRECISELY,
    389     WAS_SWEPT_CONSERVATIVELY,
    390 
    391     // Large objects can have a progress bar in their page header. These object
    392     // are scanned in increments and will be kept black while being scanned.
    393     // Even if the mutator writes to them they will be kept black and a white
    394     // to grey transition is performed in the value.
    395     HAS_PROGRESS_BAR,
    396 
    397     // Last flag, keep at bottom.
    398     NUM_MEMORY_CHUNK_FLAGS
    399   };
    400 
    401 
    402   static const int kPointersToHereAreInterestingMask =
    403       1 << POINTERS_TO_HERE_ARE_INTERESTING;
    404 
    405   static const int kPointersFromHereAreInterestingMask =
    406       1 << POINTERS_FROM_HERE_ARE_INTERESTING;
    407 
    408   static const int kEvacuationCandidateMask =
    409       1 << EVACUATION_CANDIDATE;
    410 
    411   static const int kSkipEvacuationSlotsRecordingMask =
    412       (1 << EVACUATION_CANDIDATE) |
    413       (1 << RESCAN_ON_EVACUATION) |
    414       (1 << IN_FROM_SPACE) |
    415       (1 << IN_TO_SPACE);
    416 
    417 
    418   void SetFlag(int flag) {
    419     flags_ |= static_cast<uintptr_t>(1) << flag;
    420   }
    421 
    422   void ClearFlag(int flag) {
    423     flags_ &= ~(static_cast<uintptr_t>(1) << flag);
    424   }
    425 
    426   void SetFlagTo(int flag, bool value) {
    427     if (value) {
    428       SetFlag(flag);
    429     } else {
    430       ClearFlag(flag);
    431     }
    432   }
    433 
    434   bool IsFlagSet(int flag) {
    435     return (flags_ & (static_cast<uintptr_t>(1) << flag)) != 0;
    436   }
    437 
    438   // Set or clear multiple flags at a time. The flags in the mask
    439   // are set to the value in "flags", the rest retain the current value
    440   // in flags_.
    441   void SetFlags(intptr_t flags, intptr_t mask) {
    442     flags_ = (flags_ & ~mask) | (flags & mask);
    443   }
    444 
    445   // Return all current flags.
    446   intptr_t GetFlags() { return flags_; }
    447 
    448 
    449   // PARALLEL_SWEEPING_DONE - The page state when sweeping is complete or
    450   // sweeping must not be performed on that page.
    451   // PARALLEL_SWEEPING_FINALIZE - A sweeper thread is done sweeping this
    452   // page and will not touch the page memory anymore.
    453   // PARALLEL_SWEEPING_IN_PROGRESS - This page is currently swept by a
    454   // sweeper thread.
    455   // PARALLEL_SWEEPING_PENDING - This page is ready for parallel sweeping.
    456   enum ParallelSweepingState {
    457     PARALLEL_SWEEPING_DONE,
    458     PARALLEL_SWEEPING_FINALIZE,
    459     PARALLEL_SWEEPING_IN_PROGRESS,
    460     PARALLEL_SWEEPING_PENDING
    461   };
    462 
    463   ParallelSweepingState parallel_sweeping() {
    464     return static_cast<ParallelSweepingState>(
    465         base::Acquire_Load(&parallel_sweeping_));
    466   }
    467 
    468   void set_parallel_sweeping(ParallelSweepingState state) {
    469     base::Release_Store(&parallel_sweeping_, state);
    470   }
    471 
    472   bool TryParallelSweeping() {
    473     return base::Acquire_CompareAndSwap(
    474                &parallel_sweeping_, PARALLEL_SWEEPING_PENDING,
    475                PARALLEL_SWEEPING_IN_PROGRESS) == PARALLEL_SWEEPING_PENDING;
    476   }
    477 
    478   // Manage live byte count (count of bytes known to be live,
    479   // because they are marked black).
    480   void ResetLiveBytes() {
    481     if (FLAG_gc_verbose) {
    482       PrintF("ResetLiveBytes:%p:%x->0\n",
    483              static_cast<void*>(this), live_byte_count_);
    484     }
    485     live_byte_count_ = 0;
    486   }
    487   void IncrementLiveBytes(int by) {
    488     if (FLAG_gc_verbose) {
    489       printf("UpdateLiveBytes:%p:%x%c=%x->%x\n",
    490              static_cast<void*>(this), live_byte_count_,
    491              ((by < 0) ? '-' : '+'), ((by < 0) ? -by : by),
    492              live_byte_count_ + by);
    493     }
    494     live_byte_count_ += by;
    495     ASSERT_LE(static_cast<unsigned>(live_byte_count_), size_);
    496   }
    497   int LiveBytes() {
    498     ASSERT(static_cast<unsigned>(live_byte_count_) <= size_);
    499     return live_byte_count_;
    500   }
    501 
    502   int write_barrier_counter() {
    503     return static_cast<int>(write_barrier_counter_);
    504   }
    505 
    506   void set_write_barrier_counter(int counter) {
    507     write_barrier_counter_ = counter;
    508   }
    509 
    510   int progress_bar() {
    511     ASSERT(IsFlagSet(HAS_PROGRESS_BAR));
    512     return progress_bar_;
    513   }
    514 
    515   void set_progress_bar(int progress_bar) {
    516     ASSERT(IsFlagSet(HAS_PROGRESS_BAR));
    517     progress_bar_ = progress_bar;
    518   }
    519 
    520   void ResetProgressBar() {
    521     if (IsFlagSet(MemoryChunk::HAS_PROGRESS_BAR)) {
    522       set_progress_bar(0);
    523       ClearFlag(MemoryChunk::HAS_PROGRESS_BAR);
    524     }
    525   }
    526 
    527   bool IsLeftOfProgressBar(Object** slot) {
    528     Address slot_address = reinterpret_cast<Address>(slot);
    529     ASSERT(slot_address > this->address());
    530     return (slot_address - (this->address() + kObjectStartOffset)) <
    531            progress_bar();
    532   }
    533 
    534   static void IncrementLiveBytesFromGC(Address address, int by) {
    535     MemoryChunk::FromAddress(address)->IncrementLiveBytes(by);
    536   }
    537 
    538   static void IncrementLiveBytesFromMutator(Address address, int by);
    539 
    540   static const intptr_t kAlignment =
    541       (static_cast<uintptr_t>(1) << kPageSizeBits);
    542 
    543   static const intptr_t kAlignmentMask = kAlignment - 1;
    544 
    545   static const intptr_t kSizeOffset = 0;
    546 
    547   static const intptr_t kLiveBytesOffset =
    548      kSizeOffset + kPointerSize + kPointerSize + kPointerSize +
    549      kPointerSize + kPointerSize +
    550      kPointerSize + kPointerSize + kPointerSize + kIntSize;
    551 
    552   static const size_t kSlotsBufferOffset = kLiveBytesOffset + kIntSize;
    553 
    554   static const size_t kWriteBarrierCounterOffset =
    555       kSlotsBufferOffset + kPointerSize + kPointerSize;
    556 
    557   static const size_t kHeaderSize = kWriteBarrierCounterOffset + kPointerSize +
    558                                     kIntSize + kIntSize + kPointerSize +
    559                                     5 * kPointerSize +
    560                                     kPointerSize + kPointerSize;
    561 
    562   static const int kBodyOffset =
    563       CODE_POINTER_ALIGN(kHeaderSize + Bitmap::kSize);
    564 
    565   // The start offset of the object area in a page. Aligned to both maps and
    566   // code alignment to be suitable for both.  Also aligned to 32 words because
    567   // the marking bitmap is arranged in 32 bit chunks.
    568   static const int kObjectStartAlignment = 32 * kPointerSize;
    569   static const int kObjectStartOffset = kBodyOffset - 1 +
    570       (kObjectStartAlignment - (kBodyOffset - 1) % kObjectStartAlignment);
    571 
    572   size_t size() const { return size_; }
    573 
    574   void set_size(size_t size) {
    575     size_ = size;
    576   }
    577 
    578   void SetArea(Address area_start, Address area_end) {
    579     area_start_ = area_start;
    580     area_end_ = area_end;
    581   }
    582 
    583   Executability executable() {
    584     return IsFlagSet(IS_EXECUTABLE) ? EXECUTABLE : NOT_EXECUTABLE;
    585   }
    586 
    587   bool ContainsOnlyData() {
    588     return IsFlagSet(CONTAINS_ONLY_DATA);
    589   }
    590 
    591   bool InNewSpace() {
    592     return (flags_ & ((1 << IN_FROM_SPACE) | (1 << IN_TO_SPACE))) != 0;
    593   }
    594 
    595   bool InToSpace() {
    596     return IsFlagSet(IN_TO_SPACE);
    597   }
    598 
    599   bool InFromSpace() {
    600     return IsFlagSet(IN_FROM_SPACE);
    601   }
    602 
    603   // ---------------------------------------------------------------------
    604   // Markbits support
    605 
    606   inline Bitmap* markbits() {
    607     return Bitmap::FromAddress(address() + kHeaderSize);
    608   }
    609 
    610   void PrintMarkbits() { markbits()->Print(); }
    611 
    612   inline uint32_t AddressToMarkbitIndex(Address addr) {
    613     return static_cast<uint32_t>(addr - this->address()) >> kPointerSizeLog2;
    614   }
    615 
    616   inline static uint32_t FastAddressToMarkbitIndex(Address addr) {
    617     const intptr_t offset =
    618         reinterpret_cast<intptr_t>(addr) & kAlignmentMask;
    619 
    620     return static_cast<uint32_t>(offset) >> kPointerSizeLog2;
    621   }
    622 
    623   inline Address MarkbitIndexToAddress(uint32_t index) {
    624     return this->address() + (index << kPointerSizeLog2);
    625   }
    626 
    627   void InsertAfter(MemoryChunk* other);
    628   void Unlink();
    629 
    630   inline Heap* heap() { return heap_; }
    631 
    632   static const int kFlagsOffset = kPointerSize;
    633 
    634   bool IsEvacuationCandidate() { return IsFlagSet(EVACUATION_CANDIDATE); }
    635 
    636   bool ShouldSkipEvacuationSlotRecording() {
    637     return (flags_ & kSkipEvacuationSlotsRecordingMask) != 0;
    638   }
    639 
    640   inline SkipList* skip_list() {
    641     return skip_list_;
    642   }
    643 
    644   inline void set_skip_list(SkipList* skip_list) {
    645     skip_list_ = skip_list;
    646   }
    647 
    648   inline SlotsBuffer* slots_buffer() {
    649     return slots_buffer_;
    650   }
    651 
    652   inline SlotsBuffer** slots_buffer_address() {
    653     return &slots_buffer_;
    654   }
    655 
    656   void MarkEvacuationCandidate() {
    657     ASSERT(slots_buffer_ == NULL);
    658     SetFlag(EVACUATION_CANDIDATE);
    659   }
    660 
    661   void ClearEvacuationCandidate() {
    662     ASSERT(slots_buffer_ == NULL);
    663     ClearFlag(EVACUATION_CANDIDATE);
    664   }
    665 
    666   Address area_start() { return area_start_; }
    667   Address area_end() { return area_end_; }
    668   int area_size() {
    669     return static_cast<int>(area_end() - area_start());
    670   }
    671   bool CommitArea(size_t requested);
    672 
    673   // Approximate amount of physical memory committed for this chunk.
    674   size_t CommittedPhysicalMemory() {
    675     return high_water_mark_;
    676   }
    677 
    678   static inline void UpdateHighWaterMark(Address mark);
    679 
    680  protected:
    681   size_t size_;
    682   intptr_t flags_;
    683 
    684   // Start and end of allocatable memory on this chunk.
    685   Address area_start_;
    686   Address area_end_;
    687 
    688   // If the chunk needs to remember its memory reservation, it is stored here.
    689   VirtualMemory reservation_;
    690   // The identity of the owning space.  This is tagged as a failure pointer, but
    691   // no failure can be in an object, so this can be distinguished from any entry
    692   // in a fixed array.
    693   Address owner_;
    694   Heap* heap_;
    695   // Used by the store buffer to keep track of which pages to mark scan-on-
    696   // scavenge.
    697   int store_buffer_counter_;
    698   // Count of bytes marked black on page.
    699   int live_byte_count_;
    700   SlotsBuffer* slots_buffer_;
    701   SkipList* skip_list_;
    702   intptr_t write_barrier_counter_;
    703   // Used by the incremental marker to keep track of the scanning progress in
    704   // large objects that have a progress bar and are scanned in increments.
    705   int progress_bar_;
    706   // Assuming the initial allocation on a page is sequential,
    707   // count highest number of bytes ever allocated on the page.
    708   int high_water_mark_;
    709 
    710   base::AtomicWord parallel_sweeping_;
    711 
    712   // PagedSpace free-list statistics.
    713   intptr_t available_in_small_free_list_;
    714   intptr_t available_in_medium_free_list_;
    715   intptr_t available_in_large_free_list_;
    716   intptr_t available_in_huge_free_list_;
    717   intptr_t non_available_small_blocks_;
    718 
    719   static MemoryChunk* Initialize(Heap* heap,
    720                                  Address base,
    721                                  size_t size,
    722                                  Address area_start,
    723                                  Address area_end,
    724                                  Executability executable,
    725                                  Space* owner);
    726 
    727  private:
    728   // next_chunk_ holds a pointer of type MemoryChunk
    729   base::AtomicWord next_chunk_;
    730   // prev_chunk_ holds a pointer of type MemoryChunk
    731   base::AtomicWord prev_chunk_;
    732 
    733   friend class MemoryAllocator;
    734 };
    735 
    736 
    737 STATIC_ASSERT(sizeof(MemoryChunk) <= MemoryChunk::kHeaderSize);
    738 
    739 
    740 // -----------------------------------------------------------------------------
    741 // A page is a memory chunk of a size 1MB. Large object pages may be larger.
    742 //
    743 // The only way to get a page pointer is by calling factory methods:
    744 //   Page* p = Page::FromAddress(addr); or
    745 //   Page* p = Page::FromAllocationTop(top);
    746 class Page : public MemoryChunk {
    747  public:
    748   // Returns the page containing a given address. The address ranges
    749   // from [page_addr .. page_addr + kPageSize[
    750   // This only works if the object is in fact in a page.  See also MemoryChunk::
    751   // FromAddress() and FromAnyAddress().
    752   INLINE(static Page* FromAddress(Address a)) {
    753     return reinterpret_cast<Page*>(OffsetFrom(a) & ~kPageAlignmentMask);
    754   }
    755 
    756   // Returns the page containing an allocation top. Because an allocation
    757   // top address can be the upper bound of the page, we need to subtract
    758   // it with kPointerSize first. The address ranges from
    759   // [page_addr + kObjectStartOffset .. page_addr + kPageSize].
    760   INLINE(static Page* FromAllocationTop(Address top)) {
    761     Page* p = FromAddress(top - kPointerSize);
    762     return p;
    763   }
    764 
    765   // Returns the next page in the chain of pages owned by a space.
    766   inline Page* next_page();
    767   inline Page* prev_page();
    768   inline void set_next_page(Page* page);
    769   inline void set_prev_page(Page* page);
    770 
    771   // Checks whether an address is page aligned.
    772   static bool IsAlignedToPageSize(Address a) {
    773     return 0 == (OffsetFrom(a) & kPageAlignmentMask);
    774   }
    775 
    776   // Returns the offset of a given address to this page.
    777   INLINE(int Offset(Address a)) {
    778     int offset = static_cast<int>(a - address());
    779     return offset;
    780   }
    781 
    782   // Returns the address for a given offset to the this page.
    783   Address OffsetToAddress(int offset) {
    784     ASSERT_PAGE_OFFSET(offset);
    785     return address() + offset;
    786   }
    787 
    788   // ---------------------------------------------------------------------
    789 
    790   // Page size in bytes.  This must be a multiple of the OS page size.
    791   static const int kPageSize = 1 << kPageSizeBits;
    792 
    793   // Maximum object size that fits in a page. Objects larger than that size
    794   // are allocated in large object space and are never moved in memory. This
    795   // also applies to new space allocation, since objects are never migrated
    796   // from new space to large object space.  Takes double alignment into account.
    797   static const int kMaxRegularHeapObjectSize = kPageSize - kObjectStartOffset;
    798 
    799   // Page size mask.
    800   static const intptr_t kPageAlignmentMask = (1 << kPageSizeBits) - 1;
    801 
    802   inline void ClearGCFields();
    803 
    804   static inline Page* Initialize(Heap* heap,
    805                                  MemoryChunk* chunk,
    806                                  Executability executable,
    807                                  PagedSpace* owner);
    808 
    809   void InitializeAsAnchor(PagedSpace* owner);
    810 
    811   bool WasSweptPrecisely() { return IsFlagSet(WAS_SWEPT_PRECISELY); }
    812   bool WasSweptConservatively() { return IsFlagSet(WAS_SWEPT_CONSERVATIVELY); }
    813   bool WasSwept() { return WasSweptPrecisely() || WasSweptConservatively(); }
    814 
    815   void MarkSweptPrecisely() { SetFlag(WAS_SWEPT_PRECISELY); }
    816   void MarkSweptConservatively() { SetFlag(WAS_SWEPT_CONSERVATIVELY); }
    817 
    818   void ClearSweptPrecisely() { ClearFlag(WAS_SWEPT_PRECISELY); }
    819   void ClearSweptConservatively() { ClearFlag(WAS_SWEPT_CONSERVATIVELY); }
    820 
    821   void ResetFreeListStatistics();
    822 
    823 #define FRAGMENTATION_STATS_ACCESSORS(type, name) \
    824   type name() { return name##_; }                 \
    825   void set_##name(type name) { name##_ = name; }  \
    826   void add_##name(type name) { name##_ += name; }
    827 
    828   FRAGMENTATION_STATS_ACCESSORS(intptr_t, non_available_small_blocks)
    829   FRAGMENTATION_STATS_ACCESSORS(intptr_t, available_in_small_free_list)
    830   FRAGMENTATION_STATS_ACCESSORS(intptr_t, available_in_medium_free_list)
    831   FRAGMENTATION_STATS_ACCESSORS(intptr_t, available_in_large_free_list)
    832   FRAGMENTATION_STATS_ACCESSORS(intptr_t, available_in_huge_free_list)
    833 
    834 #undef FRAGMENTATION_STATS_ACCESSORS
    835 
    836 #ifdef DEBUG
    837   void Print();
    838 #endif  // DEBUG
    839 
    840   friend class MemoryAllocator;
    841 };
    842 
    843 
    844 STATIC_ASSERT(sizeof(Page) <= MemoryChunk::kHeaderSize);
    845 
    846 
    847 class LargePage : public MemoryChunk {
    848  public:
    849   HeapObject* GetObject() {
    850     return HeapObject::FromAddress(area_start());
    851   }
    852 
    853   inline LargePage* next_page() const {
    854     return static_cast<LargePage*>(next_chunk());
    855   }
    856 
    857   inline void set_next_page(LargePage* page) {
    858     set_next_chunk(page);
    859   }
    860  private:
    861   static inline LargePage* Initialize(Heap* heap, MemoryChunk* chunk);
    862 
    863   friend class MemoryAllocator;
    864 };
    865 
    866 STATIC_ASSERT(sizeof(LargePage) <= MemoryChunk::kHeaderSize);
    867 
    868 // ----------------------------------------------------------------------------
    869 // Space is the abstract superclass for all allocation spaces.
    870 class Space : public Malloced {
    871  public:
    872   Space(Heap* heap, AllocationSpace id, Executability executable)
    873       : heap_(heap), id_(id), executable_(executable) {}
    874 
    875   virtual ~Space() {}
    876 
    877   Heap* heap() const { return heap_; }
    878 
    879   // Does the space need executable memory?
    880   Executability executable() { return executable_; }
    881 
    882   // Identity used in error reporting.
    883   AllocationSpace identity() { return id_; }
    884 
    885   // Returns allocated size.
    886   virtual intptr_t Size() = 0;
    887 
    888   // Returns size of objects. Can differ from the allocated size
    889   // (e.g. see LargeObjectSpace).
    890   virtual intptr_t SizeOfObjects() { return Size(); }
    891 
    892   virtual int RoundSizeDownToObjectAlignment(int size) {
    893     if (id_ == CODE_SPACE) {
    894       return RoundDown(size, kCodeAlignment);
    895     } else {
    896       return RoundDown(size, kPointerSize);
    897     }
    898   }
    899 
    900 #ifdef DEBUG
    901   virtual void Print() = 0;
    902 #endif
    903 
    904  private:
    905   Heap* heap_;
    906   AllocationSpace id_;
    907   Executability executable_;
    908 };
    909 
    910 
    911 // ----------------------------------------------------------------------------
    912 // All heap objects containing executable code (code objects) must be allocated
    913 // from a 2 GB range of memory, so that they can call each other using 32-bit
    914 // displacements.  This happens automatically on 32-bit platforms, where 32-bit
    915 // displacements cover the entire 4GB virtual address space.  On 64-bit
    916 // platforms, we support this using the CodeRange object, which reserves and
    917 // manages a range of virtual memory.
    918 class CodeRange {
    919  public:
    920   explicit CodeRange(Isolate* isolate);
    921   ~CodeRange() { TearDown(); }
    922 
    923   // Reserves a range of virtual memory, but does not commit any of it.
    924   // Can only be called once, at heap initialization time.
    925   // Returns false on failure.
    926   bool SetUp(size_t requested_size);
    927 
    928   // Frees the range of virtual memory, and frees the data structures used to
    929   // manage it.
    930   void TearDown();
    931 
    932   bool valid() { return code_range_ != NULL; }
    933   Address start() {
    934     ASSERT(valid());
    935     return static_cast<Address>(code_range_->address());
    936   }
    937   bool contains(Address address) {
    938     if (!valid()) return false;
    939     Address start = static_cast<Address>(code_range_->address());
    940     return start <= address && address < start + code_range_->size();
    941   }
    942 
    943   // Allocates a chunk of memory from the large-object portion of
    944   // the code range.  On platforms with no separate code range, should
    945   // not be called.
    946   MUST_USE_RESULT Address AllocateRawMemory(const size_t requested_size,
    947                                             const size_t commit_size,
    948                                             size_t* allocated);
    949   bool CommitRawMemory(Address start, size_t length);
    950   bool UncommitRawMemory(Address start, size_t length);
    951   void FreeRawMemory(Address buf, size_t length);
    952 
    953  private:
    954   Isolate* isolate_;
    955 
    956   // The reserved range of virtual memory that all code objects are put in.
    957   VirtualMemory* code_range_;
    958   // Plain old data class, just a struct plus a constructor.
    959   class FreeBlock {
    960    public:
    961     FreeBlock(Address start_arg, size_t size_arg)
    962         : start(start_arg), size(size_arg) {
    963       ASSERT(IsAddressAligned(start, MemoryChunk::kAlignment));
    964       ASSERT(size >= static_cast<size_t>(Page::kPageSize));
    965     }
    966     FreeBlock(void* start_arg, size_t size_arg)
    967         : start(static_cast<Address>(start_arg)), size(size_arg) {
    968       ASSERT(IsAddressAligned(start, MemoryChunk::kAlignment));
    969       ASSERT(size >= static_cast<size_t>(Page::kPageSize));
    970     }
    971 
    972     Address start;
    973     size_t size;
    974   };
    975 
    976   // Freed blocks of memory are added to the free list.  When the allocation
    977   // list is exhausted, the free list is sorted and merged to make the new
    978   // allocation list.
    979   List<FreeBlock> free_list_;
    980   // Memory is allocated from the free blocks on the allocation list.
    981   // The block at current_allocation_block_index_ is the current block.
    982   List<FreeBlock> allocation_list_;
    983   int current_allocation_block_index_;
    984 
    985   // Finds a block on the allocation list that contains at least the
    986   // requested amount of memory.  If none is found, sorts and merges
    987   // the existing free memory blocks, and searches again.
    988   // If none can be found, returns false.
    989   bool GetNextAllocationBlock(size_t requested);
    990   // Compares the start addresses of two free blocks.
    991   static int CompareFreeBlockAddress(const FreeBlock* left,
    992                                      const FreeBlock* right);
    993 
    994   DISALLOW_COPY_AND_ASSIGN(CodeRange);
    995 };
    996 
    997 
    998 class SkipList {
    999  public:
   1000   SkipList() {
   1001     Clear();
   1002   }
   1003 
   1004   void Clear() {
   1005     for (int idx = 0; idx < kSize; idx++) {
   1006       starts_[idx] = reinterpret_cast<Address>(-1);
   1007     }
   1008   }
   1009 
   1010   Address StartFor(Address addr) {
   1011     return starts_[RegionNumber(addr)];
   1012   }
   1013 
   1014   void AddObject(Address addr, int size) {
   1015     int start_region = RegionNumber(addr);
   1016     int end_region = RegionNumber(addr + size - kPointerSize);
   1017     for (int idx = start_region; idx <= end_region; idx++) {
   1018       if (starts_[idx] > addr) starts_[idx] = addr;
   1019     }
   1020   }
   1021 
   1022   static inline int RegionNumber(Address addr) {
   1023     return (OffsetFrom(addr) & Page::kPageAlignmentMask) >> kRegionSizeLog2;
   1024   }
   1025 
   1026   static void Update(Address addr, int size) {
   1027     Page* page = Page::FromAddress(addr);
   1028     SkipList* list = page->skip_list();
   1029     if (list == NULL) {
   1030       list = new SkipList();
   1031       page->set_skip_list(list);
   1032     }
   1033 
   1034     list->AddObject(addr, size);
   1035   }
   1036 
   1037  private:
   1038   static const int kRegionSizeLog2 = 13;
   1039   static const int kRegionSize = 1 << kRegionSizeLog2;
   1040   static const int kSize = Page::kPageSize / kRegionSize;
   1041 
   1042   STATIC_ASSERT(Page::kPageSize % kRegionSize == 0);
   1043 
   1044   Address starts_[kSize];
   1045 };
   1046 
   1047 
   1048 // ----------------------------------------------------------------------------
   1049 // A space acquires chunks of memory from the operating system. The memory
   1050 // allocator allocated and deallocates pages for the paged heap spaces and large
   1051 // pages for large object space.
   1052 //
   1053 // Each space has to manage it's own pages.
   1054 //
   1055 class MemoryAllocator {
   1056  public:
   1057   explicit MemoryAllocator(Isolate* isolate);
   1058 
   1059   // Initializes its internal bookkeeping structures.
   1060   // Max capacity of the total space and executable memory limit.
   1061   bool SetUp(intptr_t max_capacity, intptr_t capacity_executable);
   1062 
   1063   void TearDown();
   1064 
   1065   Page* AllocatePage(
   1066       intptr_t size, PagedSpace* owner, Executability executable);
   1067 
   1068   LargePage* AllocateLargePage(
   1069       intptr_t object_size, Space* owner, Executability executable);
   1070 
   1071   void Free(MemoryChunk* chunk);
   1072 
   1073   // Returns the maximum available bytes of heaps.
   1074   intptr_t Available() { return capacity_ < size_ ? 0 : capacity_ - size_; }
   1075 
   1076   // Returns allocated spaces in bytes.
   1077   intptr_t Size() { return size_; }
   1078 
   1079   // Returns the maximum available executable bytes of heaps.
   1080   intptr_t AvailableExecutable() {
   1081     if (capacity_executable_ < size_executable_) return 0;
   1082     return capacity_executable_ - size_executable_;
   1083   }
   1084 
   1085   // Returns allocated executable spaces in bytes.
   1086   intptr_t SizeExecutable() { return size_executable_; }
   1087 
   1088   // Returns maximum available bytes that the old space can have.
   1089   intptr_t MaxAvailable() {
   1090     return (Available() / Page::kPageSize) * Page::kMaxRegularHeapObjectSize;
   1091   }
   1092 
   1093   // Returns an indication of whether a pointer is in a space that has
   1094   // been allocated by this MemoryAllocator.
   1095   V8_INLINE bool IsOutsideAllocatedSpace(const void* address) const {
   1096     return address < lowest_ever_allocated_ ||
   1097         address >= highest_ever_allocated_;
   1098   }
   1099 
   1100 #ifdef DEBUG
   1101   // Reports statistic info of the space.
   1102   void ReportStatistics();
   1103 #endif
   1104 
   1105   // Returns a MemoryChunk in which the memory region from commit_area_size to
   1106   // reserve_area_size of the chunk area is reserved but not committed, it
   1107   // could be committed later by calling MemoryChunk::CommitArea.
   1108   MemoryChunk* AllocateChunk(intptr_t reserve_area_size,
   1109                              intptr_t commit_area_size,
   1110                              Executability executable,
   1111                              Space* space);
   1112 
   1113   Address ReserveAlignedMemory(size_t requested,
   1114                                size_t alignment,
   1115                                VirtualMemory* controller);
   1116   Address AllocateAlignedMemory(size_t reserve_size,
   1117                                 size_t commit_size,
   1118                                 size_t alignment,
   1119                                 Executability executable,
   1120                                 VirtualMemory* controller);
   1121 
   1122   bool CommitMemory(Address addr, size_t size, Executability executable);
   1123 
   1124   void FreeMemory(VirtualMemory* reservation, Executability executable);
   1125   void FreeMemory(Address addr, size_t size, Executability executable);
   1126 
   1127   // Commit a contiguous block of memory from the initial chunk.  Assumes that
   1128   // the address is not NULL, the size is greater than zero, and that the
   1129   // block is contained in the initial chunk.  Returns true if it succeeded
   1130   // and false otherwise.
   1131   bool CommitBlock(Address start, size_t size, Executability executable);
   1132 
   1133   // Uncommit a contiguous block of memory [start..(start+size)[.
   1134   // start is not NULL, the size is greater than zero, and the
   1135   // block is contained in the initial chunk.  Returns true if it succeeded
   1136   // and false otherwise.
   1137   bool UncommitBlock(Address start, size_t size);
   1138 
   1139   // Zaps a contiguous block of memory [start..(start+size)[ thus
   1140   // filling it up with a recognizable non-NULL bit pattern.
   1141   void ZapBlock(Address start, size_t size);
   1142 
   1143   void PerformAllocationCallback(ObjectSpace space,
   1144                                  AllocationAction action,
   1145                                  size_t size);
   1146 
   1147   void AddMemoryAllocationCallback(MemoryAllocationCallback callback,
   1148                                           ObjectSpace space,
   1149                                           AllocationAction action);
   1150 
   1151   void RemoveMemoryAllocationCallback(
   1152       MemoryAllocationCallback callback);
   1153 
   1154   bool MemoryAllocationCallbackRegistered(
   1155       MemoryAllocationCallback callback);
   1156 
   1157   static int CodePageGuardStartOffset();
   1158 
   1159   static int CodePageGuardSize();
   1160 
   1161   static int CodePageAreaStartOffset();
   1162 
   1163   static int CodePageAreaEndOffset();
   1164 
   1165   static int CodePageAreaSize() {
   1166     return CodePageAreaEndOffset() - CodePageAreaStartOffset();
   1167   }
   1168 
   1169   MUST_USE_RESULT bool CommitExecutableMemory(VirtualMemory* vm,
   1170                                               Address start,
   1171                                               size_t commit_size,
   1172                                               size_t reserved_size);
   1173 
   1174  private:
   1175   Isolate* isolate_;
   1176 
   1177   // Maximum space size in bytes.
   1178   size_t capacity_;
   1179   // Maximum subset of capacity_ that can be executable
   1180   size_t capacity_executable_;
   1181 
   1182   // Allocated space size in bytes.
   1183   size_t size_;
   1184   // Allocated executable space size in bytes.
   1185   size_t size_executable_;
   1186 
   1187   // We keep the lowest and highest addresses allocated as a quick way
   1188   // of determining that pointers are outside the heap. The estimate is
   1189   // conservative, i.e. not all addrsses in 'allocated' space are allocated
   1190   // to our heap. The range is [lowest, highest[, inclusive on the low end
   1191   // and exclusive on the high end.
   1192   void* lowest_ever_allocated_;
   1193   void* highest_ever_allocated_;
   1194 
   1195   struct MemoryAllocationCallbackRegistration {
   1196     MemoryAllocationCallbackRegistration(MemoryAllocationCallback callback,
   1197                                          ObjectSpace space,
   1198                                          AllocationAction action)
   1199         : callback(callback), space(space), action(action) {
   1200     }
   1201     MemoryAllocationCallback callback;
   1202     ObjectSpace space;
   1203     AllocationAction action;
   1204   };
   1205 
   1206   // A List of callback that are triggered when memory is allocated or free'd
   1207   List<MemoryAllocationCallbackRegistration>
   1208       memory_allocation_callbacks_;
   1209 
   1210   // Initializes pages in a chunk. Returns the first page address.
   1211   // This function and GetChunkId() are provided for the mark-compact
   1212   // collector to rebuild page headers in the from space, which is
   1213   // used as a marking stack and its page headers are destroyed.
   1214   Page* InitializePagesInChunk(int chunk_id, int pages_in_chunk,
   1215                                PagedSpace* owner);
   1216 
   1217   void UpdateAllocatedSpaceLimits(void* low, void* high) {
   1218     lowest_ever_allocated_ = Min(lowest_ever_allocated_, low);
   1219     highest_ever_allocated_ = Max(highest_ever_allocated_, high);
   1220   }
   1221 
   1222   DISALLOW_IMPLICIT_CONSTRUCTORS(MemoryAllocator);
   1223 };
   1224 
   1225 
   1226 // -----------------------------------------------------------------------------
   1227 // Interface for heap object iterator to be implemented by all object space
   1228 // object iterators.
   1229 //
   1230 // NOTE: The space specific object iterators also implements the own next()
   1231 //       method which is used to avoid using virtual functions
   1232 //       iterating a specific space.
   1233 
   1234 class ObjectIterator : public Malloced {
   1235  public:
   1236   virtual ~ObjectIterator() { }
   1237 
   1238   virtual HeapObject* next_object() = 0;
   1239 };
   1240 
   1241 
   1242 // -----------------------------------------------------------------------------
   1243 // Heap object iterator in new/old/map spaces.
   1244 //
   1245 // A HeapObjectIterator iterates objects from the bottom of the given space
   1246 // to its top or from the bottom of the given page to its top.
   1247 //
   1248 // If objects are allocated in the page during iteration the iterator may
   1249 // or may not iterate over those objects.  The caller must create a new
   1250 // iterator in order to be sure to visit these new objects.
   1251 class HeapObjectIterator: public ObjectIterator {
   1252  public:
   1253   // Creates a new object iterator in a given space.
   1254   // If the size function is not given, the iterator calls the default
   1255   // Object::Size().
   1256   explicit HeapObjectIterator(PagedSpace* space);
   1257   HeapObjectIterator(PagedSpace* space, HeapObjectCallback size_func);
   1258   HeapObjectIterator(Page* page, HeapObjectCallback size_func);
   1259 
   1260   // Advance to the next object, skipping free spaces and other fillers and
   1261   // skipping the special garbage section of which there is one per space.
   1262   // Returns NULL when the iteration has ended.
   1263   inline HeapObject* Next() {
   1264     do {
   1265       HeapObject* next_obj = FromCurrentPage();
   1266       if (next_obj != NULL) return next_obj;
   1267     } while (AdvanceToNextPage());
   1268     return NULL;
   1269   }
   1270 
   1271   virtual HeapObject* next_object() {
   1272     return Next();
   1273   }
   1274 
   1275  private:
   1276   enum PageMode { kOnePageOnly, kAllPagesInSpace };
   1277 
   1278   Address cur_addr_;  // Current iteration point.
   1279   Address cur_end_;   // End iteration point.
   1280   HeapObjectCallback size_func_;  // Size function or NULL.
   1281   PagedSpace* space_;
   1282   PageMode page_mode_;
   1283 
   1284   // Fast (inlined) path of next().
   1285   inline HeapObject* FromCurrentPage();
   1286 
   1287   // Slow path of next(), goes into the next page.  Returns false if the
   1288   // iteration has ended.
   1289   bool AdvanceToNextPage();
   1290 
   1291   // Initializes fields.
   1292   inline void Initialize(PagedSpace* owner,
   1293                          Address start,
   1294                          Address end,
   1295                          PageMode mode,
   1296                          HeapObjectCallback size_func);
   1297 };
   1298 
   1299 
   1300 // -----------------------------------------------------------------------------
   1301 // A PageIterator iterates the pages in a paged space.
   1302 
   1303 class PageIterator BASE_EMBEDDED {
   1304  public:
   1305   explicit inline PageIterator(PagedSpace* space);
   1306 
   1307   inline bool has_next();
   1308   inline Page* next();
   1309 
   1310  private:
   1311   PagedSpace* space_;
   1312   Page* prev_page_;  // Previous page returned.
   1313   // Next page that will be returned.  Cached here so that we can use this
   1314   // iterator for operations that deallocate pages.
   1315   Page* next_page_;
   1316 };
   1317 
   1318 
   1319 // -----------------------------------------------------------------------------
   1320 // A space has a circular list of pages. The next page can be accessed via
   1321 // Page::next_page() call.
   1322 
   1323 // An abstraction of allocation and relocation pointers in a page-structured
   1324 // space.
   1325 class AllocationInfo {
   1326  public:
   1327   AllocationInfo() : top_(NULL), limit_(NULL) {
   1328   }
   1329 
   1330   INLINE(void set_top(Address top)) {
   1331     SLOW_ASSERT(top == NULL ||
   1332         (reinterpret_cast<intptr_t>(top) & HeapObjectTagMask()) == 0);
   1333     top_ = top;
   1334   }
   1335 
   1336   INLINE(Address top()) const {
   1337     SLOW_ASSERT(top_ == NULL ||
   1338         (reinterpret_cast<intptr_t>(top_) & HeapObjectTagMask()) == 0);
   1339     return top_;
   1340   }
   1341 
   1342   Address* top_address() {
   1343     return &top_;
   1344   }
   1345 
   1346   INLINE(void set_limit(Address limit)) {
   1347     SLOW_ASSERT(limit == NULL ||
   1348         (reinterpret_cast<intptr_t>(limit) & HeapObjectTagMask()) == 0);
   1349     limit_ = limit;
   1350   }
   1351 
   1352   INLINE(Address limit()) const {
   1353     SLOW_ASSERT(limit_ == NULL ||
   1354         (reinterpret_cast<intptr_t>(limit_) & HeapObjectTagMask()) == 0);
   1355     return limit_;
   1356   }
   1357 
   1358   Address* limit_address() {
   1359     return &limit_;
   1360   }
   1361 
   1362 #ifdef DEBUG
   1363   bool VerifyPagedAllocation() {
   1364     return (Page::FromAllocationTop(top_) == Page::FromAllocationTop(limit_))
   1365         && (top_ <= limit_);
   1366   }
   1367 #endif
   1368 
   1369  private:
   1370   // Current allocation top.
   1371   Address top_;
   1372   // Current allocation limit.
   1373   Address limit_;
   1374 };
   1375 
   1376 
   1377 // An abstraction of the accounting statistics of a page-structured space.
   1378 // The 'capacity' of a space is the number of object-area bytes (i.e., not
   1379 // including page bookkeeping structures) currently in the space. The 'size'
   1380 // of a space is the number of allocated bytes, the 'waste' in the space is
   1381 // the number of bytes that are not allocated and not available to
   1382 // allocation without reorganizing the space via a GC (e.g. small blocks due
   1383 // to internal fragmentation, top of page areas in map space), and the bytes
   1384 // 'available' is the number of unallocated bytes that are not waste.  The
   1385 // capacity is the sum of size, waste, and available.
   1386 //
   1387 // The stats are only set by functions that ensure they stay balanced. These
   1388 // functions increase or decrease one of the non-capacity stats in
   1389 // conjunction with capacity, or else they always balance increases and
   1390 // decreases to the non-capacity stats.
   1391 class AllocationStats BASE_EMBEDDED {
   1392  public:
   1393   AllocationStats() { Clear(); }
   1394 
   1395   // Zero out all the allocation statistics (i.e., no capacity).
   1396   void Clear() {
   1397     capacity_ = 0;
   1398     max_capacity_ = 0;
   1399     size_ = 0;
   1400     waste_ = 0;
   1401   }
   1402 
   1403   void ClearSizeWaste() {
   1404     size_ = capacity_;
   1405     waste_ = 0;
   1406   }
   1407 
   1408   // Reset the allocation statistics (i.e., available = capacity with no
   1409   // wasted or allocated bytes).
   1410   void Reset() {
   1411     size_ = 0;
   1412     waste_ = 0;
   1413   }
   1414 
   1415   // Accessors for the allocation statistics.
   1416   intptr_t Capacity() { return capacity_; }
   1417   intptr_t MaxCapacity() { return max_capacity_; }
   1418   intptr_t Size() { return size_; }
   1419   intptr_t Waste() { return waste_; }
   1420 
   1421   // Grow the space by adding available bytes.  They are initially marked as
   1422   // being in use (part of the size), but will normally be immediately freed,
   1423   // putting them on the free list and removing them from size_.
   1424   void ExpandSpace(int size_in_bytes) {
   1425     capacity_ += size_in_bytes;
   1426     size_ += size_in_bytes;
   1427     if (capacity_ > max_capacity_) {
   1428       max_capacity_ = capacity_;
   1429     }
   1430     ASSERT(size_ >= 0);
   1431   }
   1432 
   1433   // Shrink the space by removing available bytes.  Since shrinking is done
   1434   // during sweeping, bytes have been marked as being in use (part of the size)
   1435   // and are hereby freed.
   1436   void ShrinkSpace(int size_in_bytes) {
   1437     capacity_ -= size_in_bytes;
   1438     size_ -= size_in_bytes;
   1439     ASSERT(size_ >= 0);
   1440   }
   1441 
   1442   // Allocate from available bytes (available -> size).
   1443   void AllocateBytes(intptr_t size_in_bytes) {
   1444     size_ += size_in_bytes;
   1445     ASSERT(size_ >= 0);
   1446   }
   1447 
   1448   // Free allocated bytes, making them available (size -> available).
   1449   void DeallocateBytes(intptr_t size_in_bytes) {
   1450     size_ -= size_in_bytes;
   1451     ASSERT(size_ >= 0);
   1452   }
   1453 
   1454   // Waste free bytes (available -> waste).
   1455   void WasteBytes(int size_in_bytes) {
   1456     size_ -= size_in_bytes;
   1457     waste_ += size_in_bytes;
   1458     ASSERT(size_ >= 0);
   1459   }
   1460 
   1461  private:
   1462   intptr_t capacity_;
   1463   intptr_t max_capacity_;
   1464   intptr_t size_;
   1465   intptr_t waste_;
   1466 };
   1467 
   1468 
   1469 // -----------------------------------------------------------------------------
   1470 // Free lists for old object spaces
   1471 //
   1472 // Free-list nodes are free blocks in the heap.  They look like heap objects
   1473 // (free-list node pointers have the heap object tag, and they have a map like
   1474 // a heap object).  They have a size and a next pointer.  The next pointer is
   1475 // the raw address of the next free list node (or NULL).
   1476 class FreeListNode: public HeapObject {
   1477  public:
   1478   // Obtain a free-list node from a raw address.  This is not a cast because
   1479   // it does not check nor require that the first word at the address is a map
   1480   // pointer.
   1481   static FreeListNode* FromAddress(Address address) {
   1482     return reinterpret_cast<FreeListNode*>(HeapObject::FromAddress(address));
   1483   }
   1484 
   1485   static inline bool IsFreeListNode(HeapObject* object);
   1486 
   1487   // Set the size in bytes, which can be read with HeapObject::Size().  This
   1488   // function also writes a map to the first word of the block so that it
   1489   // looks like a heap object to the garbage collector and heap iteration
   1490   // functions.
   1491   void set_size(Heap* heap, int size_in_bytes);
   1492 
   1493   // Accessors for the next field.
   1494   inline FreeListNode* next();
   1495   inline FreeListNode** next_address();
   1496   inline void set_next(FreeListNode* next);
   1497 
   1498   inline void Zap();
   1499 
   1500   static inline FreeListNode* cast(Object* object) {
   1501     return reinterpret_cast<FreeListNode*>(object);
   1502   }
   1503 
   1504  private:
   1505   static const int kNextOffset = POINTER_SIZE_ALIGN(FreeSpace::kHeaderSize);
   1506 
   1507   DISALLOW_IMPLICIT_CONSTRUCTORS(FreeListNode);
   1508 };
   1509 
   1510 
   1511 // The free list category holds a pointer to the top element and a pointer to
   1512 // the end element of the linked list of free memory blocks.
   1513 class FreeListCategory {
   1514  public:
   1515   FreeListCategory() :
   1516       top_(0),
   1517       end_(NULL),
   1518       available_(0) {}
   1519 
   1520   intptr_t Concatenate(FreeListCategory* category);
   1521 
   1522   void Reset();
   1523 
   1524   void Free(FreeListNode* node, int size_in_bytes);
   1525 
   1526   FreeListNode* PickNodeFromList(int *node_size);
   1527   FreeListNode* PickNodeFromList(int size_in_bytes, int *node_size);
   1528 
   1529   intptr_t EvictFreeListItemsInList(Page* p);
   1530   bool ContainsPageFreeListItemsInList(Page* p);
   1531 
   1532   void RepairFreeList(Heap* heap);
   1533 
   1534   FreeListNode* top() const {
   1535     return reinterpret_cast<FreeListNode*>(base::NoBarrier_Load(&top_));
   1536   }
   1537 
   1538   void set_top(FreeListNode* top) {
   1539     base::NoBarrier_Store(&top_, reinterpret_cast<base::AtomicWord>(top));
   1540   }
   1541 
   1542   FreeListNode** GetEndAddress() { return &end_; }
   1543   FreeListNode* end() const { return end_; }
   1544   void set_end(FreeListNode* end) { end_ = end; }
   1545 
   1546   int* GetAvailableAddress() { return &available_; }
   1547   int available() const { return available_; }
   1548   void set_available(int available) { available_ = available; }
   1549 
   1550   Mutex* mutex() { return &mutex_; }
   1551 
   1552   bool IsEmpty() {
   1553     return top() == 0;
   1554   }
   1555 
   1556 #ifdef DEBUG
   1557   intptr_t SumFreeList();
   1558   int FreeListLength();
   1559 #endif
   1560 
   1561  private:
   1562   // top_ points to the top FreeListNode* in the free list category.
   1563   base::AtomicWord top_;
   1564   FreeListNode* end_;
   1565   Mutex mutex_;
   1566 
   1567   // Total available bytes in all blocks of this free list category.
   1568   int available_;
   1569 };
   1570 
   1571 
   1572 // The free list for the old space.  The free list is organized in such a way
   1573 // as to encourage objects allocated around the same time to be near each
   1574 // other.  The normal way to allocate is intended to be by bumping a 'top'
   1575 // pointer until it hits a 'limit' pointer.  When the limit is hit we need to
   1576 // find a new space to allocate from.  This is done with the free list, which
   1577 // is divided up into rough categories to cut down on waste.  Having finer
   1578 // categories would scatter allocation more.
   1579 
   1580 // The old space free list is organized in categories.
   1581 // 1-31 words:  Such small free areas are discarded for efficiency reasons.
   1582 //     They can be reclaimed by the compactor.  However the distance between top
   1583 //     and limit may be this small.
   1584 // 32-255 words: There is a list of spaces this large.  It is used for top and
   1585 //     limit when the object we need to allocate is 1-31 words in size.  These
   1586 //     spaces are called small.
   1587 // 256-2047 words: There is a list of spaces this large.  It is used for top and
   1588 //     limit when the object we need to allocate is 32-255 words in size.  These
   1589 //     spaces are called medium.
   1590 // 1048-16383 words: There is a list of spaces this large.  It is used for top
   1591 //     and limit when the object we need to allocate is 256-2047 words in size.
   1592 //     These spaces are call large.
   1593 // At least 16384 words.  This list is for objects of 2048 words or larger.
   1594 //     Empty pages are added to this list.  These spaces are called huge.
   1595 class FreeList {
   1596  public:
   1597   explicit FreeList(PagedSpace* owner);
   1598 
   1599   intptr_t Concatenate(FreeList* free_list);
   1600 
   1601   // Clear the free list.
   1602   void Reset();
   1603 
   1604   // Return the number of bytes available on the free list.
   1605   intptr_t available() {
   1606     return small_list_.available() + medium_list_.available() +
   1607            large_list_.available() + huge_list_.available();
   1608   }
   1609 
   1610   // Place a node on the free list.  The block of size 'size_in_bytes'
   1611   // starting at 'start' is placed on the free list.  The return value is the
   1612   // number of bytes that have been lost due to internal fragmentation by
   1613   // freeing the block.  Bookkeeping information will be written to the block,
   1614   // i.e., its contents will be destroyed.  The start address should be word
   1615   // aligned, and the size should be a non-zero multiple of the word size.
   1616   int Free(Address start, int size_in_bytes);
   1617 
   1618   // Allocate a block of size 'size_in_bytes' from the free list.  The block
   1619   // is unitialized.  A failure is returned if no block is available.  The
   1620   // number of bytes lost to fragmentation is returned in the output parameter
   1621   // 'wasted_bytes'.  The size should be a non-zero multiple of the word size.
   1622   MUST_USE_RESULT HeapObject* Allocate(int size_in_bytes);
   1623 
   1624   bool IsEmpty() {
   1625     return small_list_.IsEmpty() && medium_list_.IsEmpty() &&
   1626            large_list_.IsEmpty() && huge_list_.IsEmpty();
   1627   }
   1628 
   1629 #ifdef DEBUG
   1630   void Zap();
   1631   intptr_t SumFreeLists();
   1632   bool IsVeryLong();
   1633 #endif
   1634 
   1635   // Used after booting the VM.
   1636   void RepairLists(Heap* heap);
   1637 
   1638   intptr_t EvictFreeListItems(Page* p);
   1639   bool ContainsPageFreeListItems(Page* p);
   1640 
   1641   FreeListCategory* small_list() { return &small_list_; }
   1642   FreeListCategory* medium_list() { return &medium_list_; }
   1643   FreeListCategory* large_list() { return &large_list_; }
   1644   FreeListCategory* huge_list() { return &huge_list_; }
   1645 
   1646  private:
   1647   // The size range of blocks, in bytes.
   1648   static const int kMinBlockSize = 3 * kPointerSize;
   1649   static const int kMaxBlockSize = Page::kMaxRegularHeapObjectSize;
   1650 
   1651   FreeListNode* FindNodeFor(int size_in_bytes, int* node_size);
   1652 
   1653   PagedSpace* owner_;
   1654   Heap* heap_;
   1655 
   1656   static const int kSmallListMin = 0x20 * kPointerSize;
   1657   static const int kSmallListMax = 0xff * kPointerSize;
   1658   static const int kMediumListMax = 0x7ff * kPointerSize;
   1659   static const int kLargeListMax = 0x3fff * kPointerSize;
   1660   static const int kSmallAllocationMax = kSmallListMin - kPointerSize;
   1661   static const int kMediumAllocationMax = kSmallListMax;
   1662   static const int kLargeAllocationMax = kMediumListMax;
   1663   FreeListCategory small_list_;
   1664   FreeListCategory medium_list_;
   1665   FreeListCategory large_list_;
   1666   FreeListCategory huge_list_;
   1667 
   1668   DISALLOW_IMPLICIT_CONSTRUCTORS(FreeList);
   1669 };
   1670 
   1671 
   1672 class AllocationResult {
   1673  public:
   1674   // Implicit constructor from Object*.
   1675   AllocationResult(Object* object) : object_(object),  // NOLINT
   1676                                      retry_space_(INVALID_SPACE) { }
   1677 
   1678   AllocationResult() : object_(NULL),
   1679                        retry_space_(INVALID_SPACE) { }
   1680 
   1681   static inline AllocationResult Retry(AllocationSpace space = NEW_SPACE) {
   1682     return AllocationResult(space);
   1683   }
   1684 
   1685   inline bool IsRetry() { return retry_space_ != INVALID_SPACE; }
   1686 
   1687   template <typename T>
   1688   bool To(T** obj) {
   1689     if (IsRetry()) return false;
   1690     *obj = T::cast(object_);
   1691     return true;
   1692   }
   1693 
   1694   Object* ToObjectChecked() {
   1695     CHECK(!IsRetry());
   1696     return object_;
   1697   }
   1698 
   1699   AllocationSpace RetrySpace() {
   1700     ASSERT(IsRetry());
   1701     return retry_space_;
   1702   }
   1703 
   1704  private:
   1705   explicit AllocationResult(AllocationSpace space) : object_(NULL),
   1706                                                      retry_space_(space) { }
   1707 
   1708   Object* object_;
   1709   AllocationSpace retry_space_;
   1710 };
   1711 
   1712 
   1713 class PagedSpace : public Space {
   1714  public:
   1715   // Creates a space with a maximum capacity, and an id.
   1716   PagedSpace(Heap* heap,
   1717              intptr_t max_capacity,
   1718              AllocationSpace id,
   1719              Executability executable);
   1720 
   1721   virtual ~PagedSpace() {}
   1722 
   1723   // Set up the space using the given address range of virtual memory (from
   1724   // the memory allocator's initial chunk) if possible.  If the block of
   1725   // addresses is not big enough to contain a single page-aligned page, a
   1726   // fresh chunk will be allocated.
   1727   bool SetUp();
   1728 
   1729   // Returns true if the space has been successfully set up and not
   1730   // subsequently torn down.
   1731   bool HasBeenSetUp();
   1732 
   1733   // Cleans up the space, frees all pages in this space except those belonging
   1734   // to the initial chunk, uncommits addresses in the initial chunk.
   1735   void TearDown();
   1736 
   1737   // Checks whether an object/address is in this space.
   1738   inline bool Contains(Address a);
   1739   bool Contains(HeapObject* o) { return Contains(o->address()); }
   1740 
   1741   // Given an address occupied by a live object, return that object if it is
   1742   // in this space, or a Smi if it is not.  The implementation iterates over
   1743   // objects in the page containing the address, the cost is linear in the
   1744   // number of objects in the page.  It may be slow.
   1745   Object* FindObject(Address addr);
   1746 
   1747   // During boot the free_space_map is created, and afterwards we may need
   1748   // to write it into the free list nodes that were already created.
   1749   void RepairFreeListsAfterBoot();
   1750 
   1751   // Prepares for a mark-compact GC.
   1752   void PrepareForMarkCompact();
   1753 
   1754   // Current capacity without growing (Size() + Available()).
   1755   intptr_t Capacity() { return accounting_stats_.Capacity(); }
   1756 
   1757   // Total amount of memory committed for this space.  For paged
   1758   // spaces this equals the capacity.
   1759   intptr_t CommittedMemory() { return Capacity(); }
   1760 
   1761   // The maximum amount of memory ever committed for this space.
   1762   intptr_t MaximumCommittedMemory() { return accounting_stats_.MaxCapacity(); }
   1763 
   1764   // Approximate amount of physical memory committed for this space.
   1765   size_t CommittedPhysicalMemory();
   1766 
   1767   struct SizeStats {
   1768     intptr_t Total() {
   1769       return small_size_ + medium_size_ + large_size_ + huge_size_;
   1770     }
   1771 
   1772     intptr_t small_size_;
   1773     intptr_t medium_size_;
   1774     intptr_t large_size_;
   1775     intptr_t huge_size_;
   1776   };
   1777 
   1778   void ObtainFreeListStatistics(Page* p, SizeStats* sizes);
   1779   void ResetFreeListStatistics();
   1780 
   1781   // Sets the capacity, the available space and the wasted space to zero.
   1782   // The stats are rebuilt during sweeping by adding each page to the
   1783   // capacity and the size when it is encountered.  As free spaces are
   1784   // discovered during the sweeping they are subtracted from the size and added
   1785   // to the available and wasted totals.
   1786   void ClearStats() {
   1787     accounting_stats_.ClearSizeWaste();
   1788     ResetFreeListStatistics();
   1789   }
   1790 
   1791   // Increases the number of available bytes of that space.
   1792   void AddToAccountingStats(intptr_t bytes) {
   1793     accounting_stats_.DeallocateBytes(bytes);
   1794   }
   1795 
   1796   // Available bytes without growing.  These are the bytes on the free list.
   1797   // The bytes in the linear allocation area are not included in this total
   1798   // because updating the stats would slow down allocation.  New pages are
   1799   // immediately added to the free list so they show up here.
   1800   intptr_t Available() { return free_list_.available(); }
   1801 
   1802   // Allocated bytes in this space.  Garbage bytes that were not found due to
   1803   // concurrent sweeping are counted as being allocated!  The bytes in the
   1804   // current linear allocation area (between top and limit) are also counted
   1805   // here.
   1806   virtual intptr_t Size() { return accounting_stats_.Size(); }
   1807 
   1808   // As size, but the bytes in lazily swept pages are estimated and the bytes
   1809   // in the current linear allocation area are not included.
   1810   virtual intptr_t SizeOfObjects();
   1811 
   1812   // Wasted bytes in this space.  These are just the bytes that were thrown away
   1813   // due to being too small to use for allocation.  They do not include the
   1814   // free bytes that were not found at all due to lazy sweeping.
   1815   virtual intptr_t Waste() { return accounting_stats_.Waste(); }
   1816 
   1817   // Returns the allocation pointer in this space.
   1818   Address top() { return allocation_info_.top(); }
   1819   Address limit() { return allocation_info_.limit(); }
   1820 
   1821   // The allocation top address.
   1822   Address* allocation_top_address() {
   1823     return allocation_info_.top_address();
   1824   }
   1825 
   1826   // The allocation limit address.
   1827   Address* allocation_limit_address() {
   1828     return allocation_info_.limit_address();
   1829   }
   1830 
   1831   // Allocate the requested number of bytes in the space if possible, return a
   1832   // failure object if not.
   1833   MUST_USE_RESULT inline AllocationResult AllocateRaw(int size_in_bytes);
   1834 
   1835   // Give a block of memory to the space's free list.  It might be added to
   1836   // the free list or accounted as waste.
   1837   // If add_to_freelist is false then just accounting stats are updated and
   1838   // no attempt to add area to free list is made.
   1839   int Free(Address start, int size_in_bytes) {
   1840     int wasted = free_list_.Free(start, size_in_bytes);
   1841     accounting_stats_.DeallocateBytes(size_in_bytes - wasted);
   1842     return size_in_bytes - wasted;
   1843   }
   1844 
   1845   void ResetFreeList() {
   1846     free_list_.Reset();
   1847   }
   1848 
   1849   // Set space allocation info.
   1850   void SetTopAndLimit(Address top, Address limit) {
   1851     ASSERT(top == limit ||
   1852            Page::FromAddress(top) == Page::FromAddress(limit - 1));
   1853     MemoryChunk::UpdateHighWaterMark(allocation_info_.top());
   1854     allocation_info_.set_top(top);
   1855     allocation_info_.set_limit(limit);
   1856   }
   1857 
   1858   // Empty space allocation info, returning unused area to free list.
   1859   void EmptyAllocationInfo() {
   1860     // Mark the old linear allocation area with a free space map so it can be
   1861     // skipped when scanning the heap.
   1862     int old_linear_size = static_cast<int>(limit() - top());
   1863     Free(top(), old_linear_size);
   1864     SetTopAndLimit(NULL, NULL);
   1865   }
   1866 
   1867   void Allocate(int bytes) {
   1868     accounting_stats_.AllocateBytes(bytes);
   1869   }
   1870 
   1871   void IncreaseCapacity(int size);
   1872 
   1873   // Releases an unused page and shrinks the space.
   1874   void ReleasePage(Page* page);
   1875 
   1876   // The dummy page that anchors the linked list of pages.
   1877   Page* anchor() { return &anchor_; }
   1878 
   1879 #ifdef VERIFY_HEAP
   1880   // Verify integrity of this space.
   1881   virtual void Verify(ObjectVisitor* visitor);
   1882 
   1883   // Overridden by subclasses to verify space-specific object
   1884   // properties (e.g., only maps or free-list nodes are in map space).
   1885   virtual void VerifyObject(HeapObject* obj) {}
   1886 #endif
   1887 
   1888 #ifdef DEBUG
   1889   // Print meta info and objects in this space.
   1890   virtual void Print();
   1891 
   1892   // Reports statistics for the space
   1893   void ReportStatistics();
   1894 
   1895   // Report code object related statistics
   1896   void CollectCodeStatistics();
   1897   static void ReportCodeStatistics(Isolate* isolate);
   1898   static void ResetCodeStatistics(Isolate* isolate);
   1899 #endif
   1900 
   1901   bool was_swept_conservatively() { return was_swept_conservatively_; }
   1902   void set_was_swept_conservatively(bool b) { was_swept_conservatively_ = b; }
   1903 
   1904   // Evacuation candidates are swept by evacuator.  Needs to return a valid
   1905   // result before _and_ after evacuation has finished.
   1906   static bool ShouldBeSweptBySweeperThreads(Page* p) {
   1907     return !p->IsEvacuationCandidate() &&
   1908            !p->IsFlagSet(Page::RESCAN_ON_EVACUATION) &&
   1909            !p->WasSweptPrecisely();
   1910   }
   1911 
   1912   void IncrementUnsweptFreeBytes(intptr_t by) {
   1913     unswept_free_bytes_ += by;
   1914   }
   1915 
   1916   void IncreaseUnsweptFreeBytes(Page* p) {
   1917     ASSERT(ShouldBeSweptBySweeperThreads(p));
   1918     unswept_free_bytes_ += (p->area_size() - p->LiveBytes());
   1919   }
   1920 
   1921   void DecrementUnsweptFreeBytes(intptr_t by) {
   1922     unswept_free_bytes_ -= by;
   1923   }
   1924 
   1925   void DecreaseUnsweptFreeBytes(Page* p) {
   1926     ASSERT(ShouldBeSweptBySweeperThreads(p));
   1927     unswept_free_bytes_ -= (p->area_size() - p->LiveBytes());
   1928   }
   1929 
   1930   void ResetUnsweptFreeBytes() {
   1931     unswept_free_bytes_ = 0;
   1932   }
   1933 
   1934   // This function tries to steal size_in_bytes memory from the sweeper threads
   1935   // free-lists. If it does not succeed stealing enough memory, it will wait
   1936   // for the sweeper threads to finish sweeping.
   1937   // It returns true when sweeping is completed and false otherwise.
   1938   bool EnsureSweeperProgress(intptr_t size_in_bytes);
   1939 
   1940   void set_end_of_unswept_pages(Page* page) {
   1941     end_of_unswept_pages_ = page;
   1942   }
   1943 
   1944   Page* end_of_unswept_pages() {
   1945     return end_of_unswept_pages_;
   1946   }
   1947 
   1948   Page* FirstPage() { return anchor_.next_page(); }
   1949   Page* LastPage() { return anchor_.prev_page(); }
   1950 
   1951   void EvictEvacuationCandidatesFromFreeLists();
   1952 
   1953   bool CanExpand();
   1954 
   1955   // Returns the number of total pages in this space.
   1956   int CountTotalPages();
   1957 
   1958   // Return size of allocatable area on a page in this space.
   1959   inline int AreaSize() {
   1960     return area_size_;
   1961   }
   1962 
   1963  protected:
   1964   FreeList* free_list() { return &free_list_; }
   1965 
   1966   int area_size_;
   1967 
   1968   // Maximum capacity of this space.
   1969   intptr_t max_capacity_;
   1970 
   1971   intptr_t SizeOfFirstPage();
   1972 
   1973   // Accounting information for this space.
   1974   AllocationStats accounting_stats_;
   1975 
   1976   // The dummy page that anchors the double linked list of pages.
   1977   Page anchor_;
   1978 
   1979   // The space's free list.
   1980   FreeList free_list_;
   1981 
   1982   // Normal allocation information.
   1983   AllocationInfo allocation_info_;
   1984 
   1985   bool was_swept_conservatively_;
   1986 
   1987   // The number of free bytes which could be reclaimed by advancing the
   1988   // concurrent sweeper threads.  This is only an estimation because concurrent
   1989   // sweeping is done conservatively.
   1990   intptr_t unswept_free_bytes_;
   1991 
   1992   // The sweeper threads iterate over the list of pointer and data space pages
   1993   // and sweep these pages concurrently. They will stop sweeping after the
   1994   // end_of_unswept_pages_ page.
   1995   Page* end_of_unswept_pages_;
   1996 
   1997   // Expands the space by allocating a fixed number of pages. Returns false if
   1998   // it cannot allocate requested number of pages from OS, or if the hard heap
   1999   // size limit has been hit.
   2000   bool Expand();
   2001 
   2002   // Generic fast case allocation function that tries linear allocation at the
   2003   // address denoted by top in allocation_info_.
   2004   inline HeapObject* AllocateLinearly(int size_in_bytes);
   2005 
   2006   MUST_USE_RESULT HeapObject*
   2007       WaitForSweeperThreadsAndRetryAllocation(int size_in_bytes);
   2008 
   2009   // Slow path of AllocateRaw.  This function is space-dependent.
   2010   MUST_USE_RESULT HeapObject* SlowAllocateRaw(int size_in_bytes);
   2011 
   2012   friend class PageIterator;
   2013   friend class MarkCompactCollector;
   2014 };
   2015 
   2016 
   2017 class NumberAndSizeInfo BASE_EMBEDDED {
   2018  public:
   2019   NumberAndSizeInfo() : number_(0), bytes_(0) {}
   2020 
   2021   int number() const { return number_; }
   2022   void increment_number(int num) { number_ += num; }
   2023 
   2024   int bytes() const { return bytes_; }
   2025   void increment_bytes(int size) { bytes_ += size; }
   2026 
   2027   void clear() {
   2028     number_ = 0;
   2029     bytes_ = 0;
   2030   }
   2031 
   2032  private:
   2033   int number_;
   2034   int bytes_;
   2035 };
   2036 
   2037 
   2038 // HistogramInfo class for recording a single "bar" of a histogram.  This
   2039 // class is used for collecting statistics to print to the log file.
   2040 class HistogramInfo: public NumberAndSizeInfo {
   2041  public:
   2042   HistogramInfo() : NumberAndSizeInfo() {}
   2043 
   2044   const char* name() { return name_; }
   2045   void set_name(const char* name) { name_ = name; }
   2046 
   2047  private:
   2048   const char* name_;
   2049 };
   2050 
   2051 
   2052 enum SemiSpaceId {
   2053   kFromSpace = 0,
   2054   kToSpace = 1
   2055 };
   2056 
   2057 
   2058 class SemiSpace;
   2059 
   2060 
   2061 class NewSpacePage : public MemoryChunk {
   2062  public:
   2063   // GC related flags copied from from-space to to-space when
   2064   // flipping semispaces.
   2065   static const intptr_t kCopyOnFlipFlagsMask =
   2066     (1 << MemoryChunk::POINTERS_TO_HERE_ARE_INTERESTING) |
   2067     (1 << MemoryChunk::POINTERS_FROM_HERE_ARE_INTERESTING) |
   2068     (1 << MemoryChunk::SCAN_ON_SCAVENGE);
   2069 
   2070   static const int kAreaSize = Page::kMaxRegularHeapObjectSize;
   2071 
   2072   inline NewSpacePage* next_page() const {
   2073     return static_cast<NewSpacePage*>(next_chunk());
   2074   }
   2075 
   2076   inline void set_next_page(NewSpacePage* page) {
   2077     set_next_chunk(page);
   2078   }
   2079 
   2080   inline NewSpacePage* prev_page() const {
   2081     return static_cast<NewSpacePage*>(prev_chunk());
   2082   }
   2083 
   2084   inline void set_prev_page(NewSpacePage* page) {
   2085     set_prev_chunk(page);
   2086   }
   2087 
   2088   SemiSpace* semi_space() {
   2089     return reinterpret_cast<SemiSpace*>(owner());
   2090   }
   2091 
   2092   bool is_anchor() { return !this->InNewSpace(); }
   2093 
   2094   static bool IsAtStart(Address addr) {
   2095     return (reinterpret_cast<intptr_t>(addr) & Page::kPageAlignmentMask)
   2096         == kObjectStartOffset;
   2097   }
   2098 
   2099   static bool IsAtEnd(Address addr) {
   2100     return (reinterpret_cast<intptr_t>(addr) & Page::kPageAlignmentMask) == 0;
   2101   }
   2102 
   2103   Address address() {
   2104     return reinterpret_cast<Address>(this);
   2105   }
   2106 
   2107   // Finds the NewSpacePage containg the given address.
   2108   static inline NewSpacePage* FromAddress(Address address_in_page) {
   2109     Address page_start =
   2110         reinterpret_cast<Address>(reinterpret_cast<uintptr_t>(address_in_page) &
   2111                                   ~Page::kPageAlignmentMask);
   2112     NewSpacePage* page = reinterpret_cast<NewSpacePage*>(page_start);
   2113     return page;
   2114   }
   2115 
   2116   // Find the page for a limit address. A limit address is either an address
   2117   // inside a page, or the address right after the last byte of a page.
   2118   static inline NewSpacePage* FromLimit(Address address_limit) {
   2119     return NewSpacePage::FromAddress(address_limit - 1);
   2120   }
   2121 
   2122   // Checks if address1 and address2 are on the same new space page.
   2123   static inline bool OnSamePage(Address address1, Address address2) {
   2124     return NewSpacePage::FromAddress(address1) ==
   2125            NewSpacePage::FromAddress(address2);
   2126   }
   2127 
   2128  private:
   2129   // Create a NewSpacePage object that is only used as anchor
   2130   // for the doubly-linked list of real pages.
   2131   explicit NewSpacePage(SemiSpace* owner) {
   2132     InitializeAsAnchor(owner);
   2133   }
   2134 
   2135   static NewSpacePage* Initialize(Heap* heap,
   2136                                   Address start,
   2137                                   SemiSpace* semi_space);
   2138 
   2139   // Intialize a fake NewSpacePage used as sentinel at the ends
   2140   // of a doubly-linked list of real NewSpacePages.
   2141   // Only uses the prev/next links, and sets flags to not be in new-space.
   2142   void InitializeAsAnchor(SemiSpace* owner);
   2143 
   2144   friend class SemiSpace;
   2145   friend class SemiSpaceIterator;
   2146 };
   2147 
   2148 
   2149 // -----------------------------------------------------------------------------
   2150 // SemiSpace in young generation
   2151 //
   2152 // A semispace is a contiguous chunk of memory holding page-like memory
   2153 // chunks. The mark-compact collector  uses the memory of the first page in
   2154 // the from space as a marking stack when tracing live objects.
   2155 
   2156 class SemiSpace : public Space {
   2157  public:
   2158   // Constructor.
   2159   SemiSpace(Heap* heap, SemiSpaceId semispace)
   2160     : Space(heap, NEW_SPACE, NOT_EXECUTABLE),
   2161       start_(NULL),
   2162       age_mark_(NULL),
   2163       id_(semispace),
   2164       anchor_(this),
   2165       current_page_(NULL) { }
   2166 
   2167   // Sets up the semispace using the given chunk.
   2168   void SetUp(Address start, int initial_capacity, int maximum_capacity);
   2169 
   2170   // Tear down the space.  Heap memory was not allocated by the space, so it
   2171   // is not deallocated here.
   2172   void TearDown();
   2173 
   2174   // True if the space has been set up but not torn down.
   2175   bool HasBeenSetUp() { return start_ != NULL; }
   2176 
   2177   // Grow the semispace to the new capacity.  The new capacity
   2178   // requested must be larger than the current capacity and less than
   2179   // the maximum capacity.
   2180   bool GrowTo(int new_capacity);
   2181 
   2182   // Shrinks the semispace to the new capacity.  The new capacity
   2183   // requested must be more than the amount of used memory in the
   2184   // semispace and less than the current capacity.
   2185   bool ShrinkTo(int new_capacity);
   2186 
   2187   // Returns the start address of the first page of the space.
   2188   Address space_start() {
   2189     ASSERT(anchor_.next_page() != &anchor_);
   2190     return anchor_.next_page()->area_start();
   2191   }
   2192 
   2193   // Returns the start address of the current page of the space.
   2194   Address page_low() {
   2195     return current_page_->area_start();
   2196   }
   2197 
   2198   // Returns one past the end address of the space.
   2199   Address space_end() {
   2200     return anchor_.prev_page()->area_end();
   2201   }
   2202 
   2203   // Returns one past the end address of the current page of the space.
   2204   Address page_high() {
   2205     return current_page_->area_end();
   2206   }
   2207 
   2208   bool AdvancePage() {
   2209     NewSpacePage* next_page = current_page_->next_page();
   2210     if (next_page == anchor()) return false;
   2211     current_page_ = next_page;
   2212     return true;
   2213   }
   2214 
   2215   // Resets the space to using the first page.
   2216   void Reset();
   2217 
   2218   // Age mark accessors.
   2219   Address age_mark() { return age_mark_; }
   2220   void set_age_mark(Address mark);
   2221 
   2222   // True if the address is in the address range of this semispace (not
   2223   // necessarily below the allocation pointer).
   2224   bool Contains(Address a) {
   2225     return (reinterpret_cast<uintptr_t>(a) & address_mask_)
   2226            == reinterpret_cast<uintptr_t>(start_);
   2227   }
   2228 
   2229   // True if the object is a heap object in the address range of this
   2230   // semispace (not necessarily below the allocation pointer).
   2231   bool Contains(Object* o) {
   2232     return (reinterpret_cast<uintptr_t>(o) & object_mask_) == object_expected_;
   2233   }
   2234 
   2235   // If we don't have these here then SemiSpace will be abstract.  However
   2236   // they should never be called.
   2237   virtual intptr_t Size() {
   2238     UNREACHABLE();
   2239     return 0;
   2240   }
   2241 
   2242   bool is_committed() { return committed_; }
   2243   bool Commit();
   2244   bool Uncommit();
   2245 
   2246   NewSpacePage* first_page() { return anchor_.next_page(); }
   2247   NewSpacePage* current_page() { return current_page_; }
   2248 
   2249 #ifdef VERIFY_HEAP
   2250   virtual void Verify();
   2251 #endif
   2252 
   2253 #ifdef DEBUG
   2254   virtual void Print();
   2255   // Validate a range of of addresses in a SemiSpace.
   2256   // The "from" address must be on a page prior to the "to" address,
   2257   // in the linked page order, or it must be earlier on the same page.
   2258   static void AssertValidRange(Address from, Address to);
   2259 #else
   2260   // Do nothing.
   2261   inline static void AssertValidRange(Address from, Address to) {}
   2262 #endif
   2263 
   2264   // Returns the current capacity of the semi space.
   2265   int Capacity() { return capacity_; }
   2266 
   2267   // Returns the maximum capacity of the semi space.
   2268   int MaximumCapacity() { return maximum_capacity_; }
   2269 
   2270   // Returns the initial capacity of the semi space.
   2271   int InitialCapacity() { return initial_capacity_; }
   2272 
   2273   SemiSpaceId id() { return id_; }
   2274 
   2275   static void Swap(SemiSpace* from, SemiSpace* to);
   2276 
   2277   // Returns the maximum amount of memory ever committed by the semi space.
   2278   size_t MaximumCommittedMemory() { return maximum_committed_; }
   2279 
   2280   // Approximate amount of physical memory committed for this space.
   2281   size_t CommittedPhysicalMemory();
   2282 
   2283  private:
   2284   // Flips the semispace between being from-space and to-space.
   2285   // Copies the flags into the masked positions on all pages in the space.
   2286   void FlipPages(intptr_t flags, intptr_t flag_mask);
   2287 
   2288   // Updates Capacity and MaximumCommitted based on new capacity.
   2289   void SetCapacity(int new_capacity);
   2290 
   2291   NewSpacePage* anchor() { return &anchor_; }
   2292 
   2293   // The current and maximum capacity of the space.
   2294   int capacity_;
   2295   int maximum_capacity_;
   2296   int initial_capacity_;
   2297 
   2298   intptr_t maximum_committed_;
   2299 
   2300   // The start address of the space.
   2301   Address start_;
   2302   // Used to govern object promotion during mark-compact collection.
   2303   Address age_mark_;
   2304 
   2305   // Masks and comparison values to test for containment in this semispace.
   2306   uintptr_t address_mask_;
   2307   uintptr_t object_mask_;
   2308   uintptr_t object_expected_;
   2309 
   2310   bool committed_;
   2311   SemiSpaceId id_;
   2312 
   2313   NewSpacePage anchor_;
   2314   NewSpacePage* current_page_;
   2315 
   2316   friend class SemiSpaceIterator;
   2317   friend class NewSpacePageIterator;
   2318  public:
   2319   TRACK_MEMORY("SemiSpace")
   2320 };
   2321 
   2322 
   2323 // A SemiSpaceIterator is an ObjectIterator that iterates over the active
   2324 // semispace of the heap's new space.  It iterates over the objects in the
   2325 // semispace from a given start address (defaulting to the bottom of the
   2326 // semispace) to the top of the semispace.  New objects allocated after the
   2327 // iterator is created are not iterated.
   2328 class SemiSpaceIterator : public ObjectIterator {
   2329  public:
   2330   // Create an iterator over the objects in the given space.  If no start
   2331   // address is given, the iterator starts from the bottom of the space.  If
   2332   // no size function is given, the iterator calls Object::Size().
   2333 
   2334   // Iterate over all of allocated to-space.
   2335   explicit SemiSpaceIterator(NewSpace* space);
   2336   // Iterate over all of allocated to-space, with a custome size function.
   2337   SemiSpaceIterator(NewSpace* space, HeapObjectCallback size_func);
   2338   // Iterate over part of allocated to-space, from start to the end
   2339   // of allocation.
   2340   SemiSpaceIterator(NewSpace* space, Address start);
   2341   // Iterate from one address to another in the same semi-space.
   2342   SemiSpaceIterator(Address from, Address to);
   2343 
   2344   HeapObject* Next() {
   2345     if (current_ == limit_) return NULL;
   2346     if (NewSpacePage::IsAtEnd(current_)) {
   2347       NewSpacePage* page = NewSpacePage::FromLimit(current_);
   2348       page = page->next_page();
   2349       ASSERT(!page->is_anchor());
   2350       current_ = page->area_start();
   2351       if (current_ == limit_) return NULL;
   2352     }
   2353 
   2354     HeapObject* object = HeapObject::FromAddress(current_);
   2355     int size = (size_func_ == NULL) ? object->Size() : size_func_(object);
   2356 
   2357     current_ += size;
   2358     return object;
   2359   }
   2360 
   2361   // Implementation of the ObjectIterator functions.
   2362   virtual HeapObject* next_object() { return Next(); }
   2363 
   2364  private:
   2365   void Initialize(Address start,
   2366                   Address end,
   2367                   HeapObjectCallback size_func);
   2368 
   2369   // The current iteration point.
   2370   Address current_;
   2371   // The end of iteration.
   2372   Address limit_;
   2373   // The callback function.
   2374   HeapObjectCallback size_func_;
   2375 };
   2376 
   2377 
   2378 // -----------------------------------------------------------------------------
   2379 // A PageIterator iterates the pages in a semi-space.
   2380 class NewSpacePageIterator BASE_EMBEDDED {
   2381  public:
   2382   // Make an iterator that runs over all pages in to-space.
   2383   explicit inline NewSpacePageIterator(NewSpace* space);
   2384 
   2385   // Make an iterator that runs over all pages in the given semispace,
   2386   // even those not used in allocation.
   2387   explicit inline NewSpacePageIterator(SemiSpace* space);
   2388 
   2389   // Make iterator that iterates from the page containing start
   2390   // to the page that contains limit in the same semispace.
   2391   inline NewSpacePageIterator(Address start, Address limit);
   2392 
   2393   inline bool has_next();
   2394   inline NewSpacePage* next();
   2395 
   2396  private:
   2397   NewSpacePage* prev_page_;  // Previous page returned.
   2398   // Next page that will be returned.  Cached here so that we can use this
   2399   // iterator for operations that deallocate pages.
   2400   NewSpacePage* next_page_;
   2401   // Last page returned.
   2402   NewSpacePage* last_page_;
   2403 };
   2404 
   2405 
   2406 // -----------------------------------------------------------------------------
   2407 // The young generation space.
   2408 //
   2409 // The new space consists of a contiguous pair of semispaces.  It simply
   2410 // forwards most functions to the appropriate semispace.
   2411 
   2412 class NewSpace : public Space {
   2413  public:
   2414   // Constructor.
   2415   explicit NewSpace(Heap* heap)
   2416     : Space(heap, NEW_SPACE, NOT_EXECUTABLE),
   2417       to_space_(heap, kToSpace),
   2418       from_space_(heap, kFromSpace),
   2419       reservation_(),
   2420       inline_allocation_limit_step_(0) {}
   2421 
   2422   // Sets up the new space using the given chunk.
   2423   bool SetUp(int reserved_semispace_size_, int max_semi_space_size);
   2424 
   2425   // Tears down the space.  Heap memory was not allocated by the space, so it
   2426   // is not deallocated here.
   2427   void TearDown();
   2428 
   2429   // True if the space has been set up but not torn down.
   2430   bool HasBeenSetUp() {
   2431     return to_space_.HasBeenSetUp() && from_space_.HasBeenSetUp();
   2432   }
   2433 
   2434   // Flip the pair of spaces.
   2435   void Flip();
   2436 
   2437   // Grow the capacity of the semispaces.  Assumes that they are not at
   2438   // their maximum capacity.
   2439   void Grow();
   2440 
   2441   // Shrink the capacity of the semispaces.
   2442   void Shrink();
   2443 
   2444   // True if the address or object lies in the address range of either
   2445   // semispace (not necessarily below the allocation pointer).
   2446   bool Contains(Address a) {
   2447     return (reinterpret_cast<uintptr_t>(a) & address_mask_)
   2448         == reinterpret_cast<uintptr_t>(start_);
   2449   }
   2450 
   2451   bool Contains(Object* o) {
   2452     Address a = reinterpret_cast<Address>(o);
   2453     return (reinterpret_cast<uintptr_t>(a) & object_mask_) == object_expected_;
   2454   }
   2455 
   2456   // Return the allocated bytes in the active semispace.
   2457   virtual intptr_t Size() {
   2458     return pages_used_ * NewSpacePage::kAreaSize +
   2459         static_cast<int>(top() - to_space_.page_low());
   2460   }
   2461 
   2462   // The same, but returning an int.  We have to have the one that returns
   2463   // intptr_t because it is inherited, but if we know we are dealing with the
   2464   // new space, which can't get as big as the other spaces then this is useful:
   2465   int SizeAsInt() { return static_cast<int>(Size()); }
   2466 
   2467   // Return the current capacity of a semispace.
   2468   intptr_t EffectiveCapacity() {
   2469     SLOW_ASSERT(to_space_.Capacity() == from_space_.Capacity());
   2470     return (to_space_.Capacity() / Page::kPageSize) * NewSpacePage::kAreaSize;
   2471   }
   2472 
   2473   // Return the current capacity of a semispace.
   2474   intptr_t Capacity() {
   2475     ASSERT(to_space_.Capacity() == from_space_.Capacity());
   2476     return to_space_.Capacity();
   2477   }
   2478 
   2479   // Return the total amount of memory committed for new space.
   2480   intptr_t CommittedMemory() {
   2481     if (from_space_.is_committed()) return 2 * Capacity();
   2482     return Capacity();
   2483   }
   2484 
   2485   // Return the total amount of memory committed for new space.
   2486   intptr_t MaximumCommittedMemory() {
   2487     return to_space_.MaximumCommittedMemory() +
   2488         from_space_.MaximumCommittedMemory();
   2489   }
   2490 
   2491   // Approximate amount of physical memory committed for this space.
   2492   size_t CommittedPhysicalMemory();
   2493 
   2494   // Return the available bytes without growing.
   2495   intptr_t Available() {
   2496     return Capacity() - Size();
   2497   }
   2498 
   2499   // Return the maximum capacity of a semispace.
   2500   int MaximumCapacity() {
   2501     ASSERT(to_space_.MaximumCapacity() == from_space_.MaximumCapacity());
   2502     return to_space_.MaximumCapacity();
   2503   }
   2504 
   2505   bool IsAtMaximumCapacity() {
   2506     return Capacity() == MaximumCapacity();
   2507   }
   2508 
   2509   // Returns the initial capacity of a semispace.
   2510   int InitialCapacity() {
   2511     ASSERT(to_space_.InitialCapacity() == from_space_.InitialCapacity());
   2512     return to_space_.InitialCapacity();
   2513   }
   2514 
   2515   // Return the address of the allocation pointer in the active semispace.
   2516   Address top() {
   2517     ASSERT(to_space_.current_page()->ContainsLimit(allocation_info_.top()));
   2518     return allocation_info_.top();
   2519   }
   2520 
   2521   void set_top(Address top) {
   2522     ASSERT(to_space_.current_page()->ContainsLimit(top));
   2523     allocation_info_.set_top(top);
   2524   }
   2525 
   2526   // Return the address of the allocation pointer limit in the active semispace.
   2527   Address limit() {
   2528     ASSERT(to_space_.current_page()->ContainsLimit(allocation_info_.limit()));
   2529     return allocation_info_.limit();
   2530   }
   2531 
   2532   // Return the address of the first object in the active semispace.
   2533   Address bottom() { return to_space_.space_start(); }
   2534 
   2535   // Get the age mark of the inactive semispace.
   2536   Address age_mark() { return from_space_.age_mark(); }
   2537   // Set the age mark in the active semispace.
   2538   void set_age_mark(Address mark) { to_space_.set_age_mark(mark); }
   2539 
   2540   // The start address of the space and a bit mask. Anding an address in the
   2541   // new space with the mask will result in the start address.
   2542   Address start() { return start_; }
   2543   uintptr_t mask() { return address_mask_; }
   2544 
   2545   INLINE(uint32_t AddressToMarkbitIndex(Address addr)) {
   2546     ASSERT(Contains(addr));
   2547     ASSERT(IsAligned(OffsetFrom(addr), kPointerSize) ||
   2548            IsAligned(OffsetFrom(addr) - 1, kPointerSize));
   2549     return static_cast<uint32_t>(addr - start_) >> kPointerSizeLog2;
   2550   }
   2551 
   2552   INLINE(Address MarkbitIndexToAddress(uint32_t index)) {
   2553     return reinterpret_cast<Address>(index << kPointerSizeLog2);
   2554   }
   2555 
   2556   // The allocation top and limit address.
   2557   Address* allocation_top_address() {
   2558     return allocation_info_.top_address();
   2559   }
   2560 
   2561   // The allocation limit address.
   2562   Address* allocation_limit_address() {
   2563     return allocation_info_.limit_address();
   2564   }
   2565 
   2566   MUST_USE_RESULT INLINE(AllocationResult AllocateRaw(int size_in_bytes));
   2567 
   2568   // Reset the allocation pointer to the beginning of the active semispace.
   2569   void ResetAllocationInfo();
   2570 
   2571   void UpdateInlineAllocationLimit(int size_in_bytes);
   2572   void LowerInlineAllocationLimit(intptr_t step) {
   2573     inline_allocation_limit_step_ = step;
   2574     UpdateInlineAllocationLimit(0);
   2575     top_on_previous_step_ = allocation_info_.top();
   2576   }
   2577 
   2578   // Get the extent of the inactive semispace (for use as a marking stack,
   2579   // or to zap it). Notice: space-addresses are not necessarily on the
   2580   // same page, so FromSpaceStart() might be above FromSpaceEnd().
   2581   Address FromSpacePageLow() { return from_space_.page_low(); }
   2582   Address FromSpacePageHigh() { return from_space_.page_high(); }
   2583   Address FromSpaceStart() { return from_space_.space_start(); }
   2584   Address FromSpaceEnd() { return from_space_.space_end(); }
   2585 
   2586   // Get the extent of the active semispace's pages' memory.
   2587   Address ToSpaceStart() { return to_space_.space_start(); }
   2588   Address ToSpaceEnd() { return to_space_.space_end(); }
   2589 
   2590   inline bool ToSpaceContains(Address address) {
   2591     return to_space_.Contains(address);
   2592   }
   2593   inline bool FromSpaceContains(Address address) {
   2594     return from_space_.Contains(address);
   2595   }
   2596 
   2597   // True if the object is a heap object in the address range of the
   2598   // respective semispace (not necessarily below the allocation pointer of the
   2599   // semispace).
   2600   inline bool ToSpaceContains(Object* o) { return to_space_.Contains(o); }
   2601   inline bool FromSpaceContains(Object* o) { return from_space_.Contains(o); }
   2602 
   2603   // Try to switch the active semispace to a new, empty, page.
   2604   // Returns false if this isn't possible or reasonable (i.e., there
   2605   // are no pages, or the current page is already empty), or true
   2606   // if successful.
   2607   bool AddFreshPage();
   2608 
   2609 #ifdef VERIFY_HEAP
   2610   // Verify the active semispace.
   2611   virtual void Verify();
   2612 #endif
   2613 
   2614 #ifdef DEBUG
   2615   // Print the active semispace.
   2616   virtual void Print() { to_space_.Print(); }
   2617 #endif
   2618 
   2619   // Iterates the active semispace to collect statistics.
   2620   void CollectStatistics();
   2621   // Reports previously collected statistics of the active semispace.
   2622   void ReportStatistics();
   2623   // Clears previously collected statistics.
   2624   void ClearHistograms();
   2625 
   2626   // Record the allocation or promotion of a heap object.  Note that we don't
   2627   // record every single allocation, but only those that happen in the
   2628   // to space during a scavenge GC.
   2629   void RecordAllocation(HeapObject* obj);
   2630   void RecordPromotion(HeapObject* obj);
   2631 
   2632   // Return whether the operation succeded.
   2633   bool CommitFromSpaceIfNeeded() {
   2634     if (from_space_.is_committed()) return true;
   2635     return from_space_.Commit();
   2636   }
   2637 
   2638   bool UncommitFromSpace() {
   2639     if (!from_space_.is_committed()) return true;
   2640     return from_space_.Uncommit();
   2641   }
   2642 
   2643   inline intptr_t inline_allocation_limit_step() {
   2644     return inline_allocation_limit_step_;
   2645   }
   2646 
   2647   SemiSpace* active_space() { return &to_space_; }
   2648 
   2649  private:
   2650   // Update allocation info to match the current to-space page.
   2651   void UpdateAllocationInfo();
   2652 
   2653   Address chunk_base_;
   2654   uintptr_t chunk_size_;
   2655 
   2656   // The semispaces.
   2657   SemiSpace to_space_;
   2658   SemiSpace from_space_;
   2659   VirtualMemory reservation_;
   2660   int pages_used_;
   2661 
   2662   // Start address and bit mask for containment testing.
   2663   Address start_;
   2664   uintptr_t address_mask_;
   2665   uintptr_t object_mask_;
   2666   uintptr_t object_expected_;
   2667 
   2668   // Allocation pointer and limit for normal allocation and allocation during
   2669   // mark-compact collection.
   2670   AllocationInfo allocation_info_;
   2671 
   2672   // When incremental marking is active we will set allocation_info_.limit
   2673   // to be lower than actual limit and then will gradually increase it
   2674   // in steps to guarantee that we do incremental marking steps even
   2675   // when all allocation is performed from inlined generated code.
   2676   intptr_t inline_allocation_limit_step_;
   2677 
   2678   Address top_on_previous_step_;
   2679 
   2680   HistogramInfo* allocated_histogram_;
   2681   HistogramInfo* promoted_histogram_;
   2682 
   2683   MUST_USE_RESULT AllocationResult SlowAllocateRaw(int size_in_bytes);
   2684 
   2685   friend class SemiSpaceIterator;
   2686 
   2687  public:
   2688   TRACK_MEMORY("NewSpace")
   2689 };
   2690 
   2691 
   2692 // -----------------------------------------------------------------------------
   2693 // Old object space (excluding map objects)
   2694 
   2695 class OldSpace : public PagedSpace {
   2696  public:
   2697   // Creates an old space object with a given maximum capacity.
   2698   // The constructor does not allocate pages from OS.
   2699   OldSpace(Heap* heap,
   2700            intptr_t max_capacity,
   2701            AllocationSpace id,
   2702            Executability executable)
   2703       : PagedSpace(heap, max_capacity, id, executable) {
   2704   }
   2705 
   2706  public:
   2707   TRACK_MEMORY("OldSpace")
   2708 };
   2709 
   2710 
   2711 // For contiguous spaces, top should be in the space (or at the end) and limit
   2712 // should be the end of the space.
   2713 #define ASSERT_SEMISPACE_ALLOCATION_INFO(info, space) \
   2714   SLOW_ASSERT((space).page_low() <= (info).top() \
   2715               && (info).top() <= (space).page_high() \
   2716               && (info).limit() <= (space).page_high())
   2717 
   2718 
   2719 // -----------------------------------------------------------------------------
   2720 // Old space for all map objects
   2721 
   2722 class MapSpace : public PagedSpace {
   2723  public:
   2724   // Creates a map space object with a maximum capacity.
   2725   MapSpace(Heap* heap, intptr_t max_capacity, AllocationSpace id)
   2726       : PagedSpace(heap, max_capacity, id, NOT_EXECUTABLE),
   2727         max_map_space_pages_(kMaxMapPageIndex - 1) {
   2728   }
   2729 
   2730   // Given an index, returns the page address.
   2731   // TODO(1600): this limit is artifical just to keep code compilable
   2732   static const int kMaxMapPageIndex = 1 << 16;
   2733 
   2734   virtual int RoundSizeDownToObjectAlignment(int size) {
   2735     if (IsPowerOf2(Map::kSize)) {
   2736       return RoundDown(size, Map::kSize);
   2737     } else {
   2738       return (size / Map::kSize) * Map::kSize;
   2739     }
   2740   }
   2741 
   2742  protected:
   2743   virtual void VerifyObject(HeapObject* obj);
   2744 
   2745  private:
   2746   static const int kMapsPerPage = Page::kMaxRegularHeapObjectSize / Map::kSize;
   2747 
   2748   // Do map space compaction if there is a page gap.
   2749   int CompactionThreshold() {
   2750     return kMapsPerPage * (max_map_space_pages_ - 1);
   2751   }
   2752 
   2753   const int max_map_space_pages_;
   2754 
   2755  public:
   2756   TRACK_MEMORY("MapSpace")
   2757 };
   2758 
   2759 
   2760 // -----------------------------------------------------------------------------
   2761 // Old space for simple property cell objects
   2762 
   2763 class CellSpace : public PagedSpace {
   2764  public:
   2765   // Creates a property cell space object with a maximum capacity.
   2766   CellSpace(Heap* heap, intptr_t max_capacity, AllocationSpace id)
   2767       : PagedSpace(heap, max_capacity, id, NOT_EXECUTABLE) {
   2768   }
   2769 
   2770   virtual int RoundSizeDownToObjectAlignment(int size) {
   2771     if (IsPowerOf2(Cell::kSize)) {
   2772       return RoundDown(size, Cell::kSize);
   2773     } else {
   2774       return (size / Cell::kSize) * Cell::kSize;
   2775     }
   2776   }
   2777 
   2778  protected:
   2779   virtual void VerifyObject(HeapObject* obj);
   2780 
   2781  public:
   2782   TRACK_MEMORY("CellSpace")
   2783 };
   2784 
   2785 
   2786 // -----------------------------------------------------------------------------
   2787 // Old space for all global object property cell objects
   2788 
   2789 class PropertyCellSpace : public PagedSpace {
   2790  public:
   2791   // Creates a property cell space object with a maximum capacity.
   2792   PropertyCellSpace(Heap* heap, intptr_t max_capacity,
   2793                     AllocationSpace id)
   2794       : PagedSpace(heap, max_capacity, id, NOT_EXECUTABLE) {
   2795   }
   2796 
   2797   virtual int RoundSizeDownToObjectAlignment(int size) {
   2798     if (IsPowerOf2(PropertyCell::kSize)) {
   2799       return RoundDown(size, PropertyCell::kSize);
   2800     } else {
   2801       return (size / PropertyCell::kSize) * PropertyCell::kSize;
   2802     }
   2803   }
   2804 
   2805  protected:
   2806   virtual void VerifyObject(HeapObject* obj);
   2807 
   2808  public:
   2809   TRACK_MEMORY("PropertyCellSpace")
   2810 };
   2811 
   2812 
   2813 // -----------------------------------------------------------------------------
   2814 // Large objects ( > Page::kMaxHeapObjectSize ) are allocated and managed by
   2815 // the large object space. A large object is allocated from OS heap with
   2816 // extra padding bytes (Page::kPageSize + Page::kObjectStartOffset).
   2817 // A large object always starts at Page::kObjectStartOffset to a page.
   2818 // Large objects do not move during garbage collections.
   2819 
   2820 class LargeObjectSpace : public Space {
   2821  public:
   2822   LargeObjectSpace(Heap* heap, intptr_t max_capacity, AllocationSpace id);
   2823   virtual ~LargeObjectSpace() {}
   2824 
   2825   // Initializes internal data structures.
   2826   bool SetUp();
   2827 
   2828   // Releases internal resources, frees objects in this space.
   2829   void TearDown();
   2830 
   2831   static intptr_t ObjectSizeFor(intptr_t chunk_size) {
   2832     if (chunk_size <= (Page::kPageSize + Page::kObjectStartOffset)) return 0;
   2833     return chunk_size - Page::kPageSize - Page::kObjectStartOffset;
   2834   }
   2835 
   2836   // Shared implementation of AllocateRaw, AllocateRawCode and
   2837   // AllocateRawFixedArray.
   2838   MUST_USE_RESULT AllocationResult AllocateRaw(int object_size,
   2839                                                Executability executable);
   2840 
   2841   // Available bytes for objects in this space.
   2842   inline intptr_t Available();
   2843 
   2844   virtual intptr_t Size() {
   2845     return size_;
   2846   }
   2847 
   2848   virtual intptr_t SizeOfObjects() {
   2849     return objects_size_;
   2850   }
   2851 
   2852   intptr_t MaximumCommittedMemory() {
   2853     return maximum_committed_;
   2854   }
   2855 
   2856   intptr_t CommittedMemory() {
   2857     return Size();
   2858   }
   2859 
   2860   // Approximate amount of physical memory committed for this space.
   2861   size_t CommittedPhysicalMemory();
   2862 
   2863   int PageCount() {
   2864     return page_count_;
   2865   }
   2866 
   2867   // Finds an object for a given address, returns a Smi if it is not found.
   2868   // The function iterates through all objects in this space, may be slow.
   2869   Object* FindObject(Address a);
   2870 
   2871   // Finds a large object page containing the given address, returns NULL
   2872   // if such a page doesn't exist.
   2873   LargePage* FindPage(Address a);
   2874 
   2875   // Frees unmarked objects.
   2876   void FreeUnmarkedObjects();
   2877 
   2878   // Checks whether a heap object is in this space; O(1).
   2879   bool Contains(HeapObject* obj);
   2880 
   2881   // Checks whether the space is empty.
   2882   bool IsEmpty() { return first_page_ == NULL; }
   2883 
   2884   LargePage* first_page() { return first_page_; }
   2885 
   2886 #ifdef VERIFY_HEAP
   2887   virtual void Verify();
   2888 #endif
   2889 
   2890 #ifdef DEBUG
   2891   virtual void Print();
   2892   void ReportStatistics();
   2893   void CollectCodeStatistics();
   2894 #endif
   2895   // Checks whether an address is in the object area in this space.  It
   2896   // iterates all objects in the space. May be slow.
   2897   bool SlowContains(Address addr) { return FindObject(addr)->IsHeapObject(); }
   2898 
   2899  private:
   2900   intptr_t max_capacity_;
   2901   intptr_t maximum_committed_;
   2902   // The head of the linked list of large object chunks.
   2903   LargePage* first_page_;
   2904   intptr_t size_;  // allocated bytes
   2905   int page_count_;  // number of chunks
   2906   intptr_t objects_size_;  // size of objects
   2907   // Map MemoryChunk::kAlignment-aligned chunks to large pages covering them
   2908   HashMap chunk_map_;
   2909 
   2910   friend class LargeObjectIterator;
   2911 
   2912  public:
   2913   TRACK_MEMORY("LargeObjectSpace")
   2914 };
   2915 
   2916 
   2917 class LargeObjectIterator: public ObjectIterator {
   2918  public:
   2919   explicit LargeObjectIterator(LargeObjectSpace* space);
   2920   LargeObjectIterator(LargeObjectSpace* space, HeapObjectCallback size_func);
   2921 
   2922   HeapObject* Next();
   2923 
   2924   // implementation of ObjectIterator.
   2925   virtual HeapObject* next_object() { return Next(); }
   2926 
   2927  private:
   2928   LargePage* current_;
   2929   HeapObjectCallback size_func_;
   2930 };
   2931 
   2932 
   2933 // Iterates over the chunks (pages and large object pages) that can contain
   2934 // pointers to new space.
   2935 class PointerChunkIterator BASE_EMBEDDED {
   2936  public:
   2937   inline explicit PointerChunkIterator(Heap* heap);
   2938 
   2939   // Return NULL when the iterator is done.
   2940   MemoryChunk* next() {
   2941     switch (state_) {
   2942       case kOldPointerState: {
   2943         if (old_pointer_iterator_.has_next()) {
   2944           return old_pointer_iterator_.next();
   2945         }
   2946         state_ = kMapState;
   2947         // Fall through.
   2948       }
   2949       case kMapState: {
   2950         if (map_iterator_.has_next()) {
   2951           return map_iterator_.next();
   2952         }
   2953         state_ = kLargeObjectState;
   2954         // Fall through.
   2955       }
   2956       case kLargeObjectState: {
   2957         HeapObject* heap_object;
   2958         do {
   2959           heap_object = lo_iterator_.Next();
   2960           if (heap_object == NULL) {
   2961             state_ = kFinishedState;
   2962             return NULL;
   2963           }
   2964           // Fixed arrays are the only pointer-containing objects in large
   2965           // object space.
   2966         } while (!heap_object->IsFixedArray());
   2967         MemoryChunk* answer = MemoryChunk::FromAddress(heap_object->address());
   2968         return answer;
   2969       }
   2970       case kFinishedState:
   2971         return NULL;
   2972       default:
   2973         break;
   2974     }
   2975     UNREACHABLE();
   2976     return NULL;
   2977   }
   2978 
   2979 
   2980  private:
   2981   enum State {
   2982     kOldPointerState,
   2983     kMapState,
   2984     kLargeObjectState,
   2985     kFinishedState
   2986   };
   2987   State state_;
   2988   PageIterator old_pointer_iterator_;
   2989   PageIterator map_iterator_;
   2990   LargeObjectIterator lo_iterator_;
   2991 };
   2992 
   2993 
   2994 #ifdef DEBUG
   2995 struct CommentStatistic {
   2996   const char* comment;
   2997   int size;
   2998   int count;
   2999   void Clear() {
   3000     comment = NULL;
   3001     size = 0;
   3002     count = 0;
   3003   }
   3004   // Must be small, since an iteration is used for lookup.
   3005   static const int kMaxComments = 64;
   3006 };
   3007 #endif
   3008 
   3009 
   3010 } }  // namespace v8::internal
   3011 
   3012 #endif  // V8_SPACES_H_
   3013