X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/1df5f87f1309a8daa30dabdee855f48ae40d14ab..6fe7ccc865dc7d7541b93c5bcaf6368d2c98a174:/heap/HandleSet.h?ds=inline diff --git a/heap/HandleSet.h b/heap/HandleSet.h new file mode 100644 index 0000000..c22ffa4 --- /dev/null +++ b/heap/HandleSet.h @@ -0,0 +1,208 @@ +/* + * 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 HandleSet_h +#define HandleSet_h + +#include +#include "Handle.h" +#include +#include +#include + +namespace JSC { + +class HandleSet; +class HeapRootVisitor; +class JSGlobalData; +class JSValue; +class SlotVisitor; + +class HandleSet { +public: + static HandleSet* heapFor(HandleSlot); + + HandleSet(JSGlobalData*); + + JSGlobalData* globalData(); + + HandleSlot allocate(); + void deallocate(HandleSlot); + + void visitStrongHandles(HeapRootVisitor&); + + JS_EXPORT_PRIVATE void writeBarrier(HandleSlot, const JSValue&); + + unsigned protectedGlobalObjectCount(); + + template void forEachStrongHandle(Functor&, const HashCountedSet& skipSet); + +private: + class Node { + public: + Node(WTF::SentinelTag); + Node(HandleSet*); + + HandleSlot slot(); + HandleSet* handleSet(); + + void setPrev(Node*); + Node* prev(); + + void setNext(Node*); + Node* next(); + + private: + JSValue m_value; + HandleSet* m_handleSet; + Node* m_prev; + Node* m_next; + }; + + static HandleSlot toHandle(Node*); + static Node* toNode(HandleSlot); + + JS_EXPORT_PRIVATE void grow(); + +#if ENABLE(GC_VALIDATION) || !ASSERT_DISABLED + bool isLiveNode(Node*); +#endif + + JSGlobalData* m_globalData; + BlockStack m_blockStack; + + SentinelLinkedList m_strongList; + SentinelLinkedList m_immediateList; + SinglyLinkedList m_freeList; + Node* m_nextToFinalize; +}; + +inline HandleSet* HandleSet::heapFor(HandleSlot handle) +{ + return toNode(handle)->handleSet(); +} + +inline JSGlobalData* HandleSet::globalData() +{ + return m_globalData; +} + +inline HandleSlot HandleSet::toHandle(Node* node) +{ + return reinterpret_cast(node); +} + +inline HandleSet::Node* HandleSet::toNode(HandleSlot handle) +{ + return reinterpret_cast(handle); +} + +inline HandleSlot HandleSet::allocate() +{ + // Forbid assignment to handles during the finalization phase, since it would violate many GC invariants. + // File a bug with stack trace if you hit this. + if (m_nextToFinalize) + CRASH(); + if (m_freeList.isEmpty()) + grow(); + + Node* node = m_freeList.pop(); + new (NotNull, node) Node(this); + m_immediateList.push(node); + return toHandle(node); +} + +inline void HandleSet::deallocate(HandleSlot handle) +{ + Node* node = toNode(handle); + if (node == m_nextToFinalize) { + ASSERT(m_nextToFinalize->next()); + m_nextToFinalize = m_nextToFinalize->next(); + } + + SentinelLinkedList::remove(node); + m_freeList.push(node); +} + +inline HandleSet::Node::Node(HandleSet* handleSet) + : m_handleSet(handleSet) + , m_prev(0) + , m_next(0) +{ +} + +inline HandleSet::Node::Node(WTF::SentinelTag) + : m_handleSet(0) + , m_prev(0) + , m_next(0) +{ +} + +inline HandleSlot HandleSet::Node::slot() +{ + return &m_value; +} + +inline HandleSet* HandleSet::Node::handleSet() +{ + return m_handleSet; +} + +inline void HandleSet::Node::setPrev(Node* prev) +{ + m_prev = prev; +} + +inline HandleSet::Node* HandleSet::Node::prev() +{ + return m_prev; +} + +inline void HandleSet::Node::setNext(Node* next) +{ + m_next = next; +} + +inline HandleSet::Node* HandleSet::Node::next() +{ + return m_next; +} + +template void HandleSet::forEachStrongHandle(Functor& functor, const HashCountedSet& skipSet) +{ + Node* end = m_strongList.end(); + for (Node* node = m_strongList.begin(); node != end; node = node->next()) { + JSValue value = *node->slot(); + if (!value || !value.isCell()) + continue; + if (skipSet.contains(value.asCell())) + continue; + functor(value.asCell()); + } +} + +} + +#endif