Butterflies should be allocated in Auxiliary MarkedSpace instead of CopiedSpace and...
[WebKit-https.git] / Source / JavaScriptCore / heap / MarkedAllocator.h
1 /*
2  * Copyright (C) 2012, 2013, 2016 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #ifndef MarkedAllocator_h
27 #define MarkedAllocator_h
28
29 #include "AllocatorAttributes.h"
30 #include "FreeList.h"
31 #include "MarkedBlock.h"
32 #include <wtf/DoublyLinkedList.h>
33
34 namespace JSC {
35
36 class Heap;
37 class MarkedSpace;
38 class LLIntOffsetsExtractor;
39
40 class MarkedAllocator {
41     friend class LLIntOffsetsExtractor;
42
43 public:
44     static ptrdiff_t offsetOfFreeList();
45     static ptrdiff_t offsetOfCellSize();
46
47     MarkedAllocator(Heap*, MarkedSpace*, size_t cellSize, const AllocatorAttributes&);
48     void lastChanceToFinalize();
49     void reset();
50     void stopAllocating();
51     void resumeAllocating();
52     size_t cellSize() const { return m_cellSize; }
53     const AllocatorAttributes& attributes() const { return m_attributes; }
54     bool needsDestruction() const { return m_attributes.destruction == NeedsDestruction; }
55     DestructionMode destruction() const { return m_attributes.destruction; }
56     HeapCell::Kind cellKind() const { return m_attributes.cellKind; }
57     void* allocate(size_t);
58     void* tryAllocate(size_t);
59     Heap* heap() { return m_heap; }
60     MarkedBlock* takeLastActiveBlock()
61     {
62         MarkedBlock* block = m_lastActiveBlock;
63         m_lastActiveBlock = 0;
64         return block;
65     }
66     
67     template<typename Functor> void forEachBlock(const Functor&);
68     
69     void addBlock(MarkedBlock*);
70     void removeBlock(MarkedBlock*);
71
72     bool isPagedOut(double deadline);
73     
74     static size_t blockSizeForBytes(size_t);
75    
76 private:
77     JS_EXPORT_PRIVATE void* allocateSlowCase(size_t);
78     JS_EXPORT_PRIVATE void* tryAllocateSlowCase(size_t);
79     void* allocateSlowCaseImpl(size_t, bool crashOnFailure);
80     void* tryAllocateWithoutCollecting(size_t);
81     void* tryAllocateWithoutCollectingImpl(size_t);
82     MarkedBlock* tryAllocateBlock();
83     ALWAYS_INLINE void doTestCollectionsIfNeeded();
84     void retire(MarkedBlock*, FreeList&);
85     
86     void setFreeList(const FreeList&);
87     
88     FreeList m_freeList;
89     MarkedBlock* m_currentBlock;
90     MarkedBlock* m_lastActiveBlock;
91     MarkedBlock* m_nextBlockToSweep;
92     DoublyLinkedList<MarkedBlock> m_blockList;
93     DoublyLinkedList<MarkedBlock> m_retiredBlocks;
94     unsigned m_cellSize;
95     AllocatorAttributes m_attributes;
96     Heap* m_heap;
97     MarkedSpace* m_markedSpace;
98 };
99
100 inline ptrdiff_t MarkedAllocator::offsetOfFreeList()
101 {
102     return OBJECT_OFFSETOF(MarkedAllocator, m_freeList);
103 }
104
105 inline ptrdiff_t MarkedAllocator::offsetOfCellSize()
106 {
107     return OBJECT_OFFSETOF(MarkedAllocator, m_cellSize);
108 }
109
110 ALWAYS_INLINE void* MarkedAllocator::tryAllocate(size_t bytes)
111 {
112     unsigned remaining = m_freeList.remaining;
113     if (remaining) {
114         unsigned cellSize = m_cellSize;
115         remaining -= cellSize;
116         m_freeList.remaining = remaining;
117         return m_freeList.payloadEnd - remaining - cellSize;
118     }
119     
120     FreeCell* head = m_freeList.head;
121     if (UNLIKELY(!head))
122         return tryAllocateSlowCase(bytes);
123     
124     m_freeList.head = head->next;
125     return head;
126 }
127
128 ALWAYS_INLINE void* MarkedAllocator::allocate(size_t bytes)
129 {
130     unsigned remaining = m_freeList.remaining;
131     if (remaining) {
132         unsigned cellSize = m_cellSize;
133         remaining -= cellSize;
134         m_freeList.remaining = remaining;
135         return m_freeList.payloadEnd - remaining - cellSize;
136     }
137     
138     FreeCell* head = m_freeList.head;
139     if (UNLIKELY(!head))
140         return allocateSlowCase(bytes);
141     
142     m_freeList.head = head->next;
143     return head;
144 }
145
146 inline void MarkedAllocator::stopAllocating()
147 {
148     ASSERT(!m_lastActiveBlock);
149     if (!m_currentBlock) {
150         ASSERT(!m_freeList);
151         return;
152     }
153     
154     m_currentBlock->stopAllocating(m_freeList);
155     m_lastActiveBlock = m_currentBlock;
156     m_currentBlock = 0;
157     m_freeList = FreeList();
158 }
159
160 inline void MarkedAllocator::resumeAllocating()
161 {
162     if (!m_lastActiveBlock)
163         return;
164
165     m_freeList = m_lastActiveBlock->resumeAllocating();
166     m_currentBlock = m_lastActiveBlock;
167     m_lastActiveBlock = 0;
168 }
169
170 template <typename Functor> inline void MarkedAllocator::forEachBlock(const Functor& functor)
171 {
172     MarkedBlock* next;
173     for (MarkedBlock* block = m_blockList.head(); block; block = next) {
174         next = block->next();
175         functor(block);
176     }
177
178     for (MarkedBlock* block = m_retiredBlocks.head(); block; block = next) {
179         next = block->next();
180         functor(block);
181     }
182 }
183
184 } // namespace JSC
185
186 #endif // MarkedAllocator_h