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