1/* 2 * Copyright (C) 2012 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#ifndef SlotVisitorInlines_h 27#define SlotVisitorInlines_h 28 29#include "CopiedBlockInlines.h" 30#include "CopiedSpaceInlines.h" 31#include "Options.h" 32#include "SlotVisitor.h" 33#include "Weak.h" 34#include "WeakInlines.h" 35 36namespace JSC { 37 38ALWAYS_INLINE void SlotVisitor::append(JSValue* slot, size_t count) 39{ 40 for (size_t i = 0; i < count; ++i) { 41 JSValue& value = slot[i]; 42 internalAppend(value); 43 } 44} 45 46template<typename T> 47inline void SlotVisitor::appendUnbarrieredPointer(T** slot) 48{ 49 ASSERT(slot); 50 JSCell* cell = *slot; 51 internalAppend(cell); 52} 53 54ALWAYS_INLINE void SlotVisitor::append(JSValue* slot) 55{ 56 ASSERT(slot); 57 internalAppend(*slot); 58} 59 60ALWAYS_INLINE void SlotVisitor::appendUnbarrieredValue(JSValue* slot) 61{ 62 ASSERT(slot); 63 internalAppend(*slot); 64} 65 66ALWAYS_INLINE void SlotVisitor::append(JSCell** slot) 67{ 68 ASSERT(slot); 69 internalAppend(*slot); 70} 71 72template<typename T> 73ALWAYS_INLINE void SlotVisitor::appendUnbarrieredWeak(Weak<T>* weak) 74{ 75 ASSERT(weak); 76 if (weak->get()) 77 internalAppend(weak->get()); 78} 79 80ALWAYS_INLINE void SlotVisitor::internalAppend(JSValue value) 81{ 82 if (!value || !value.isCell()) 83 return; 84 internalAppend(value.asCell()); 85} 86 87inline void SlotVisitor::addWeakReferenceHarvester(WeakReferenceHarvester* weakReferenceHarvester) 88{ 89 m_shared.m_weakReferenceHarvesters.addThreadSafe(weakReferenceHarvester); 90} 91 92inline void SlotVisitor::addUnconditionalFinalizer(UnconditionalFinalizer* unconditionalFinalizer) 93{ 94 m_shared.m_unconditionalFinalizers.addThreadSafe(unconditionalFinalizer); 95} 96 97inline void SlotVisitor::addOpaqueRoot(void* root) 98{ 99#if ENABLE(PARALLEL_GC) 100 if (Options::numberOfGCMarkers() == 1) { 101 // Put directly into the shared HashSet. 102 m_shared.m_opaqueRoots.add(root); 103 return; 104 } 105 // Put into the local set, but merge with the shared one every once in 106 // a while to make sure that the local sets don't grow too large. 107 mergeOpaqueRootsIfProfitable(); 108 m_opaqueRoots.add(root); 109#else 110 m_opaqueRoots.add(root); 111#endif 112} 113 114inline bool SlotVisitor::containsOpaqueRoot(void* root) 115{ 116 ASSERT(!m_isInParallelMode); 117#if ENABLE(PARALLEL_GC) 118 ASSERT(m_opaqueRoots.isEmpty()); 119 return m_shared.m_opaqueRoots.contains(root); 120#else 121 return m_opaqueRoots.contains(root); 122#endif 123} 124 125inline TriState SlotVisitor::containsOpaqueRootTriState(void* root) 126{ 127 if (m_opaqueRoots.contains(root)) 128 return TrueTriState; 129 MutexLocker locker(m_shared.m_opaqueRootsLock); 130 if (m_shared.m_opaqueRoots.contains(root)) 131 return TrueTriState; 132 return MixedTriState; 133} 134 135inline int SlotVisitor::opaqueRootCount() 136{ 137 ASSERT(!m_isInParallelMode); 138#if ENABLE(PARALLEL_GC) 139 ASSERT(m_opaqueRoots.isEmpty()); 140 return m_shared.m_opaqueRoots.size(); 141#else 142 return m_opaqueRoots.size(); 143#endif 144} 145 146inline void SlotVisitor::mergeOpaqueRootsIfNecessary() 147{ 148 if (m_opaqueRoots.isEmpty()) 149 return; 150 mergeOpaqueRoots(); 151} 152 153inline void SlotVisitor::mergeOpaqueRootsIfProfitable() 154{ 155 if (static_cast<unsigned>(m_opaqueRoots.size()) < Options::opaqueRootMergeThreshold()) 156 return; 157 mergeOpaqueRoots(); 158} 159 160inline void SlotVisitor::donate() 161{ 162 ASSERT(m_isInParallelMode); 163 if (Options::numberOfGCMarkers() == 1) 164 return; 165 166 donateKnownParallel(); 167} 168 169inline void SlotVisitor::donateAndDrain() 170{ 171 donate(); 172 drain(); 173} 174 175inline void SlotVisitor::copyLater(JSCell* owner, void* ptr, size_t bytes) 176{ 177 ASSERT(bytes); 178 CopiedBlock* block = CopiedSpace::blockFor(ptr); 179 if (block->isOversize()) { 180 m_shared.m_copiedSpace->pin(block); 181 return; 182 } 183 184 if (block->isPinned()) 185 return; 186 187 block->reportLiveBytes(owner, bytes); 188} 189 190} // namespace JSC 191 192#endif // SlotVisitorInlines_h 193 194