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
writeBarrier(JSGlobalData &,const JSCell *,JSValue)35 inline void writeBarrier(JSGlobalData&, const JSCell*, JSValue)
36 {
37 }
38
writeBarrier(JSGlobalData &,const JSCell *,JSCell *)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