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