Get rid of HeapRootVisitor and make SlotVisitor less painful to use
[WebKit-https.git] / Source / JavaScriptCore / heap / HandleSet.h
1 /*
2  * Copyright (C) 2011, 2016 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 #pragma once
27
28 #include "Handle.h"
29 #include "HandleBlock.h"
30 #include "HeapCell.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 HandleSet;
39 class VM;
40 class JSValue;
41 class SlotVisitor;
42
43 class HandleNode {
44 public:
45     HandleNode(WTF::SentinelTag);
46     HandleNode();
47     
48     HandleSlot slot();
49     HandleSet* handleSet();
50
51     void setPrev(HandleNode*);
52     HandleNode* prev();
53
54     void setNext(HandleNode*);
55     HandleNode* next();
56
57 private:
58     JSValue m_value;
59     HandleNode* m_prev;
60     HandleNode* m_next;
61 };
62
63 class HandleSet {
64     friend class HandleBlock;
65 public:
66     static HandleSet* heapFor(HandleSlot);
67
68     HandleSet(VM*);
69     ~HandleSet();
70
71     VM* vm();
72
73     HandleSlot allocate();
74     void deallocate(HandleSlot);
75
76     void visitStrongHandles(SlotVisitor&);
77
78     JS_EXPORT_PRIVATE void writeBarrier(HandleSlot, const JSValue&);
79
80     unsigned protectedGlobalObjectCount();
81
82     template<typename Functor> void forEachStrongHandle(const Functor&, const HashCountedSet<JSCell*>& skipSet);
83
84 private:
85     typedef HandleNode Node;
86     static HandleSlot toHandle(Node*);
87     static Node* toNode(HandleSlot);
88
89     JS_EXPORT_PRIVATE void grow();
90     
91 #if ENABLE(GC_VALIDATION) || !ASSERT_DISABLED
92     bool isLiveNode(Node*);
93 #endif
94
95     VM* m_vm;
96     DoublyLinkedList<HandleBlock> m_blockList;
97
98     SentinelLinkedList<Node> m_strongList;
99     SentinelLinkedList<Node> m_immediateList;
100     SinglyLinkedList<Node> m_freeList;
101 };
102
103 inline HandleSet* HandleSet::heapFor(HandleSlot handle)
104 {
105     return toNode(handle)->handleSet();
106 }
107
108 inline VM* HandleSet::vm()
109 {
110     return m_vm;
111 }
112
113 inline HandleSlot HandleSet::toHandle(HandleSet::Node* node)
114 {
115     return reinterpret_cast<HandleSlot>(node);
116 }
117
118 inline HandleSet::Node* HandleSet::toNode(HandleSlot handle)
119 {
120     return reinterpret_cast<HandleSet::Node*>(handle);
121 }
122
123 inline HandleSlot HandleSet::allocate()
124 {
125     if (m_freeList.isEmpty())
126         grow();
127
128     HandleSet::Node* node = m_freeList.pop();
129     new (NotNull, node) HandleSet::Node();
130     m_immediateList.push(node);
131     return toHandle(node);
132 }
133
134 inline void HandleSet::deallocate(HandleSlot handle)
135 {
136     HandleSet::Node* node = toNode(handle);
137     SentinelLinkedList<HandleSet::Node>::remove(node);
138     m_freeList.push(node);
139 }
140
141 inline HandleNode::HandleNode()
142     : m_prev(0)
143     , m_next(0)
144 {
145 }
146
147 inline HandleNode::HandleNode(WTF::SentinelTag)
148     : m_prev(0)
149     , m_next(0)
150 {
151 }
152
153 inline HandleSlot HandleNode::slot()
154 {
155     return &m_value;
156 }
157
158 inline HandleSet* HandleNode::handleSet()
159 {
160     return HandleBlock::blockFor(this)->handleSet();
161 }
162
163 inline void HandleNode::setPrev(HandleNode* prev)
164 {
165     m_prev = prev;
166 }
167
168 inline HandleNode* HandleNode::prev()
169 {
170     return m_prev;
171 }
172
173 inline void HandleNode::setNext(HandleNode* next)
174 {
175     m_next = next;
176 }
177
178 inline HandleNode* HandleNode::next()
179 {
180     return m_next;
181 }
182
183 template<typename Functor> void HandleSet::forEachStrongHandle(const Functor& functor, const HashCountedSet<JSCell*>& skipSet)
184 {
185     HandleSet::Node* end = m_strongList.end();
186     for (HandleSet::Node* node = m_strongList.begin(); node != end; node = node->next()) {
187         JSValue value = *node->slot();
188         if (!value || !value.isCell())
189             continue;
190         if (skipSet.contains(value.asCell()))
191             continue;
192         functor(value.asCell());
193     }
194 }
195
196 } // namespace JSC