DelayedReleaseScope in MarkedAllocator::tryAllocateHelper is wrong
[WebKit-https.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     void* tryPopFreeList(size_t);
51     MarkedBlock* allocateBlock(size_t);
52     
53     MarkedBlock::FreeList m_freeList;
54     MarkedBlock* m_currentBlock;
55     MarkedBlock* m_lastActiveBlock;
56     MarkedBlock* m_nextBlockToSweep;
57     MarkedBlock* m_lastFullBlock;
58     DoublyLinkedList<MarkedBlock> m_blockList;
59     size_t m_cellSize;
60     MarkedBlock::DestructorType m_destructorType;
61     Heap* m_heap;
62     MarkedSpace* m_markedSpace;
63 };
64
65 inline ptrdiff_t MarkedAllocator::offsetOfFreeListHead()
66 {
67     return OBJECT_OFFSETOF(MarkedAllocator, m_freeList) + OBJECT_OFFSETOF(MarkedBlock::FreeList, head);
68 }
69
70 inline MarkedAllocator::MarkedAllocator()
71     : m_currentBlock(0)
72     , m_lastActiveBlock(0)
73     , m_nextBlockToSweep(0)
74     , m_lastFullBlock(0)
75     , m_cellSize(0)
76     , m_destructorType(MarkedBlock::None)
77     , m_heap(0)
78     , m_markedSpace(0)
79 {
80 }
81
82 inline void MarkedAllocator::init(Heap* heap, MarkedSpace* markedSpace, size_t cellSize, MarkedBlock::DestructorType destructorType)
83 {
84     m_heap = heap;
85     m_markedSpace = markedSpace;
86     m_cellSize = cellSize;
87     m_destructorType = destructorType;
88 }
89
90 inline void* MarkedAllocator::allocate(size_t bytes)
91 {
92     MarkedBlock::FreeCell* head = m_freeList.head;
93     if (UNLIKELY(!head)) {
94         void* result = allocateSlowCase(bytes);
95 #ifndef NDEBUG
96         memset(result, 0xCD, bytes);
97 #endif
98         return result;
99     }
100     
101     m_freeList.head = head->next;
102 #ifndef NDEBUG
103     memset(head, 0xCD, bytes);
104 #endif
105     return head;
106 }
107
108 inline void MarkedAllocator::stopAllocating()
109 {
110     ASSERT(!m_lastActiveBlock);
111     if (!m_currentBlock) {
112         ASSERT(!m_freeList.head);
113         return;
114     }
115     
116     m_currentBlock->stopAllocating(m_freeList);
117     m_lastActiveBlock = m_currentBlock;
118     m_currentBlock = 0;
119     m_freeList = MarkedBlock::FreeList();
120 }
121
122 inline void MarkedAllocator::resumeAllocating()
123 {
124     if (!m_lastActiveBlock)
125         return;
126
127     m_freeList = m_lastActiveBlock->resumeAllocating();
128     m_currentBlock = m_lastActiveBlock;
129     m_lastActiveBlock = 0;
130 }
131
132 template <typename Functor> inline void MarkedAllocator::forEachBlock(Functor& functor)
133 {
134     MarkedBlock* next;
135     for (MarkedBlock* block = m_blockList.head(); block; block = next) {
136         next = block->next();
137         functor(block);
138     }
139 }
140
141 } // namespace JSC
142
143 #endif