initial import
[vuplus_webkit] / Source / JavaScriptCore / runtime / PropertySlot.h
1 /*
2  *  Copyright (C) 2005, 2007, 2008 Apple Inc. All rights reserved.
3  *
4  *  This library is free software; you can redistribute it and/or
5  *  modify it under the terms of the GNU Library General Public
6  *  License as published by the Free Software Foundation; either
7  *  version 2 of the License, or (at your option) any later version.
8  *
9  *  This library is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  *  Library General Public License for more details.
13  *
14  *  You should have received a copy of the GNU Library General Public License
15  *  along with this library; see the file COPYING.LIB.  If not, write to
16  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  *  Boston, MA 02110-1301, USA.
18  *
19  */
20
21 #ifndef PropertySlot_h
22 #define PropertySlot_h
23
24 #include "Identifier.h"
25 #include "JSValue.h"
26 #include "Register.h"
27 #include <wtf/Assertions.h>
28 #include <wtf/NotFound.h>
29
30 namespace JSC {
31
32     class ExecState;
33     class JSObject;
34
35 #define JSC_VALUE_MARKER 0
36 #define INDEX_GETTER_MARKER reinterpret_cast<GetValueFunc>(2)
37 #define GETTER_FUNCTION_MARKER reinterpret_cast<GetValueFunc>(3)
38
39     class PropertySlot {
40     public:
41         enum CachedPropertyType {
42             Uncacheable,
43             Getter,
44             Custom,
45             Value
46         };
47
48         PropertySlot()
49             : m_cachedPropertyType(Uncacheable)
50         {
51             clearBase();
52             clearOffset();
53             clearValue();
54         }
55
56         explicit PropertySlot(const JSValue base)
57             : m_slotBase(base)
58             , m_cachedPropertyType(Uncacheable)
59         {
60             clearOffset();
61             clearValue();
62         }
63
64         typedef JSValue (*GetValueFunc)(ExecState*, JSValue slotBase, const Identifier&);
65         typedef JSValue (*GetIndexValueFunc)(ExecState*, JSValue slotBase, unsigned);
66
67         JSValue getValue(ExecState* exec, const Identifier& propertyName) const
68         {
69             if (m_getValue == JSC_VALUE_MARKER)
70                 return m_value;
71             if (m_getValue == INDEX_GETTER_MARKER)
72                 return m_getIndexValue(exec, slotBase(), index());
73             if (m_getValue == GETTER_FUNCTION_MARKER)
74                 return functionGetter(exec);
75             return m_getValue(exec, slotBase(), propertyName);
76         }
77
78         JSValue getValue(ExecState* exec, unsigned propertyName) const
79         {
80             if (m_getValue == JSC_VALUE_MARKER)
81                 return m_value;
82             if (m_getValue == INDEX_GETTER_MARKER)
83                 return m_getIndexValue(exec, m_slotBase, m_data.index);
84             if (m_getValue == GETTER_FUNCTION_MARKER)
85                 return functionGetter(exec);
86             return m_getValue(exec, slotBase(), Identifier::from(exec, propertyName));
87         }
88
89         CachedPropertyType cachedPropertyType() const { return m_cachedPropertyType; }
90         bool isCacheable() const { return m_cachedPropertyType != Uncacheable; }
91         bool isCacheableValue() const { return m_cachedPropertyType == Value; }
92         size_t cachedOffset() const
93         {
94             ASSERT(isCacheable());
95             return m_offset;
96         }
97
98         void setValue(JSValue slotBase, JSValue value)
99         {
100             ASSERT(value);
101             clearOffset();
102             m_getValue = JSC_VALUE_MARKER;
103             m_slotBase = slotBase;
104             m_value = value;
105         }
106         
107         void setValue(JSValue slotBase, JSValue value, size_t offset)
108         {
109             ASSERT(value);
110             m_getValue = JSC_VALUE_MARKER;
111             m_slotBase = slotBase;
112             m_value = value;
113             m_offset = offset;
114             m_cachedPropertyType = Value;
115         }
116
117         void setValue(JSValue value)
118         {
119             ASSERT(value);
120             clearBase();
121             clearOffset();
122             m_getValue = JSC_VALUE_MARKER;
123             m_value = value;
124         }
125
126         void setCustom(JSValue slotBase, GetValueFunc getValue)
127         {
128             ASSERT(slotBase);
129             ASSERT(getValue);
130             m_getValue = getValue;
131             m_getIndexValue = 0;
132             m_slotBase = slotBase;
133         }
134         
135         void setCacheableCustom(JSValue slotBase, GetValueFunc getValue)
136         {
137             ASSERT(slotBase);
138             ASSERT(getValue);
139             m_getValue = getValue;
140             m_getIndexValue = 0;
141             m_slotBase = slotBase;
142             m_cachedPropertyType = Custom;
143         }
144
145         void setCustomIndex(JSValue slotBase, unsigned index, GetIndexValueFunc getIndexValue)
146         {
147             ASSERT(slotBase);
148             ASSERT(getIndexValue);
149             m_getValue = INDEX_GETTER_MARKER;
150             m_getIndexValue = getIndexValue;
151             m_slotBase = slotBase;
152             m_data.index = index;
153         }
154
155         void setGetterSlot(JSObject* getterFunc)
156         {
157             ASSERT(getterFunc);
158             m_thisValue = m_slotBase;
159             m_getValue = GETTER_FUNCTION_MARKER;
160             m_data.getterFunc = getterFunc;
161         }
162
163         void setCacheableGetterSlot(JSValue slotBase, JSObject* getterFunc, unsigned offset)
164         {
165             ASSERT(getterFunc);
166             m_getValue = GETTER_FUNCTION_MARKER;
167             m_thisValue = m_slotBase;
168             m_slotBase = slotBase;
169             m_data.getterFunc = getterFunc;
170             m_offset = offset;
171             m_cachedPropertyType = Getter;
172         }
173
174         void setUndefined()
175         {
176             setValue(jsUndefined());
177         }
178
179         JSValue slotBase() const
180         {
181             return m_slotBase;
182         }
183
184         void setBase(JSValue base)
185         {
186             ASSERT(m_slotBase);
187             ASSERT(base);
188             m_slotBase = base;
189         }
190
191         void clearBase()
192         {
193 #ifndef NDEBUG
194             m_slotBase = JSValue();
195 #endif
196         }
197
198         void clearValue()
199         {
200 #ifndef NDEBUG
201             m_value = JSValue();
202 #endif
203         }
204
205         void clearOffset()
206         {
207             // Clear offset even in release builds, in case this PropertySlot has been used before.
208             // (For other data members, we don't need to clear anything because reuse would meaningfully overwrite them.)
209             m_offset = 0;
210             m_cachedPropertyType = Uncacheable;
211         }
212
213         unsigned index() const { return m_data.index; }
214
215         GetValueFunc customGetter() const
216         {
217             ASSERT(m_cachedPropertyType == Custom);
218             return m_getValue;
219         }
220     private:
221         JSValue functionGetter(ExecState*) const;
222
223         GetValueFunc m_getValue;
224         GetIndexValueFunc m_getIndexValue;
225         
226         JSValue m_slotBase;
227         union {
228             JSObject* getterFunc;
229             unsigned index;
230         } m_data;
231
232         JSValue m_value;
233         JSValue m_thisValue;
234
235         size_t m_offset;
236         CachedPropertyType m_cachedPropertyType;
237     };
238
239 } // namespace JSC
240
241 #endif // PropertySlot_h