2 * Copyright (C) 2011 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
29 #include "BlockStack.h"
31 #include "SentinelLinkedList.h"
32 #include "SinglyLinkedList.h"
43 class WeakHandleOwner {
45 virtual ~WeakHandleOwner();
46 virtual bool isReachableFromOpaqueRoots(Handle<Unknown>, void* context, MarkStack&);
47 virtual void finalize(Handle<Unknown>, void* context);
52 static HandleHeap* heapFor(HandleSlot);
54 HandleHeap(JSGlobalData*);
56 JSGlobalData* globalData();
58 HandleSlot allocate();
59 void deallocate(HandleSlot);
61 void makeWeak(HandleSlot, WeakHandleOwner* = 0, void* context = 0);
62 HandleSlot copyWeak(HandleSlot);
64 void markStrongHandles(HeapRootMarker&);
65 void markWeakHandles(HeapRootMarker&);
66 void finalizeWeakHandles();
68 void writeBarrier(HandleSlot, const JSValue&);
71 bool hasWeakOwner(HandleSlot, WeakHandleOwner*);
74 unsigned protectedGlobalObjectCount();
75 void protectedObjectTypeCounts(TypeCounter&);
80 Node(WTF::SentinelTag);
84 HandleHeap* handleHeap();
86 void makeWeak(WeakHandleOwner*, void* context);
89 WeakHandleOwner* weakOwner();
90 void* weakOwnerContext();
99 WeakHandleOwner* emptyWeakOwner();
102 HandleHeap* m_handleHeap;
103 WeakHandleOwner* m_weakOwner;
104 void* m_weakOwnerContext;
109 static HandleSlot toHandle(Node*);
110 static Node* toNode(HandleSlot);
115 bool isValidWeakNode(Node*);
118 JSGlobalData* m_globalData;
119 BlockStack<Node> m_blockStack;
121 SentinelLinkedList<Node> m_strongList;
122 SentinelLinkedList<Node> m_weakList;
123 SentinelLinkedList<Node> m_immediateList;
124 SinglyLinkedList<Node> m_freeList;
125 Node* m_nextToFinalize;
128 inline HandleHeap* HandleHeap::heapFor(HandleSlot handle)
130 return toNode(handle)->handleHeap();
133 inline JSGlobalData* HandleHeap::globalData()
138 inline HandleSlot HandleHeap::toHandle(Node* node)
140 return reinterpret_cast<HandleSlot>(node);
143 inline HandleHeap::Node* HandleHeap::toNode(HandleSlot handle)
145 return reinterpret_cast<Node*>(handle);
148 inline HandleSlot HandleHeap::allocate()
150 if (m_freeList.isEmpty())
153 Node* node = m_freeList.pop();
154 new (node) Node(this);
155 m_immediateList.push(node);
156 return toHandle(node);
159 inline void HandleHeap::deallocate(HandleSlot handle)
161 Node* node = toNode(handle);
162 if (node == m_nextToFinalize) {
163 m_nextToFinalize = node->next();
164 ASSERT(m_nextToFinalize->next());
167 SentinelLinkedList<Node>::remove(node);
168 m_freeList.push(node);
171 inline HandleSlot HandleHeap::copyWeak(HandleSlot other)
173 Node* node = toNode(allocate());
174 node->makeWeak(toNode(other)->weakOwner(), toNode(other)->weakOwnerContext());
175 writeBarrier(node->slot(), *other);
176 *node->slot() = *other;
177 return toHandle(node);
180 inline void HandleHeap::makeWeak(HandleSlot handle, WeakHandleOwner* weakOwner, void* context)
182 Node* node = toNode(handle);
183 node->makeWeak(weakOwner, context);
185 SentinelLinkedList<Node>::remove(node);
186 if (!*handle || !handle->isCell()) {
187 m_immediateList.push(node);
191 m_weakList.push(node);
195 inline bool HandleHeap::hasWeakOwner(HandleSlot handle, WeakHandleOwner* weakOwner)
197 return toNode(handle)->weakOwner() == weakOwner;
201 inline HandleHeap::Node::Node(HandleHeap* handleHeap)
202 : m_handleHeap(handleHeap)
204 , m_weakOwnerContext(0)
208 inline HandleHeap::Node::Node(WTF::SentinelTag)
211 , m_weakOwnerContext(0)
215 inline HandleSlot HandleHeap::Node::slot()
220 inline HandleHeap* HandleHeap::Node::handleHeap()
225 inline void HandleHeap::Node::makeWeak(WeakHandleOwner* weakOwner, void* context)
227 m_weakOwner = weakOwner ? weakOwner : emptyWeakOwner();
228 m_weakOwnerContext = context;
231 inline bool HandleHeap::Node::isWeak()
233 return m_weakOwner; // True for emptyWeakOwner().
236 inline WeakHandleOwner* HandleHeap::Node::weakOwner()
238 return m_weakOwner == emptyWeakOwner() ? 0 : m_weakOwner; // 0 for emptyWeakOwner().
241 inline void* HandleHeap::Node::weakOwnerContext()
244 return m_weakOwnerContext;
247 inline void HandleHeap::Node::setPrev(Node* prev)
252 inline HandleHeap::Node* HandleHeap::Node::prev()
257 inline void HandleHeap::Node::setNext(Node* next)
262 inline HandleHeap::Node* HandleHeap::Node::next()
267 // Sentinel to indicate that a node is weak, but its owner has no meaningful
268 // callbacks. This allows us to optimize by skipping such nodes.
269 inline WeakHandleOwner* HandleHeap::Node::emptyWeakOwner()
271 return reinterpret_cast<WeakHandleOwner*>(-1);