]> git.saurik.com Git - apple/javascriptcore.git/blob - heap/HandleSet.h
JavaScriptCore-7600.1.4.15.12.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 };
104
105 inline HandleSet* HandleSet::heapFor(HandleSlot handle)
106 {
107 return toNode(handle)->handleSet();
108 }
109
110 inline VM* HandleSet::vm()
111 {
112 return m_vm;
113 }
114
115 inline HandleSlot HandleSet::toHandle(HandleSet::Node* node)
116 {
117 return reinterpret_cast<HandleSlot>(node);
118 }
119
120 inline HandleSet::Node* HandleSet::toNode(HandleSlot handle)
121 {
122 return reinterpret_cast<HandleSet::Node*>(handle);
123 }
124
125 inline HandleSlot HandleSet::allocate()
126 {
127 if (m_freeList.isEmpty())
128 grow();
129
130 HandleSet::Node* node = m_freeList.pop();
131 new (NotNull, node) HandleSet::Node();
132 m_immediateList.push(node);
133 return toHandle(node);
134 }
135
136 inline void HandleSet::deallocate(HandleSlot handle)
137 {
138 HandleSet::Node* node = toNode(handle);
139 SentinelLinkedList<HandleSet::Node>::remove(node);
140 m_freeList.push(node);
141 }
142
143 inline HandleNode::HandleNode()
144 : m_prev(0)
145 , m_next(0)
146 {
147 }
148
149 inline HandleNode::HandleNode(WTF::SentinelTag)
150 : m_prev(0)
151 , m_next(0)
152 {
153 }
154
155 inline HandleSlot HandleNode::slot()
156 {
157 return &m_value;
158 }
159
160 inline HandleSet* HandleNode::handleSet()
161 {
162 return HandleBlock::blockFor(this)->handleSet();
163 }
164
165 inline void HandleNode::setPrev(HandleNode* prev)
166 {
167 m_prev = prev;
168 }
169
170 inline HandleNode* HandleNode::prev()
171 {
172 return m_prev;
173 }
174
175 inline void HandleNode::setNext(HandleNode* next)
176 {
177 m_next = next;
178 }
179
180 inline HandleNode* HandleNode::next()
181 {
182 return m_next;
183 }
184
185 template<typename Functor> void HandleSet::forEachStrongHandle(Functor& functor, const HashCountedSet<JSCell*>& skipSet)
186 {
187 HandleSet::Node* end = m_strongList.end();
188 for (HandleSet::Node* node = m_strongList.begin(); node != end; node = node->next()) {
189 JSValue value = *node->slot();
190 if (!value || !value.isCell())
191 continue;
192 if (skipSet.contains(value.asCell()))
193 continue;
194 functor(value.asCell());
195 }
196 }
197
198 }
199
200 #endif