]> git.saurik.com Git - apple/javascriptcore.git/blame - runtime/WriteBarrier.h
JavaScriptCore-903.5.tar.gz
[apple/javascriptcore.git] / runtime / WriteBarrier.h
CommitLineData
14957cd0
A
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 "HandleTypes.h"
30#include "Heap.h"
31#include "TypeTraits.h"
32
33namespace JSC {
34
35class JSCell;
36class JSGlobalData;
37class JSGlobalObject;
38
39template<class T> class WriteBarrierBase;
40template<> class WriteBarrierBase<JSValue>;
41
42void slowValidateCell(JSCell*);
43void slowValidateCell(JSGlobalObject*);
44
45#if ENABLE(GC_VALIDATION)
46template<class T> inline void validateCell(T cell)
47{
48 ASSERT_GC_OBJECT_INHERITS(cell, &WTF::RemovePointer<T>::Type::s_info);
49}
50
51template<> inline void validateCell<JSCell*>(JSCell* cell)
52{
53 slowValidateCell(cell);
54}
55
56template<> inline void validateCell<JSGlobalObject*>(JSGlobalObject* globalObject)
57{
58 slowValidateCell(globalObject);
59}
60#else
61template<class T> inline void validateCell(T)
62{
63}
64#endif
65
66// We have a separate base class with no constructors for use in Unions.
67template <typename T> class WriteBarrierBase {
68public:
69 void set(JSGlobalData& globalData, const JSCell* owner, T* value)
70 {
71 ASSERT(value);
72 validateCell(value);
73 setEarlyValue(globalData, owner, value);
74 }
75
76 void setMayBeNull(JSGlobalData& globalData, const JSCell* owner, T* value)
77 {
78 if (value)
79 validateCell(value);
80 setEarlyValue(globalData, owner, value);
81 }
82
83 // Should only be used by JSCell during early initialisation
84 // when some basic types aren't yet completely instantiated
85 void setEarlyValue(JSGlobalData&, const JSCell* owner, T* value)
86 {
87 this->m_cell = reinterpret_cast<JSCell*>(value);
88 Heap::writeBarrier(owner, this->m_cell);
89#if ENABLE(JSC_ZOMBIES)
90 ASSERT(!isZombie(owner));
91 ASSERT(!isZombie(m_cell));
92#endif
93 }
94
95 T* get() const
96 {
97 if (m_cell)
98 validateCell(m_cell);
99 return reinterpret_cast<T*>(m_cell);
100 }
101
102 T* operator*() const
103 {
104 ASSERT(m_cell);
105#if ENABLE(JSC_ZOMBIES)
106 ASSERT(!isZombie(m_cell));
107#endif
108 validateCell<T>(static_cast<T*>(m_cell));
109 return static_cast<T*>(m_cell);
110 }
111
112 T* operator->() const
113 {
114 ASSERT(m_cell);
115 validateCell(static_cast<T*>(m_cell));
116 return static_cast<T*>(m_cell);
117 }
118
119 void clear() { m_cell = 0; }
120
121 JSCell** slot() { return &m_cell; }
122
123 typedef T* (WriteBarrierBase::*UnspecifiedBoolType);
124 operator UnspecifiedBoolType*() const { return m_cell ? reinterpret_cast<UnspecifiedBoolType*>(1) : 0; }
125
126 bool operator!() const { return !m_cell; }
127
128 void setWithoutWriteBarrier(T* value)
129 {
130 this->m_cell = reinterpret_cast<JSCell*>(value);
131#if ENABLE(JSC_ZOMBIES)
132 ASSERT(!m_cell || !isZombie(m_cell));
133#endif
134 }
135
136#if ENABLE(GC_VALIDATION)
137 T* unvalidatedGet() const { return reinterpret_cast<T*>(m_cell); }
138#endif
139
140private:
141 JSCell* m_cell;
142};
143
144template <> class WriteBarrierBase<Unknown> {
145public:
146 void set(JSGlobalData&, const JSCell* owner, JSValue value)
147 {
148#if ENABLE(JSC_ZOMBIES)
149 ASSERT(!isZombie(owner));
150 ASSERT(!value.isZombie());
151#endif
152 m_value = JSValue::encode(value);
153 Heap::writeBarrier(owner, value);
154 }
155
156 void setWithoutWriteBarrier(JSValue value)
157 {
158#if ENABLE(JSC_ZOMBIES)
159 ASSERT(!value.isZombie());
160#endif
161 m_value = JSValue::encode(value);
162 }
163
164 JSValue get() const
165 {
166 return JSValue::decode(m_value);
167 }
168 void clear() { m_value = JSValue::encode(JSValue()); }
169 void setUndefined() { m_value = JSValue::encode(jsUndefined()); }
170 bool isNumber() const { return get().isNumber(); }
171 bool isObject() const { return get().isObject(); }
172 bool isNull() const { return get().isNull(); }
173 bool isGetterSetter() const { return get().isGetterSetter(); }
174
175 JSValue* slot()
176 {
177 union {
178 EncodedJSValue* v;
179 JSValue* slot;
180 } u;
181 u.v = &m_value;
182 return u.slot;
183 }
184
185 typedef JSValue (WriteBarrierBase::*UnspecifiedBoolType);
186 operator UnspecifiedBoolType*() const { return get() ? reinterpret_cast<UnspecifiedBoolType*>(1) : 0; }
187 bool operator!() const { return !get(); }
188
189private:
190 EncodedJSValue m_value;
191};
192
193template <typename T> class WriteBarrier : public WriteBarrierBase<T> {
194public:
195 WriteBarrier()
196 {
197 this->setWithoutWriteBarrier(0);
198 }
199
200 WriteBarrier(JSGlobalData& globalData, const JSCell* owner, T* value)
201 {
202 this->set(globalData, owner, value);
203 }
204
205 enum MayBeNullTag { MayBeNull };
206 WriteBarrier(JSGlobalData& globalData, const JSCell* owner, T* value, MayBeNullTag)
207 {
208 this->setMayBeNull(globalData, owner, value);
209 }
210};
211
212template <> class WriteBarrier<Unknown> : public WriteBarrierBase<Unknown> {
213public:
214 WriteBarrier()
215 {
216 this->setWithoutWriteBarrier(JSValue());
217 }
218
219 WriteBarrier(JSGlobalData& globalData, const JSCell* owner, JSValue value)
220 {
221 this->set(globalData, owner, value);
222 }
223};
224
225template <typename U, typename V> inline bool operator==(const WriteBarrierBase<U>& lhs, const WriteBarrierBase<V>& rhs)
226{
227 return lhs.get() == rhs.get();
228}
229
230// MarkStack functions
231
232template<typename T> inline void MarkStack::append(WriteBarrierBase<T>* slot)
233{
234 internalAppend(*slot->slot());
235}
236
237inline void MarkStack::appendValues(WriteBarrierBase<Unknown>* barriers, size_t count, MarkSetProperties properties)
238{
239 JSValue* values = barriers->slot();
240#if ENABLE(GC_VALIDATION)
241 validateSet(values, count);
242#endif
243 if (count)
244 m_markSets.append(MarkSet(values, values + count, properties));
245}
246
247} // namespace JSC
248
249#endif // WriteBarrier_h