]> git.saurik.com Git - apple/javascriptcore.git/blob - runtime/WriteBarrier.h
JavaScriptCore-7600.1.4.16.1.tar.gz
[apple/javascriptcore.git] / runtime / WriteBarrier.h
1 /*
2 * Copyright (C) 2011, 2013 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 "GCAssertions.h"
30 #include "HandleTypes.h"
31 #include "Heap.h"
32 #include "SamplingCounter.h"
33
34 namespace JSC {
35
36 namespace DFG {
37 class DesiredWriteBarrier;
38 }
39
40 class JSCell;
41 class VM;
42 class JSGlobalObject;
43
44 template<class T> class WriteBarrierBase;
45 template<> class WriteBarrierBase<JSValue>;
46
47 JS_EXPORT_PRIVATE void slowValidateCell(JSCell*);
48 JS_EXPORT_PRIVATE void slowValidateCell(JSGlobalObject*);
49
50 #if ENABLE(GC_VALIDATION)
51 template<class T> inline void validateCell(T cell)
52 {
53 ASSERT_GC_OBJECT_INHERITS(cell, std::remove_pointer<T>::type::info());
54 }
55
56 template<> inline void validateCell<JSCell*>(JSCell* cell)
57 {
58 slowValidateCell(cell);
59 }
60
61 template<> inline void validateCell<JSGlobalObject*>(JSGlobalObject* globalObject)
62 {
63 slowValidateCell(globalObject);
64 }
65 #else
66 template<class T> inline void validateCell(T)
67 {
68 }
69 #endif
70
71 // We have a separate base class with no constructors for use in Unions.
72 template <typename T> class WriteBarrierBase {
73 public:
74 void set(VM&, const JSCell* owner, T* value);
75
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)
79 {
80 m_cell = other.m_cell;
81 }
82
83 void setMayBeNull(VM&, const JSCell* owner, T* value);
84
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);
88
89 T* get() const
90 {
91 // Copy m_cell to a local to avoid multiple-read issues. (See <http://webkit.org/b/110854>)
92 JSCell* cell = m_cell;
93 if (cell)
94 validateCell(cell);
95 return reinterpret_cast<T*>(static_cast<void*>(cell));
96 }
97
98 T* operator*() const
99 {
100 ASSERT(m_cell);
101 validateCell<T>(static_cast<T*>(m_cell));
102 return static_cast<T*>(m_cell);
103 }
104
105 T* operator->() const
106 {
107 ASSERT(m_cell);
108 validateCell(static_cast<T*>(m_cell));
109 return static_cast<T*>(m_cell);
110 }
111
112 void clear() { m_cell = 0; }
113
114 T** slot() { return reinterpret_cast<T**>(&m_cell); }
115
116 typedef T* (WriteBarrierBase::*UnspecifiedBoolType);
117 operator UnspecifiedBoolType*() const { return m_cell ? reinterpret_cast<UnspecifiedBoolType*>(1) : 0; }
118
119 bool operator!() const { return !m_cell; }
120
121 void setWithoutWriteBarrier(T* value)
122 {
123 #if ENABLE(WRITE_BARRIER_PROFILING)
124 WriteBarrierCounters::usesWithoutBarrierFromCpp.count();
125 #endif
126 this->m_cell = reinterpret_cast<JSCell*>(value);
127 }
128
129 #if ENABLE(GC_VALIDATION)
130 T* unvalidatedGet() const { return reinterpret_cast<T*>(static_cast<void*>(m_cell)); }
131 #endif
132
133 private:
134 JSCell* m_cell;
135 };
136
137 template <> class WriteBarrierBase<Unknown> {
138 public:
139 void set(VM&, const JSCell* owner, JSValue);
140 void setWithoutWriteBarrier(JSValue value)
141 {
142 m_value = JSValue::encode(value);
143 }
144
145 JSValue get() const
146 {
147 return JSValue::decode(m_value);
148 }
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(); }
156
157 JSValue* slot()
158 {
159 union {
160 EncodedJSValue* v;
161 JSValue* slot;
162 } u;
163 u.v = &m_value;
164 return u.slot;
165 }
166
167 int32_t* tagPointer() { return &bitwise_cast<EncodedValueDescriptor*>(&m_value)->asBits.tag; }
168 int32_t* payloadPointer() { return &bitwise_cast<EncodedValueDescriptor*>(&m_value)->asBits.payload; }
169
170 typedef JSValue (WriteBarrierBase::*UnspecifiedBoolType);
171 operator UnspecifiedBoolType*() const { return get() ? reinterpret_cast<UnspecifiedBoolType*>(1) : 0; }
172 bool operator!() const { return !get(); }
173
174 private:
175 EncodedJSValue m_value;
176 };
177
178 template <typename T> class WriteBarrier : public WriteBarrierBase<T> {
179 WTF_MAKE_FAST_ALLOCATED;
180 public:
181 WriteBarrier()
182 {
183 this->setWithoutWriteBarrier(0);
184 }
185
186 WriteBarrier(VM& vm, const JSCell* owner, T* value)
187 {
188 this->set(vm, owner, value);
189 }
190
191 WriteBarrier(DFG::DesiredWriteBarrier&, T* value)
192 {
193 ASSERT(isCompilationThread());
194 this->setWithoutWriteBarrier(value);
195 }
196
197 enum MayBeNullTag { MayBeNull };
198 WriteBarrier(VM& vm, const JSCell* owner, T* value, MayBeNullTag)
199 {
200 this->setMayBeNull(vm, owner, value);
201 }
202 };
203
204 template <> class WriteBarrier<Unknown> : public WriteBarrierBase<Unknown> {
205 WTF_MAKE_FAST_ALLOCATED;
206 public:
207 WriteBarrier()
208 {
209 this->setWithoutWriteBarrier(JSValue());
210 }
211
212 WriteBarrier(VM& vm, const JSCell* owner, JSValue value)
213 {
214 this->set(vm, owner, value);
215 }
216
217 WriteBarrier(DFG::DesiredWriteBarrier&, JSValue value)
218 {
219 ASSERT(isCompilationThread());
220 this->setWithoutWriteBarrier(value);
221 }
222 };
223
224 template <typename U, typename V> inline bool operator==(const WriteBarrierBase<U>& lhs, const WriteBarrierBase<V>& rhs)
225 {
226 return lhs.get() == rhs.get();
227 }
228
229 } // namespace JSC
230
231 #endif // WriteBarrier_h