]> git.saurik.com Git - apple/javascriptcore.git/blame_incremental - heap/HandleSet.h
JavaScriptCore-7600.1.4.16.1.tar.gz
[apple/javascriptcore.git] / heap / HandleSet.h
... / ...
CommitLineData
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
36namespace JSC {
37
38class HandleBlock;
39class HandleSet;
40class HeapRootVisitor;
41class VM;
42class JSValue;
43class SlotVisitor;
44
45class HandleNode {
46public:
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
59private:
60 JSValue m_value;
61 HandleNode* m_prev;
62 HandleNode* m_next;
63};
64
65class HandleSet {
66 friend class HandleBlock;
67public:
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
86private:
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
105inline HandleSet* HandleSet::heapFor(HandleSlot handle)
106{
107 return toNode(handle)->handleSet();
108}
109
110inline VM* HandleSet::vm()
111{
112 return m_vm;
113}
114
115inline HandleSlot HandleSet::toHandle(HandleSet::Node* node)
116{
117 return reinterpret_cast<HandleSlot>(node);
118}
119
120inline HandleSet::Node* HandleSet::toNode(HandleSlot handle)
121{
122 return reinterpret_cast<HandleSet::Node*>(handle);
123}
124
125inline 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
136inline 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
143inline HandleNode::HandleNode()
144 : m_prev(0)
145 , m_next(0)
146{
147}
148
149inline HandleNode::HandleNode(WTF::SentinelTag)
150 : m_prev(0)
151 , m_next(0)
152{
153}
154
155inline HandleSlot HandleNode::slot()
156{
157 return &m_value;
158}
159
160inline HandleSet* HandleNode::handleSet()
161{
162 return HandleBlock::blockFor(this)->handleSet();
163}
164
165inline void HandleNode::setPrev(HandleNode* prev)
166{
167 m_prev = prev;
168}
169
170inline HandleNode* HandleNode::prev()
171{
172 return m_prev;
173}
174
175inline void HandleNode::setNext(HandleNode* next)
176{
177 m_next = next;
178}
179
180inline HandleNode* HandleNode::next()
181{
182 return m_next;
183}
184
185template<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