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#ifndef JITWriteBarrier_h 27#define JITWriteBarrier_h 28 29#if ENABLE(JIT) 30 31#include "MacroAssembler.h" 32#include "SlotVisitor.h" 33#include "UnusedPointer.h" 34#include "WriteBarrier.h" 35 36namespace JSC { 37 38class JSCell; 39class VM; 40 41// Needs to be even to appease some of the backends. 42#define JITWriteBarrierFlag ((void*)2) 43class JITWriteBarrierBase { 44public: 45 typedef void* (JITWriteBarrierBase::*UnspecifiedBoolType); 46 operator UnspecifiedBoolType*() const { return get() ? reinterpret_cast<UnspecifiedBoolType*>(1) : 0; } 47 bool operator!() const { return !get(); } 48 49 void setFlagOnBarrier() 50 { 51 ASSERT(!m_location); 52 m_location = CodeLocationDataLabelPtr(JITWriteBarrierFlag); 53 } 54 55 bool isFlagged() const 56 { 57 return !!m_location; 58 } 59 60 void setLocation(CodeLocationDataLabelPtr location) 61 { 62 ASSERT(!m_location); 63 m_location = location; 64 } 65 66 CodeLocationDataLabelPtr location() const 67 { 68 ASSERT((!!m_location) && m_location.executableAddress() != JITWriteBarrierFlag); 69 return m_location; 70 } 71 72 void clear() { clear(0); } 73 void clearToUnusedPointer() { clear(reinterpret_cast<void*>(unusedPointer)); } 74 75protected: 76 JITWriteBarrierBase() 77 { 78 } 79 80 void set(VM& vm, CodeLocationDataLabelPtr location, JSCell* owner, JSCell* value) 81 { 82 vm.heap.writeBarrier(owner, value); 83 m_location = location; 84 ASSERT(((!!m_location) && m_location.executableAddress() != JITWriteBarrierFlag) || (location.executableAddress() == m_location.executableAddress())); 85 MacroAssembler::repatchPointer(m_location, value); 86 ASSERT(get() == value); 87 } 88 89 JSCell* get() const 90 { 91 if (!m_location || m_location.executableAddress() == JITWriteBarrierFlag) 92 return 0; 93 void* result = static_cast<JSCell*>(MacroAssembler::readPointer(m_location)); 94 if (result == reinterpret_cast<void*>(unusedPointer)) 95 return 0; 96 return static_cast<JSCell*>(result); 97 } 98 99private: 100 void clear(void* clearedValue) 101 { 102 if (!m_location) 103 return; 104 if (m_location.executableAddress() != JITWriteBarrierFlag) 105 MacroAssembler::repatchPointer(m_location, clearedValue); 106 } 107 108 CodeLocationDataLabelPtr m_location; 109}; 110 111#undef JITWriteBarrierFlag 112 113template <typename T> class JITWriteBarrier : public JITWriteBarrierBase { 114public: 115 JITWriteBarrier() 116 { 117 } 118 119 void set(VM& vm, CodeLocationDataLabelPtr location, JSCell* owner, T* value) 120 { 121 validateCell(owner); 122 validateCell(value); 123 JITWriteBarrierBase::set(vm, location, owner, value); 124 } 125 void set(VM& vm, JSCell* owner, T* value) 126 { 127 set(vm, location(), owner, value); 128 } 129 T* get() const 130 { 131 T* result = static_cast<T*>(JITWriteBarrierBase::get()); 132 if (result) 133 validateCell(result); 134 return result; 135 } 136}; 137 138template<typename T> inline void SlotVisitor::append(JITWriteBarrier<T>* slot) 139{ 140 internalAppend(0, slot->get()); 141} 142 143} 144 145#endif // ENABLE(JIT) 146 147#endif 148