]> git.saurik.com Git - apple/javascriptcore.git/blame - heap/HandleSet.h
JavaScriptCore-1097.13.tar.gz
[apple/javascriptcore.git] / heap / HandleSet.h
CommitLineData
6fe7ccc8
A
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
35namespace JSC {
36
37class HandleSet;
38class HeapRootVisitor;
39class JSGlobalData;
40class JSValue;
41class SlotVisitor;
42
43class HandleSet {
44public:
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
62private:
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
102inline HandleSet* HandleSet::heapFor(HandleSlot handle)
103{
104 return toNode(handle)->handleSet();
105}
106
107inline JSGlobalData* HandleSet::globalData()
108{
109 return m_globalData;
110}
111
112inline HandleSlot HandleSet::toHandle(Node* node)
113{
114 return reinterpret_cast<HandleSlot>(node);
115}
116
117inline HandleSet::Node* HandleSet::toNode(HandleSlot handle)
118{
119 return reinterpret_cast<Node*>(handle);
120}
121
122inline 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
137inline 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
149inline HandleSet::Node::Node(HandleSet* handleSet)
150 : m_handleSet(handleSet)
151 , m_prev(0)
152 , m_next(0)
153{
154}
155
156inline HandleSet::Node::Node(WTF::SentinelTag)
157 : m_handleSet(0)
158 , m_prev(0)
159 , m_next(0)
160{
161}
162
163inline HandleSlot HandleSet::Node::slot()
164{
165 return &m_value;
166}
167
168inline HandleSet* HandleSet::Node::handleSet()
169{
170 return m_handleSet;
171}
172
173inline void HandleSet::Node::setPrev(Node* prev)
174{
175 m_prev = prev;
176}
177
178inline HandleSet::Node* HandleSet::Node::prev()
179{
180 return m_prev;
181}
182
183inline void HandleSet::Node::setNext(Node* next)
184{
185 m_next = next;
186}
187
188inline HandleSet::Node* HandleSet::Node::next()
189{
190 return m_next;
191}
192
193template<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