diff options
Diffstat (limited to 'Source/JavaScriptCore/heap/HandleHeap.h')
-rw-r--r-- | Source/JavaScriptCore/heap/HandleHeap.h | 276 |
1 files changed, 276 insertions, 0 deletions
diff --git a/Source/JavaScriptCore/heap/HandleHeap.h b/Source/JavaScriptCore/heap/HandleHeap.h new file mode 100644 index 0000000..886c94a --- /dev/null +++ b/Source/JavaScriptCore/heap/HandleHeap.h @@ -0,0 +1,276 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef HandleHeap_h +#define HandleHeap_h + +#include "BlockStack.h" +#include "Handle.h" +#include "SentinelLinkedList.h" +#include "SinglyLinkedList.h" + +namespace JSC { + +class HandleHeap; +class HeapRootMarker; +class JSGlobalData; +class JSValue; +class MarkStack; +class TypeCounter; + +class WeakHandleOwner { +public: + virtual ~WeakHandleOwner(); + virtual bool isReachableFromOpaqueRoots(Handle<Unknown>, void* context, MarkStack&); + virtual void finalize(Handle<Unknown>, void* context); +}; + +class HandleHeap { +public: + static HandleHeap* heapFor(HandleSlot); + + HandleHeap(JSGlobalData*); + + JSGlobalData* globalData(); + + HandleSlot allocate(); + void deallocate(HandleSlot); + + void makeWeak(HandleSlot, WeakHandleOwner* = 0, void* context = 0); + HandleSlot copyWeak(HandleSlot); + + void markStrongHandles(HeapRootMarker&); + void markWeakHandles(HeapRootMarker&); + void finalizeWeakHandles(); + + void writeBarrier(HandleSlot, const JSValue&); + +#if !ASSERT_DISABLED + bool hasWeakOwner(HandleSlot, WeakHandleOwner*); +#endif + + unsigned protectedGlobalObjectCount(); + void protectedObjectTypeCounts(TypeCounter&); + +private: + class Node { + public: + Node(WTF::SentinelTag); + Node(HandleHeap*); + + HandleSlot slot(); + HandleHeap* handleHeap(); + + void makeWeak(WeakHandleOwner*, void* context); + bool isWeak(); + + WeakHandleOwner* weakOwner(); + void* weakOwnerContext(); + + void setPrev(Node*); + Node* prev(); + + void setNext(Node*); + Node* next(); + + private: + WeakHandleOwner* emptyWeakOwner(); + + JSValue m_value; + HandleHeap* m_handleHeap; + WeakHandleOwner* m_weakOwner; + void* m_weakOwnerContext; + Node* m_prev; + Node* m_next; + }; + + static HandleSlot toHandle(Node*); + static Node* toNode(HandleSlot); + + void grow(); + +#if !ASSERT_DISABLED + bool isValidWeakNode(Node*); +#endif + + JSGlobalData* m_globalData; + BlockStack<Node> m_blockStack; + + SentinelLinkedList<Node> m_strongList; + SentinelLinkedList<Node> m_weakList; + SentinelLinkedList<Node> m_immediateList; + SinglyLinkedList<Node> m_freeList; + Node* m_nextToFinalize; +}; + +inline HandleHeap* HandleHeap::heapFor(HandleSlot handle) +{ + return toNode(handle)->handleHeap(); +} + +inline JSGlobalData* HandleHeap::globalData() +{ + return m_globalData; +} + +inline HandleSlot HandleHeap::toHandle(Node* node) +{ + return reinterpret_cast<HandleSlot>(node); +} + +inline HandleHeap::Node* HandleHeap::toNode(HandleSlot handle) +{ + return reinterpret_cast<Node*>(handle); +} + +inline HandleSlot HandleHeap::allocate() +{ + if (m_freeList.isEmpty()) + grow(); + + Node* node = m_freeList.pop(); + new (node) Node(this); + m_immediateList.push(node); + return toHandle(node); +} + +inline void HandleHeap::deallocate(HandleSlot handle) +{ + Node* node = toNode(handle); + if (node == m_nextToFinalize) { + m_nextToFinalize = node->next(); + ASSERT(m_nextToFinalize->next()); + } + + SentinelLinkedList<Node>::remove(node); + m_freeList.push(node); +} + +inline HandleSlot HandleHeap::copyWeak(HandleSlot other) +{ + Node* node = toNode(allocate()); + node->makeWeak(toNode(other)->weakOwner(), toNode(other)->weakOwnerContext()); + writeBarrier(node->slot(), *other); + *node->slot() = *other; + return toHandle(node); +} + +inline void HandleHeap::makeWeak(HandleSlot handle, WeakHandleOwner* weakOwner, void* context) +{ + Node* node = toNode(handle); + node->makeWeak(weakOwner, context); + + SentinelLinkedList<Node>::remove(node); + if (!*handle || !handle->isCell()) { + m_immediateList.push(node); + return; + } + + m_weakList.push(node); +} + +#if !ASSERT_DISABLED +inline bool HandleHeap::hasWeakOwner(HandleSlot handle, WeakHandleOwner* weakOwner) +{ + return toNode(handle)->weakOwner() == weakOwner; +} +#endif + +inline HandleHeap::Node::Node(HandleHeap* handleHeap) + : m_handleHeap(handleHeap) + , m_weakOwner(0) + , m_weakOwnerContext(0) +{ +} + +inline HandleHeap::Node::Node(WTF::SentinelTag) + : m_handleHeap(0) + , m_weakOwner(0) + , m_weakOwnerContext(0) +{ +} + +inline HandleSlot HandleHeap::Node::slot() +{ + return &m_value; +} + +inline HandleHeap* HandleHeap::Node::handleHeap() +{ + return m_handleHeap; +} + +inline void HandleHeap::Node::makeWeak(WeakHandleOwner* weakOwner, void* context) +{ + m_weakOwner = weakOwner ? weakOwner : emptyWeakOwner(); + m_weakOwnerContext = context; +} + +inline bool HandleHeap::Node::isWeak() +{ + return m_weakOwner; // True for emptyWeakOwner(). +} + +inline WeakHandleOwner* HandleHeap::Node::weakOwner() +{ + return m_weakOwner == emptyWeakOwner() ? 0 : m_weakOwner; // 0 for emptyWeakOwner(). +} + +inline void* HandleHeap::Node::weakOwnerContext() +{ + ASSERT(weakOwner()); + return m_weakOwnerContext; +} + +inline void HandleHeap::Node::setPrev(Node* prev) +{ + m_prev = prev; +} + +inline HandleHeap::Node* HandleHeap::Node::prev() +{ + return m_prev; +} + +inline void HandleHeap::Node::setNext(Node* next) +{ + m_next = next; +} + +inline HandleHeap::Node* HandleHeap::Node::next() +{ + return m_next; +} + +// Sentinel to indicate that a node is weak, but its owner has no meaningful +// callbacks. This allows us to optimize by skipping such nodes. +inline WeakHandleOwner* HandleHeap::Node::emptyWeakOwner() +{ + return reinterpret_cast<WeakHandleOwner*>(-1); +} + +} + +#endif |