]> git.saurik.com Git - apple/javascriptcore.git/blob - heap/HandleSet.h
JavaScriptCore-1218.35.tar.gz
[apple/javascriptcore.git] / heap / HandleSet.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 HandleSet_h
27 #define HandleSet_h
28
29 #include "Handle.h"
30 #include "HandleBlock.h"
31 #include <wtf/DoublyLinkedList.h>
32 #include <wtf/HashCountedSet.h>
33 #include <wtf/SentinelLinkedList.h>
34 #include <wtf/SinglyLinkedList.h>
35
36 namespace JSC {
37
38 class HandleBlock;
39 class HandleSet;
40 class HeapRootVisitor;
41 class VM;
42 class JSValue;
43 class SlotVisitor;
44
45 class HandleNode {
46 public:
47 HandleNode(WTF::SentinelTag);
48 HandleNode();
49
50 HandleSlot slot();
51 HandleSet* handleSet();
52
53 void setPrev(HandleNode*);
54 HandleNode* prev();
55
56 void setNext(HandleNode*);
57 HandleNode* next();
58
59 private:
60 JSValue m_value;
61 HandleNode* m_prev;
62 HandleNode* m_next;
63 };
64
65 class HandleSet {
66 friend class HandleBlock;
67 public:
68 static HandleSet* heapFor(HandleSlot);
69
70 HandleSet(VM*);
71 ~HandleSet();
72
73 VM* vm();
74
75 HandleSlot allocate();
76 void deallocate(HandleSlot);
77
78 void visitStrongHandles(HeapRootVisitor&);
79
80 JS_EXPORT_PRIVATE void writeBarrier(HandleSlot, const JSValue&);
81
82 unsigned protectedGlobalObjectCount();
83
84 template<typename Functor> void forEachStrongHandle(Functor&, const HashCountedSet<JSCell*>& skipSet);
85
86 private:
87 typedef HandleNode Node;
88 static HandleSlot toHandle(Node*);
89 static Node* toNode(HandleSlot);
90
91 JS_EXPORT_PRIVATE void grow();
92
93 #if ENABLE(GC_VALIDATION) || !ASSERT_DISABLED
94 bool isLiveNode(Node*);
95 #endif
96
97 VM* m_vm;
98 DoublyLinkedList<HandleBlock> m_blockList;
99
100 SentinelLinkedList<Node> m_strongList;
101 SentinelLinkedList<Node> m_immediateList;
102 SinglyLinkedList<Node> m_freeList;
103 Node* m_nextToFinalize;
104 };
105
106 inline HandleSet* HandleSet::heapFor(HandleSlot handle)
107 {
108 return toNode(handle)->handleSet();
109 }
110
111 inline VM* HandleSet::vm()
112 {
113 return m_vm;
114 }
115
116 inline HandleSlot HandleSet::toHandle(HandleSet::Node* node)
117 {
118 return reinterpret_cast<HandleSlot>(node);
119 }
120
121 inline HandleSet::Node* HandleSet::toNode(HandleSlot handle)
122 {
123 return reinterpret_cast<HandleSet::Node*>(handle);
124 }
125
126 inline HandleSlot HandleSet::allocate()
127 {
128 // Forbid assignment to handles during the finalization phase, since it would violate many GC invariants.
129 // File a bug with stack trace if you hit this.
130 RELEASE_ASSERT(!m_nextToFinalize);
131
132 if (m_freeList.isEmpty())
133 grow();
134
135 HandleSet::Node* node = m_freeList.pop();
136 new (NotNull, node) HandleSet::Node();
137 m_immediateList.push(node);
138 return toHandle(node);
139 }
140
141 inline void HandleSet::deallocate(HandleSlot handle)
142 {
143 HandleSet::Node* node = toNode(handle);
144 if (node == m_nextToFinalize) {
145 ASSERT(m_nextToFinalize->next());
146 m_nextToFinalize = m_nextToFinalize->next();
147 }
148
149 SentinelLinkedList<HandleSet::Node>::remove(node);
150 m_freeList.push(node);
151 }
152
153 inline HandleNode::HandleNode()
154 : m_prev(0)
155 , m_next(0)
156 {
157 }
158
159 inline HandleNode::HandleNode(WTF::SentinelTag)
160 : m_prev(0)
161 , m_next(0)
162 {
163 }
164
165 inline HandleSlot HandleNode::slot()
166 {
167 return &m_value;
168 }
169
170 inline HandleSet* HandleNode::handleSet()
171 {
172 return HandleBlock::blockFor(this)->handleSet();
173 }
174
175 inline void HandleNode::setPrev(HandleNode* prev)
176 {
177 m_prev = prev;
178 }
179
180 inline HandleNode* HandleNode::prev()
181 {
182 return m_prev;
183 }
184
185 inline void HandleNode::setNext(HandleNode* next)
186 {
187 m_next = next;
188 }
189
190 inline HandleNode* HandleNode::next()
191 {
192 return m_next;
193 }
194
195 template<typename Functor> void HandleSet::forEachStrongHandle(Functor& functor, const HashCountedSet<JSCell*>& skipSet)
196 {
197 HandleSet::Node* end = m_strongList.end();
198 for (HandleSet::Node* node = m_strongList.begin(); node != end; node = node->next()) {
199 JSValue value = *node->slot();
200 if (!value || !value.isCell())
201 continue;
202 if (skipSet.contains(value.asCell()))
203 continue;
204 functor(value.asCell());
205 }
206 }
207
208 }
209
210 #endif