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