1257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Copyright 2011 the V8 project authors. All rights reserved.
2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file.
4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifndef V8_HEAP_SPACES_H_
6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define V8_HEAP_SPACES_H_
7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
8bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch#include <list>
9f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include <memory>
10f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include <unordered_set>
11bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/allocation.h"
13bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch#include "src/base/atomic-utils.h"
14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/base/atomicops.h"
15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/base/bits.h"
1613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch#include "src/base/hashmap.h"
17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/base/platform/mutex.h"
18014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/flags.h"
19f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#include "src/globals.h"
20f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#include "src/heap/heap.h"
21f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include "src/heap/marking.h"
22b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/list.h"
23014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/objects.h"
24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/utils.h"
25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 {
27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal {
28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
29109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochclass AllocationInfo;
30109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochclass AllocationObserver;
31109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochclass CompactionSpace;
32014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochclass CompactionSpaceCollection;
33109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochclass FreeList;
3444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockclass Isolate;
3513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochclass LocalArrayBufferTracker;
36109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochclass MemoryAllocator;
37109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochclass MemoryChunk;
383b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochclass Page;
39109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochclass PagedSpace;
40109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochclass SemiSpace;
41109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochclass SkipList;
42109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochclass SlotsBuffer;
43109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochclass SlotSet;
443b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochclass TypedSlotSet;
45109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochclass Space;
4644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// -----------------------------------------------------------------------------
48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Heap structures:
49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A JS heap consists of a young generation, an old generation, and a large
51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// object space. The young generation is divided into two semispaces. A
52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// scavenger implements Cheney's copying algorithm. The old generation is
53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// separated into a map space and an old object space. The map space contains
54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// all (and only) map objects, the rest of old objects go into the old space.
55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The old generation is collected by a mark-sweep-compact collector.
56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The semispaces of the young generation are contiguous.  The old and map
587f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// spaces consists of a list of pages. A page has a page header and an object
593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// area.
60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// There is a separate large object space for objects larger than
62f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch// kMaxRegularHeapObjectSize, so that they do not have to move during
637f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch// collection. The large object space is paged. Pages in large object space
643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// may be larger than the page size.
657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch//
663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// A store-buffer based write barrier is used to keep track of intergenerational
67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// references.  See heap/store-buffer.h.
687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch//
693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// During scavenges and mark-sweep collections we sometimes (after a store
703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// buffer overflow) iterate intergenerational pointers without decoding heap
71014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// object maps so if the page belongs to old space or large object space
72014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// it is essential to guarantee that the page does not contain any
733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// garbage pointers to new space: every pointer aligned word which satisfies
743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// the Heap::InNewSpace() predicate must be a pointer to a live heap object in
75014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// new space. Thus objects in old space and large object spaces should have a
763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// special layout (e.g. no bare integer fields). This requirement does not
773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// apply to map space which is iterated in a special fashion. However we still
783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// require pointer fields of dead maps to be cleaned.
797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch//
803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// To enable lazy cleaning of old space pages we can mark chunks of the page
813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// as being garbage.  Garbage sections are marked with a special map.  These
823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// sections are skipped when scanning the page, even if we are otherwise
833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// scanning without regard for object boundaries.  Garbage sections are chained
843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// together to form a free list after a GC.  Garbage sections created outside
853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// of GCs by object trunctation etc. may not be in the free list chain.  Very
863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// small free spaces are ignored, they need only be cleaned of bogus pointers
873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// into new space.
88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Each page may have up to one special garbage section.  The start of this
903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// section is denoted by the top field in the space.  The end of the section
913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// is denoted by the limit field in the space.  This special garbage section
923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// is not marked with a free space map in the data.  The point of this section
933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// is to enable linear allocation without having to constantly update the byte
943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// array every time the top field is updated and a new object is created.  The
953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// special garbage section is not in the chain of garbage sections.
963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//
973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Since the top and limit fields are in the space, not the page, only one page
983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// has a special garbage section, and if the top and limit are equal then there
993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// is no special garbage section.
100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Some assertion macros used in the debugging mode.
102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define DCHECK_PAGE_ALIGNED(address) \
104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((OffsetFrom(address) & Page::kPageAlignmentMask) == 0)
105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define DCHECK_OBJECT_ALIGNED(address) \
107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((OffsetFrom(address) & kObjectAlignmentMask) == 0)
108e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define DCHECK_OBJECT_SIZE(size) \
110f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  DCHECK((0 < size) && (size <= kMaxRegularHeapObjectSize))
111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
112014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define DCHECK_CODEOBJECT_SIZE(size, code_space) \
113014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  DCHECK((0 < size) && (size <= code_space->AreaSize()))
114014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define DCHECK_PAGE_OFFSET(offset) \
116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK((Page::kObjectStartOffset <= offset) && (offset <= Page::kPageSize))
117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1183b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochenum FreeListCategoryType {
1193b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  kTiniest,
1203b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  kTiny,
1213b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  kSmall,
1223b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  kMedium,
1233b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  kLarge,
1243b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  kHuge,
1253b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
1263b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  kFirstCategory = kTiniest,
1273b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  kLastCategory = kHuge,
1283b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  kNumberOfCategories = kLastCategory + 1,
1293b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  kInvalidCategory
1303b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch};
1313b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
1323b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochenum FreeMode { kLinkCategory, kDoNotLinkCategory };
1333b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
1343b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch// A free list category maintains a linked list of free memory blocks.
1353b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochclass FreeListCategory {
1363b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch public:
1373b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  static const int kSize = kIntSize +      // FreeListCategoryType type_
138c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                           kIntSize +      // padding for type_
139c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                           kSizetSize +    // size_t available_
1403b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                           kPointerSize +  // FreeSpace* top_
1413b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                           kPointerSize +  // FreeListCategory* prev_
1423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                           kPointerSize;   // FreeListCategory* next_
1433b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
1443b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  FreeListCategory()
1453b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      : type_(kInvalidCategory),
1463b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        available_(0),
1473b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        top_(nullptr),
1483b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        prev_(nullptr),
1493b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        next_(nullptr) {}
1503b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
1513b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void Initialize(FreeListCategoryType type) {
1523b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    type_ = type;
1533b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    available_ = 0;
1543b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    top_ = nullptr;
1553b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    prev_ = nullptr;
1563b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    next_ = nullptr;
1573b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
1583b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
1593b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void Invalidate();
1603b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
1613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void Reset();
1623b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
1633b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void ResetStats() { Reset(); }
1643b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
1653b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void RepairFreeList(Heap* heap);
1663b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
1673b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Relinks the category into the currently owning free list. Requires that the
1683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // category is currently unlinked.
1693b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void Relink();
1703b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
171c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  bool Free(FreeSpace* node, size_t size_in_bytes, FreeMode mode);
1723b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
1733b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Picks a node from the list and stores its size in |node_size|. Returns
1743b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // nullptr if the category is empty.
175c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  FreeSpace* PickNodeFromList(size_t* node_size);
1763b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
1773b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Performs a single try to pick a node of at least |minimum_size| from the
1783b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // category. Stores the actual size in |node_size|. Returns nullptr if no
1793b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // node is found.
180c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  FreeSpace* TryPickNodeFromList(size_t minimum_size, size_t* node_size);
1813b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
1823b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Picks a node of at least |minimum_size| from the category. Stores the
1833b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // actual size in |node_size|. Returns nullptr if no node is found.
184c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  FreeSpace* SearchForNodeInList(size_t minimum_size, size_t* node_size);
1853b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
1863b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  inline FreeList* owner();
1873b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  inline bool is_linked();
1883b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  bool is_empty() { return top() == nullptr; }
189c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  size_t available() const { return available_; }
1903b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
1913b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch#ifdef DEBUG
192c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  size_t SumFreeList();
1933b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  int FreeListLength();
1943b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch#endif
1953b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
1963b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch private:
1973b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // For debug builds we accurately compute free lists lengths up until
1983b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // {kVeryLongFreeList} by manually walking the list.
1993b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  static const int kVeryLongFreeList = 500;
2003b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
2013b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  inline Page* page();
2023b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
2033b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  FreeSpace* top() { return top_; }
2043b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void set_top(FreeSpace* top) { top_ = top; }
2053b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  FreeListCategory* prev() { return prev_; }
2063b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void set_prev(FreeListCategory* prev) { prev_ = prev; }
2073b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  FreeListCategory* next() { return next_; }
2083b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void set_next(FreeListCategory* next) { next_ = next; }
2093b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
2103b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // |type_|: The type of this free list category.
2113b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  FreeListCategoryType type_;
2123b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
2133b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // |available_|: Total available bytes in all blocks of this free list
2143b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // category.
215c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  size_t available_;
2163b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
2173b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // |top_|: Points to the top FreeSpace* in the free list category.
2183b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  FreeSpace* top_;
2193b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
2203b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  FreeListCategory* prev_;
2213b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  FreeListCategory* next_;
2223b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
2233b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  friend class FreeList;
2243b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  friend class PagedSpace;
2253b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch};
2263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// MemoryChunk represents a memory region owned by a specific space.
2283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// It is divided into the header and the body. Chunk start is always
2293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// 1MB aligned. Start of the body is aligned so it can accommodate
2303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// any heap object.
2313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochclass MemoryChunk {
2323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch public:
233f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  enum Flag {
234f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    NO_FLAGS = 0u,
235f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    IS_EXECUTABLE = 1u << 0,
236f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    POINTERS_TO_HERE_ARE_INTERESTING = 1u << 1,
237f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    POINTERS_FROM_HERE_ARE_INTERESTING = 1u << 2,
238f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    // A page in new space has one of the next to flags set.
239f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    IN_FROM_SPACE = 1u << 3,
240f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    IN_TO_SPACE = 1u << 4,
241f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    NEW_SPACE_BELOW_AGE_MARK = 1u << 5,
242f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    EVACUATION_CANDIDATE = 1u << 6,
243f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    NEVER_EVACUATE = 1u << 7,
244014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
245014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Large objects can have a progress bar in their page header. These object
246014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // are scanned in increments and will be kept black while being scanned.
247014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Even if the mutator writes to them they will be kept black and a white
248014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // to grey transition is performed in the value.
249f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    HAS_PROGRESS_BAR = 1u << 8,
250014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
251bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    // |PAGE_NEW_OLD_PROMOTION|: A page tagged with this flag has been promoted
252bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    // from new to old space during evacuation.
253f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    PAGE_NEW_OLD_PROMOTION = 1u << 9,
254bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
25513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    // |PAGE_NEW_NEW_PROMOTION|: A page tagged with this flag has been moved
25613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    // within the new space during evacuation.
257f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    PAGE_NEW_NEW_PROMOTION = 1u << 10,
25813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
259014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // This flag is intended to be used for testing. Works only when both
260014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // FLAG_stress_compaction and FLAG_manual_evacuation_candidates_selection
261014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // are set. It forces the page to become an evacuation candidate at next
262014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // candidates selection cycle.
263f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    FORCE_EVACUATION_CANDIDATE_FOR_TESTING = 1u << 11,
264014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
265109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    // This flag is intended to be used for testing.
266f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    NEVER_ALLOCATE_ON_PAGE = 1u << 12,
267014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
268014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // The memory chunk is already logically freed, however the actual freeing
269014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // still has to be performed.
270f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    PRE_FREED = 1u << 13,
271014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
272bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    // |POOLED|: When actually freeing this chunk, only uncommit and do not
273bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    // give up the reservation as we still reuse the chunk at some point.
274f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    POOLED = 1u << 14,
275bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
276014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // |COMPACTION_WAS_ABORTED|: Indicates that the compaction in this page
277014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    //   has been aborted and needs special handling by the sweeper.
278f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    COMPACTION_WAS_ABORTED = 1u << 15,
279014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
28013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    // |COMPACTION_WAS_ABORTED_FOR_TESTING|: During stress testing evacuation
28113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    // on pages is sometimes aborted. The flag is used to avoid repeatedly
28213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    // triggering on the same page.
283f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    COMPACTION_WAS_ABORTED_FOR_TESTING = 1u << 16,
28413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
285bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    // |ANCHOR|: Flag is set if page is an anchor.
286f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    ANCHOR = 1u << 17,
287014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  };
288f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  typedef base::Flags<Flag, uintptr_t> Flags;
289f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
290f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  static const int kPointersToHereAreInterestingMask =
291f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      POINTERS_TO_HERE_ARE_INTERESTING;
292f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
293f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  static const int kPointersFromHereAreInterestingMask =
294f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      POINTERS_FROM_HERE_ARE_INTERESTING;
295f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
296f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  static const int kEvacuationCandidateMask = EVACUATION_CANDIDATE;
297f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
298f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  static const int kIsInNewSpaceMask = IN_FROM_SPACE | IN_TO_SPACE;
299f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
300f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  static const int kSkipEvacuationSlotsRecordingMask =
301f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      kEvacuationCandidateMask | kIsInNewSpaceMask;
302014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
303014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // |kSweepingDone|: The page state when sweeping is complete or sweeping must
304109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  //   not be performed on that page. Sweeper threads that are done with their
305109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  //   work will set this value and not touch the page anymore.
306f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch  // |kSweepingPending|: This page is ready for parallel sweeping.
307109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // |kSweepingInProgress|: This page is currently swept by a sweeper thread.
308109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  enum ConcurrentSweepingState {
309014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    kSweepingDone,
310109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    kSweepingPending,
311014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    kSweepingInProgress,
312014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  };
313014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
314014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static const intptr_t kAlignment =
315014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      (static_cast<uintptr_t>(1) << kPageSizeBits);
316014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
317014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static const intptr_t kAlignmentMask = kAlignment - 1;
318014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
319014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static const intptr_t kSizeOffset = 0;
32062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  static const intptr_t kFlagsOffset = kSizeOffset + kSizetSize;
32162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  static const intptr_t kAreaStartOffset = kFlagsOffset + kIntptrSize;
32262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  static const intptr_t kAreaEndOffset = kAreaStartOffset + kPointerSize;
32362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  static const intptr_t kReservationOffset = kAreaEndOffset + kPointerSize;
32462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  static const intptr_t kOwnerOffset = kReservationOffset + 2 * kPointerSize;
3253b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
326014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static const size_t kMinHeaderSize =
327c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      kSizeOffset + kSizetSize  // size_t size
328c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      + kIntptrSize             // Flags flags_
329c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      + kPointerSize            // Address area_start_
330c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      + kPointerSize            // Address area_end_
331c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      + 2 * kPointerSize        // base::VirtualMemory reservation_
332c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      + kPointerSize            // Address owner_
333c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      + kPointerSize            // Heap* heap_
334c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      + kIntSize                // int progress_bar_
335c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      + kIntSize                // int live_bytes_count_
336c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      + kPointerSize            // SlotSet* old_to_new_slots_
337c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      + kPointerSize            // SlotSet* old_to_old_slots_
338c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      + kPointerSize            // TypedSlotSet* typed_old_to_new_slots_
339c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      + kPointerSize            // TypedSlotSet* typed_old_to_old_slots_
340c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      + kPointerSize            // SkipList* skip_list_
341c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      + kPointerSize            // AtomicValue high_water_mark_
342c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      + kPointerSize            // base::Mutex* mutex_
343c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      + kPointerSize            // base::AtomicWord concurrent_sweeping_
344c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      + 2 * kSizetSize          // AtomicNumber free-list statistics
345c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      + kPointerSize            // AtomicValue next_chunk_
346c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      + kPointerSize            // AtomicValue prev_chunk_
3473b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      // FreeListCategory categories_[kNumberOfCategories]
34813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      + FreeListCategory::kSize * kNumberOfCategories +
349c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      kPointerSize;  // LocalArrayBufferTracker* local_tracker_
350014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
351014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // We add some more space to the computed header size to amount for missing
352014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // alignment requirements in our computation.
353014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Try to get kHeaderSize properly aligned on 32-bit and 64-bit machines.
354109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  static const size_t kHeaderSize = kMinHeaderSize;
355014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
356014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static const int kBodyOffset =
357014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      CODE_POINTER_ALIGN(kHeaderSize + Bitmap::kSize);
358014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
359014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // The start offset of the object area in a page. Aligned to both maps and
360014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // code alignment to be suitable for both.  Also aligned to 32 words because
361014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // the marking bitmap is arranged in 32 bit chunks.
362014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static const int kObjectStartAlignment = 32 * kPointerSize;
363014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static const int kObjectStartOffset =
364014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      kBodyOffset - 1 +
365014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      (kObjectStartAlignment - (kBodyOffset - 1) % kObjectStartAlignment);
366014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3673b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Page size in bytes.  This must be a multiple of the OS page size.
3683b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  static const int kPageSize = 1 << kPageSizeBits;
3693b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  static const intptr_t kPageAlignmentMask = (1 << kPageSizeBits) - 1;
3703b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
3713b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  static const int kAllocatableMemory = kPageSize - kObjectStartOffset;
372014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
37362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  static inline void IncrementLiveBytes(HeapObject* object, int by);
374014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
3753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Only works if the pointer is in the first kPageSize of the MemoryChunk.
3763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static MemoryChunk* FromAddress(Address a) {
3773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return reinterpret_cast<MemoryChunk*>(OffsetFrom(a) & ~kAlignmentMask);
3783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
379014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static inline MemoryChunk* FromAnyPointerAddress(Heap* heap, Address addr);
3813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
382014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static inline void UpdateHighWaterMark(Address mark) {
383014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (mark == nullptr) return;
384014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // Need to subtract one from the mark because when a chunk is full the
385014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // top points to the next address after the chunk, which effectively belongs
386bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    // to another chunk. See the comment to Page::FromTopOrLimit.
387014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    MemoryChunk* chunk = MemoryChunk::FromAddress(mark - 1);
388014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    intptr_t new_mark = static_cast<intptr_t>(mark - chunk->address());
389014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    intptr_t old_mark = 0;
390014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    do {
391014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      old_mark = chunk->high_water_mark_.Value();
392014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } while ((new_mark > old_mark) &&
393014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch             !chunk->high_water_mark_.TrySetValue(old_mark, new_mark));
394014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
395014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
396bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  static bool IsValid(MemoryChunk* chunk) { return chunk != nullptr; }
3973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
398bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Address address() { return reinterpret_cast<Address>(this); }
3993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
400109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  base::Mutex* mutex() { return mutex_; }
4013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool Contains(Address addr) {
4033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return addr >= area_start() && addr < area_end();
4043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
406109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Checks whether |addr| can be a limit of addresses in this page. It's a
407109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // limit if it's in the page, or if it's just after the last byte of the page.
4083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool ContainsLimit(Address addr) {
4093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return addr >= area_start() && addr <= area_end();
4103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
412bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  base::AtomicValue<ConcurrentSweepingState>& concurrent_sweeping_state() {
413109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    return concurrent_sweeping_;
414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
416c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  bool SweepingDone() {
417c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    return concurrent_sweeping_state().Value() == kSweepingDone;
418c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
419c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
420109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Manage live byte count, i.e., count of bytes in black objects.
421109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  inline void ResetLiveBytes();
422109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  inline void IncrementLiveBytes(int by);
423014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
4243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int LiveBytes() {
4253b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    DCHECK_LE(static_cast<unsigned>(live_byte_count_), size_);
4263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return live_byte_count_;
4273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
429014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void SetLiveBytes(int live_bytes) {
430014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK_GE(live_bytes, 0);
431109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    DCHECK_LE(static_cast<size_t>(live_bytes), size_);
432014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    live_byte_count_ = live_bytes;
433014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
434014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
435109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  size_t size() const { return size_; }
436f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  void set_size(size_t size) { size_ = size; }
437109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
438109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  inline Heap* heap() const { return heap_; }
439109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
440109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  inline SkipList* skip_list() { return skip_list_; }
441109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
442109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  inline void set_skip_list(SkipList* skip_list) { skip_list_ = skip_list; }
443109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
444f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  inline SlotSet* old_to_new_slots() { return old_to_new_slots_.Value(); }
445109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  inline SlotSet* old_to_old_slots() { return old_to_old_slots_; }
44613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  inline TypedSlotSet* typed_old_to_new_slots() {
447f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    return typed_old_to_new_slots_.Value();
44813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
4493b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  inline TypedSlotSet* typed_old_to_old_slots() {
4503b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    return typed_old_to_old_slots_;
4513b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
45213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  inline LocalArrayBufferTracker* local_tracker() { return local_tracker_; }
453109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
454f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  V8_EXPORT_PRIVATE void AllocateOldToNewSlots();
455109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  void ReleaseOldToNewSlots();
456c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  V8_EXPORT_PRIVATE void AllocateOldToOldSlots();
457109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  void ReleaseOldToOldSlots();
45813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  void AllocateTypedOldToNewSlots();
45913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  void ReleaseTypedOldToNewSlots();
4603b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void AllocateTypedOldToOldSlots();
4613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void ReleaseTypedOldToOldSlots();
46213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  void AllocateLocalTracker();
46313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  void ReleaseLocalTracker();
464109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
465109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Address area_start() { return area_start_; }
466109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Address area_end() { return area_end_; }
467c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  size_t area_size() { return static_cast<size_t>(area_end() - area_start()); }
468109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
469109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  bool CommitArea(size_t requested);
470109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
471109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Approximate amount of physical memory committed for this chunk.
472f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  size_t CommittedPhysicalMemory();
473109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
47413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Address HighWaterMark() { return address() + high_water_mark_.Value(); }
47513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int progress_bar() {
477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(IsFlagSet(HAS_PROGRESS_BAR));
478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return progress_bar_;
479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void set_progress_bar(int progress_bar) {
482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(IsFlagSet(HAS_PROGRESS_BAR));
483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    progress_bar_ = progress_bar;
484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void ResetProgressBar() {
487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (IsFlagSet(MemoryChunk::HAS_PROGRESS_BAR)) {
488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      set_progress_bar(0);
489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
492f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch  inline Bitmap* markbits() {
493f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch    return Bitmap::FromAddress(address() + kHeaderSize);
4948389745919cae02139ddc085a63c00d024269cf2Ben Murdoch  }
4958389745919cae02139ddc085a63c00d024269cf2Ben Murdoch
496f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch  inline uint32_t AddressToMarkbitIndex(Address addr) {
497f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch    return static_cast<uint32_t>(addr - this->address()) >> kPointerSizeLog2;
4988389745919cae02139ddc085a63c00d024269cf2Ben Murdoch  }
4998389745919cae02139ddc085a63c00d024269cf2Ben Murdoch
500f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch  inline Address MarkbitIndexToAddress(uint32_t index) {
501f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch    return this->address() + (index << kPointerSizeLog2);
502f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch  }
503f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch
504f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  void ClearLiveness();
505f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
506109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  void PrintMarkbits() { markbits()->Print(); }
507f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch
508f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  void SetFlag(Flag flag) { flags_ |= flag; }
509f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  void ClearFlag(Flag flag) { flags_ &= ~Flags(flag); }
510f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  bool IsFlagSet(Flag flag) { return flags_ & flag; }
511109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
512109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Set or clear multiple flags at a time. The flags in the mask are set to
513109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // the value in "flags", the rest retain the current value in |flags_|.
514f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  void SetFlags(uintptr_t flags, uintptr_t mask) {
515f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    flags_ = (flags_ & ~Flags(mask)) | (Flags(flags) & Flags(mask));
516109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
517109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
518109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Return all current flags.
519f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  uintptr_t GetFlags() { return flags_; }
5203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
521014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool NeverEvacuate() { return IsFlagSet(NEVER_EVACUATE); }
522014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
523014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void MarkNeverEvacuate() { SetFlag(NEVER_EVACUATE); }
5243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
525014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool IsEvacuationCandidate() {
526014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    DCHECK(!(IsFlagSet(NEVER_EVACUATE) && IsFlagSet(EVACUATION_CANDIDATE)));
527014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return IsFlagSet(EVACUATION_CANDIDATE);
528014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
529014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
530014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool CanAllocate() {
531014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return !IsEvacuationCandidate() && !IsFlagSet(NEVER_ALLOCATE_ON_PAGE);
532014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
5333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool ShouldSkipEvacuationSlotRecording() {
53513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    return ((flags_ & kSkipEvacuationSlotsRecordingMask) != 0) &&
53613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch           !IsFlagSet(COMPACTION_WAS_ABORTED);
5373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
5383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
539109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Executability executable() {
540109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    return IsFlagSet(IS_EXECUTABLE) ? EXECUTABLE : NOT_EXECUTABLE;
541109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
5423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
543f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  bool InNewSpace() { return (flags_ & kIsInNewSpaceMask) != 0; }
5448389745919cae02139ddc085a63c00d024269cf2Ben Murdoch
545109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  bool InToSpace() { return IsFlagSet(IN_TO_SPACE); }
5468389745919cae02139ddc085a63c00d024269cf2Ben Murdoch
547109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  bool InFromSpace() { return IsFlagSet(IN_FROM_SPACE); }
5488389745919cae02139ddc085a63c00d024269cf2Ben Murdoch
549109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  MemoryChunk* next_chunk() { return next_chunk_.Value(); }
5503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
551109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  MemoryChunk* prev_chunk() { return prev_chunk_.Value(); }
552109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
553109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  void set_next_chunk(MemoryChunk* next) { next_chunk_.SetValue(next); }
554109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
555109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  void set_prev_chunk(MemoryChunk* prev) { prev_chunk_.SetValue(prev); }
556109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
557109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Space* owner() const {
55862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    intptr_t owner_value = base::NoBarrierAtomicValue<intptr_t>::FromAddress(
55962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                               const_cast<Address*>(&owner_))
56062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                               ->Value();
56162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if ((owner_value & kPageHeaderTagMask) == kPageHeaderTag) {
56262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      return reinterpret_cast<Space*>(owner_value - kPageHeaderTag);
563109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    } else {
564109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      return nullptr;
565109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    }
5668389745919cae02139ddc085a63c00d024269cf2Ben Murdoch  }
567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
568109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  void set_owner(Space* space) {
569109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    DCHECK((reinterpret_cast<intptr_t>(space) & kPageHeaderTagMask) == 0);
570109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    owner_ = reinterpret_cast<Address>(space) + kPageHeaderTag;
571109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    DCHECK((reinterpret_cast<intptr_t>(owner_) & kPageHeaderTagMask) ==
572109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch           kPageHeaderTag);
573109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
5743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
575109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  bool HasPageHeader() { return owner() != nullptr; }
5768389745919cae02139ddc085a63c00d024269cf2Ben Murdoch
577109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  void InsertAfter(MemoryChunk* other);
578109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  void Unlink();
5798389745919cae02139ddc085a63c00d024269cf2Ben Murdoch
580f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch protected:
581f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch  static MemoryChunk* Initialize(Heap* heap, Address base, size_t size,
582f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch                                 Address area_start, Address area_end,
583109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                 Executability executable, Space* owner,
584109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch                                 base::VirtualMemory* reservation);
585109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
586109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Should be called when memory chunk is about to be freed.
587109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  void ReleaseAllocatedMemory();
588109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
589109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  base::VirtualMemory* reserved_memory() { return &reservation_; }
590014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
5913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  size_t size_;
592f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Flags flags_;
5933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Start and end of allocatable memory on this chunk.
5953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Address area_start_;
5963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Address area_end_;
5973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // If the chunk needs to remember its memory reservation, it is stored here.
599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  base::VirtualMemory reservation_;
600109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
6013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The identity of the owning space.  This is tagged as a failure pointer, but
6023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // no failure can be in an object, so this can be distinguished from any entry
6033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // in a fixed array.
6043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Address owner_;
605109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
6063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Heap* heap_;
607109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
608109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Used by the incremental marker to keep track of the scanning progress in
609109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // large objects that have a progress bar and are scanned in increments.
610109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  int progress_bar_;
611109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
6123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Count of bytes marked black on page.
6133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int live_byte_count_;
614109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
615109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // A single slot set for small pages (of size kPageSize) or an array of slot
616109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // set for large pages. In the latter case the number of entries in the array
617109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // is ceil(size() / kPageSize).
618f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  base::AtomicValue<SlotSet*> old_to_new_slots_;
619109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  SlotSet* old_to_old_slots_;
620f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  base::AtomicValue<TypedSlotSet*> typed_old_to_new_slots_;
6213b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  TypedSlotSet* typed_old_to_old_slots_;
622109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
6233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  SkipList* skip_list_;
624109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Assuming the initial allocation on a page is sequential,
626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // count highest number of bytes ever allocated on the page.
627bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  base::AtomicValue<intptr_t> high_water_mark_;
628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
629014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  base::Mutex* mutex_;
630109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
631bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  base::AtomicValue<ConcurrentSweepingState> concurrent_sweeping_;
632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // PagedSpace free-list statistics.
634bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  base::AtomicNumber<intptr_t> available_in_free_list_;
635bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  base::AtomicNumber<intptr_t> wasted_memory_;
6363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // next_chunk_ holds a pointer of type MemoryChunk
638bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  base::AtomicValue<MemoryChunk*> next_chunk_;
639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // prev_chunk_ holds a pointer of type MemoryChunk
640bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  base::AtomicValue<MemoryChunk*> prev_chunk_;
641014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
6423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  FreeListCategory categories_[kNumberOfCategories];
6433b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
64413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  LocalArrayBufferTracker* local_tracker_;
64513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
646014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch private:
647014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void InitializeReservedMemory() { reservation_.Reset(); }
6483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  friend class MemoryAllocator;
650014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  friend class MemoryChunkValidator;
6513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch};
6523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
653f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben MurdochDEFINE_OPERATORS_FOR_FLAGS(MemoryChunk::Flags)
654f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
655f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochstatic_assert(kMaxRegularHeapObjectSize <= MemoryChunk::kAllocatableMemory,
656f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch              "kMaxRegularHeapObjectSize <= MemoryChunk::kAllocatableMemory");
657f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// -----------------------------------------------------------------------------
6593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// A page is a memory chunk of a size 1MB. Large object pages may be larger.
660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The only way to get a page pointer is by calling factory methods:
662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//   Page* p = Page::FromAddress(addr); or
663bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch//   Page* p = Page::FromTopOrLimit(top);
6643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochclass Page : public MemoryChunk {
665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
666bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  static const intptr_t kCopyAllFlags = ~0;
667bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
668bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Page flags copied from from-space to to-space when flipping semispaces.
669bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  static const intptr_t kCopyOnFlipFlagsMask =
670f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      static_cast<intptr_t>(MemoryChunk::POINTERS_TO_HERE_ARE_INTERESTING) |
671f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      static_cast<intptr_t>(MemoryChunk::POINTERS_FROM_HERE_ARE_INTERESTING);
672bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
673c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  static inline Page* ConvertNewToOld(Page* old_page);
674bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Returns the page containing a given address. The address ranges
676bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // from [page_addr .. page_addr + kPageSize[. This only works if the object
677bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // is in fact in a page.
678bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  static Page* FromAddress(Address addr) {
679bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    return reinterpret_cast<Page*>(OffsetFrom(addr) & ~kPageAlignmentMask);
680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
682bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Returns the page containing the address provided. The address can
683bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // potentially point righter after the page. To be also safe for tagged values
684bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // we subtract a hole word. The valid address ranges from
685bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // [page_addr + kObjectStartOffset .. page_addr + kPageSize + kPointerSize].
686bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  static Page* FromAllocationAreaAddress(Address address) {
687bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    return Page::FromAddress(address - kPointerSize);
688bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
689109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
690bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Checks if address1 and address2 are on the same new space page.
691bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  static bool OnSamePage(Address address1, Address address2) {
692bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    return Page::FromAddress(address1) == Page::FromAddress(address2);
693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
695bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Checks whether an address is page aligned.
696bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  static bool IsAlignedToPageSize(Address addr) {
697bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    return (OffsetFrom(addr) & kPageAlignmentMask) == 0;
698014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
699bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
700bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  static bool IsAtObjectStart(Address addr) {
701bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    return (reinterpret_cast<intptr_t>(addr) & kPageAlignmentMask) ==
702bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch           kObjectStartOffset;
703014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
705bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  inline static Page* FromAnyPointerAddress(Heap* heap, Address addr);
706bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
707bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Create a Page object that is only used as anchor for the doubly-linked
708bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // list of real pages.
709bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  explicit Page(Space* owner) { InitializeAsAnchor(owner); }
710bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
711bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  inline void MarkNeverAllocateForTesting();
712bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  inline void MarkEvacuationCandidate();
713bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  inline void ClearEvacuationCandidate();
714bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
715bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Page* next_page() { return static_cast<Page*>(next_chunk()); }
716bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Page* prev_page() { return static_cast<Page*>(prev_chunk()); }
717bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  void set_next_page(Page* page) { set_next_chunk(page); }
718bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  void set_prev_page(Page* page) { set_prev_chunk(page); }
719bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
720bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  template <typename Callback>
721bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  inline void ForAllFreeListCategories(Callback callback) {
722bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    for (int i = kFirstCategory; i < kNumberOfCategories; i++) {
723bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      callback(&categories_[i]);
724bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    }
725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Returns the offset of a given address to this page.
728c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  inline size_t Offset(Address a) { return static_cast<size_t>(a - address()); }
729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Returns the address for a given offset to the this page.
731c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Address OffsetToAddress(size_t offset) {
732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK_PAGE_OFFSET(offset);
733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return address() + offset;
734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
736109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // WaitUntilSweepingCompleted only works when concurrent sweeping is in
737109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // progress. In particular, when we know that right before this call a
738109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // sweeper thread was sweeping this page.
739109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  void WaitUntilSweepingCompleted() {
740109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    mutex_->Lock();
741109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    mutex_->Unlock();
742109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    DCHECK(SweepingDone());
743109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
744109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void ResetFreeListStatistics();
7467f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
747c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  size_t AvailableInFreeList();
748c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
749c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  size_t LiveBytesFromFreeList() {
750c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    DCHECK_GE(area_size(), wasted_memory() + available_in_free_list());
751c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    return area_size() - wasted_memory() - available_in_free_list();
752014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
753014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
7543b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  FreeListCategory* free_list_category(FreeListCategoryType type) {
7553b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    return &categories_[type];
7563b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
7573b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
758bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  bool is_anchor() { return IsFlagSet(Page::ANCHOR); }
759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
760c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  size_t wasted_memory() { return wasted_memory_.Value(); }
761c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  void add_wasted_memory(size_t waste) { wasted_memory_.Increment(waste); }
762c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  size_t available_in_free_list() { return available_in_free_list_.Value(); }
763c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  void add_available_in_free_list(size_t available) {
764c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    DCHECK_LE(available, area_size());
765bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    available_in_free_list_.Increment(available);
766bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
767c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  void remove_available_in_free_list(size_t available) {
768c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    DCHECK_LE(available, area_size());
769c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    DCHECK_GE(available_in_free_list(), available);
770c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    available_in_free_list_.Decrement(available);
771c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
7727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
773f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  size_t ShrinkToHighWaterMark();
774f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
77562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  void CreateBlackArea(Address start, Address end);
77662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
7773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifdef DEBUG
7783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void Print();
7793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif  // DEBUG
7807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
7813b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch private:
782bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  enum InitializationMode { kFreeMemory, kDoNotFreeMemory };
783bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
784bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  template <InitializationMode mode = kFreeMemory>
785bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  static inline Page* Initialize(Heap* heap, MemoryChunk* chunk,
786bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                                 Executability executable, PagedSpace* owner);
787bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  static inline Page* Initialize(Heap* heap, MemoryChunk* chunk,
788bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                                 Executability executable, SemiSpace* owner);
789bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
7903b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  inline void InitializeFreeListCategories();
7913b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
792bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  void InitializeAsAnchor(Space* owner);
793bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
7943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  friend class MemoryAllocator;
7953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch};
7967f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
7973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochclass LargePage : public MemoryChunk {
7983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch public:
799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HeapObject* GetObject() { return HeapObject::FromAddress(area_start()); }
800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
801014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline LargePage* next_page() {
8023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return static_cast<LargePage*>(next_chunk());
8033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
80444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  inline void set_next_page(LargePage* page) { set_next_chunk(page); }
806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
807f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Uncommit memory that is not in use anymore by the object. If the object
808f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // cannot be shrunk 0 is returned.
809f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Address GetAddressToShrink();
810f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
811f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  void ClearOutOfLiveRangeSlots(Address free_start);
812f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
8133b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // A limit to guarantee that we do not overflow typed slot offset in
8143b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // the old to old remembered set.
8153b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Note that this limit is higher than what assembler already imposes on
8163b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // x64 and ia32 architectures.
8173b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  static const int kMaxCodePageSize = 512 * MB;
8183b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
8193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch private:
820bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  static inline LargePage* Initialize(Heap* heap, MemoryChunk* chunk,
821bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                                      Executability executable, Space* owner);
82285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
8233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  friend class MemoryAllocator;
824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ----------------------------------------------------------------------------
828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Space is the abstract superclass for all allocation spaces.
829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass Space : public Malloced {
830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
83144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Space(Heap* heap, AllocationSpace id, Executability executable)
832109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      : allocation_observers_(new List<AllocationObserver*>()),
833109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        allocation_observers_paused_(false),
834109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        heap_(heap),
835014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        id_(id),
836014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        executable_(executable),
837014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        committed_(0),
838014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        max_committed_(0) {}
839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual ~Space() {}
841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
84244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Heap* heap() const { return heap_; }
84344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Does the space need executable memory?
845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Executability executable() { return executable_; }
846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Identity used in error reporting.
848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AllocationSpace identity() { return id_; }
849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
850109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  virtual void AddAllocationObserver(AllocationObserver* observer) {
851109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    allocation_observers_->Add(observer);
852109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
853109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
854109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  virtual void RemoveAllocationObserver(AllocationObserver* observer) {
855109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    bool removed = allocation_observers_->RemoveElement(observer);
856109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    USE(removed);
857109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    DCHECK(removed);
858109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
859109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
860109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  virtual void PauseAllocationObservers() {
861109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    allocation_observers_paused_ = true;
862109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
863109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
864109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  virtual void ResumeAllocationObservers() {
865109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    allocation_observers_paused_ = false;
866109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
867109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
868109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  void AllocationStep(Address soon_object, int size);
869109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
870014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Return the total amount committed memory for this space, i.e., allocatable
871014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // memory and page headers.
872f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  virtual size_t CommittedMemory() { return committed_; }
873014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
874f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  virtual size_t MaximumCommittedMemory() { return max_committed_; }
875014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
8768a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Returns allocated size.
877c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  virtual size_t Size() = 0;
878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8798a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // Returns size of objects. Can differ from the allocated size
8808a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang  // (e.g. see LargeObjectSpace).
881c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  virtual size_t SizeOfObjects() { return Size(); }
8828a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
883014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Approximate amount of physical memory committed for this space.
884014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  virtual size_t CommittedPhysicalMemory() = 0;
885014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
886014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Return the available bytes without growing.
887c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  virtual size_t Available() = 0;
888014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
8893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  virtual int RoundSizeDownToObjectAlignment(int size) {
8903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (id_ == CODE_SPACE) {
8913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return RoundDown(size, kCodeAlignment);
8923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
8933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return RoundDown(size, kPointerSize);
8943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
8953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
8963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
897f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  virtual std::unique_ptr<ObjectIterator> GetObjectIterator() = 0;
898f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
899f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  void AccountCommitted(size_t bytes) {
900f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    DCHECK_GE(committed_ + bytes, committed_);
901014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    committed_ += bytes;
902014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (committed_ > max_committed_) {
903014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      max_committed_ = committed_;
904014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
905014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
906014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
907f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  void AccountUncommitted(size_t bytes) {
908f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    DCHECK_GE(committed_, committed_ - bytes);
909014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    committed_ -= bytes;
910014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
911014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
912bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch#ifdef DEBUG
913bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  virtual void Print() = 0;
914bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch#endif
915bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
916bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch protected:
917f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  std::unique_ptr<List<AllocationObserver*>> allocation_observers_;
918109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  bool allocation_observers_paused_;
919109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
92144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Heap* heap_;
922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AllocationSpace id_;
923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Executability executable_;
924014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
925014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Keeps track of committed memory in a space.
926f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  size_t committed_;
927f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  size_t max_committed_;
928f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
929f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DISALLOW_COPY_AND_ASSIGN(Space);
930014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch};
931014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
932014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
933014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochclass MemoryChunkValidator {
934014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Computed offsets should match the compiler generated ones.
935014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  STATIC_ASSERT(MemoryChunk::kSizeOffset == offsetof(MemoryChunk, size_));
936014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
937014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Validate our estimates on the header size.
938014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  STATIC_ASSERT(sizeof(MemoryChunk) <= MemoryChunk::kHeaderSize);
939014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  STATIC_ASSERT(sizeof(LargePage) <= MemoryChunk::kHeaderSize);
940014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  STATIC_ASSERT(sizeof(Page) <= MemoryChunk::kHeaderSize);
941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ----------------------------------------------------------------------------
945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// All heap objects containing executable code (code objects) must be allocated
946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// from a 2 GB range of memory, so that they can call each other using 32-bit
947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// displacements.  This happens automatically on 32-bit platforms, where 32-bit
948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// displacements cover the entire 4GB virtual address space.  On 64-bit
949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// platforms, we support this using the CodeRange object, which reserves and
950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// manages a range of virtual memory.
95144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockclass CodeRange {
952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
95369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  explicit CodeRange(Isolate* isolate);
95469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  ~CodeRange() { TearDown(); }
95569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Reserves a range of virtual memory, but does not commit any of it.
957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Can only be called once, at heap initialization time.
958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Returns false on failure.
959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool SetUp(size_t requested_size);
960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool valid() { return code_range_ != NULL; }
962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Address start() {
963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(valid());
964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return static_cast<Address>(code_range_->address());
965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
966958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  size_t size() {
967958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(valid());
968958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return code_range_->size();
969958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
97044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  bool contains(Address address) {
971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (!valid()) return false;
972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Address start = static_cast<Address>(code_range_->address());
973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return start <= address && address < start + code_range_->size();
974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Allocates a chunk of memory from the large-object portion of
977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the code range.  On platforms with no separate code range, should
978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // not be called.
979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MUST_USE_RESULT Address AllocateRawMemory(const size_t requested_size,
980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                            const size_t commit_size,
9813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                            size_t* allocated);
982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool CommitRawMemory(Address start, size_t length);
983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool UncommitRawMemory(Address start, size_t length);
9843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void FreeRawMemory(Address buf, size_t length);
985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  class FreeBlock {
988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block   public:
989958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    FreeBlock() : start(0), size(0) {}
990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    FreeBlock(Address start_arg, size_t size_arg)
9913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        : start(start_arg), size(size_arg) {
992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(IsAddressAligned(start, MemoryChunk::kAlignment));
993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(size >= static_cast<size_t>(Page::kPageSize));
9943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    FreeBlock(void* start_arg, size_t size_arg)
9963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        : start(static_cast<Address>(start_arg)), size(size_arg) {
997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(IsAddressAligned(start, MemoryChunk::kAlignment));
998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(size >= static_cast<size_t>(Page::kPageSize));
9993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
1000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Address start;
1002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    size_t size;
1003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  };
1004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
100513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // Frees the range of virtual memory, and frees the data structures used to
100613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // manage it.
100713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  void TearDown();
100813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
100913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // Finds a block on the allocation list that contains at least the
101013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // requested amount of memory.  If none is found, sorts and merges
101113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // the existing free memory blocks, and searches again.
101213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // If none can be found, returns false.
101313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  bool GetNextAllocationBlock(size_t requested);
101413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // Compares the start addresses of two free blocks.
101513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  static int CompareFreeBlockAddress(const FreeBlock* left,
101613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch                                     const FreeBlock* right);
101713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  bool ReserveBlock(const size_t requested_size, FreeBlock* block);
101813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  void ReleaseBlock(const FreeBlock* block);
101913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
102013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Isolate* isolate_;
102113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
102213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // The reserved range of virtual memory that all code objects are put in.
102313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  base::VirtualMemory* code_range_;
102413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
1025014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // The global mutex guards free_list_ and allocation_list_ as GC threads may
1026014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // access both lists concurrently to the main thread.
1027014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  base::Mutex code_range_mutex_;
1028014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Freed blocks of memory are added to the free list.  When the allocation
1030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // list is exhausted, the free list is sorted and merged to make the new
1031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // allocation list.
103244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  List<FreeBlock> free_list_;
1033014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Memory is allocated from the free blocks on the allocation list.
1035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The block at current_allocation_block_index_ is the current block.
103644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  List<FreeBlock> allocation_list_;
103744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int current_allocation_block_index_;
1038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
103944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  DISALLOW_COPY_AND_ASSIGN(CodeRange);
1040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
1041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochclass SkipList {
10443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch public:
1045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SkipList() { Clear(); }
10463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void Clear() {
10483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    for (int idx = 0; idx < kSize; idx++) {
10493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      starts_[idx] = reinterpret_cast<Address>(-1);
10503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
10513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
10523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Address StartFor(Address addr) { return starts_[RegionNumber(addr)]; }
10543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void AddObject(Address addr, int size) {
10563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int start_region = RegionNumber(addr);
10573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int end_region = RegionNumber(addr + size - kPointerSize);
10583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    for (int idx = start_region; idx <= end_region; idx++) {
10593b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      if (starts_[idx] > addr) {
10603b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        starts_[idx] = addr;
10613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      } else {
10623b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        // In the first region, there may already be an object closer to the
10633b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        // start of the region. Do not change the start in that case. If this
10643b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        // is not the first region, you probably added overlapping objects.
10653b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        DCHECK_EQ(start_region, idx);
10663b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      }
10673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
10683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
10693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static inline int RegionNumber(Address addr) {
10713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return (OffsetFrom(addr) & Page::kPageAlignmentMask) >> kRegionSizeLog2;
10723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
10733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static void Update(Address addr, int size) {
10753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Page* page = Page::FromAddress(addr);
10763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    SkipList* list = page->skip_list();
10773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (list == NULL) {
10783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      list = new SkipList();
10793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      page->set_skip_list(list);
10803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
10813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    list->AddObject(addr, size);
10833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
10843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch private:
10863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static const int kRegionSizeLog2 = 13;
10873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static const int kRegionSize = 1 << kRegionSizeLog2;
10883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static const int kSize = Page::kPageSize / kRegionSize;
10893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT(Page::kPageSize % kRegionSize == 0);
10913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Address starts_[kSize];
10933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch};
10943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ----------------------------------------------------------------------------
1097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A space acquires chunks of memory from the operating system. The memory
1098c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch// allocator allocates and deallocates pages for the paged heap spaces and large
10993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// pages for large object space.
110062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochclass V8_EXPORT_PRIVATE MemoryAllocator {
1101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
1102bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Unmapper takes care of concurrently unmapping and uncommitting memory
1103bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // chunks.
1104bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  class Unmapper {
1105bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch   public:
1106bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    class UnmapFreeMemoryTask;
1107bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1108bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    explicit Unmapper(MemoryAllocator* allocator)
1109bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        : allocator_(allocator),
1110bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          pending_unmapping_tasks_semaphore_(0),
111162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          concurrent_unmapping_tasks_active_(0) {
111262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      chunks_[kRegular].reserve(kReservedQueueingSlots);
111362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      chunks_[kPooled].reserve(kReservedQueueingSlots);
111462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    }
1115bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1116bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    void AddMemoryChunkSafe(MemoryChunk* chunk) {
1117bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      if ((chunk->size() == Page::kPageSize) &&
1118bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          (chunk->executable() != EXECUTABLE)) {
1119bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        AddMemoryChunkSafe<kRegular>(chunk);
1120bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      } else {
1121bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        AddMemoryChunkSafe<kNonRegular>(chunk);
1122bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      }
1123bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    }
1124bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1125bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    MemoryChunk* TryGetPooledMemoryChunkSafe() {
1126bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      // Procedure:
1127bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      // (1) Try to get a chunk that was declared as pooled and already has
1128bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      // been uncommitted.
1129bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      // (2) Try to steal any memory chunk of kPageSize that would've been
1130bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      // unmapped.
1131bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      MemoryChunk* chunk = GetMemoryChunkSafe<kPooled>();
1132bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      if (chunk == nullptr) {
1133bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        chunk = GetMemoryChunkSafe<kRegular>();
1134bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        if (chunk != nullptr) {
1135bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          // For stolen chunks we need to manually free any allocated memory.
1136bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch          chunk->ReleaseAllocatedMemory();
1137bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch        }
1138bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      }
1139bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      return chunk;
1140bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    }
1141bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1142bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    void FreeQueuedChunks();
1143bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    bool WaitUntilCompleted();
1144c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    void TearDown();
1145bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1146bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch   private:
114762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    static const int kReservedQueueingSlots = 64;
114862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
1149bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    enum ChunkQueueType {
1150bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      kRegular,     // Pages of kPageSize that do not live in a CodeRange and
1151bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch                    // can thus be used for stealing.
1152bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      kNonRegular,  // Large chunks and executable chunks.
1153bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      kPooled,      // Pooled chunks, already uncommited and ready for reuse.
1154bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      kNumberOfChunkQueues,
1155bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    };
1156bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
115762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    enum class FreeMode {
115862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      kUncommitPooled,
115962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      kReleasePooled,
116062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    };
116162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
1162bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    template <ChunkQueueType type>
1163bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    void AddMemoryChunkSafe(MemoryChunk* chunk) {
1164bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      base::LockGuard<base::Mutex> guard(&mutex_);
116513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      if (type != kRegular || allocator_->CanFreeMemoryChunk(chunk)) {
116613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        chunks_[type].push_back(chunk);
116713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      } else {
116813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        DCHECK_EQ(type, kRegular);
116913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        delayed_regular_chunks_.push_back(chunk);
117013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      }
1171bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    }
1172bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1173bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    template <ChunkQueueType type>
1174bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    MemoryChunk* GetMemoryChunkSafe() {
1175bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      base::LockGuard<base::Mutex> guard(&mutex_);
1176bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      if (chunks_[type].empty()) return nullptr;
117762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      MemoryChunk* chunk = chunks_[type].back();
117862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      chunks_[type].pop_back();
1179bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      return chunk;
1180bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    }
1181bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
118213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    void ReconsiderDelayedChunks();
118362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    template <FreeMode mode>
1184bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    void PerformFreeMemoryOnQueuedChunks();
1185bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1186bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    base::Mutex mutex_;
1187bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    MemoryAllocator* allocator_;
118862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    std::vector<MemoryChunk*> chunks_[kNumberOfChunkQueues];
118913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    // Delayed chunks cannot be processed in the current unmapping cycle because
119013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    // of dependencies such as an active sweeper.
119113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    // See MemoryAllocator::CanFreeMemoryChunk.
119213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    std::list<MemoryChunk*> delayed_regular_chunks_;
1193bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    base::Semaphore pending_unmapping_tasks_semaphore_;
1194bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    intptr_t concurrent_unmapping_tasks_active_;
1195bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1196bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    friend class MemoryAllocator;
1197bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  };
1198bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
11993b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  enum AllocationMode {
12003b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    kRegular,
12013b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    kPooled,
12023b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  };
1203f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
1204bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  enum FreeMode {
1205bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    kFull,
120662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    kAlreadyPooled,
1207bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    kPreFreeAndQueue,
1208bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    kPooledAndQueue,
1209bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  };
12103b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
1211c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  static size_t CodePageGuardStartOffset();
1212f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
1213c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  static size_t CodePageGuardSize();
1214f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
1215c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  static size_t CodePageAreaStartOffset();
1216f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
1217c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  static size_t CodePageAreaEndOffset();
1218f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
1219c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  static size_t CodePageAreaSize() {
1220f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    return CodePageAreaEndOffset() - CodePageAreaStartOffset();
1221f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  }
1222f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
1223c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  static size_t PageAreaSize(AllocationSpace space) {
1224f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    DCHECK_NE(LO_SPACE, space);
1225f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    return (space == CODE_SPACE) ? CodePageAreaSize()
1226f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch                                 : Page::kAllocatableMemory;
1227f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  }
1228f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
1229c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  static intptr_t GetCommitPageSize();
1230c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
123169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  explicit MemoryAllocator(Isolate* isolate);
123269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
1233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Initializes its internal bookkeeping structures.
123490bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner  // Max capacity of the total space and executable memory limit.
1235c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  bool SetUp(size_t max_capacity, size_t capacity_executable,
1236c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch             size_t code_range_size);
1237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
123844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void TearDown();
1239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1240bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // Allocates a Page from the allocator. AllocationMode is used to indicate
1241bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // whether pooled allocation, which only works for MemoryChunk::kPageSize,
1242bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // should be tried first.
1243bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  template <MemoryAllocator::AllocationMode alloc_mode = kRegular,
12443b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch            typename SpaceType>
1245c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Page* AllocatePage(size_t size, SpaceType* owner, Executability executable);
12463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1247c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  LargePage* AllocateLargePage(size_t size, LargeObjectSpace* owner,
1248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               Executability executable);
12493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1250bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  template <MemoryAllocator::FreeMode mode = kFull>
1251014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Free(MemoryChunk* chunk);
12523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
125313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  bool CanFreeMemoryChunk(MemoryChunk* chunk);
125413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
12553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Returns allocated spaces in bytes.
1256f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  size_t Size() { return size_.Value(); }
1257014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1258014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Returns allocated executable spaces in bytes.
1259f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  size_t SizeExecutable() { return size_executable_.Value(); }
1260014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1261014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Returns the maximum available bytes of heaps.
1262f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  size_t Available() {
1263f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    const size_t size = Size();
1264014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return capacity_ < size ? 0 : capacity_ - size;
1265014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
12663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Returns the maximum available executable bytes of heaps.
1268f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  size_t AvailableExecutable() {
1269f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch    const size_t executable_size = SizeExecutable();
1270014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (capacity_executable_ < executable_size) return 0;
1271014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return capacity_executable_ - executable_size;
12723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
12733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Returns maximum available bytes that the old space can have.
1275f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  size_t MaxAvailable() {
1276014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return (Available() / Page::kPageSize) * Page::kAllocatableMemory;
1277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Returns an indication of whether a pointer is in a space that has
1280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // been allocated by this MemoryAllocator.
1281014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  V8_INLINE bool IsOutsideAllocatedSpace(const void* address) {
1282014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return address < lowest_ever_allocated_.Value() ||
1283014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch           address >= highest_ever_allocated_.Value();
12843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
12853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Returns a MemoryChunk in which the memory region from commit_area_size to
1287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // reserve_area_size of the chunk area is reserved but not committed, it
1288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // could be committed later by calling MemoryChunk::CommitArea.
1289c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  MemoryChunk* AllocateChunk(size_t reserve_area_size, size_t commit_area_size,
1290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                             Executability executable, Space* space);
1291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1292f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  void ShrinkChunk(MemoryChunk* chunk, size_t bytes_to_shrink);
1293f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
1294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Address ReserveAlignedMemory(size_t requested, size_t alignment,
1295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                               base::VirtualMemory* controller);
1296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Address AllocateAlignedMemory(size_t reserve_size, size_t commit_size,
1297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                size_t alignment, Executability executable,
1298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                base::VirtualMemory* controller);
12993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool CommitMemory(Address addr, size_t size, Executability executable);
13013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void FreeMemory(base::VirtualMemory* reservation, Executability executable);
1303f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  void PartialFreeMemory(MemoryChunk* chunk, Address start_free);
13043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void FreeMemory(Address addr, size_t size, Executability executable);
1305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Commit a contiguous block of memory from the initial chunk.  Assumes that
1307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the address is not NULL, the size is greater than zero, and that the
1308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // block is contained in the initial chunk.  Returns true if it succeeded
1309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // and false otherwise.
131044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  bool CommitBlock(Address start, size_t size, Executability executable);
1311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Uncommit a contiguous block of memory [start..(start+size)[.
1313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // start is not NULL, the size is greater than zero, and the
1314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // block is contained in the initial chunk.  Returns true if it succeeded
1315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // and false otherwise.
131644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  bool UncommitBlock(Address start, size_t size);
1317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13184515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // Zaps a contiguous block of memory [start..(start+size)[ thus
13194515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  // filling it up with a recognizable non-NULL bit pattern.
132044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void ZapBlock(Address start, size_t size);
13214515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
1322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MUST_USE_RESULT bool CommitExecutableMemory(base::VirtualMemory* vm,
1323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                              Address start, size_t commit_size,
1324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch                                              size_t reserved_size);
1325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1326bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  CodeRange* code_range() { return code_range_; }
1327bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Unmapper* unmapper() { return &unmapper_; }
1328bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1329f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#ifdef DEBUG
1330f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Reports statistic info of the space.
1331f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  void ReportStatistics();
1332f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#endif
1333f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
1334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
1335bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // PreFree logically frees the object, i.e., it takes care of the size
1336bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // bookkeeping and calls the allocation callback.
1337bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  void PreFreeMemory(MemoryChunk* chunk);
1338bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1339bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  // FreeMemory can be called concurrently when PreFree was executed before.
1340bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  void PerformFreeMemory(MemoryChunk* chunk);
1341bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
13423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // See AllocatePage for public interface. Note that currently we only support
13433b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // pools for NOT_EXECUTABLE pages of size MemoryChunk::kPageSize.
13443b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  template <typename SpaceType>
13453b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  MemoryChunk* AllocatePagePooled(SpaceType* owner);
13463b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
1347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Initializes pages in a chunk. Returns the first page address.
1348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // This function and GetChunkId() are provided for the mark-compact
1349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // collector to rebuild page headers in the from space, which is
1350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // used as a marking stack and its page headers are destroyed.
135144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Page* InitializePagesInChunk(int chunk_id, int pages_in_chunk,
135244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                               PagedSpace* owner);
13536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void UpdateAllocatedSpaceLimits(void* low, void* high) {
1355014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // The use of atomic primitives does not guarantee correctness (wrt.
1356014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // desired semantics) by default. The loop here ensures that we update the
1357014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    // values only if they did not change in between.
1358014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    void* ptr = nullptr;
1359014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    do {
1360014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      ptr = lowest_ever_allocated_.Value();
1361014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } while ((low < ptr) && !lowest_ever_allocated_.TrySetValue(ptr, low));
1362014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    do {
1363014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      ptr = highest_ever_allocated_.Value();
1364014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    } while ((high > ptr) && !highest_ever_allocated_.TrySetValue(ptr, high));
1365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1367f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  Isolate* isolate_;
1368f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  CodeRange* code_range_;
1369f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
1370f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Maximum space size in bytes.
1371f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  size_t capacity_;
1372f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Maximum subset of capacity_ that can be executable
1373f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  size_t capacity_executable_;
1374f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
1375f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Allocated space size in bytes.
1376f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  base::AtomicNumber<size_t> size_;
1377f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Allocated executable space size in bytes.
1378f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  base::AtomicNumber<size_t> size_executable_;
1379f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
1380f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // We keep the lowest and highest addresses allocated as a quick way
1381f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // of determining that pointers are outside the heap. The estimate is
1382f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // conservative, i.e. not all addresses in 'allocated' space are allocated
1383f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // to our heap. The range is [lowest, highest[, inclusive on the low end
1384f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // and exclusive on the high end.
1385f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  base::AtomicValue<void*> lowest_ever_allocated_;
1386f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  base::AtomicValue<void*> highest_ever_allocated_;
1387f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
1388bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  base::VirtualMemory last_chunk_;
1389bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Unmapper unmapper_;
1390bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
1391bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  friend class TestCodeRangeScope;
13923b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
13933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DISALLOW_IMPLICIT_CONSTRUCTORS(MemoryAllocator);
1394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
1395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
139662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochextern template Page*
139762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochMemoryAllocator::AllocatePage<MemoryAllocator::kRegular, PagedSpace>(
139862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    size_t size, PagedSpace* owner, Executability executable);
139962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochextern template Page*
140062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochMemoryAllocator::AllocatePage<MemoryAllocator::kRegular, SemiSpace>(
140162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    size_t size, SemiSpace* owner, Executability executable);
140262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochextern template Page*
140362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochMemoryAllocator::AllocatePage<MemoryAllocator::kPooled, SemiSpace>(
140462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    size_t size, SemiSpace* owner, Executability executable);
1405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// -----------------------------------------------------------------------------
1407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Interface for heap object iterator to be implemented by all object space
1408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// object iterators.
1409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
1410d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// NOTE: The space specific object iterators also implements the own next()
1411d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke//       method which is used to avoid using virtual functions
1412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       iterating a specific space.
1413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1414f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochclass V8_EXPORT_PRIVATE ObjectIterator : public Malloced {
1415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
1416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  virtual ~ObjectIterator() {}
141713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  virtual HeapObject* Next() = 0;
141813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch};
1419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
142013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochtemplate <class PAGE_TYPE>
142113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochclass PageIteratorImpl
142213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    : public std::iterator<std::forward_iterator_tag, PAGE_TYPE> {
142313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch public:
142413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  explicit PageIteratorImpl(PAGE_TYPE* p) : p_(p) {}
142513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  PageIteratorImpl(const PageIteratorImpl<PAGE_TYPE>& other) : p_(other.p_) {}
142613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  PAGE_TYPE* operator*() { return p_; }
142713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  bool operator==(const PageIteratorImpl<PAGE_TYPE>& rhs) {
142813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    return rhs.p_ == p_;
142913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
143013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  bool operator!=(const PageIteratorImpl<PAGE_TYPE>& rhs) {
143113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    return rhs.p_ != p_;
143213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  }
143313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  inline PageIteratorImpl<PAGE_TYPE>& operator++();
143413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  inline PageIteratorImpl<PAGE_TYPE> operator++(int);
143513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
143613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch private:
143713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  PAGE_TYPE* p_;
1438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
1439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
144013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochtypedef PageIteratorImpl<Page> PageIterator;
144113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochtypedef PageIteratorImpl<LargePage> LargePageIterator;
144213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
144313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdochclass PageRange {
144413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch public:
144513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  typedef PageIterator iterator;
144613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  PageRange(Page* begin, Page* end) : begin_(begin), end_(end) {}
144713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  explicit PageRange(Page* page) : PageRange(page, page->next_page()) {}
144862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  inline PageRange(Address start, Address limit);
144962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
145013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  iterator begin() { return iterator(begin_); }
145113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  iterator end() { return iterator(end_); }
145213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
145313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch private:
145413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Page* begin_;
145513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Page* end_;
145613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch};
1457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// -----------------------------------------------------------------------------
1459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Heap object iterator in new/old/map spaces.
1460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
14613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// A HeapObjectIterator iterates objects from the bottom of the given space
14623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// to its top or from the bottom of the given page to its top.
1463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
14643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// If objects are allocated in the page during iteration the iterator may
14653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// or may not iterate over those objects.  The caller must create a new
14663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// iterator in order to be sure to visit these new objects.
1467f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochclass V8_EXPORT_PRIVATE HeapObjectIterator : public ObjectIterator {
1468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
14693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Creates a new object iterator in a given space.
1470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  explicit HeapObjectIterator(PagedSpace* space);
1471014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  explicit HeapObjectIterator(Page* page);
1472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
14733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Advance to the next object, skipping free spaces and other fillers and
14743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // skipping the special garbage section of which there is one per space.
147513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // Returns nullptr when the iteration has ended.
147613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  inline HeapObject* Next() override;
1477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
14793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Fast (inlined) path of next().
14803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  inline HeapObject* FromCurrentPage();
148185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
14823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Slow path of next(), goes into the next page.  Returns false if the
14833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // iteration has ended.
14843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool AdvanceToNextPage();
1485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
148613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Address cur_addr_;  // Current iteration point.
148713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Address cur_end_;   // End iteration point.
1488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  PagedSpace* space_;
148913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  PageRange page_range_;
149013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  PageRange::iterator current_page_;
1491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
1492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// -----------------------------------------------------------------------------
14953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// A space has a circular list of pages. The next page can be accessed via
14963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Page::next_page() call.
1497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// An abstraction of allocation and relocation pointers in a page-structured
1499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// space.
1500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass AllocationInfo {
1501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
1502f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  AllocationInfo() : original_top_(nullptr), top_(nullptr), limit_(nullptr) {}
1503f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  AllocationInfo(Address top, Address limit)
1504f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      : original_top_(top), top_(top), limit_(limit) {}
1505014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1506014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Reset(Address top, Address limit) {
1507f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    original_top_ = top;
1508014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    set_top(top);
1509014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    set_limit(limit);
1510014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1512f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Address original_top() {
1513f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    SLOW_DCHECK(top_ == NULL ||
1514f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                (reinterpret_cast<intptr_t>(top_) & kHeapObjectTagMask) == 0);
1515f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return original_top_;
1516f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
1517f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  INLINE(void set_top(Address top)) {
1519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SLOW_DCHECK(top == NULL ||
1520014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                (reinterpret_cast<intptr_t>(top) & kHeapObjectTagMask) == 0);
1521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    top_ = top;
15223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
15233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  INLINE(Address top()) const {
1525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    SLOW_DCHECK(top_ == NULL ||
1526014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                (reinterpret_cast<intptr_t>(top_) & kHeapObjectTagMask) == 0);
1527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return top_;
1528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Address* top_address() { return &top_; }
1531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  INLINE(void set_limit(Address limit)) {
1533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    limit_ = limit;
1534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  INLINE(Address limit()) const {
1537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return limit_;
1538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Address* limit_address() { return &limit_; }
1541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
1543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool VerifyPagedAllocation() {
1544bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    return (Page::FromAllocationAreaAddress(top_) ==
1545bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch            Page::FromAllocationAreaAddress(limit_)) &&
1546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           (top_ <= limit_);
1547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
1549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private:
1551f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // The original top address when the allocation info was initialized.
1552f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Address original_top_;
1553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Current allocation top.
1554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Address top_;
1555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Current allocation limit.
1556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Address limit_;
1557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
1558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// An abstraction of the accounting statistics of a page-structured space.
1561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
1562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The stats are only set by functions that ensure they stay balanced. These
1563014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// functions increase or decrease one of the non-capacity stats in conjunction
1564014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// with capacity, or else they always balance increases and decreases to the
1565014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// non-capacity stats.
1566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass AllocationStats BASE_EMBEDDED {
1567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
1568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AllocationStats() { Clear(); }
1569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Zero out all the allocation statistics (i.e., no capacity).
1571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Clear() {
1572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    capacity_ = 0;
1573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    max_capacity_ = 0;
1574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    size_ = 0;
1575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1577014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void ClearSize() { size_ = capacity_; }
15783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Accessors for the allocation statistics.
1580f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  size_t Capacity() { return capacity_; }
1581f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  size_t MaxCapacity() { return max_capacity_; }
1582f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  size_t Size() { return size_; }
1583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Grow the space by adding available bytes.  They are initially marked as
15853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // being in use (part of the size), but will normally be immediately freed,
15863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // putting them on the free list and removing them from size_.
1587f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  void ExpandSpace(size_t bytes) {
1588f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DCHECK_GE(size_ + bytes, size_);
1589f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DCHECK_GE(capacity_ + bytes, capacity_);
1590f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    capacity_ += bytes;
1591f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    size_ += bytes;
1592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (capacity_ > max_capacity_) {
1593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      max_capacity_ = capacity_;
1594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
15973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Shrink the space by removing available bytes.  Since shrinking is done
15983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // during sweeping, bytes have been marked as being in use (part of the size)
15993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // and are hereby freed.
1600f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  void ShrinkSpace(size_t bytes) {
1601f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DCHECK_GE(capacity_, bytes);
1602f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DCHECK_GE(size_, bytes);
1603f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    capacity_ -= bytes;
1604f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    size_ -= bytes;
1605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1607f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  void AllocateBytes(size_t bytes) {
1608f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DCHECK_GE(size_ + bytes, size_);
1609f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    size_ += bytes;
1610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1612f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  void DeallocateBytes(size_t bytes) {
1613f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DCHECK_GE(size_, bytes);
1614f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    size_ -= bytes;
1615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1617f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  void DecreaseCapacity(size_t bytes) {
1618f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DCHECK_GE(capacity_, bytes);
1619f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DCHECK_GE(capacity_ - bytes, size_);
1620f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    capacity_ -= bytes;
1621f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
1622f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1623f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  void IncreaseCapacity(size_t bytes) {
1624f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DCHECK_GE(capacity_ + bytes, capacity_);
1625f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    capacity_ += bytes;
1626f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
1627f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1628f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Merge |other| into |this|.
1629014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Merge(const AllocationStats& other) {
1630f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DCHECK_GE(capacity_ + other.capacity_, capacity_);
1631f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    DCHECK_GE(size_ + other.size_, size_);
1632014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    capacity_ += other.capacity_;
1633014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    size_ += other.size_;
1634014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (other.max_capacity_ > max_capacity_) {
1635014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      max_capacity_ = other.max_capacity_;
1636014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
1637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
16393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch private:
1640014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // |capacity_|: The number of object-area bytes (i.e., not including page
1641014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // bookkeeping structures) currently in the space.
1642f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  size_t capacity_;
1643014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1644014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // |max_capacity_|: The maximum capacity ever observed.
1645f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  size_t max_capacity_;
16463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1647014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // |size_|: The number of allocated bytes.
1648f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  size_t size_;
16493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch};
16503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1651014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// A free list maintaining free blocks of memory. The free list is organized in
1652014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// a way to encourage objects allocated around the same time to be near each
1653014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// other. The normal way to allocate is intended to be by bumping a 'top'
1654014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// pointer until it hits a 'limit' pointer.  When the limit is hit we need to
1655014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// find a new space to allocate from. This is done with the free list, which is
1656014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// divided up into rough categories to cut down on waste. Having finer
1657014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// categories would scatter allocation more.
16583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1659014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// The free list is organized in categories as follows:
16603b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch// kMinBlockSize-10 words (tiniest): The tiniest blocks are only used for
16613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch//   allocation, when categories >= small do not have entries anymore.
16623b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch// 11-31 words (tiny): The tiny blocks are only used for allocation, when
16633b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch//   categories >= small do not have entries anymore.
1664014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// 32-255 words (small): Used for allocating free space between 1-31 words in
1665014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch//   size.
1666014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// 256-2047 words (medium): Used for allocating free space between 32-255 words
1667014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch//   in size.
1668014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// 1048-16383 words (large): Used for allocating free space between 256-2047
1669014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch//   words in size.
1670014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// At least 16384 words (huge): This list is for objects of 2048 words or
1671014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch//   larger. Empty pages are also added to this list.
167262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochclass V8_EXPORT_PRIVATE FreeList {
1673014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch public:
1674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // This method returns how much memory can be allocated after freeing
1675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // maximum_freed memory.
1676c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  static inline size_t GuaranteedAllocatable(size_t maximum_freed) {
16773b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    if (maximum_freed <= kTiniestListMax) {
16783b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      // Since we are not iterating over all list entries, we cannot guarantee
16793b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      // that we can find the maximum freed block in that free list.
1680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return 0;
16813b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    } else if (maximum_freed <= kTinyListMax) {
16823b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      return kTinyAllocationMax;
1683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else if (maximum_freed <= kSmallListMax) {
1684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return kSmallAllocationMax;
1685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else if (maximum_freed <= kMediumListMax) {
1686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return kMediumAllocationMax;
1687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else if (maximum_freed <= kLargeListMax) {
1688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      return kLargeAllocationMax;
1689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
1690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return maximum_freed;
1691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1693014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  explicit FreeList(PagedSpace* owner);
1694014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1695014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Adds a node on the free list. The block of size {size_in_bytes} starting
1696014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // at {start} is placed on the free list. The return value is the number of
1697014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // bytes that were not added to the free list, because they freed memory block
1698014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // was too small. Bookkeeping information will be written to the block, i.e.,
1699014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // its contents will be destroyed. The start address should be word aligned,
1700014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // and the size should be a non-zero multiple of the word size.
1701c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  size_t Free(Address start, size_t size_in_bytes, FreeMode mode);
1702014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1703014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Allocate a block of size {size_in_bytes} from the free list. The block is
1704014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // unitialized. A failure is returned if no block is available. The size
1705014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // should be a non-zero multiple of the word size.
1706c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  MUST_USE_RESULT HeapObject* Allocate(size_t size_in_bytes);
17073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1708014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Clear the free list.
1709014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Reset();
1710014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
17113b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void ResetStats() {
17123b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    wasted_bytes_.SetValue(0);
17133b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    ForAllFreeListCategories(
17143b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        [](FreeListCategory* category) { category->ResetStats(); });
17153b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
1716014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1717014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Return the number of bytes available on the free list.
1718c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  size_t Available() {
1719c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    size_t available = 0;
17203b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    ForAllFreeListCategories([&available](FreeListCategory* category) {
17213b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      available += category->available();
17223b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    });
1723109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    return available;
1724014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1725014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool IsEmpty() {
17273b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    bool empty = true;
17283b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    ForAllFreeListCategories([&empty](FreeListCategory* category) {
17293b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      if (!category->is_empty()) empty = false;
17303b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    });
17313b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    return empty;
1732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Used after booting the VM.
1735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void RepairLists(Heap* heap);
17363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1737c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  size_t EvictFreeListItems(Page* page);
17383b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  bool ContainsPageFreeListItems(Page* page);
1739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1740014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  PagedSpace* owner() { return owner_; }
1741c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  size_t wasted_bytes() { return wasted_bytes_.Value(); }
17423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
17433b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  template <typename Callback>
17443b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void ForAllFreeListCategories(FreeListCategoryType type, Callback callback) {
17453b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    FreeListCategory* current = categories_[type];
17463b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    while (current != nullptr) {
17473b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      FreeListCategory* next = current->next();
17483b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      callback(current);
17493b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      current = next;
17503b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    }
17513b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
17523b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
17533b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  template <typename Callback>
17543b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void ForAllFreeListCategories(Callback callback) {
17553b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    for (int i = kFirstCategory; i < kNumberOfCategories; i++) {
17563b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      ForAllFreeListCategories(static_cast<FreeListCategoryType>(i), callback);
17573b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    }
17583b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
17593b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
17603b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  bool AddCategory(FreeListCategory* category);
17613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void RemoveCategory(FreeListCategory* category);
17623b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void PrintCategories(FreeListCategoryType type);
1763014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1764014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#ifdef DEBUG
1765c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  size_t SumFreeLists();
1766014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool IsVeryLong();
1767014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#endif
17683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
17693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch private:
17703b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  class FreeListCategoryIterator {
17713b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch   public:
17723b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    FreeListCategoryIterator(FreeList* free_list, FreeListCategoryType type)
17733b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        : current_(free_list->categories_[type]) {}
17743b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
17753b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    bool HasNext() { return current_ != nullptr; }
17763b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
17773b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    FreeListCategory* Next() {
17783b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      DCHECK(HasNext());
17793b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      FreeListCategory* tmp = current_;
17803b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      current_ = current_->next();
17813b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      return tmp;
17823b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    }
17833b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
17843b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch   private:
17853b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    FreeListCategory* current_;
17863b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  };
17873b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
17883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The size range of blocks, in bytes.
1789c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  static const size_t kMinBlockSize = 3 * kPointerSize;
1790c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  static const size_t kMaxBlockSize = Page::kAllocatableMemory;
17913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1792c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  static const size_t kTiniestListMax = 0xa * kPointerSize;
1793c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  static const size_t kTinyListMax = 0x1f * kPointerSize;
1794c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  static const size_t kSmallListMax = 0xff * kPointerSize;
1795c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  static const size_t kMediumListMax = 0x7ff * kPointerSize;
1796c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  static const size_t kLargeListMax = 0x3fff * kPointerSize;
1797c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  static const size_t kTinyAllocationMax = kTiniestListMax;
1798c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  static const size_t kSmallAllocationMax = kTinyListMax;
1799c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  static const size_t kMediumAllocationMax = kSmallListMax;
1800c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  static const size_t kLargeAllocationMax = kMediumListMax;
1801014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1802c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  FreeSpace* FindNodeFor(size_t size_in_bytes, size_t* node_size);
1803014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
18043b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Walks all available categories for a given |type| and tries to retrieve
18053b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // a node. Returns nullptr if the category is empty.
1806c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  FreeSpace* FindNodeIn(FreeListCategoryType type, size_t* node_size);
18073b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
18083b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Tries to retrieve a node from the first category in a given |type|.
18093b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Returns nullptr if the category is empty.
1810c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  FreeSpace* TryFindNodeIn(FreeListCategoryType type, size_t* node_size,
1811c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                           size_t minimum_size);
18123b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
18133b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Searches a given |type| for a node of at least |minimum_size|.
1814c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  FreeSpace* SearchForNodeInList(FreeListCategoryType type, size_t* node_size,
1815c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                                 size_t minimum_size);
1816109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
1817109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  FreeListCategoryType SelectFreeListCategoryType(size_t size_in_bytes) {
18183b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    if (size_in_bytes <= kTiniestListMax) {
18193b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      return kTiniest;
18203b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    } else if (size_in_bytes <= kTinyListMax) {
18213b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      return kTiny;
18223b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    } else if (size_in_bytes <= kSmallListMax) {
1823109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      return kSmall;
1824109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    } else if (size_in_bytes <= kMediumListMax) {
1825109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      return kMedium;
1826109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    } else if (size_in_bytes <= kLargeListMax) {
1827109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      return kLarge;
18288389745919cae02139ddc085a63c00d024269cf2Ben Murdoch    }
1829109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    return kHuge;
1830109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
1831109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
18323b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // The tiny categories are not used for fast allocation.
1833109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  FreeListCategoryType SelectFastAllocationFreeListCategoryType(
1834109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      size_t size_in_bytes) {
1835109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    if (size_in_bytes <= kSmallAllocationMax) {
1836109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      return kSmall;
1837109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    } else if (size_in_bytes <= kMediumAllocationMax) {
1838109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      return kMedium;
1839109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    } else if (size_in_bytes <= kLargeAllocationMax) {
1840109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch      return kLarge;
1841109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    }
1842109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    return kHuge;
1843014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
1844014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
18453b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  FreeListCategory* top(FreeListCategoryType type) { return categories_[type]; }
18463b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
1847014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  PagedSpace* owner_;
1848c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  base::AtomicNumber<size_t> wasted_bytes_;
18493b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  FreeListCategory* categories_[kNumberOfCategories];
18503b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
18513b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  friend class FreeListCategory;
18523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
18533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DISALLOW_IMPLICIT_CONSTRUCTORS(FreeList);
18543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch};
18553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1856014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// LocalAllocationBuffer represents a linear allocation area that is created
1857014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// from a given {AllocationResult} and can be used to allocate memory without
1858014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// synchronization.
1859014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch//
1860014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// The buffer is properly closed upon destruction and reassignment.
1861014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Example:
1862014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch//   {
1863014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch//     AllocationResult result = ...;
1864014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch//     LocalAllocationBuffer a(heap, result, size);
1865014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch//     LocalAllocationBuffer b = a;
1866014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch//     CHECK(!a.IsValid());
1867014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch//     CHECK(b.IsValid());
1868014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch//     // {a} is invalid now and cannot be used for further allocations.
1869014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch//   }
1870014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch//   // Since {b} went out of scope, the LAB is closed, resulting in creating a
1871014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch//   // filler object for the remaining area.
1872014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochclass LocalAllocationBuffer {
1873014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch public:
1874014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Indicates that a buffer cannot be used for allocations anymore. Can result
1875014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // from either reassigning a buffer, or trying to construct it from an
1876014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // invalid {AllocationResult}.
1877014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static inline LocalAllocationBuffer InvalidBuffer();
1878014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1879014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Creates a new LAB from a given {AllocationResult}. Results in
1880014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // InvalidBuffer if the result indicates a retry.
1881014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static inline LocalAllocationBuffer FromResult(Heap* heap,
1882014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                                 AllocationResult result,
1883014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                                 intptr_t size);
1884014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1885014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ~LocalAllocationBuffer() { Close(); }
1886014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1887014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Convert to C++11 move-semantics once allowed by the style guide.
1888014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  LocalAllocationBuffer(const LocalAllocationBuffer& other);
1889014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  LocalAllocationBuffer& operator=(const LocalAllocationBuffer& other);
1890014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1891014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  MUST_USE_RESULT inline AllocationResult AllocateRawAligned(
1892014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      int size_in_bytes, AllocationAlignment alignment);
1893014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1894014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline bool IsValid() { return allocation_info_.top() != nullptr; }
1895014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1896014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Try to merge LABs, which is only possible when they are adjacent in memory.
1897014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Returns true if the merge was successful, false otherwise.
1898014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline bool TryMerge(LocalAllocationBuffer* other);
1899014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1900014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch private:
1901014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  LocalAllocationBuffer(Heap* heap, AllocationInfo allocation_info);
1902014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1903014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Close();
1904014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1905014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Heap* heap_;
1906014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  AllocationInfo allocation_info_;
1907014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch};
1908014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
190962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochclass V8_EXPORT_PRIVATE PagedSpace : NON_EXPORTED_BASE(public Space) {
1910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
191113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  typedef PageIterator iterator;
191213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
1913014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  static const intptr_t kCompactionMemoryWanted = 500 * KB;
1914014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
1915014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Creates a space with an id.
1916014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  PagedSpace(Heap* heap, AllocationSpace id, Executability executable);
1917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1918014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ~PagedSpace() override { TearDown(); }
1919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set up the space using the given address range of virtual memory (from
1921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // the memory allocator's initial chunk) if possible.  If the block of
1922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // addresses is not big enough to contain a single page-aligned page, a
1923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // fresh chunk will be allocated.
19243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool SetUp();
1925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Returns true if the space has been successfully set up and not
1927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // subsequently torn down.
19283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool HasBeenSetUp();
1929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Checks whether an object/address is in this space.
1931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  inline bool Contains(Address a);
1932109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  inline bool Contains(Object* o);
1933109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  bool ContainsSlow(Address addr);
1934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // During boot the free_space_map is created, and afterwards we may need
1936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // to write it into the free list nodes that were already created.
1937014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void RepairFreeListsAfterDeserialization();
1938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Prepares for a mark-compact GC.
1940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void PrepareForMarkCompact();
1941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
19423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Current capacity without growing (Size() + Available()).
1943c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  size_t Capacity() { return accounting_stats_.Capacity(); }
1944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Approximate amount of physical memory committed for this space.
1946014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  size_t CommittedPhysicalMemory() override;
1947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void ResetFreeListStatistics();
1949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
19503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Sets the capacity, the available space and the wasted space to zero.
19513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The stats are rebuilt during sweeping by adding each page to the
19523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // capacity and the size when it is encountered.  As free spaces are
19533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // discovered during the sweeping they are subtracted from the size and added
19543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // to the available and wasted totals.
19553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void ClearStats() {
1956014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    accounting_stats_.ClearSize();
1957014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    free_list_.ResetStats();
1958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    ResetFreeListStatistics();
1959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
19613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Available bytes without growing.  These are the bytes on the free list.
19623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The bytes in the linear allocation area are not included in this total
19633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // because updating the stats would slow down allocation.  New pages are
19643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // immediately added to the free list so they show up here.
1965c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  size_t Available() override { return free_list_.Available(); }
1966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
19673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Allocated bytes in this space.  Garbage bytes that were not found due to
1968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // concurrent sweeping are counted as being allocated!  The bytes in the
1969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // current linear allocation area (between top and limit) are also counted
1970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // here.
1971c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  size_t Size() override { return accounting_stats_.Size(); }
1972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
19733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // As size, but the bytes in lazily swept pages are estimated and the bytes
19743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // in the current linear allocation area are not included.
1975c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  size_t SizeOfObjects() override;
1976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
19773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Wasted bytes in this space.  These are just the bytes that were thrown away
1978014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // due to being too small to use for allocation.
1979c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  virtual size_t Waste() { return free_list_.wasted_bytes(); }
1980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Returns the allocation pointer in this space.
1982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Address top() { return allocation_info_.top(); }
1983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Address limit() { return allocation_info_.limit(); }
1984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The allocation top address.
1986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Address* allocation_top_address() { return allocation_info_.top_address(); }
1987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The allocation limit address.
1989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Address* allocation_limit_address() {
1990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return allocation_info_.limit_address();
1991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
19933b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  enum UpdateSkipList { UPDATE_SKIP_LIST, IGNORE_SKIP_LIST };
19943b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
1995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Allocate the requested number of bytes in the space if possible, return a
19963b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // failure object if not. Only use IGNORE_SKIP_LIST if the skip list is going
19973b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // to be manually updated later.
1998014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  MUST_USE_RESULT inline AllocationResult AllocateRawUnaligned(
19993b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      int size_in_bytes, UpdateSkipList update_skip_list = UPDATE_SKIP_LIST);
2000014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2001014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  MUST_USE_RESULT inline AllocationResult AllocateRawUnalignedSynchronized(
2002014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      int size_in_bytes);
2003014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2004014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Allocate the requested number of bytes in the space double aligned if
2005014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // possible, return a failure object if not.
2006014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  MUST_USE_RESULT inline AllocationResult AllocateRawAligned(
2007014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      int size_in_bytes, AllocationAlignment alignment);
2008014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2009014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Allocate the requested number of bytes in the space and consider allocation
2010014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // alignment if needed.
2011014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  MUST_USE_RESULT inline AllocationResult AllocateRaw(
2012014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      int size_in_bytes, AllocationAlignment alignment);
2013e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
20143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Give a block of memory to the space's free list.  It might be added to
20153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // the free list or accounted as waste.
20163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // If add_to_freelist is false then just accounting stats are updated and
20173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // no attempt to add area to free list is made.
2018c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  size_t Free(Address start, size_t size_in_bytes) {
2019c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    size_t wasted = free_list_.Free(start, size_in_bytes, kLinkCategory);
2020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    accounting_stats_.DeallocateBytes(size_in_bytes);
2021c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    DCHECK_GE(size_in_bytes, wasted);
20223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return size_in_bytes - wasted;
20233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
202480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
2025c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  size_t UnaccountedFree(Address start, size_t size_in_bytes) {
2026c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    size_t wasted = free_list_.Free(start, size_in_bytes, kDoNotLinkCategory);
2027c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    DCHECK_GE(size_in_bytes, wasted);
20283b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    return size_in_bytes - wasted;
20293b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  }
20303b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
2031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void ResetFreeList() { free_list_.Reset(); }
2032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
20336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // Set space allocation info.
2034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void SetTopAndLimit(Address top, Address limit) {
2035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(top == limit ||
20363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           Page::FromAddress(top) == Page::FromAddress(limit - 1));
2037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MemoryChunk::UpdateHighWaterMark(allocation_info_.top());
2038014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    allocation_info_.Reset(top, limit);
20396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
20406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
2041f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  void SetAllocationInfo(Address top, Address limit);
2042f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
2043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Empty space allocation info, returning unused area to free list.
2044f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  void EmptyAllocationInfo();
2045f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
2046f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  void MarkAllocationInfoBlack();
2047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
204862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  void AccountAllocatedBytes(size_t bytes) {
204962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    accounting_stats_.AllocateBytes(bytes);
205062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
2051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2052f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  void IncreaseCapacity(size_t bytes);
2053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
20543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Releases an unused page and shrinks the space.
20553b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void ReleasePage(Page* page);
2056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
20573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The dummy page that anchors the linked list of pages.
20583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Page* anchor() { return &anchor_; }
2059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
206013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
2061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef VERIFY_HEAP
2062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Verify integrity of this space.
2063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual void Verify(ObjectVisitor* visitor);
2064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Overridden by subclasses to verify space-specific object
2066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // properties (e.g., only maps or free-list nodes are in map space).
2067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual void VerifyObject(HeapObject* obj) {}
2068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
2069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG
2071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Print meta info and objects in this space.
2072014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Print() override;
2073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Reports statistics for the space
2075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void ReportStatistics();
2076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Report code object related statistics
2078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static void ReportCodeStatistics(Isolate* isolate);
2079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  static void ResetCodeStatistics(Isolate* isolate);
2080a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
2081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
20823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Page* FirstPage() { return anchor_.next_page(); }
20833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Page* LastPage() { return anchor_.prev_page(); }
20843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2085014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool CanExpand(size_t size);
20863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
20873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Returns the number of total pages in this space.
20883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int CountTotalPages();
20896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
20903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Return size of allocatable area on a page in this space.
2091c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  inline int AreaSize() { return static_cast<int>(area_size_); }
2092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2093014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  virtual bool is_local() { return false; }
2094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2095014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Merges {other} into the current space. Note that this modifies {other},
2096014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // e.g., removes its bump pointer area and resets statistics.
2097014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void MergeCompactionSpace(CompactionSpace* other);
20983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2099014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Refills the free list from the corresponding free list filled by the
2100014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // sweeper.
2101014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  virtual void RefillFreeList();
2102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
21033b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  FreeList* free_list() { return &free_list_; }
2104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
21053b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  base::Mutex* mutex() { return &space_mutex_; }
21066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
21073b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  inline void UnlinkFreeListCategories(Page* page);
21083b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  inline intptr_t RelinkFreeListCategories(Page* page);
21093b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
211013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  iterator begin() { return iterator(anchor_.next_page()); }
211113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  iterator end() { return iterator(&anchor_); }
211213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
2113f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Shrink immortal immovable pages of the space to be exactly the size needed
2114f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // using the high water mark.
2115f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  void ShrinkImmortalImmovablePages();
2116f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
2117f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  std::unique_ptr<ObjectIterator> GetObjectIterator() override;
2118f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
21193b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch protected:
2120014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // PagedSpaces that should be included in snapshots have different, i.e.,
2121014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // smaller, initial pages.
2122014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  virtual bool snapshotable() { return true; }
2123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2124014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool HasPages() { return anchor_.next_page() != &anchor_; }
2125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2126014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Cleans up the space, frees all pages in this space except those belonging
2127014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // to the initial chunk, uncommits addresses in the initial chunk.
2128014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void TearDown();
2129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Expands the space by allocating a fixed number of pages. Returns false if
21313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // it cannot allocate requested number of pages from OS, or if the hard heap
21323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // size limit has been hit.
21333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool Expand();
2134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
21353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Generic fast case allocation function that tries linear allocation at the
21363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // address denoted by top in allocation_info_.
21373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  inline HeapObject* AllocateLinearly(int size_in_bytes);
2138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2139014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Generic fast case allocation function that tries aligned linear allocation
2140014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // at the address denoted by top in allocation_info_. Writes the aligned
2141014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // allocation size, which includes the filler size, to size_in_bytes.
2142014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline HeapObject* AllocateLinearlyAligned(int* size_in_bytes,
2143014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                             AllocationAlignment alignment);
2144014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // If sweeping is still in progress try to sweep unswept pages. If that is
2146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // not successful, wait for the sweeper threads and re-try free-list
2147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // allocation.
2148014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  MUST_USE_RESULT virtual HeapObject* SweepAndRetryAllocation(
2149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      int size_in_bytes);
2150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Slow path of AllocateRaw.  This function is space-dependent.
2152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MUST_USE_RESULT HeapObject* SlowAllocateRaw(int size_in_bytes);
2153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2154c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  size_t area_size_;
2155014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2156014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Accounting information for this space.
2157014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  AllocationStats accounting_stats_;
2158014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2159014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // The dummy page that anchors the double linked list of pages.
2160014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Page anchor_;
2161014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2162014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // The space's free list.
2163014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  FreeList free_list_;
2164014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2165014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Normal allocation information.
2166014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  AllocationInfo allocation_info_;
2167014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2168014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Mutex guarding any concurrent access to the space.
2169014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  base::Mutex space_mutex_;
2170014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
21713b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  friend class IncrementalMarking;
2172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  friend class MarkCompactCollector;
2173014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2174014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Used in cctest.
2175014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  friend class HeapTester;
2176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
2177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochenum SemiSpaceId { kFromSpace = 0, kToSpace = 1 };
21793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// -----------------------------------------------------------------------------
2181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SemiSpace in young generation
2182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
2183109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// A SemiSpace is a contiguous chunk of memory holding page-like memory chunks.
2184109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// The mark-compact collector  uses the memory of the first page in the from
2185109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch// space as a marking stack when tracing live objects.
2186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass SemiSpace : public Space {
2187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
218813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  typedef PageIterator iterator;
218913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
2190109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  static void Swap(SemiSpace* from, SemiSpace* to);
2191109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
21923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  SemiSpace(Heap* heap, SemiSpaceId semispace)
2193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : Space(heap, NEW_SPACE, NOT_EXECUTABLE),
2194109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        current_capacity_(0),
2195109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        maximum_capacity_(0),
2196109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        minimum_capacity_(0),
2197109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        age_mark_(nullptr),
2198109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        committed_(false),
2199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        id_(semispace),
2200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        anchor_(this),
220113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        current_page_(nullptr),
220213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch        pages_used_(0) {}
2203109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
2204109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  inline bool Contains(HeapObject* o);
2205109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  inline bool Contains(Object* o);
2206109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  inline bool ContainsSlow(Address a);
2207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2208c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  void SetUp(size_t initial_capacity, size_t maximum_capacity);
2209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void TearDown();
22103b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  bool HasBeenSetUp() { return maximum_capacity_ != 0; }
2211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
22123b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  bool Commit();
22133b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  bool Uncommit();
22143b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  bool is_committed() { return committed_; }
2215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
22163b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Grow the semispace to the new capacity.  The new capacity requested must
22173b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // be larger than the current capacity and less than the maximum capacity.
2218c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  bool GrowTo(size_t new_capacity);
2219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
22203b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Shrinks the semispace to the new capacity.  The new capacity requested
22213b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // must be more than the amount of used memory in the semispace and less
22223b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // than the current capacity.
2223c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  bool ShrinkTo(size_t new_capacity);
2224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
222513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  bool EnsureCurrentCapacity();
222613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
22273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Returns the start address of the first page of the space.
22283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Address space_start() {
22293b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    DCHECK_NE(anchor_.next_page(), anchor());
22303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return anchor_.next_page()->area_start();
22313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
22323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2233bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Page* first_page() { return anchor_.next_page(); }
2234bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Page* current_page() { return current_page_; }
223513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  int pages_used() { return pages_used_; }
22363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Returns one past the end address of the space.
2238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Address space_end() { return anchor_.prev_page()->area_end(); }
22393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
22403b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Returns the start address of the current page of the space.
22413b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Address page_low() { return current_page_->area_start(); }
22423b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
22433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Returns one past the end address of the current page of the space.
2244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Address page_high() { return current_page_->area_end(); }
22453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
22463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool AdvancePage() {
2247bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    Page* next_page = current_page_->next_page();
224813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    // We cannot expand if we reached the maximum number of pages already. Note
224913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    // that we need to account for the next page already for this check as we
225013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    // could potentially fill the whole page after advancing.
225113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    const bool reached_max_pages = (pages_used_ + 1) == max_pages();
225213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    if (next_page == anchor() || reached_max_pages) {
225313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      return false;
225413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    }
22553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    current_page_ = next_page;
225613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    pages_used_++;
22573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return true;
22583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
22593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
22603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Resets the space to using the first page.
22613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void Reset();
2262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
226313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  void RemovePage(Page* page);
226413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  void PrependPage(Page* page);
2265bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
2266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Age mark accessors.
2267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address age_mark() { return age_mark_; }
22683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void set_age_mark(Address mark);
2269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
22703b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Returns the current capacity of the semispace.
2271c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  size_t current_capacity() { return current_capacity_; }
2272109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
22733b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // Returns the maximum capacity of the semispace.
2274c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  size_t maximum_capacity() { return maximum_capacity_; }
2275109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
2276109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Returns the initial capacity of the semispace.
2277c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  size_t minimum_capacity() { return minimum_capacity_; }
2278109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
2279109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  SemiSpaceId id() { return id_; }
2280109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
2281109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Approximate amount of physical memory committed for this space.
2282109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  size_t CommittedPhysicalMemory() override;
2283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2284e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // If we don't have these here then SemiSpace will be abstract.  However
2285014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // they should never be called:
2286014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2287c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  size_t Size() override {
2288014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    UNREACHABLE();
2289014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return 0;
2290014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2291014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2292c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  size_t SizeOfObjects() override { return Size(); }
2293014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2294c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  size_t Available() override {
2295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    UNREACHABLE();
2296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return 0;
2297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2299f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  iterator begin() { return iterator(anchor_.next_page()); }
2300f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  iterator end() { return iterator(anchor()); }
2301f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
2302f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  std::unique_ptr<ObjectIterator> GetObjectIterator() override;
2303f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
2304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
2305014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Print() override;
23063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Validate a range of of addresses in a SemiSpace.
23073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The "from" address must be on a page prior to the "to" address,
23083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // in the linked page order, or it must be earlier on the same page.
23093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static void AssertValidRange(Address from, Address to);
23103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#else
23113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Do nothing.
23123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  inline static void AssertValidRange(Address from, Address to) {}
2313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
2314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2315109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#ifdef VERIFY_HEAP
2316109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  virtual void Verify();
2317109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#endif
2318f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch
2319109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch private:
2320bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  void RewindPages(Page* start, int num_pages);
2321f2e3994fa5148cc3d9946666f0b0596290192b0eBen Murdoch
2322bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  inline Page* anchor() { return &anchor_; }
2323c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  inline int max_pages() {
2324c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    return static_cast<int>(current_capacity_ / Page::kPageSize);
2325c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
2326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
23273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Copies the flags into the masked positions on all pages in the space.
2328109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  void FixPagesFlags(intptr_t flags, intptr_t flag_mask);
23293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2330109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // The currently committed space capacity.
2331c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  size_t current_capacity_;
2332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
233313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // The maximum capacity that can be used by this space. A space cannot grow
233413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // beyond that size.
2335c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  size_t maximum_capacity_;
23363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
23373b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  // The minimum capacity for the space. A space cannot shrink below this size.
2338c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  size_t minimum_capacity_;
2339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Used to govern object promotion during mark-compact collection.
2341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address age_mark_;
2342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool committed_;
23443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  SemiSpaceId id_;
2345592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
2346bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Page anchor_;
2347bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  Page* current_page_;
234813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  int pages_used_;
23493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
235013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  friend class NewSpace;
23513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  friend class SemiSpaceIterator;
2352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
2353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A SemiSpaceIterator is an ObjectIterator that iterates over the active
2356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// semispace of the heap's new space.  It iterates over the objects in the
2357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// semispace from a given start address (defaulting to the bottom of the
2358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// semispace) to the top of the semispace.  New objects allocated after the
2359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// iterator is created are not iterated.
2360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass SemiSpaceIterator : public ObjectIterator {
2361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
2362014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Create an iterator over the allocated objects in the given to-space.
2363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  explicit SemiSpaceIterator(NewSpace* space);
2364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
236513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  inline HeapObject* Next() override;
2366592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
2367592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch private:
2368014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Initialize(Address start, Address end);
2369592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
23703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The current iteration point.
23713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Address current_;
23723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The end of iteration.
23733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Address limit_;
23743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch};
23753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// -----------------------------------------------------------------------------
2377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The young generation space.
2378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
2379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The new space consists of a contiguous pair of semispaces.  It simply
2380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// forwards most functions to the appropriate semispace.
2381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass NewSpace : public Space {
2383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
238413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  typedef PageIterator iterator;
238513e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
238644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  explicit NewSpace(Heap* heap)
2387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      : Space(heap, NEW_SPACE, NOT_EXECUTABLE),
2388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        to_space_(heap, kToSpace),
2389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        from_space_(heap, kFromSpace),
2390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        reservation_(),
23913b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        top_on_previous_step_(0),
23923b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        allocated_histogram_(nullptr),
23933b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch        promoted_histogram_(nullptr) {}
2394109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
2395109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  inline bool Contains(HeapObject* o);
2396109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  inline bool ContainsSlow(Address a);
2397109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  inline bool Contains(Object* o);
2398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2399c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  bool SetUp(size_t initial_semispace_capacity, size_t max_semispace_capacity);
2400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Tears down the space.  Heap memory was not allocated by the space, so it
2402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // is not deallocated here.
2403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void TearDown();
2404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // True if the space has been set up but not torn down.
24063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool HasBeenSetUp() {
24073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return to_space_.HasBeenSetUp() && from_space_.HasBeenSetUp();
2408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Flip the pair of spaces.
2411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Flip();
2412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Grow the capacity of the semispaces.  Assumes that they are not at
2414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // their maximum capacity.
2415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Grow();
2416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Shrink the capacity of the semispaces.
2418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Shrink();
2419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the allocated bytes in the active semispace.
2421c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  size_t Size() override {
2422c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    DCHECK_GE(top(), to_space_.page_low());
242313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    return to_space_.pages_used() * Page::kAllocatableMemory +
2424c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch           static_cast<size_t>(top() - to_space_.page_low());
24253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
24263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2427c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  size_t SizeOfObjects() override { return Size(); }
24283ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Return the allocatable capacity of a semispace.
2430c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  size_t Capacity() {
2431109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    SLOW_DCHECK(to_space_.current_capacity() == from_space_.current_capacity());
2432109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    return (to_space_.current_capacity() / Page::kPageSize) *
2433bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch           Page::kAllocatableMemory;
24343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
24353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Return the current size of a semispace, allocatable and non-allocatable
2437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // memory.
2438c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  size_t TotalCapacity() {
2439109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    DCHECK(to_space_.current_capacity() == from_space_.current_capacity());
2440109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    return to_space_.current_capacity();
2441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
24423ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2443014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Committed memory for NewSpace is the committed memory of both semi-spaces
2444014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // combined.
2445f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  size_t CommittedMemory() override {
2446014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return from_space_.CommittedMemory() + to_space_.CommittedMemory();
24473ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block  }
24483ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block
2449f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  size_t MaximumCommittedMemory() override {
2450014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return from_space_.MaximumCommittedMemory() +
2451014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch           to_space_.MaximumCommittedMemory();
24523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Approximate amount of physical memory committed for this space.
2455014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  size_t CommittedPhysicalMemory() override;
2456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Return the available bytes without growing.
2458c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  size_t Available() override {
2459c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    DCHECK_GE(Capacity(), Size());
2460c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    return Capacity() - Size();
2461c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
2462014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2463014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  size_t AllocatedSinceLastGC() {
246462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    const Address age_mark = to_space_.age_mark();
246562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    DCHECK_NOT_NULL(age_mark);
246662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    DCHECK_NOT_NULL(top());
246762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Page* const age_mark_page = Page::FromAllocationAreaAddress(age_mark);
246862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Page* const last_page = Page::FromAllocationAreaAddress(top());
246962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Page* current_page = age_mark_page;
247062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    size_t allocated = 0;
247162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (current_page != last_page) {
247262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      DCHECK_EQ(current_page, age_mark_page);
247362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      DCHECK_GE(age_mark_page->area_end(), age_mark);
247462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      allocated += age_mark_page->area_end() - age_mark;
24753b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      current_page = current_page->next_page();
247662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    } else {
247762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      DCHECK_GE(top(), age_mark);
247862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      return top() - age_mark;
24793b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    }
24803b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    while (current_page != last_page) {
248162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      DCHECK_NE(current_page, age_mark_page);
2482bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch      allocated += Page::kAllocatableMemory;
24833b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      current_page = current_page->next_page();
24843b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    }
2485c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    DCHECK_GE(top(), current_page->area_start());
24863b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    allocated += top() - current_page->area_start();
24873b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    DCHECK_LE(allocated, Size());
2488c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    return allocated;
2489014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
249113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  void MovePageFromSpaceToSpace(Page* page) {
2492bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch    DCHECK(page->InFromSpace());
249313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    from_space_.RemovePage(page);
249413e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch    to_space_.PrependPage(page);
2495bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch  }
2496bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8Ben Murdoch
249713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  bool Rebalance();
249813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
2499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the maximum capacity of a semispace.
2500c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  size_t MaximumCapacity() {
2501109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    DCHECK(to_space_.maximum_capacity() == from_space_.maximum_capacity());
2502109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    return to_space_.maximum_capacity();
2503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  bool IsAtMaximumCapacity() { return TotalCapacity() == MaximumCapacity(); }
2506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Returns the initial capacity of a semispace.
2508c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  size_t InitialTotalCapacity() {
2509109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    DCHECK(to_space_.minimum_capacity() == from_space_.minimum_capacity());
2510109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    return to_space_.minimum_capacity();
2511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the address of the allocation pointer in the active semispace.
25143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Address top() {
2515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(to_space_.current_page()->ContainsLimit(allocation_info_.top()));
2516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return allocation_info_.top();
25173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Return the address of the allocation pointer limit in the active semispace.
2520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Address limit() {
2521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(to_space_.current_page()->ContainsLimit(allocation_info_.limit()));
2522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return allocation_info_.limit();
2523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return the address of the first object in the active semispace.
25263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Address bottom() { return to_space_.space_start(); }
2527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Get the age mark of the inactive semispace.
2529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address age_mark() { return from_space_.age_mark(); }
2530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Set the age mark in the active semispace.
2531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void set_age_mark(Address mark) { to_space_.set_age_mark(mark); }
2532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The allocation top and limit address.
2534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Address* allocation_top_address() { return allocation_info_.top_address(); }
2535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The allocation limit address.
2537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Address* allocation_limit_address() {
2538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return allocation_info_.limit_address();
2539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
2540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2541014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  MUST_USE_RESULT INLINE(AllocationResult AllocateRawAligned(
2542014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      int size_in_bytes, AllocationAlignment alignment));
2543014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2544014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  MUST_USE_RESULT INLINE(
2545014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      AllocationResult AllocateRawUnaligned(int size_in_bytes));
2546014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2547014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  MUST_USE_RESULT INLINE(AllocationResult AllocateRaw(
2548014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      int size_in_bytes, AllocationAlignment alignment));
2549014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2550014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  MUST_USE_RESULT inline AllocationResult AllocateRawSynchronized(
2551014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      int size_in_bytes, AllocationAlignment alignment);
2552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Reset the allocation pointer to the beginning of the active semispace.
2554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void ResetAllocationInfo();
2555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2556109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // When inline allocation stepping is active, either because of incremental
2557109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // marking, idle scavenge, or allocation statistics gathering, we 'interrupt'
2558109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // inline allocation every once in a while. This is done by setting
2559109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // allocation_info_.limit to be lower than the actual limit and and increasing
2560109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // it in steps to guarantee that the observers are notified periodically.
2561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  void UpdateInlineAllocationLimit(int size_in_bytes);
2562014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2563109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  void DisableInlineAllocationSteps() {
2564109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    top_on_previous_step_ = 0;
2565109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch    UpdateInlineAllocationLimit(0);
2566109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  }
2567109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
2568014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Allows observation of inline allocation. The observer->Step() method gets
2569014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // called after every step_size bytes have been allocated (approximately).
2570014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // This works by adjusting the allocation limit to a lower value and adjusting
2571014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // it after each step.
2572109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  void AddAllocationObserver(AllocationObserver* observer) override;
2573014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2574109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  void RemoveAllocationObserver(AllocationObserver* observer) override;
25753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
25763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Get the extent of the inactive semispace (for use as a marking stack,
25773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // or to zap it). Notice: space-addresses are not necessarily on the
25783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // same page, so FromSpaceStart() might be above FromSpaceEnd().
25793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Address FromSpacePageLow() { return from_space_.page_low(); }
25803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Address FromSpacePageHigh() { return from_space_.page_high(); }
25813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Address FromSpaceStart() { return from_space_.space_start(); }
25823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Address FromSpaceEnd() { return from_space_.space_end(); }
2583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
25843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Get the extent of the active semispace's pages' memory.
25853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Address ToSpaceStart() { return to_space_.space_start(); }
25863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Address ToSpaceEnd() { return to_space_.space_end(); }
2587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2588109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  inline bool ToSpaceContainsSlow(Address a);
2589109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  inline bool FromSpaceContainsSlow(Address a);
2590109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  inline bool ToSpaceContains(Object* o);
2591109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  inline bool FromSpaceContains(Object* o);
2592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
25933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Try to switch the active semispace to a new, empty, page.
25943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Returns false if this isn't possible or reasonable (i.e., there
25953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // are no pages, or the current page is already empty), or true
25963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // if successful.
25973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool AddFreshPage();
2598014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool AddFreshPageSynchronized();
2599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef VERIFY_HEAP
2601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Verify the active semispace.
2602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual void Verify();
2603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
2604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG
2606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Print the active semispace.
2607014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Print() override { to_space_.Print(); }
2608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
2609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Iterates the active semispace to collect statistics.
2611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void CollectStatistics();
2612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Reports previously collected statistics of the active semispace.
2613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void ReportStatistics();
2614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Clears previously collected statistics.
2615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void ClearHistograms();
2616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Record the allocation or promotion of a heap object.  Note that we don't
2618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // record every single allocation, but only those that happen in the
2619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // to space during a scavenge GC.
2620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void RecordAllocation(HeapObject* obj);
2621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void RecordPromotion(HeapObject* obj);
2622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Return whether the operation succeded.
2624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool CommitFromSpaceIfNeeded() {
2625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (from_space_.is_committed()) return true;
2626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return from_space_.Commit();
2627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool UncommitFromSpace() {
2630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (!from_space_.is_committed()) return true;
2631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return from_space_.Uncommit();
2632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
2633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2634014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool IsFromSpaceCommitted() { return from_space_.is_committed(); }
26353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
26363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  SemiSpace* active_space() { return &to_space_; }
26373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2638109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  void PauseAllocationObservers() override;
2639109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  void ResumeAllocationObservers() override;
2640109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch
264113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  iterator begin() { return to_space_.begin(); }
264213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  iterator end() { return to_space_.end(); }
264313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
2644f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  std::unique_ptr<ObjectIterator> GetObjectIterator() override;
2645f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
2646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
26473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Update allocation info to match the current to-space page.
26483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void UpdateAllocationInfo();
26493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2650014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  base::Mutex mutex_;
2651014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The semispaces.
2653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SemiSpace to_space_;
2654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  SemiSpace from_space_;
2655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  base::VirtualMemory reservation_;
2656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Allocation pointer and limit for normal allocation and allocation during
2658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // mark-compact collection.
2659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  AllocationInfo allocation_info_;
26603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
26613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Address top_on_previous_step_;
2662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  HistogramInfo* allocated_histogram_;
2664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  HistogramInfo* promoted_histogram_;
2665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2666014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool EnsureAllocation(int size_in_bytes, AllocationAlignment alignment);
2667014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2668014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // If we are doing inline allocation in steps, this method performs the 'step'
2669014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // operation. top is the memory address of the bump pointer at the last
2670014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // inline allocation (i.e. it determines the numbers of bytes actually
2671014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // allocated since the last step.) new_top is the address of the bump pointer
2672014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // where the next byte is going to be allocated from. top and new_top may be
2673014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // different when we cross a page boundary or reset the space.
2674014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void InlineAllocationStep(Address top, Address new_top, Address soon_object,
2675014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                            size_t size);
2676014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  intptr_t GetNextInlineAllocationStepSize();
2677014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void StartNextInlineAllocationStep();
2678014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  friend class SemiSpaceIterator;
2680014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch};
2681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2682109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdochclass PauseAllocationObserversScope {
2683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
2684109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  explicit PauseAllocationObserversScope(Heap* heap);
2685109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  ~PauseAllocationObserversScope();
2686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2687014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch private:
2688109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  Heap* heap_;
2689109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  DISALLOW_COPY_AND_ASSIGN(PauseAllocationObserversScope);
2690014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch};
2691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// -----------------------------------------------------------------------------
2693014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Compaction space that is used temporarily during compaction.
2694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2695014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochclass CompactionSpace : public PagedSpace {
2696014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch public:
2697014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CompactionSpace(Heap* heap, AllocationSpace id, Executability executable)
2698014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      : PagedSpace(heap, id, executable) {}
2699014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2700014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool is_local() override { return true; }
2701014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2702014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch protected:
2703014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // The space is temporary and not included in any snapshots.
2704014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  bool snapshotable() override { return false; }
2705014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2706014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  MUST_USE_RESULT HeapObject* SweepAndRetryAllocation(
2707014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      int size_in_bytes) override;
2708014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch};
2709014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2710014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2711014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// A collection of |CompactionSpace|s used by a single compaction task.
2712014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochclass CompactionSpaceCollection : public Malloced {
2713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
2714014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  explicit CompactionSpaceCollection(Heap* heap)
2715014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      : old_space_(heap, OLD_SPACE, Executability::NOT_EXECUTABLE),
2716109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch        code_space_(heap, CODE_SPACE, Executability::EXECUTABLE) {}
2717014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2718014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CompactionSpace* Get(AllocationSpace space) {
2719014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    switch (space) {
2720014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case OLD_SPACE:
2721014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        return &old_space_;
2722014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      case CODE_SPACE:
2723014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        return &code_space_;
2724014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      default:
2725014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        UNREACHABLE();
2726014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    }
2727014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    UNREACHABLE();
2728014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    return nullptr;
2729014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
2730014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2731014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch private:
2732014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CompactionSpace old_space_;
2733014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CompactionSpace code_space_;
2734014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch};
2735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2736014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2737014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// -----------------------------------------------------------------------------
2738014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// Old object space (includes the old space of objects and code space)
2739014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2740014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochclass OldSpace : public PagedSpace {
2741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
2742014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Creates an old space object. The constructor does not allocate pages
2743014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // from OS.
2744014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  OldSpace(Heap* heap, AllocationSpace id, Executability executable)
2745014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      : PagedSpace(heap, id, executable) {}
2746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
2747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
27493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// For contiguous spaces, top should be in the space (or at the end) and limit
27503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// should be the end of the space.
2751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define DCHECK_SEMISPACE_ALLOCATION_INFO(info, space) \
2752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SLOW_DCHECK((space).page_low() <= (info).top() &&   \
2753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              (info).top() <= (space).page_high() &&  \
2754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch              (info).limit() <= (space).page_high())
2755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// -----------------------------------------------------------------------------
2758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Old space for all map objects
2759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass MapSpace : public PagedSpace {
2761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
2762014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Creates a map space object.
2763014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  MapSpace(Heap* heap, AllocationSpace id)
27643b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      : PagedSpace(heap, id, NOT_EXECUTABLE) {}
27653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2766014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int RoundSizeDownToObjectAlignment(int size) override {
2767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (base::bits::IsPowerOfTwo32(Map::kSize)) {
27683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return RoundDown(size, Map::kSize);
27693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
27703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return (size / Map::kSize) * Map::kSize;
2771e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke    }
2772e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  }
2773e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
2774014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#ifdef VERIFY_HEAP
2775014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void VerifyObject(HeapObject* obj) override;
2776014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#endif
2777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch};
2778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// -----------------------------------------------------------------------------
2781f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch// Large objects ( > kMaxRegularHeapObjectSize ) are allocated and
2782014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// managed by the large object space. A large object is allocated from OS
2783014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch// heap with extra padding bytes (Page::kPageSize + Page::kObjectStartOffset).
2784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A large object always starts at Page::kObjectStartOffset to a page.
2785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Large objects do not move during garbage collections.
2786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
278785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdochclass LargeObjectSpace : public Space {
278885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch public:
278913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  typedef LargePageIterator iterator;
279013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
2791014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  LargeObjectSpace(Heap* heap, AllocationSpace id);
2792014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  virtual ~LargeObjectSpace();
279385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
279485b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  // Initializes internal data structures.
27953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool SetUp();
279685b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
279785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  // Releases internal resources, frees objects in this space.
279885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch  void TearDown();
279985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
2800c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  static size_t ObjectSizeFor(size_t chunk_size) {
28013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (chunk_size <= (Page::kPageSize + Page::kObjectStartOffset)) return 0;
28023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return chunk_size - Page::kPageSize - Page::kObjectStartOffset;
28033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
28043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
28053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Shared implementation of AllocateRaw, AllocateRawCode and
28063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // AllocateRawFixedArray.
2807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  MUST_USE_RESULT AllocationResult
2808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      AllocateRaw(int object_size, Executability executable);
2809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Available bytes for objects in this space.
2811c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  inline size_t Available() override;
2812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2813c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  size_t Size() override { return size_; }
28148a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
2815c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  size_t SizeOfObjects() override { return objects_size_; }
2816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Approximate amount of physical memory committed for this space.
2818014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  size_t CommittedPhysicalMemory() override;
2819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int PageCount() { return page_count_; }
2821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Finds an object for a given address, returns a Smi if it is not found.
2823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // The function iterates through all objects in this space, may be slow.
2824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Object* FindObject(Address a);
2825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
282662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // Takes the chunk_map_mutex_ and calls FindPage after that.
282762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  LargePage* FindPageThreadSafe(Address a);
282862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
28293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Finds a large object page containing the given address, returns NULL
283080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // if such a page doesn't exist.
28313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LargePage* FindPage(Address a);
2832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2833014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Clears the marking state of live objects.
2834014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void ClearMarkingStateOfLiveObjects();
2835014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
2836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Frees unmarked objects.
2837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void FreeUnmarkedObjects();
2838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2839f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  void InsertChunkMapEntries(LargePage* page);
2840f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  void RemoveChunkMapEntries(LargePage* page);
2841f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  void RemoveChunkMapEntries(LargePage* page, Address free_start);
2842f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
2843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Checks whether a heap object is in this space; O(1).
2844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool Contains(HeapObject* obj);
2845109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // Checks whether an address is in the object area in this space. Iterates
2846109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  // all objects in the space. May be slow.
2847109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  bool ContainsSlow(Address addr) { return FindObject(addr)->IsHeapObject(); }
2848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Checks whether the space is empty.
28503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool IsEmpty() { return first_page_ == NULL; }
2851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28523b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  void AdjustLiveBytes(int by) { objects_size_ += by; }
28533b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch
28543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LargePage* first_page() { return first_page_; }
28553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
285613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  // Collect code statistics.
285713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  void CollectCodeStatistics();
285813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
285913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  iterator begin() { return iterator(first_page_); }
286013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  iterator end() { return iterator(nullptr); }
286113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch
2862f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  std::unique_ptr<ObjectIterator> GetObjectIterator() override;
2863f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
2864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef VERIFY_HEAP
2865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  virtual void Verify();
2866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
2867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG
2869014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  void Print() override;
2870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void ReportStatistics();
2871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
2872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
2874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // The head of the linked list of large object chunks.
28753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LargePage* first_page_;
2876c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  size_t size_;            // allocated bytes
2877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int page_count_;         // number of chunks
2878c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  size_t objects_size_;    // size of objects
287962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // The chunk_map_mutex_ has to be used when the chunk map is accessed
288062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // concurrently.
288162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  base::Mutex chunk_map_mutex_;
28823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Map MemoryChunk::kAlignment-aligned chunks to large pages covering them
288313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  base::HashMap chunk_map_;
2884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  friend class LargeObjectIterator;
2886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
2887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass LargeObjectIterator : public ObjectIterator {
2890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
2891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  explicit LargeObjectIterator(LargeObjectSpace* space);
2892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
289313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  HeapObject* Next() override;
2894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
28963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LargePage* current_;
2897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
2898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Iterates over the chunks (pages and large object pages) that can contain
29003b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch// pointers to new space or to evacuation candidates.
29013b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdochclass MemoryChunkIterator BASE_EMBEDDED {
29023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch public:
290313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  inline explicit MemoryChunkIterator(Heap* heap);
29043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
29053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Return NULL when the iterator is done.
2906014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  inline MemoryChunk* next();
29073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
29083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch private:
29093b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  enum State {
29103b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    kOldSpaceState,
29113b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    kMapState,
29123b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    kCodeState,
29133b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    kLargeObjectState,
29143b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    kFinishedState
29153b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  };
291613e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  Heap* heap_;
29173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  State state_;
2918014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  PageIterator old_iterator_;
29193b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  PageIterator code_iterator_;
29203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  PageIterator map_iterator_;
29213b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  LargePageIterator lo_iterator_;
29223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch};
29233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2924014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace internal
2925014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace v8
292644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
2927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif  // V8_HEAP_SPACES_H_
2928