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 WriteBarrier_h 27#define WriteBarrier_h 28 29#include "JSValue.h" 30 31namespace JSC { 32class JSCell; 33class JSGlobalData; 34 35inline void writeBarrier(JSGlobalData&, const JSCell*, JSValue) 36{ 37} 38 39inline void writeBarrier(JSGlobalData&, const JSCell*, JSCell*) 40{ 41} 42 43typedef enum { } Unknown; 44typedef JSValue* HandleSlot; 45 46template <typename T> struct JSValueChecker { 47 static const bool IsJSValue = false; 48}; 49 50template <> struct JSValueChecker<JSValue> { 51 static const bool IsJSValue = true; 52}; 53 54// We have a separate base class with no constructors for use in Unions. 55template <typename T> class WriteBarrierBase { 56public: 57 COMPILE_ASSERT(!JSValueChecker<T>::IsJSValue, WriteBarrier_JSValue_is_invalid__use_unknown); 58 void set(JSGlobalData& globalData, const JSCell* owner, T* value) 59 { 60 this->m_cell = reinterpret_cast<JSCell*>(value); 61 writeBarrier(globalData, owner, this->m_cell); 62#if ENABLE(JSC_ZOMBIES) 63 ASSERT(!isZombie(owner)); 64 ASSERT(!isZombie(m_cell)); 65#endif 66 } 67 68 T* get() const 69 { 70 return reinterpret_cast<T*>(m_cell); 71 } 72 73 T* operator*() const 74 { 75 ASSERT(m_cell); 76#if ENABLE(JSC_ZOMBIES) 77 ASSERT(!isZombie(m_cell)); 78#endif 79 return static_cast<T*>(m_cell); 80 } 81 82 T* operator->() const 83 { 84 ASSERT(m_cell); 85 return static_cast<T*>(m_cell); 86 } 87 88 void clear() { m_cell = 0; } 89 90 JSCell** slot() { return &m_cell; } 91 92 typedef T* (WriteBarrierBase::*UnspecifiedBoolType); 93 operator UnspecifiedBoolType*() const { return m_cell ? reinterpret_cast<UnspecifiedBoolType*>(1) : 0; } 94 95 bool operator!() const { return !m_cell; } 96 97 void setWithoutWriteBarrier(T* value) 98 { 99 this->m_cell = reinterpret_cast<JSCell*>(value); 100#if ENABLE(JSC_ZOMBIES) 101 ASSERT(!m_cell || !isZombie(m_cell)); 102#endif 103 } 104 105private: 106 JSCell* m_cell; 107}; 108 109template <> class WriteBarrierBase<Unknown> { 110public: 111 void set(JSGlobalData& globalData, const JSCell* owner, JSValue value) 112 { 113#if ENABLE(JSC_ZOMBIES) 114 ASSERT(!isZombie(owner)); 115 ASSERT(!value.isZombie()); 116#endif 117 m_value = JSValue::encode(value); 118 writeBarrier(globalData, owner, value); 119 } 120 void setWithoutWriteBarrier(JSValue value) 121 { 122#if ENABLE(JSC_ZOMBIES) 123 ASSERT(!value.isZombie()); 124#endif 125 m_value = JSValue::encode(value); 126 } 127 128 JSValue get() const 129 { 130 return JSValue::decode(m_value); 131 } 132 void clear() { m_value = JSValue::encode(JSValue()); } 133 void setUndefined() { m_value = JSValue::encode(jsUndefined()); } 134 bool isNumber() const { return get().isNumber(); } 135 bool isObject() const { return get().isObject(); } 136 bool isNull() const { return get().isNull(); } 137 bool isGetterSetter() const { return get().isGetterSetter(); } 138 139 JSValue* slot() 140 { 141 union { 142 EncodedJSValue* v; 143 JSValue* slot; 144 } u; 145 u.v = &m_value; 146 return u.slot; 147 } 148 149 typedef JSValue (WriteBarrierBase::*UnspecifiedBoolType); 150 operator UnspecifiedBoolType*() const { return get() ? reinterpret_cast<UnspecifiedBoolType*>(1) : 0; } 151 bool operator!() const { return !get(); } 152 153private: 154 EncodedJSValue m_value; 155}; 156 157template <typename T> class WriteBarrier : public WriteBarrierBase<T> { 158public: 159 WriteBarrier() 160 { 161 this->setWithoutWriteBarrier(0); 162 } 163 164 WriteBarrier(JSGlobalData& globalData, const JSCell* owner, T* value) 165 { 166 this->set(globalData, owner, value); 167 } 168}; 169 170template <> class WriteBarrier<Unknown> : public WriteBarrierBase<Unknown> { 171public: 172 WriteBarrier() 173 { 174 this->setWithoutWriteBarrier(JSValue()); 175 } 176 177 WriteBarrier(JSGlobalData& globalData, const JSCell* owner, JSValue value) 178 { 179 this->set(globalData, owner, value); 180 } 181}; 182 183template <typename U, typename V> inline bool operator==(const WriteBarrierBase<U>& lhs, const WriteBarrierBase<V>& rhs) 184{ 185 return lhs.get() == rhs.get(); 186} 187 188} // namespace JSC 189 190#endif // WriteBarrier_h 191