HandleHeap.h revision 2daae5fd11344eaa88a0d92b0f6d65f8d2255c00
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 34namespace JSC { 35 36class HandleHeap; 37class HeapRootMarker; 38class JSGlobalData; 39class JSValue; 40class MarkStack; 41class TypeCounter; 42 43class WeakHandleOwner { 44public: 45 virtual ~WeakHandleOwner(); 46 virtual bool isReachableFromOpaqueRoots(Handle<Unknown>, void* context, MarkStack&); 47 virtual void finalize(Handle<Unknown>, void* context); 48}; 49 50class HandleHeap { 51public: 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 77private: 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 128inline HandleHeap* HandleHeap::heapFor(HandleSlot handle) 129{ 130 return toNode(handle)->handleHeap(); 131} 132 133inline JSGlobalData* HandleHeap::globalData() 134{ 135 return m_globalData; 136} 137 138inline HandleSlot HandleHeap::toHandle(Node* node) 139{ 140 return reinterpret_cast<HandleSlot>(node); 141} 142 143inline HandleHeap::Node* HandleHeap::toNode(HandleSlot handle) 144{ 145 return reinterpret_cast<Node*>(handle); 146} 147 148inline 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 159inline 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 171inline 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 180inline 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 195inline bool HandleHeap::hasWeakOwner(HandleSlot handle, WeakHandleOwner* weakOwner) 196{ 197 return toNode(handle)->weakOwner() == weakOwner; 198} 199#endif 200 201inline HandleHeap::Node::Node(HandleHeap* handleHeap) 202 : m_handleHeap(handleHeap) 203 , m_weakOwner(0) 204 , m_weakOwnerContext(0) 205{ 206} 207 208inline HandleHeap::Node::Node(WTF::SentinelTag) 209 : m_handleHeap(0) 210 , m_weakOwner(0) 211 , m_weakOwnerContext(0) 212{ 213} 214 215inline HandleSlot HandleHeap::Node::slot() 216{ 217 return &m_value; 218} 219 220inline HandleHeap* HandleHeap::Node::handleHeap() 221{ 222 return m_handleHeap; 223} 224 225inline void HandleHeap::Node::makeWeak(WeakHandleOwner* weakOwner, void* context) 226{ 227 m_weakOwner = weakOwner ? weakOwner : emptyWeakOwner(); 228 m_weakOwnerContext = context; 229} 230 231inline bool HandleHeap::Node::isWeak() 232{ 233 return m_weakOwner; // True for emptyWeakOwner(). 234} 235 236inline WeakHandleOwner* HandleHeap::Node::weakOwner() 237{ 238 return m_weakOwner == emptyWeakOwner() ? 0 : m_weakOwner; // 0 for emptyWeakOwner(). 239} 240 241inline void* HandleHeap::Node::weakOwnerContext() 242{ 243 ASSERT(weakOwner()); 244 return m_weakOwnerContext; 245} 246 247inline void HandleHeap::Node::setPrev(Node* prev) 248{ 249 m_prev = prev; 250} 251 252inline HandleHeap::Node* HandleHeap::Node::prev() 253{ 254 return m_prev; 255} 256 257inline void HandleHeap::Node::setNext(Node* next) 258{ 259 m_next = next; 260} 261 262inline 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. 269inline WeakHandleOwner* HandleHeap::Node::emptyWeakOwner() 270{ 271 return reinterpret_cast<WeakHandleOwner*>(-1); 272} 273 274} 275 276#endif 277