1#ifndef MarkedAllocator_h
2#define MarkedAllocator_h
3
4#include "MarkedBlock.h"
5#include <wtf/DoublyLinkedList.h>
6
7namespace JSC {
8
9class Heap;
10class MarkedSpace;
11class LLIntOffsetsExtractor;
12
13namespace DFG {
14class SpeculativeJIT;
15}
16
17class MarkedAllocator {
18    friend class LLIntOffsetsExtractor;
19
20public:
21    static ptrdiff_t offsetOfFreeListHead();
22
23    MarkedAllocator();
24    void reset();
25    void canonicalizeCellLivenessData();
26    size_t cellSize() { return m_cellSize; }
27    MarkedBlock::DestructorType destructorType() { return m_destructorType; }
28    void* allocate(size_t);
29    Heap* heap() { return m_heap; }
30
31    template<typename Functor> void forEachBlock(Functor&);
32
33    void addBlock(MarkedBlock*);
34    void removeBlock(MarkedBlock*);
35    void init(Heap*, MarkedSpace*, size_t cellSize, MarkedBlock::DestructorType);
36
37    bool isPagedOut(double deadline);
38
39private:
40    JS_EXPORT_PRIVATE void* allocateSlowCase(size_t);
41    void* tryAllocate(size_t);
42    void* tryAllocateHelper(size_t);
43    MarkedBlock* allocateBlock(size_t);
44
45    MarkedBlock::FreeList m_freeList;
46    MarkedBlock* m_currentBlock;
47    MarkedBlock* m_blocksToSweep;
48    DoublyLinkedList<MarkedBlock> m_blockList;
49    size_t m_cellSize;
50    MarkedBlock::DestructorType m_destructorType;
51    Heap* m_heap;
52    MarkedSpace* m_markedSpace;
53};
54
55inline ptrdiff_t MarkedAllocator::offsetOfFreeListHead()
56{
57    return OBJECT_OFFSETOF(MarkedAllocator, m_freeList) + OBJECT_OFFSETOF(MarkedBlock::FreeList, head);
58}
59
60inline MarkedAllocator::MarkedAllocator()
61    : m_currentBlock(0)
62    , m_blocksToSweep(0)
63    , m_cellSize(0)
64    , m_destructorType(MarkedBlock::None)
65    , m_heap(0)
66    , m_markedSpace(0)
67{
68}
69
70inline void MarkedAllocator::init(Heap* heap, MarkedSpace* markedSpace, size_t cellSize, MarkedBlock::DestructorType destructorType)
71{
72    m_heap = heap;
73    m_markedSpace = markedSpace;
74    m_cellSize = cellSize;
75    m_destructorType = destructorType;
76}
77
78inline void* MarkedAllocator::allocate(size_t bytes)
79{
80    MarkedBlock::FreeCell* head = m_freeList.head;
81    if (UNLIKELY(!head)) {
82        void* result = allocateSlowCase(bytes);
83#ifndef NDEBUG
84        memset(result, 0xCD, bytes);
85#endif
86        return result;
87    }
88
89    m_freeList.head = head->next;
90#ifndef NDEBUG
91    memset(head, 0xCD, bytes);
92#endif
93    return head;
94}
95
96inline void MarkedAllocator::reset()
97{
98    m_currentBlock = 0;
99    m_freeList = MarkedBlock::FreeList();
100    m_blocksToSweep = m_blockList.head();
101}
102
103inline void MarkedAllocator::canonicalizeCellLivenessData()
104{
105    if (!m_currentBlock) {
106        ASSERT(!m_freeList.head);
107        return;
108    }
109
110    m_currentBlock->canonicalizeCellLivenessData(m_freeList);
111    m_currentBlock = 0;
112    m_freeList = MarkedBlock::FreeList();
113}
114
115template <typename Functor> inline void MarkedAllocator::forEachBlock(Functor& functor)
116{
117    MarkedBlock* next;
118    for (MarkedBlock* block = m_blockList.head(); block; block = next) {
119        next = block->next();
120        functor(block);
121    }
122}
123
124} // namespace JSC
125
126#endif
127