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 HandleHeap_h 27 #define HandleHeap_h 28 29 #include "BlockStack.h" 30 #include "Handle.h" 31 #include "SentinelLinkedList.h" 32 #include "SinglyLinkedList.h" 33 34 namespace JSC { 35 36 class HandleHeap; 37 class HeapRootMarker; 38 class JSGlobalData; 39 class JSValue; 40 class MarkStack; 41 class TypeCounter; 42 43 class WeakHandleOwner { 44 public: 45 virtual ~WeakHandleOwner(); 46 virtual bool isReachableFromOpaqueRoots(Handle<Unknown>, void* context, MarkStack&); 47 virtual void finalize(Handle<Unknown>, void* context); 48 }; 49 50 class HandleHeap { 51 public: 52 static HandleHeap* heapFor(HandleSlot); 53 54 HandleHeap(JSGlobalData*); 55 56 JSGlobalData* globalData(); 57 58 HandleSlot allocate(); 59 void deallocate(HandleSlot); 60 61 void makeWeak(HandleSlot, WeakHandleOwner* = 0, void* context = 0); 62 HandleSlot copyWeak(HandleSlot); 63 64 void markStrongHandles(HeapRootMarker&); 65 void markWeakHandles(HeapRootMarker&); 66 void finalizeWeakHandles(); 67 68 void writeBarrier(HandleSlot, const JSValue&); 69 70 #if !ASSERT_DISABLED 71 bool hasWeakOwner(HandleSlot, WeakHandleOwner*); 72 #endif 73 74 unsigned protectedGlobalObjectCount(); 75 void protectedObjectTypeCounts(TypeCounter&); 76 77 private: 78 class Node { 79 public: 80 Node(WTF::SentinelTag); 81 Node(HandleHeap*); 82 83 HandleSlot slot(); 84 HandleHeap* handleHeap(); 85 86 void makeWeak(WeakHandleOwner*, void* context); 87 bool isWeak(); 88 89 WeakHandleOwner* weakOwner(); 90 void* weakOwnerContext(); 91 92 void setPrev(Node*); 93 Node* prev(); 94 95 void setNext(Node*); 96 Node* next(); 97 98 private: 99 WeakHandleOwner* emptyWeakOwner(); 100 101 JSValue m_value; 102 HandleHeap* m_handleHeap; 103 WeakHandleOwner* m_weakOwner; 104 void* m_weakOwnerContext; 105 Node* m_prev; 106 Node* m_next; 107 }; 108 109 static HandleSlot toHandle(Node*); 110 static Node* toNode(HandleSlot); 111 112 void grow(); 113 114 #if !ASSERT_DISABLED 115 bool isValidWeakNode(Node*); 116 #endif 117 118 JSGlobalData* m_globalData; 119 BlockStack<Node> m_blockStack; 120 121 SentinelLinkedList<Node> m_strongList; 122 SentinelLinkedList<Node> m_weakList; 123 SentinelLinkedList<Node> m_immediateList; 124 SinglyLinkedList<Node> m_freeList; 125 Node* m_nextToFinalize; 126 }; 127 128 inline HandleHeap* HandleHeap::heapFor(HandleSlot handle) 129 { 130 return toNode(handle)->handleHeap(); 131 } 132 133 inline JSGlobalData* HandleHeap::globalData() 134 { 135 return m_globalData; 136 } 137 138 inline HandleSlot HandleHeap::toHandle(Node* node) 139 { 140 return reinterpret_cast<HandleSlot>(node); 141 } 142 143 inline HandleHeap::Node* HandleHeap::toNode(HandleSlot handle) 144 { 145 return reinterpret_cast<Node*>(handle); 146 } 147 148 inline HandleSlot HandleHeap::allocate() 149 { 150 if (m_freeList.isEmpty()) 151 grow(); 152 153 Node* node = m_freeList.pop(); 154 new (node) Node(this); 155 m_immediateList.push(node); 156 return toHandle(node); 157 } 158 159 inline void HandleHeap::deallocate(HandleSlot handle) 160 { 161 Node* node = toNode(handle); 162 if (node == m_nextToFinalize) { 163 m_nextToFinalize = node->next(); 164 ASSERT(m_nextToFinalize->next()); 165 } 166 167 SentinelLinkedList<Node>::remove(node); 168 m_freeList.push(node); 169 } 170 171 inline HandleSlot HandleHeap::copyWeak(HandleSlot other) 172 { 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); 178 } 179 180 inline void HandleHeap::makeWeak(HandleSlot handle, WeakHandleOwner* weakOwner, void* context) 181 { 182 Node* node = toNode(handle); 183 node->makeWeak(weakOwner, context); 184 185 SentinelLinkedList<Node>::remove(node); 186 if (!*handle || !handle->isCell()) { 187 m_immediateList.push(node); 188 return; 189 } 190 191 m_weakList.push(node); 192 } 193 194 #if !ASSERT_DISABLED 195 inline bool HandleHeap::hasWeakOwner(HandleSlot handle, WeakHandleOwner* weakOwner) 196 { 197 return toNode(handle)->weakOwner() == weakOwner; 198 } 199 #endif 200 201 inline HandleHeap::Node::Node(HandleHeap* handleHeap) 202 : m_handleHeap(handleHeap) 203 , m_weakOwner(0) 204 , m_weakOwnerContext(0) 205 { 206 } 207 208 inline HandleHeap::Node::Node(WTF::SentinelTag) 209 : m_handleHeap(0) 210 , m_weakOwner(0) 211 , m_weakOwnerContext(0) 212 { 213 } 214 215 inline HandleSlot HandleHeap::Node::slot() 216 { 217 return &m_value; 218 } 219 220 inline HandleHeap* HandleHeap::Node::handleHeap() 221 { 222 return m_handleHeap; 223 } 224 225 inline void HandleHeap::Node::makeWeak(WeakHandleOwner* weakOwner, void* context) 226 { 227 m_weakOwner = weakOwner ? weakOwner : emptyWeakOwner(); 228 m_weakOwnerContext = context; 229 } 230 231 inline bool HandleHeap::Node::isWeak() 232 { 233 return m_weakOwner; // True for emptyWeakOwner(). 234 } 235 236 inline WeakHandleOwner* HandleHeap::Node::weakOwner() 237 { 238 return m_weakOwner == emptyWeakOwner() ? 0 : m_weakOwner; // 0 for emptyWeakOwner(). 239 } 240 241 inline void* HandleHeap::Node::weakOwnerContext() 242 { 243 ASSERT(weakOwner()); 244 return m_weakOwnerContext; 245 } 246 247 inline void HandleHeap::Node::setPrev(Node* prev) 248 { 249 m_prev = prev; 250 } 251 252 inline HandleHeap::Node* HandleHeap::Node::prev() 253 { 254 return m_prev; 255 } 256 257 inline void HandleHeap::Node::setNext(Node* next) 258 { 259 m_next = next; 260 } 261 262 inline HandleHeap::Node* HandleHeap::Node::next() 263 { 264 return m_next; 265 } 266 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() 270 { 271 return reinterpret_cast<WeakHandleOwner*>(-1); 272 } 273 274 } 275 276 #endif 277