summaryrefslogtreecommitdiffstats
path: root/Source/JavaScriptCore/collector
diff options
context:
space:
mode:
authorBen Murdoch <benm@google.com>2011-05-24 11:24:40 +0100
committerBen Murdoch <benm@google.com>2011-06-02 09:53:15 +0100
commit81bc750723a18f21cd17d1b173cd2a4dda9cea6e (patch)
tree7a9e5ed86ff429fd347a25153107221543909b19 /Source/JavaScriptCore/collector
parent94088a6d336c1dd80a1e734af51e96abcbb689a7 (diff)
downloadexternal_webkit-81bc750723a18f21cd17d1b173cd2a4dda9cea6e.zip
external_webkit-81bc750723a18f21cd17d1b173cd2a4dda9cea6e.tar.gz
external_webkit-81bc750723a18f21cd17d1b173cd2a4dda9cea6e.tar.bz2
Merge WebKit at r80534: Intial merge by Git
Change-Id: Ia7a83357124c9e1cdb1debf55d9661ec0bd09a61
Diffstat (limited to 'Source/JavaScriptCore/collector')
-rw-r--r--Source/JavaScriptCore/collector/handles/Global.h159
-rw-r--r--Source/JavaScriptCore/collector/handles/Handle.h189
-rw-r--r--Source/JavaScriptCore/collector/handles/HandleHeap.cpp137
-rw-r--r--Source/JavaScriptCore/collector/handles/HandleHeap.h273
4 files changed, 758 insertions, 0 deletions
diff --git a/Source/JavaScriptCore/collector/handles/Global.h b/Source/JavaScriptCore/collector/handles/Global.h
new file mode 100644
index 0000000..571fe31
--- /dev/null
+++ b/Source/JavaScriptCore/collector/handles/Global.h
@@ -0,0 +1,159 @@
+/*
+ * 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 Global_h
+#define Global_h
+
+#include "Assertions.h"
+#include "Handle.h"
+#include "HandleHeap.h"
+#include "JSGlobalData.h"
+
+namespace JSC {
+
+/*
+ A Global is a persistent handle whose lifetime is not limited to any given
+ scope. Use Globals for data members and global variables.
+*/
+
+template <typename T> class Global : public Handle<T> {
+public:
+ typedef typename Handle<T>::ExternalType ExternalType;
+ Global(JSGlobalData& globalData, ExternalType ptr = ExternalType())
+ : Handle<T>(globalData.allocateGlobalHandle())
+ {
+ internalSet(ptr);
+ }
+
+ Global(JSGlobalData& globalData, Handle<T> handle)
+ : Handle<T>(globalData.allocateGlobalHandle())
+ {
+ internalSet(handle.get());
+ }
+
+ enum EmptyValueTag { EmptyValue };
+ Global(EmptyValueTag)
+ : Handle<T>(0, HandleBase::DontNullCheckSlot)
+ {
+ }
+
+ ~Global()
+ {
+ HandleSlot slot = this->slot();
+ if (slot)
+ HandleHeap::heapFor(slot)->deallocate(slot);
+ }
+
+ void set(JSGlobalData& globalData, ExternalType value)
+ {
+ if (!value) {
+ clear();
+ return;
+ }
+ if (!this->slot())
+ this->setSlot(globalData.allocateGlobalHandle());
+ internalSet(value);
+ }
+
+ template <typename U> Global& operator=(const Global<U>& handle)
+ {
+ if (handle.slot()) {
+ if (!this->slot())
+ this->setSlot(HandleHeap::heapFor(handle.slot())->allocate());
+ internalSet(handle.get());
+ } else
+ clear();
+
+ return *this;
+ }
+
+ Global& operator=(const Global& handle)
+ {
+ if (handle.slot()) {
+ if (!this->slot())
+ this->setSlot(HandleHeap::heapFor(handle.slot())->allocate());
+ internalSet(handle.get());
+ } else
+ clear();
+
+ return *this;
+ }
+
+ void clear()
+ {
+ if (this->slot())
+ internalSet(ExternalType());
+ }
+
+ enum HashTableDeletedValueType { HashTableDeletedValue };
+ const static intptr_t HashTableDeletedValueTag = 0x1;
+ Global(HashTableDeletedValueType)
+ : Handle<T>(reinterpret_cast<HandleSlot>(HashTableDeletedValueTag))
+ {
+ }
+ bool isHashTableDeletedValue() const { return slot() == reinterpret_cast<HandleSlot>(HashTableDeletedValueTag); }
+
+ template <typename U> Global(const Global<U>& other)
+ : Handle<T>(other.slot() ? HandleHeap::heapFor(other.slot())->allocate() : 0, Handle<T>::DontNullCheckSlot)
+ {
+ if (other.slot())
+ internalSet(other.get());
+ }
+
+ Global(const Global& other)
+ : Handle<T>(other.slot() ? HandleHeap::heapFor(other.slot())->allocate() : 0, Handle<T>::DontNullCheckSlot)
+ {
+ if (other.slot())
+ internalSet(other.get());
+ }
+
+protected:
+ void internalSet(ExternalType value)
+ {
+ JSValue newValue(HandleTypes<T>::toJSValue(value));
+ HandleSlot slot = this->slot();
+ ASSERT(slot);
+ HandleHeap::heapFor(slot)->writeBarrier(slot, newValue);
+ *slot = newValue;
+ }
+
+ using Handle<T>::slot;
+
+};
+
+}
+
+namespace WTF {
+
+template<typename P> struct HashTraits<JSC::Global<P> > : GenericHashTraits<JSC::Global<P> > {
+ static const bool emptyValueIsZero = true;
+ static JSC::Global<P> emptyValue() { return JSC::Global<P>(JSC::Global<P>::EmptyValue); }
+ static void constructDeletedValue(JSC::Global<P>& slot) { new (&slot) JSC::Global<P>(JSC::Global<P>::HashTableDeletedValue); }
+ static bool isDeletedValue(const JSC::Global<P>& value) { return value.isHashTableDeletedValue(); }
+};
+
+}
+
+#endif // Global_h
diff --git a/Source/JavaScriptCore/collector/handles/Handle.h b/Source/JavaScriptCore/collector/handles/Handle.h
new file mode 100644
index 0000000..98c60ec
--- /dev/null
+++ b/Source/JavaScriptCore/collector/handles/Handle.h
@@ -0,0 +1,189 @@
+/*
+ * 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 Handle_h
+#define Handle_h
+
+#include "WriteBarrier.h"
+
+#include <wtf/Assertions.h>
+
+namespace JSC {
+
+/*
+ A Handle is a smart pointer that updates automatically when the garbage
+ collector moves the object to which it points.
+
+ The base Handle class represents a temporary reference to a pointer whose
+ lifetime is guaranteed by something else.
+*/
+
+template <class T> class Handle;
+
+// Creating a JSValue Handle is invalid
+template <> class Handle<JSValue>;
+
+class HandleBase {
+ friend class HandleHeap;
+
+public:
+ bool operator!() const { return isEmpty(); }
+
+ // This conversion operator allows implicit conversion to bool but not to other integer types.
+ typedef JSValue (HandleBase::*UnspecifiedBoolType);
+ operator UnspecifiedBoolType*() const { return (m_slot && *m_slot) ? reinterpret_cast<UnspecifiedBoolType*>(1) : 0; }
+
+ bool isEmpty() const { return !m_slot || !*m_slot; }
+
+protected:
+ HandleBase(HandleSlot slot)
+ : m_slot(slot)
+ {
+ ASSERT(slot);
+ }
+
+ enum DontNullCheckSlotTag { DontNullCheckSlot };
+ HandleBase(HandleSlot slot, DontNullCheckSlotTag)
+ : m_slot(slot)
+ {
+ }
+
+ HandleSlot slot() const { return m_slot; }
+ void invalidate()
+ {
+ // It is unsafe to use a handle after invalidating it.
+ m_slot = 0;
+ }
+
+ // needed by Global<>::operator= and Global<>::set if it's an empty handle
+ void setSlot(HandleSlot slot)
+ {
+ ASSERT(!m_slot);
+ ASSERT(slot);
+ m_slot = slot;
+ }
+
+private:
+ HandleSlot m_slot;
+};
+
+template <typename T> struct HandleTypes {
+ typedef T* ExternalType;
+ static ExternalType getFromSlot(HandleSlot slot) { return (slot && *slot) ? reinterpret_cast<ExternalType>(slot->asCell()) : 0; }
+ static JSValue toJSValue(T* cell) { return reinterpret_cast<JSCell*>(cell); }
+ template <typename U> static void validateUpcast() { T* temp; temp = (U*)0; }
+};
+
+template <> struct HandleTypes<Unknown> {
+ typedef JSValue ExternalType;
+ static ExternalType getFromSlot(HandleSlot slot) { return slot ? *slot : JSValue(); }
+ static JSValue toJSValue(const JSValue& v) { return v; }
+ template <typename U> static void validateUpcast() {}
+};
+
+template <typename Base, typename T> struct HandleConverter {
+ T* operator->() { return static_cast<Base*>(this)->get(); }
+ const T* operator->() const { return static_cast<const Base*>(this)->get(); }
+ T* operator*() { return static_cast<Base*>(this)->get(); }
+ const T* operator*() const { return static_cast<const Base*>(this)->get(); }
+};
+
+template <typename Base> struct HandleConverter<Base, Unknown> {
+};
+
+template <typename T> class Handle : public HandleBase, public HandleConverter<Handle<T>, T> {
+public:
+ typedef typename HandleTypes<T>::ExternalType ExternalType;
+ template <typename U> Handle(Handle<U> o)
+ {
+ typename HandleTypes<T>::template validateUpcast<U>();
+ m_slot = o.slot();
+ }
+
+ ExternalType get() const { return HandleTypes<T>::getFromSlot(this->slot()); }
+
+protected:
+
+ Handle(HandleSlot slot)
+ : HandleBase(slot)
+ {
+ }
+ Handle(HandleSlot slot, HandleBase::DontNullCheckSlotTag)
+ : HandleBase(slot, HandleBase::DontNullCheckSlot)
+ {
+ }
+
+private:
+ friend class HandleHeap;
+
+ static Handle<T> wrapSlot(HandleSlot slot)
+ {
+ return Handle<T>(slot);
+ }
+};
+
+template <typename T, typename U> inline bool operator==(const Handle<T>& a, const Handle<U>& b)
+{
+ return a.get() == b.get();
+}
+
+template <typename T, typename U> inline bool operator==(const Handle<T>& a, U* b)
+{
+ return a.get() == b;
+}
+
+template <typename T, typename U> inline bool operator==(T* a, const Handle<U>& b)
+{
+ return a == b.get();
+}
+
+template <typename T, typename U> inline bool operator!=(const Handle<T>& a, const Handle<U>& b)
+{
+ return a.get() != b.get();
+}
+
+template <typename T, typename U> inline bool operator!=(const Handle<T>& a, U* b)
+{
+ return a.get() != b;
+}
+
+template <typename T, typename U> inline bool operator!=(T* a, const Handle<U>& b)
+{
+ return a != b.get();
+}
+
+template <typename T, typename U> inline bool operator!=(const Handle<T>& a, JSValue b)
+{
+ return a.get() != b;
+}
+
+template <typename T, typename U> inline bool operator!=(JSValue a, const Handle<U>& b)
+{
+ return a != b.get();
+}
+
+}
+
+#endif
diff --git a/Source/JavaScriptCore/collector/handles/HandleHeap.cpp b/Source/JavaScriptCore/collector/handles/HandleHeap.cpp
new file mode 100644
index 0000000..32fa42d
--- /dev/null
+++ b/Source/JavaScriptCore/collector/handles/HandleHeap.cpp
@@ -0,0 +1,137 @@
+/*
+ * 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.
+ */
+
+#include "config.h"
+
+#include "HandleHeap.h"
+
+#include "JSObject.h"
+
+namespace JSC {
+
+HandleHeap::HandleHeap(JSGlobalData* globalData)
+ : m_globalData(globalData)
+ , m_nextToFinalize(0)
+#if !ASSERT_DISABLED
+ , m_handlingFinalizers(false)
+#endif
+{
+ grow();
+}
+
+void HandleHeap::grow()
+{
+ Node* block = m_blockStack.grow();
+ for (int i = m_blockStack.blockLength - 1; i >= 0; --i) {
+ Node* node = &block[i];
+ new (node) Node(this);
+ m_freeList.push(node);
+ }
+}
+
+void HandleHeap::markStrongHandles(MarkStack& markStack)
+{
+ Node* end = m_strongList.end();
+ for (Node* node = m_strongList.begin(); node != end; node = node->next())
+ markStack.deprecatedAppend(node->slot());
+}
+
+void HandleHeap::updateAfterMark()
+{
+ clearWeakPointers();
+}
+
+void HandleHeap::clearWeakPointers()
+{
+#if !ASSERT_DISABLED
+ m_handlingFinalizers = true;
+#endif
+ Node* end = m_weakList.end();
+ for (Node* node = m_weakList.begin(); node != end;) {
+ Node* current = node;
+ node = current->next();
+
+ JSValue value = *current->slot();
+ if (!value || !value.isCell())
+ continue;
+
+ JSCell* cell = value.asCell();
+ ASSERT(!cell || cell->structure());
+
+ if (Heap::isMarked(cell))
+ continue;
+
+ if (Finalizer* finalizer = current->finalizer()) {
+ m_nextToFinalize = node;
+ finalizer->finalize(Handle<Unknown>::wrapSlot(current->slot()), current->finalizerContext());
+ node = m_nextToFinalize;
+ m_nextToFinalize = 0;
+ }
+
+ if (current->isSelfDestroying()) {
+ ASSERT(node != current);
+ ASSERT(current->next() == node);
+ deallocate(toHandle(current));
+ } else if (current->next() == node) { // if current->next() != node, then current has been deallocated
+ SentinelLinkedList<Node>::remove(current);
+ *current->slot() = JSValue();
+ m_immediateList.push(current);
+ }
+ }
+#if !ASSERT_DISABLED
+ m_handlingFinalizers = false;
+#endif
+}
+
+void HandleHeap::writeBarrier(HandleSlot slot, const JSValue& value)
+{
+ ASSERT(!m_handlingFinalizers);
+ if (slot->isCell() == value.isCell() && !value == !*slot)
+ return;
+ Node* node = toNode(slot);
+ SentinelLinkedList<Node>::remove(node);
+ if (!value.isCell() || !value) {
+ m_immediateList.push(node);
+ return;
+ }
+ if (node->isWeak())
+ m_weakList.push(node);
+ else
+ m_strongList.push(node);
+}
+
+unsigned HandleHeap::protectedGlobalObjectCount()
+{
+ unsigned count = 0;
+ Node* end = m_strongList.end();
+ for (Node* node = m_strongList.begin(); node != end; node = node->next()) {
+ JSValue value = *node->slot();
+ if (value.isObject() && asObject(value.asCell())->isGlobalObject())
+ count++;
+ }
+ return count;
+}
+
+}
diff --git a/Source/JavaScriptCore/collector/handles/HandleHeap.h b/Source/JavaScriptCore/collector/handles/HandleHeap.h
new file mode 100644
index 0000000..4bb9b00
--- /dev/null
+++ b/Source/JavaScriptCore/collector/handles/HandleHeap.h
@@ -0,0 +1,273 @@
+/*
+ * 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 JSGlobalData;
+class JSValue;
+class MarkStack;
+
+class Finalizer {
+public:
+ virtual void finalize(Handle<Unknown>, void*) = 0;
+ virtual ~Finalizer() {}
+};
+
+class HandleHeap {
+public:
+ static HandleHeap* heapFor(HandleSlot);
+
+ HandleHeap(JSGlobalData*);
+
+ HandleSlot allocate();
+ void deallocate(HandleSlot);
+
+ void makeWeak(HandleSlot, Finalizer*, void* context);
+ void makeSelfDestroying(HandleSlot, Finalizer*, void* context);
+
+ void markStrongHandles(MarkStack&);
+ void updateAfterMark();
+
+ // Should only be called during teardown.
+ void clearWeakPointers();
+
+ void writeBarrier(HandleSlot, const JSValue&);
+
+#if !ASSERT_DISABLED
+ Finalizer* getFinalizer(HandleSlot handle)
+ {
+ return toNode(handle)->finalizer();
+ }
+#endif
+
+ unsigned protectedGlobalObjectCount();
+
+private:
+ typedef uintptr_t HandleHeapWithFlags;
+ enum { FlagsMask = 3, WeakFlag = 1, SelfDestroyingFlag = 2 };
+ class Node {
+ public:
+ Node(WTF::SentinelTag);
+ Node(HandleHeap*);
+
+ HandleSlot slot();
+ HandleHeap* handleHeap();
+
+ void setFinalizer(Finalizer*, void* context);
+ Finalizer* finalizer();
+ void* finalizerContext();
+
+ void setPrev(Node*);
+ Node* prev();
+
+ void setNext(Node*);
+ Node* next();
+
+ bool isWeak();
+ void makeWeak();
+
+ bool isSelfDestroying();
+ void makeSelfDestroying();
+
+ private:
+ JSValue m_value;
+ HandleHeapWithFlags m_handleHeapWithFlags;
+ Finalizer* m_finalizer;
+ void* m_finalizerContext;
+ Node* m_prev;
+ Node* m_next;
+ };
+
+ static HandleSlot toHandle(Node*);
+ static Node* toNode(HandleSlot);
+
+ void grow();
+
+ 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;
+
+#if !ASSERT_DISABLED
+ bool m_handlingFinalizers;
+#endif
+};
+
+inline HandleHeap* HandleHeap::heapFor(HandleSlot handle)
+{
+ return toNode(handle)->handleHeap();
+}
+
+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 (m_nextToFinalize == node) {
+ m_nextToFinalize = node->next();
+ ASSERT(m_nextToFinalize->next());
+ }
+ SentinelLinkedList<Node>::remove(node);
+ m_freeList.push(node);
+}
+
+inline void HandleHeap::makeWeak(HandleSlot handle, Finalizer* finalizer, void* context)
+{
+ Node* node = toNode(handle);
+ SentinelLinkedList<Node>::remove(node);
+ node->setFinalizer(finalizer, context);
+ node->makeWeak();
+ if (handle->isCell() && *handle)
+ m_weakList.push(node);
+ else
+ m_immediateList.push(node);
+}
+
+inline void HandleHeap::makeSelfDestroying(HandleSlot handle, Finalizer* finalizer, void* context)
+{
+ makeWeak(handle, finalizer, context);
+ Node* node = toNode(handle);
+ node->makeSelfDestroying();
+}
+
+inline HandleHeap::Node::Node(HandleHeap* handleHeap)
+ : m_handleHeapWithFlags(reinterpret_cast<uintptr_t>(handleHeap))
+ , m_finalizer(0)
+ , m_finalizerContext(0)
+{
+}
+
+inline HandleHeap::Node::Node(WTF::SentinelTag)
+ : m_handleHeapWithFlags(0)
+ , m_finalizer(0)
+ , m_finalizerContext(0)
+{
+}
+
+inline HandleSlot HandleHeap::Node::slot()
+{
+ return &m_value;
+}
+
+inline HandleHeap* HandleHeap::Node::handleHeap()
+{
+ return reinterpret_cast<HandleHeap*>(m_handleHeapWithFlags & ~FlagsMask);
+}
+
+inline void HandleHeap::Node::setFinalizer(Finalizer* finalizer, void* context)
+{
+ m_finalizer = finalizer;
+ m_finalizerContext = context;
+}
+
+inline void HandleHeap::Node::makeWeak()
+{
+ ASSERT(!(m_handleHeapWithFlags & WeakFlag));
+ m_handleHeapWithFlags |= WeakFlag;
+}
+
+inline bool HandleHeap::Node::isWeak()
+{
+ return !!(m_handleHeapWithFlags & WeakFlag);
+}
+
+inline void HandleHeap::Node::makeSelfDestroying()
+{
+ ASSERT(m_handleHeapWithFlags & WeakFlag);
+ ASSERT(!(m_handleHeapWithFlags & SelfDestroyingFlag));
+ m_handleHeapWithFlags |= SelfDestroyingFlag;
+}
+
+inline bool HandleHeap::Node::isSelfDestroying()
+{
+ return !!(m_handleHeapWithFlags & SelfDestroyingFlag);
+}
+
+inline Finalizer* HandleHeap::Node::finalizer()
+{
+ return m_finalizer;
+}
+
+inline void* HandleHeap::Node::finalizerContext()
+{
+ ASSERT(m_finalizer);
+ return m_finalizerContext;
+}
+
+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;
+}
+
+}
+
+#endif