2011-01-27 Oliver Hunt <oliver@apple.com>
[WebKit-https.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 "JSValue.h"
30
31 namespace JSC {
32 class JSCell;
33 class JSGlobalData;
34
35 typedef enum { } Unknown;
36
37 template <class T> class DeprecatedPtr {
38 public:
39     DeprecatedPtr() : m_cell(0) { }
40     DeprecatedPtr(T* cell) : m_cell(reinterpret_cast<JSCell*>(cell)) { }
41     T* get() const { return reinterpret_cast<T*>(m_cell); }
42     T* operator*() const { return static_cast<T*>(m_cell); }
43     T* operator->() const { return static_cast<T*>(m_cell); }
44     
45     JSCell** slot() { return &m_cell; }
46     
47     typedef T* (DeprecatedPtr::*UnspecifiedBoolType);
48     operator UnspecifiedBoolType*() const { return m_cell ? reinterpret_cast<UnspecifiedBoolType*>(1) : 0; }
49
50     bool operator!() const { return !m_cell; }
51
52 protected:
53     JSCell* m_cell;
54 };
55
56 template <> class DeprecatedPtr<Unknown> {
57 public:
58     DeprecatedPtr() { }
59     DeprecatedPtr(JSValue value) : m_value(value) { }
60     DeprecatedPtr(JSCell* value) : m_value(value) { }
61     const JSValue& get() const { return m_value; }
62     const JSValue* operator*() const { return &m_value; }
63     const JSValue* operator->() const { return &m_value; }
64     
65     JSValue* slot() { return &m_value; }
66     
67     typedef JSValue (DeprecatedPtr::*UnspecifiedBoolType);
68     operator UnspecifiedBoolType*() const { return m_value ? reinterpret_cast<UnspecifiedBoolType*>(1) : 0; }
69     bool operator!() const { return !m_value; }
70     
71 private:
72     JSValue m_value;
73 };
74
75 template <typename T> struct WriteBarrierCheck {
76     static const bool IsJSValue = false;
77 };
78
79 template <> struct WriteBarrierCheck<JSValue> {
80     static const bool IsJSValue = true;
81 };
82
83 template <typename T> class WriteBarrierBase {
84 public:
85     COMPILE_ASSERT(!WriteBarrierCheck<T>::IsJSValue, WriteBarrier_JSValue_is_invalid__use_unknown);
86     void set(JSGlobalData&, const JSCell*, T* value) { this->m_cell = reinterpret_cast<JSCell*>(value); }
87     
88     T* get() const { return reinterpret_cast<T*>(m_cell); }
89     T* operator*() const { return static_cast<T*>(m_cell); }
90     T* operator->() const { return static_cast<T*>(m_cell); }
91     
92     JSCell** slot() { return &m_cell; }
93     
94     typedef T* (WriteBarrierBase::*UnspecifiedBoolType);
95     operator UnspecifiedBoolType*() const { return m_cell ? reinterpret_cast<UnspecifiedBoolType*>(1) : 0; }
96     
97     bool operator!() const { return !m_cell; }
98
99 protected:
100     JSCell* m_cell;
101 };
102
103 template <typename T> class WriteBarrier : public WriteBarrierBase<T> {
104 public:
105     WriteBarrier() { this->m_cell = 0; }
106     WriteBarrier(JSGlobalData& globalData, const JSCell* owner, T* value)
107     {
108         set(globalData, owner, value);
109     }
110
111 };
112
113 template <> class WriteBarrierBase<Unknown> {
114 public:
115     void set(JSGlobalData&, const JSCell*, JSValue value) { m_value = JSValue::encode(value); }
116     void setWithoutWriteBarrier(JSValue value) { m_value = JSValue::encode(value); }
117     JSValue get() const { return JSValue::decode(m_value); }
118     void clear() { m_value = JSValue::encode(JSValue()); }
119     void setUndefined() { m_value = JSValue::encode(jsUndefined()); }
120     bool isNumber() const { return get().isNumber(); }
121     JSValue* slot()
122     { 
123         union {
124             EncodedJSValue* v;
125             JSValue* slot;
126         } u;
127         u.v = &m_value;
128         return u.slot;
129     }
130     
131     typedef JSValue (WriteBarrierBase::*UnspecifiedBoolType);
132     operator UnspecifiedBoolType*() const { return m_value ? reinterpret_cast<UnspecifiedBoolType*>(1) : 0; }
133     bool operator!() const { return !m_value; } 
134     
135 protected:
136     EncodedJSValue m_value;
137 };
138
139 template <> class WriteBarrier<Unknown> : public WriteBarrierBase<Unknown> {
140 public:
141     WriteBarrier() { m_value = JSValue::encode(JSValue()); }
142     WriteBarrier(JSGlobalData& globalData, const JSCell* owner, JSValue value)
143     {
144         set(globalData, owner, value);
145     }
146 };
147
148 template <typename U, typename V> inline bool operator==(const DeprecatedPtr<U>& lhs, const DeprecatedPtr<V>& rhs)
149 {
150     return lhs.get() == rhs.get();
151 }
152
153 template <typename U, typename V> inline bool operator==(const WriteBarrierBase<U>& lhs, const WriteBarrierBase<V>& rhs)
154 {
155     return lhs.get() == rhs.get();
156 }
157
158 }
159
160 #endif // WriteBarrier_h