2 * Copyright (C) 2011, 2013 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 "GCAssertions.h"
30 #include "HandleTypes.h"
32 #include "SamplingCounter.h"
37 class DesiredWriteBarrier
;
44 template<class T
> class WriteBarrierBase
;
45 template<> class WriteBarrierBase
<JSValue
>;
47 JS_EXPORT_PRIVATE
void slowValidateCell(JSCell
*);
48 JS_EXPORT_PRIVATE
void slowValidateCell(JSGlobalObject
*);
50 #if ENABLE(GC_VALIDATION)
51 template<class T
> inline void validateCell(T cell
)
53 ASSERT_GC_OBJECT_INHERITS(cell
, std::remove_pointer
<T
>::type::info());
56 template<> inline void validateCell
<JSCell
*>(JSCell
* cell
)
58 slowValidateCell(cell
);
61 template<> inline void validateCell
<JSGlobalObject
*>(JSGlobalObject
* globalObject
)
63 slowValidateCell(globalObject
);
66 template<class T
> inline void validateCell(T
)
71 // We have a separate base class with no constructors for use in Unions.
72 template <typename T
> class WriteBarrierBase
{
74 void set(VM
&, const JSCell
* owner
, T
* value
);
76 // This is meant to be used like operator=, but is called copyFrom instead, in
77 // order to kindly inform the C++ compiler that its advice is not appreciated.
78 void copyFrom(const WriteBarrierBase
<T
>& other
)
80 m_cell
= other
.m_cell
;
83 void setMayBeNull(VM
&, const JSCell
* owner
, T
* value
);
85 // Should only be used by JSCell during early initialisation
86 // when some basic types aren't yet completely instantiated
87 void setEarlyValue(VM
&, const JSCell
* owner
, T
* value
);
91 // Copy m_cell to a local to avoid multiple-read issues. (See <http://webkit.org/b/110854>)
92 JSCell
* cell
= m_cell
;
95 return reinterpret_cast<T
*>(static_cast<void*>(cell
));
101 validateCell
<T
>(static_cast<T
*>(m_cell
));
102 return static_cast<T
*>(m_cell
);
105 T
* operator->() const
108 validateCell(static_cast<T
*>(m_cell
));
109 return static_cast<T
*>(m_cell
);
112 void clear() { m_cell
= 0; }
114 T
** slot() { return reinterpret_cast<T
**>(&m_cell
); }
116 typedef T
* (WriteBarrierBase::*UnspecifiedBoolType
);
117 operator UnspecifiedBoolType
*() const { return m_cell
? reinterpret_cast<UnspecifiedBoolType
*>(1) : 0; }
119 bool operator!() const { return !m_cell
; }
121 void setWithoutWriteBarrier(T
* value
)
123 #if ENABLE(WRITE_BARRIER_PROFILING)
124 WriteBarrierCounters::usesWithoutBarrierFromCpp
.count();
126 this->m_cell
= reinterpret_cast<JSCell
*>(value
);
129 #if ENABLE(GC_VALIDATION)
130 T
* unvalidatedGet() const { return reinterpret_cast<T
*>(static_cast<void*>(m_cell
)); }
137 template <> class WriteBarrierBase
<Unknown
> {
139 void set(VM
&, const JSCell
* owner
, JSValue
);
140 void setWithoutWriteBarrier(JSValue value
)
142 m_value
= JSValue::encode(value
);
147 return JSValue::decode(m_value
);
149 void clear() { m_value
= JSValue::encode(JSValue()); }
150 void setUndefined() { m_value
= JSValue::encode(jsUndefined()); }
151 bool isNumber() const { return get().isNumber(); }
152 bool isObject() const { return get().isObject(); }
153 bool isNull() const { return get().isNull(); }
154 bool isGetterSetter() const { return get().isGetterSetter(); }
155 bool isCustomGetterSetter() const { return get().isCustomGetterSetter(); }
167 int32_t* tagPointer() { return &bitwise_cast
<EncodedValueDescriptor
*>(&m_value
)->asBits
.tag
; }
168 int32_t* payloadPointer() { return &bitwise_cast
<EncodedValueDescriptor
*>(&m_value
)->asBits
.payload
; }
170 typedef JSValue (WriteBarrierBase::*UnspecifiedBoolType
);
171 operator UnspecifiedBoolType
*() const { return get() ? reinterpret_cast<UnspecifiedBoolType
*>(1) : 0; }
172 bool operator!() const { return !get(); }
175 EncodedJSValue m_value
;
178 template <typename T
> class WriteBarrier
: public WriteBarrierBase
<T
> {
179 WTF_MAKE_FAST_ALLOCATED
;
183 this->setWithoutWriteBarrier(0);
186 WriteBarrier(VM
& vm
, const JSCell
* owner
, T
* value
)
188 this->set(vm
, owner
, value
);
191 WriteBarrier(DFG::DesiredWriteBarrier
&, T
* value
)
193 ASSERT(isCompilationThread());
194 this->setWithoutWriteBarrier(value
);
197 enum MayBeNullTag
{ MayBeNull
};
198 WriteBarrier(VM
& vm
, const JSCell
* owner
, T
* value
, MayBeNullTag
)
200 this->setMayBeNull(vm
, owner
, value
);
204 template <> class WriteBarrier
<Unknown
> : public WriteBarrierBase
<Unknown
> {
205 WTF_MAKE_FAST_ALLOCATED
;
209 this->setWithoutWriteBarrier(JSValue());
212 WriteBarrier(VM
& vm
, const JSCell
* owner
, JSValue value
)
214 this->set(vm
, owner
, value
);
217 WriteBarrier(DFG::DesiredWriteBarrier
&, JSValue value
)
219 ASSERT(isCompilationThread());
220 this->setWithoutWriteBarrier(value
);
224 template <typename U
, typename V
> inline bool operator==(const WriteBarrierBase
<U
>& lhs
, const WriteBarrierBase
<V
>& rhs
)
226 return lhs
.get() == rhs
.get();
231 #endif // WriteBarrier_h