summaryrefslogtreecommitdiffstats
path: root/Source/JavaScriptCore/heap/HandleHeap.h
diff options
context:
space:
mode:
Diffstat (limited to 'Source/JavaScriptCore/heap/HandleHeap.h')
-rw-r--r--Source/JavaScriptCore/heap/HandleHeap.h276
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