/* * 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 { WeakHandleOwner::~WeakHandleOwner() { } bool WeakHandleOwner::isReachableFromOpaqueRoots(Handle, void*, MarkStack&) { return false; } void WeakHandleOwner::finalize(Handle, void*) { } HandleHeap::HandleHeap(JSGlobalData* globalData) : m_globalData(globalData) , m_nextToFinalize(0) { 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(HeapRootMarker& heapRootMarker) { Node* end = m_strongList.end(); for (Node* node = m_strongList.begin(); node != end; node = node->next()) heapRootMarker.mark(node->slot()); } void HandleHeap::markWeakHandles(HeapRootMarker& heapRootMarker) { MarkStack& markStack = heapRootMarker.markStack(); Node* end = m_weakList.end(); for (Node* node = m_weakList.begin(); node != end; node = node->next()) { ASSERT(isValidWeakNode(node)); JSCell* cell = node->slot()->asCell(); if (Heap::isMarked(cell)) continue; WeakHandleOwner* weakOwner = node->weakOwner(); if (!weakOwner) continue; if (!weakOwner->isReachableFromOpaqueRoots(Handle::wrapSlot(node->slot()), node->weakOwnerContext(), markStack)) continue; heapRootMarker.mark(node->slot()); } } void HandleHeap::finalizeWeakHandles() { Node* end = m_weakList.end(); for (Node* node = m_weakList.begin(); node != end; node = m_nextToFinalize) { m_nextToFinalize = node->next(); ASSERT(isValidWeakNode(node)); JSCell* cell = node->slot()->asCell(); if (Heap::isMarked(cell)) continue; if (WeakHandleOwner* weakOwner = node->weakOwner()) { weakOwner->finalize(Handle::wrapSlot(node->slot()), node->weakOwnerContext()); if (m_nextToFinalize != node->next()) // Owner deallocated node. continue; } *node->slot() = JSValue(); SentinelLinkedList::remove(node); m_immediateList.push(node); } m_nextToFinalize = 0; } void HandleHeap::writeBarrier(HandleSlot slot, const JSValue& value) { ASSERT(!m_nextToFinalize); // Forbid assignment to handles during the finalization phase, since it would violate many GC invariants. if (!value == !*slot && slot->isCell() == value.isCell()) return; Node* node = toNode(slot); SentinelLinkedList::remove(node); if (!value || !value.isCell()) { m_immediateList.push(node); return; } if (node->isWeak()) { m_weakList.push(node); return; } 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; } #if !ASSERT_DISABLED bool HandleHeap::isValidWeakNode(Node* node) { if (!node->isWeak()) return false; JSValue value = *node->slot(); if (!value || !value.isCell()) return false; JSCell* cell = value.asCell(); if (!cell || !cell->structure()) return false; #if ENABLE(JSC_ZOMBIES) if (cell->isZombie()) return false; #endif return true; } #endif } // namespace JSC