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