ad68c9a5baba6eb0df8050a8280a77c541505e1c
[WebKit-https.git] / Source / JavaScriptCore / collector / handles / HandleHeap.h
1 /*
2  * Copyright (C) 2011 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. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #ifndef HandleHeap_h
27 #define HandleHeap_h
28
29 #include "BlockStack.h"
30 #include "Handle.h"
31 #include "SentinelLinkedList.h"
32 #include "SinglyLinkedList.h"
33
34 namespace JSC {
35
36 class HandleHeap;
37 class HeapRootMarker;
38 class JSGlobalData;
39 class JSValue;
40 class MarkStack;
41
42 class WeakHandleOwner {
43 public:
44     virtual ~WeakHandleOwner();
45     virtual bool isReachableFromOpaqueRoots(Handle<Unknown>, void* context, MarkStack&);
46     virtual void finalize(Handle<Unknown>, void* context);
47 };
48
49 class HandleHeap {
50 public:
51     static HandleHeap* heapFor(HandleSlot);
52
53     HandleHeap(JSGlobalData*);
54
55     HandleSlot allocate();
56     void deallocate(HandleSlot);
57
58     void makeWeak(HandleSlot, WeakHandleOwner* = 0, void* context = 0);
59
60     void markStrongHandles(HeapRootMarker&);
61     void markWeakHandles(HeapRootMarker&);
62     void finalizeWeakHandles();
63
64     void writeBarrier(HandleSlot, const JSValue&);
65
66 #if !ASSERT_DISABLED
67     bool hasWeakOwner(HandleSlot, WeakHandleOwner*);
68 #endif
69
70     unsigned protectedGlobalObjectCount();
71
72 private:
73     class Node {
74     public:
75         Node(WTF::SentinelTag);
76         Node(HandleHeap*);
77         
78         HandleSlot slot();
79         HandleHeap* handleHeap();
80
81         void makeWeak(WeakHandleOwner*, void* context);
82         bool isWeak();
83         
84         WeakHandleOwner* weakOwner();
85         void* weakOwnerContext();
86
87         void setPrev(Node*);
88         Node* prev();
89
90         void setNext(Node*);
91         Node* next();
92
93     private:
94         WeakHandleOwner* emptyWeakOwner();
95
96         JSValue m_value;
97         HandleHeap* m_handleHeap;
98         WeakHandleOwner* m_weakOwner;
99         void* m_weakOwnerContext;
100         Node* m_prev;
101         Node* m_next;
102     };
103
104     static HandleSlot toHandle(Node*);
105     static Node* toNode(HandleSlot);
106
107     void grow();
108
109     JSGlobalData* m_globalData;
110     BlockStack<Node> m_blockStack;
111
112     SentinelLinkedList<Node> m_strongList;
113     SentinelLinkedList<Node> m_weakList;
114     SentinelLinkedList<Node> m_immediateList;
115     SinglyLinkedList<Node> m_freeList;
116     Node* m_nextToFinalize;
117 };
118
119 inline HandleHeap* HandleHeap::heapFor(HandleSlot handle)
120 {
121     return toNode(handle)->handleHeap();
122 }
123
124 inline HandleSlot HandleHeap::toHandle(Node* node)
125 {
126     return reinterpret_cast<HandleSlot>(node);
127 }
128
129 inline HandleHeap::Node* HandleHeap::toNode(HandleSlot handle)
130 {
131     return reinterpret_cast<Node*>(handle);
132 }
133
134 inline HandleSlot HandleHeap::allocate()
135 {
136     if (m_freeList.isEmpty())
137         grow();
138
139     Node* node = m_freeList.pop();
140     new (node) Node(this);
141     m_immediateList.push(node);
142     return toHandle(node);
143 }
144
145 inline void HandleHeap::deallocate(HandleSlot handle)
146 {
147     Node* node = toNode(handle);
148     if (node == m_nextToFinalize) {
149         m_nextToFinalize = node->next();
150         ASSERT(m_nextToFinalize->next());
151     }
152
153     SentinelLinkedList<Node>::remove(node);
154     m_freeList.push(node);
155 }
156
157 inline void HandleHeap::makeWeak(HandleSlot handle, WeakHandleOwner* weakOwner, void* context)
158 {
159     Node* node = toNode(handle);
160     node->makeWeak(weakOwner, context);
161
162     SentinelLinkedList<Node>::remove(node);
163     if (!*handle || !handle->isCell()) {
164         m_immediateList.push(node);
165         return;
166     }
167
168     m_weakList.push(node);
169 }
170
171 #if !ASSERT_DISABLED
172 inline bool HandleHeap::hasWeakOwner(HandleSlot handle, WeakHandleOwner* weakOwner)
173 {
174     return toNode(handle)->weakOwner() == weakOwner;
175 }
176 #endif
177
178 inline HandleHeap::Node::Node(HandleHeap* handleHeap)
179     : m_handleHeap(handleHeap)
180     , m_weakOwner(0)
181     , m_weakOwnerContext(0)
182 {
183 }
184
185 inline HandleHeap::Node::Node(WTF::SentinelTag)
186     : m_handleHeap(0)
187     , m_weakOwner(0)
188     , m_weakOwnerContext(0)
189 {
190 }
191
192 inline HandleSlot HandleHeap::Node::slot()
193 {
194     return &m_value;
195 }
196
197 inline HandleHeap* HandleHeap::Node::handleHeap()
198 {
199     return m_handleHeap;
200 }
201
202 inline void HandleHeap::Node::makeWeak(WeakHandleOwner* weakOwner, void* context)
203 {
204     m_weakOwner = weakOwner ? weakOwner : emptyWeakOwner();
205     m_weakOwnerContext = context;
206 }
207
208 inline bool HandleHeap::Node::isWeak()
209 {
210     return m_weakOwner; // True for emptyWeakOwner().
211 }
212
213 inline WeakHandleOwner* HandleHeap::Node::weakOwner()
214 {
215     return m_weakOwner == emptyWeakOwner() ? 0 : m_weakOwner; // 0 for emptyWeakOwner().
216 }
217
218 inline void* HandleHeap::Node::weakOwnerContext()
219 {
220     ASSERT(weakOwner());
221     return m_weakOwnerContext;
222 }
223
224 inline void HandleHeap::Node::setPrev(Node* prev)
225 {
226     m_prev = prev;
227 }
228
229 inline HandleHeap::Node* HandleHeap::Node::prev()
230 {
231     return m_prev;
232 }
233
234 inline void HandleHeap::Node::setNext(Node* next)
235 {
236     m_next = next;
237 }
238
239 inline HandleHeap::Node* HandleHeap::Node::next()
240 {
241     return m_next;
242 }
243
244 // Sentinel to indicate that a node is weak, but its owner has no meaningful
245 // callbacks. This allows us to optimize by skipping such nodes.
246 inline WeakHandleOwner* HandleHeap::Node::emptyWeakOwner()
247 {
248     return reinterpret_cast<WeakHandleOwner*>(-1);
249 }
250
251 }
252
253 #endif