1 /* 2 * Copyright (C) 2011 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 23 * THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #include "config.h" 27 #include "HandleHeap.h" 28 29 #include "JSObject.h" 30 31 namespace JSC { 32 33 WeakHandleOwner::~WeakHandleOwner() 34 { 35 } 36 37 bool WeakHandleOwner::isReachableFromOpaqueRoots(Handle<Unknown>, void*, MarkStack&) 38 { 39 return false; 40 } 41 42 void WeakHandleOwner::finalize(Handle<Unknown>, void*) 43 { 44 } 45 46 HandleHeap::HandleHeap(JSGlobalData* globalData) 47 : m_globalData(globalData) 48 , m_nextToFinalize(0) 49 { 50 grow(); 51 } 52 53 void HandleHeap::grow() 54 { 55 Node* block = m_blockStack.grow(); 56 for (int i = m_blockStack.blockLength - 1; i >= 0; --i) { 57 Node* node = &block[i]; 58 new (node) Node(this); 59 m_freeList.push(node); 60 } 61 } 62 63 void HandleHeap::markStrongHandles(HeapRootMarker& heapRootMarker) 64 { 65 Node* end = m_strongList.end(); 66 for (Node* node = m_strongList.begin(); node != end; node = node->next()) 67 heapRootMarker.mark(node->slot()); 68 } 69 70 void HandleHeap::markWeakHandles(HeapRootMarker& heapRootMarker) 71 { 72 MarkStack& markStack = heapRootMarker.markStack(); 73 74 Node* end = m_weakList.end(); 75 for (Node* node = m_weakList.begin(); node != end; node = node->next()) { 76 ASSERT(isValidWeakNode(node)); 77 JSCell* cell = node->slot()->asCell(); 78 if (Heap::isMarked(cell)) 79 continue; 80 81 WeakHandleOwner* weakOwner = node->weakOwner(); 82 if (!weakOwner) 83 continue; 84 85 if (!weakOwner->isReachableFromOpaqueRoots(Handle<Unknown>::wrapSlot(node->slot()), node->weakOwnerContext(), markStack)) 86 continue; 87 88 heapRootMarker.mark(node->slot()); 89 } 90 } 91 92 void HandleHeap::finalizeWeakHandles() 93 { 94 Node* end = m_weakList.end(); 95 for (Node* node = m_weakList.begin(); node != end; node = m_nextToFinalize) { 96 m_nextToFinalize = node->next(); 97 98 ASSERT(isValidWeakNode(node)); 99 JSCell* cell = node->slot()->asCell(); 100 if (Heap::isMarked(cell)) 101 continue; 102 103 if (WeakHandleOwner* weakOwner = node->weakOwner()) { 104 weakOwner->finalize(Handle<Unknown>::wrapSlot(node->slot()), node->weakOwnerContext()); 105 if (m_nextToFinalize != node->next()) // Owner deallocated node. 106 continue; 107 } 108 109 *node->slot() = JSValue(); 110 SentinelLinkedList<Node>::remove(node); 111 m_immediateList.push(node); 112 } 113 114 m_nextToFinalize = 0; 115 } 116 117 void HandleHeap::writeBarrier(HandleSlot slot, const JSValue& value) 118 { 119 ASSERT(!m_nextToFinalize); // Forbid assignment to handles during the finalization phase, since it would violate many GC invariants. 120 121 if (!value == !*slot && slot->isCell() == value.isCell()) 122 return; 123 124 Node* node = toNode(slot); 125 SentinelLinkedList<Node>::remove(node); 126 if (!value || !value.isCell()) { 127 m_immediateList.push(node); 128 return; 129 } 130 131 if (node->isWeak()) { 132 m_weakList.push(node); 133 return; 134 } 135 136 m_strongList.push(node); 137 } 138 139 unsigned HandleHeap::protectedGlobalObjectCount() 140 { 141 unsigned count = 0; 142 Node* end = m_strongList.end(); 143 for (Node* node = m_strongList.begin(); node != end; node = node->next()) { 144 JSValue value = *node->slot(); 145 if (value.isObject() && asObject(value.asCell())->isGlobalObject()) 146 count++; 147 } 148 return count; 149 } 150 151 #if !ASSERT_DISABLED 152 bool HandleHeap::isValidWeakNode(Node* node) 153 { 154 if (!node->isWeak()) 155 return false; 156 157 JSValue value = *node->slot(); 158 if (!value || !value.isCell()) 159 return false; 160 161 JSCell* cell = value.asCell(); 162 if (!cell || !cell->structure()) 163 return false; 164 165 #if ENABLE(JSC_ZOMBIES) 166 if (cell->isZombie()) 167 return false; 168 #endif 169 170 return true; 171 } 172 #endif 173 174 } // namespace JSC 175