2 * Copyright (C) 2011 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
26 #ifndef WriteBarrier_h
27 #define WriteBarrier_h
29 #include "HandleTypes.h"
31 #include "TypeTraits.h"
39 template<class T
> class WriteBarrierBase
;
40 template<> class WriteBarrierBase
<JSValue
>;
42 void slowValidateCell(JSCell
*);
43 void slowValidateCell(JSGlobalObject
*);
45 #if ENABLE(GC_VALIDATION)
46 template<class T
> inline void validateCell(T cell
)
48 ASSERT_GC_OBJECT_INHERITS(cell
, &WTF::RemovePointer
<T
>::Type::s_info
);
51 template<> inline void validateCell
<JSCell
*>(JSCell
* cell
)
53 slowValidateCell(cell
);
56 template<> inline void validateCell
<JSGlobalObject
*>(JSGlobalObject
* globalObject
)
58 slowValidateCell(globalObject
);
61 template<class T
> inline void validateCell(T
)
66 // We have a separate base class with no constructors for use in Unions.
67 template <typename T
> class WriteBarrierBase
{
69 void set(JSGlobalData
& globalData
, const JSCell
* owner
, T
* value
)
73 setEarlyValue(globalData
, owner
, value
);
76 void setMayBeNull(JSGlobalData
& globalData
, const JSCell
* owner
, T
* value
)
80 setEarlyValue(globalData
, owner
, value
);
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
)
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
));
99 return reinterpret_cast<T
*>(m_cell
);
105 #if ENABLE(JSC_ZOMBIES)
106 ASSERT(!isZombie(m_cell
));
108 validateCell
<T
>(static_cast<T
*>(m_cell
));
109 return static_cast<T
*>(m_cell
);
112 T
* operator->() const
115 validateCell(static_cast<T
*>(m_cell
));
116 return static_cast<T
*>(m_cell
);
119 void clear() { m_cell
= 0; }
121 JSCell
** slot() { return &m_cell
; }
123 typedef T
* (WriteBarrierBase::*UnspecifiedBoolType
);
124 operator UnspecifiedBoolType
*() const { return m_cell
? reinterpret_cast<UnspecifiedBoolType
*>(1) : 0; }
126 bool operator!() const { return !m_cell
; }
128 void setWithoutWriteBarrier(T
* value
)
130 this->m_cell
= reinterpret_cast<JSCell
*>(value
);
131 #if ENABLE(JSC_ZOMBIES)
132 ASSERT(!m_cell
|| !isZombie(m_cell
));
136 #if ENABLE(GC_VALIDATION)
137 T
* unvalidatedGet() const { return reinterpret_cast<T
*>(m_cell
); }
144 template <> class WriteBarrierBase
<Unknown
> {
146 void set(JSGlobalData
&, const JSCell
* owner
, JSValue value
)
148 #if ENABLE(JSC_ZOMBIES)
149 ASSERT(!isZombie(owner
));
150 ASSERT(!value
.isZombie());
152 m_value
= JSValue::encode(value
);
153 Heap::writeBarrier(owner
, value
);
156 void setWithoutWriteBarrier(JSValue value
)
158 #if ENABLE(JSC_ZOMBIES)
159 ASSERT(!value
.isZombie());
161 m_value
= JSValue::encode(value
);
166 return JSValue::decode(m_value
);
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(); }
185 typedef JSValue (WriteBarrierBase::*UnspecifiedBoolType
);
186 operator UnspecifiedBoolType
*() const { return get() ? reinterpret_cast<UnspecifiedBoolType
*>(1) : 0; }
187 bool operator!() const { return !get(); }
190 EncodedJSValue m_value
;
193 template <typename T
> class WriteBarrier
: public WriteBarrierBase
<T
> {
197 this->setWithoutWriteBarrier(0);
200 WriteBarrier(JSGlobalData
& globalData
, const JSCell
* owner
, T
* value
)
202 this->set(globalData
, owner
, value
);
205 enum MayBeNullTag
{ MayBeNull
};
206 WriteBarrier(JSGlobalData
& globalData
, const JSCell
* owner
, T
* value
, MayBeNullTag
)
208 this->setMayBeNull(globalData
, owner
, value
);
212 template <> class WriteBarrier
<Unknown
> : public WriteBarrierBase
<Unknown
> {
216 this->setWithoutWriteBarrier(JSValue());
219 WriteBarrier(JSGlobalData
& globalData
, const JSCell
* owner
, JSValue value
)
221 this->set(globalData
, owner
, value
);
225 template <typename U
, typename V
> inline bool operator==(const WriteBarrierBase
<U
>& lhs
, const WriteBarrierBase
<V
>& rhs
)
227 return lhs
.get() == rhs
.get();
230 // MarkStack functions
232 template<typename T
> inline void MarkStack::append(WriteBarrierBase
<T
>* slot
)
234 internalAppend(*slot
->slot());
237 inline void MarkStack::appendValues(WriteBarrierBase
<Unknown
>* barriers
, size_t count
, MarkSetProperties properties
)
239 JSValue
* values
= barriers
->slot();
240 #if ENABLE(GC_VALIDATION)
241 validateSet(values
, count
);
244 m_markSets
.append(MarkSet(values
, values
+ count
, properties
));
249 #endif // WriteBarrier_h