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