]> git.saurik.com Git - apple/javascriptcore.git/blame - runtime/WriteBarrier.h
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / runtime / WriteBarrier.h
CommitLineData
14957cd0 1/*
81345200 2 * Copyright (C) 2011, 2013 Apple Inc. All rights reserved.
14957cd0
A
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
6fe7ccc8 29#include "GCAssertions.h"
14957cd0
A
30#include "HandleTypes.h"
31#include "Heap.h"
6fe7ccc8 32#include "SamplingCounter.h"
14957cd0
A
33
34namespace JSC {
35
81345200
A
36namespace DFG {
37class DesiredWriteBarrier;
38}
39
14957cd0 40class JSCell;
93a37866 41class VM;
14957cd0
A
42class JSGlobalObject;
43
44template<class T> class WriteBarrierBase;
45template<> class WriteBarrierBase<JSValue>;
46
6fe7ccc8
A
47JS_EXPORT_PRIVATE void slowValidateCell(JSCell*);
48JS_EXPORT_PRIVATE void slowValidateCell(JSGlobalObject*);
14957cd0
A
49
50#if ENABLE(GC_VALIDATION)
51template<class T> inline void validateCell(T cell)
52{
81345200 53 ASSERT_GC_OBJECT_INHERITS(cell, std::remove_pointer<T>::type::info());
14957cd0
A
54}
55
56template<> inline void validateCell<JSCell*>(JSCell* cell)
57{
58 slowValidateCell(cell);
59}
60
61template<> inline void validateCell<JSGlobalObject*>(JSGlobalObject* globalObject)
62{
63 slowValidateCell(globalObject);
64}
65#else
66template<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.
72template <typename T> class WriteBarrierBase {
73public:
81345200 74 void set(VM&, const JSCell* owner, T* value);
6fe7ccc8
A
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 }
14957cd0 82
81345200 83 void setMayBeNull(VM&, const JSCell* owner, T* value);
14957cd0
A
84
85 // Should only be used by JSCell during early initialisation
86 // when some basic types aren't yet completely instantiated
81345200 87 void setEarlyValue(VM&, const JSCell* owner, T* value);
14957cd0
A
88
89 T* get() const
90 {
93a37866
A
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));
14957cd0
A
96 }
97
98 T* operator*() const
99 {
100 ASSERT(m_cell);
14957cd0
A
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
81345200 114 T** slot() { return reinterpret_cast<T**>(&m_cell); }
14957cd0 115
ed1e77d3 116 explicit operator bool() const { return m_cell; }
14957cd0
A
117
118 bool operator!() const { return !m_cell; }
119
120 void setWithoutWriteBarrier(T* value)
121 {
6fe7ccc8
A
122#if ENABLE(WRITE_BARRIER_PROFILING)
123 WriteBarrierCounters::usesWithoutBarrierFromCpp.count();
14957cd0 124#endif
6fe7ccc8 125 this->m_cell = reinterpret_cast<JSCell*>(value);
14957cd0
A
126 }
127
6fe7ccc8 128 T* unvalidatedGet() const { return reinterpret_cast<T*>(static_cast<void*>(m_cell)); }
14957cd0
A
129
130private:
131 JSCell* m_cell;
132};
133
134template <> class WriteBarrierBase<Unknown> {
135public:
81345200 136 void set(VM&, const JSCell* owner, JSValue);
14957cd0
A
137 void setWithoutWriteBarrier(JSValue value)
138 {
14957cd0
A
139 m_value = JSValue::encode(value);
140 }
141
142 JSValue get() const
143 {
144 return JSValue::decode(m_value);
145 }
146 void clear() { m_value = JSValue::encode(JSValue()); }
147 void setUndefined() { m_value = JSValue::encode(jsUndefined()); }
148 bool isNumber() const { return get().isNumber(); }
149 bool isObject() const { return get().isObject(); }
150 bool isNull() const { return get().isNull(); }
151 bool isGetterSetter() const { return get().isGetterSetter(); }
81345200 152 bool isCustomGetterSetter() const { return get().isCustomGetterSetter(); }
14957cd0
A
153
154 JSValue* slot()
155 {
156 union {
157 EncodedJSValue* v;
158 JSValue* slot;
159 } u;
160 u.v = &m_value;
161 return u.slot;
162 }
163
93a37866
A
164 int32_t* tagPointer() { return &bitwise_cast<EncodedValueDescriptor*>(&m_value)->asBits.tag; }
165 int32_t* payloadPointer() { return &bitwise_cast<EncodedValueDescriptor*>(&m_value)->asBits.payload; }
166
ed1e77d3 167 explicit operator bool() const { return !!get(); }
14957cd0
A
168 bool operator!() const { return !get(); }
169
170private:
171 EncodedJSValue m_value;
172};
173
174template <typename T> class WriteBarrier : public WriteBarrierBase<T> {
81345200 175 WTF_MAKE_FAST_ALLOCATED;
14957cd0
A
176public:
177 WriteBarrier()
178 {
179 this->setWithoutWriteBarrier(0);
180 }
181
93a37866 182 WriteBarrier(VM& vm, const JSCell* owner, T* value)
14957cd0 183 {
93a37866 184 this->set(vm, owner, value);
14957cd0
A
185 }
186
81345200
A
187 WriteBarrier(DFG::DesiredWriteBarrier&, T* value)
188 {
189 ASSERT(isCompilationThread());
190 this->setWithoutWriteBarrier(value);
191 }
192
14957cd0 193 enum MayBeNullTag { MayBeNull };
93a37866 194 WriteBarrier(VM& vm, const JSCell* owner, T* value, MayBeNullTag)
14957cd0 195 {
93a37866 196 this->setMayBeNull(vm, owner, value);
14957cd0
A
197 }
198};
199
ed1e77d3 200enum UndefinedWriteBarrierTagType { UndefinedWriteBarrierTag };
14957cd0 201template <> class WriteBarrier<Unknown> : public WriteBarrierBase<Unknown> {
81345200 202 WTF_MAKE_FAST_ALLOCATED;
14957cd0
A
203public:
204 WriteBarrier()
205 {
206 this->setWithoutWriteBarrier(JSValue());
207 }
ed1e77d3
A
208 WriteBarrier(UndefinedWriteBarrierTagType)
209 {
210 this->setWithoutWriteBarrier(jsUndefined());
211 }
14957cd0 212
93a37866 213 WriteBarrier(VM& vm, const JSCell* owner, JSValue value)
14957cd0 214 {
93a37866 215 this->set(vm, owner, value);
14957cd0 216 }
81345200
A
217
218 WriteBarrier(DFG::DesiredWriteBarrier&, JSValue value)
219 {
220 ASSERT(isCompilationThread());
221 this->setWithoutWriteBarrier(value);
222 }
14957cd0
A
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
14957cd0
A
230} // namespace JSC
231
232#endif // WriteBarrier_h