]>
Commit | Line | Data |
---|---|---|
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 |