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 "ConservativeRoots.h" 28 29#include "CodeBlock.h" 30#include "CodeBlockSet.h" 31#include "CopiedSpace.h" 32#include "CopiedSpaceInlines.h" 33#include "JSCell.h" 34#include "JSObject.h" 35#include "JSCInlines.h" 36#include "Structure.h" 37 38namespace JSC { 39 40ConservativeRoots::ConservativeRoots(const MarkedBlockSet* blocks, CopiedSpace* copiedSpace) 41 : m_roots(m_inlineRoots) 42 , m_size(0) 43 , m_capacity(inlineCapacity) 44 , m_blocks(blocks) 45 , m_copiedSpace(copiedSpace) 46{ 47} 48 49ConservativeRoots::~ConservativeRoots() 50{ 51 if (m_roots != m_inlineRoots) 52 OSAllocator::decommitAndRelease(m_roots, m_capacity * sizeof(JSCell*)); 53} 54 55void ConservativeRoots::grow() 56{ 57 size_t newCapacity = m_capacity == inlineCapacity ? nonInlineCapacity : m_capacity * 2; 58 JSCell** newRoots = static_cast<JSCell**>(OSAllocator::reserveAndCommit(newCapacity * sizeof(JSCell*))); 59 memcpy(newRoots, m_roots, m_size * sizeof(JSCell*)); 60 if (m_roots != m_inlineRoots) 61 OSAllocator::decommitAndRelease(m_roots, m_capacity * sizeof(JSCell*)); 62 m_capacity = newCapacity; 63 m_roots = newRoots; 64} 65 66template<typename MarkHook> 67inline void ConservativeRoots::genericAddPointer(void* p, TinyBloomFilter filter, MarkHook& markHook) 68{ 69 markHook.mark(p); 70 71 m_copiedSpace->pinIfNecessary(p); 72 73 MarkedBlock* candidate = MarkedBlock::blockFor(p); 74 if (filter.ruleOut(reinterpret_cast<Bits>(candidate))) { 75 ASSERT(!candidate || !m_blocks->set().contains(candidate)); 76 return; 77 } 78 79 if (!MarkedBlock::isAtomAligned(p)) 80 return; 81 82 if (!m_blocks->set().contains(candidate)) 83 return; 84 85 if (!candidate->isLiveCell(p)) 86 return; 87 88 if (m_size == m_capacity) 89 grow(); 90 91 m_roots[m_size++] = static_cast<JSCell*>(p); 92} 93 94template<typename MarkHook> 95void ConservativeRoots::genericAddSpan(void* begin, void* end, MarkHook& markHook) 96{ 97 if (begin > end) { 98 void* swapTemp = begin; 99 begin = end; 100 end = swapTemp; 101 } 102 103 RELEASE_ASSERT(isPointerAligned(begin)); 104 RELEASE_ASSERT(isPointerAligned(end)); 105 106 TinyBloomFilter filter = m_blocks->filter(); // Make a local copy of filter to show the compiler it won't alias, and can be register-allocated. 107 for (char** it = static_cast<char**>(begin); it != static_cast<char**>(end); ++it) 108 genericAddPointer(*it, filter, markHook); 109} 110 111class DummyMarkHook { 112public: 113 void mark(void*) { } 114}; 115 116void ConservativeRoots::add(void* begin, void* end) 117{ 118 DummyMarkHook dummy; 119 genericAddSpan(begin, end, dummy); 120} 121 122void ConservativeRoots::add(void* begin, void* end, JITStubRoutineSet& jitStubRoutines) 123{ 124 genericAddSpan(begin, end, jitStubRoutines); 125} 126 127template<typename T, typename U> 128class CompositeMarkHook { 129public: 130 CompositeMarkHook(T& first, U& second) 131 : m_first(first) 132 , m_second(second) 133 { 134 } 135 136 void mark(void* address) 137 { 138 m_first.mark(address); 139 m_second.mark(address); 140 } 141 142private: 143 T& m_first; 144 U& m_second; 145}; 146 147void ConservativeRoots::add( 148 void* begin, void* end, JITStubRoutineSet& jitStubRoutines, CodeBlockSet& codeBlocks) 149{ 150 CompositeMarkHook<JITStubRoutineSet, CodeBlockSet> markHook(jitStubRoutines, codeBlocks); 151 genericAddSpan(begin, end, markHook); 152} 153 154} // namespace JSC 155