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 31 namespace JSC { 32 class JSCell; 33 class JSGlobalData; 34 35 inline void writeBarrier(JSGlobalData&, const JSCell*, JSValue) 36 { 37 } 38 39 inline void writeBarrier(JSGlobalData&, const JSCell*, JSCell*) 40 { 41 } 42 43 typedef enum { } Unknown; 44 typedef JSValue* HandleSlot; 45 46 template <typename T> struct JSValueChecker { 47 static const bool IsJSValue = false; 48 }; 49 50 template <> 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. 55 template <typename T> class WriteBarrierBase { 56 public: 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 105 private: 106 JSCell* m_cell; 107 }; 108 109 template <> class WriteBarrierBase<Unknown> { 110 public: 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 153 private: 154 EncodedJSValue m_value; 155 }; 156 157 template <typename T> class WriteBarrier : public WriteBarrierBase<T> { 158 public: 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 170 template <> class WriteBarrier<Unknown> : public WriteBarrierBase<Unknown> { 171 public: 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 183 template <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