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 36namespace JSC { 37 38class HandleBlock; 39class HandleSet; 40class HeapRootVisitor; 41class VM; 42class JSValue; 43class SlotVisitor; 44 45class HandleNode { 46public: 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 59private: 60 JSValue m_value; 61 HandleNode* m_prev; 62 HandleNode* m_next; 63}; 64 65class HandleSet { 66 friend class HandleBlock; 67public: 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 86private: 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 105inline HandleSet* HandleSet::heapFor(HandleSlot handle) 106{ 107 return toNode(handle)->handleSet(); 108} 109 110inline VM* HandleSet::vm() 111{ 112 return m_vm; 113} 114 115inline HandleSlot HandleSet::toHandle(HandleSet::Node* node) 116{ 117 return reinterpret_cast<HandleSlot>(node); 118} 119 120inline HandleSet::Node* HandleSet::toNode(HandleSlot handle) 121{ 122 return reinterpret_cast<HandleSet::Node*>(handle); 123} 124 125inline 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 136inline 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 143inline HandleNode::HandleNode() 144 : m_prev(0) 145 , m_next(0) 146{ 147} 148 149inline HandleNode::HandleNode(WTF::SentinelTag) 150 : m_prev(0) 151 , m_next(0) 152{ 153} 154 155inline HandleSlot HandleNode::slot() 156{ 157 return &m_value; 158} 159 160inline HandleSet* HandleNode::handleSet() 161{ 162 return HandleBlock::blockFor(this)->handleSet(); 163} 164 165inline void HandleNode::setPrev(HandleNode* prev) 166{ 167 m_prev = prev; 168} 169 170inline HandleNode* HandleNode::prev() 171{ 172 return m_prev; 173} 174 175inline void HandleNode::setNext(HandleNode* next) 176{ 177 m_next = next; 178} 179 180inline HandleNode* HandleNode::next() 181{ 182 return m_next; 183} 184 185template<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 201