]> git.saurik.com Git - apple/javascriptcore.git/blob - runtime/PropertySlot.h
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / 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 "JSCJSValue.h"
25 #include "PropertyName.h"
26 #include "PropertyOffset.h"
27 #include "Register.h"
28 #include <wtf/Assertions.h>
29
30 namespace JSC {
31
32 class ExecState;
33 class GetterSetter;
34 class JSObject;
35
36 // ECMA 262-3 8.6.1
37 // Property attributes
38 enum Attribute {
39 None = 0,
40 ReadOnly = 1 << 1, // property can be only read, not written
41 DontEnum = 1 << 2, // property doesn't appear in (for .. in ..)
42 DontDelete = 1 << 3, // property can't be deleted
43 Function = 1 << 4, // property is a function - only used by static hashtables
44 Accessor = 1 << 5, // property is a getter/setter
45 CustomAccessor = 1 << 6,
46 Builtin = 1 << 7, // property is a builtin function - only used by static hashtables
47 ConstantInteger = 1 << 8, // property is a constant integer - only used by static hashtables
48 BuiltinOrFunction = Builtin | Function, // helper only used by static hashtables
49 BuiltinOrFunctionOrAccessor = Builtin | Function | Accessor, // helper only used by static hashtables
50 BuiltinOrFunctionOrAccessorOrConstant = Builtin | Function | Accessor | ConstantInteger, // helper only used by static hashtables
51 };
52
53 class PropertySlot {
54 enum PropertyType {
55 TypeUnset,
56 TypeValue,
57 TypeGetter,
58 TypeCustom
59 };
60
61 enum CacheabilityType {
62 CachingDisallowed,
63 CachingAllowed
64 };
65
66 public:
67 explicit PropertySlot(const JSValue thisValue)
68 : m_propertyType(TypeUnset)
69 , m_offset(invalidOffset)
70 , m_thisValue(thisValue)
71 , m_watchpointSet(nullptr)
72 , m_cacheability(CachingAllowed)
73 {
74 }
75
76 typedef EncodedJSValue (*GetValueFunc)(ExecState*, JSObject* slotBase, EncodedJSValue thisValue, PropertyName);
77
78 JSValue getValue(ExecState*, PropertyName) const;
79 JSValue getValue(ExecState*, unsigned propertyName) const;
80
81 bool isCacheable() const { return m_cacheability == CachingAllowed && m_offset != invalidOffset; }
82 bool isUnset() const { return m_propertyType == TypeUnset; }
83 bool isValue() const { return m_propertyType == TypeValue; }
84 bool isAccessor() const { return m_propertyType == TypeGetter; }
85 bool isCustom() const { return m_propertyType == TypeCustom; }
86 bool isCacheableValue() const { return isCacheable() && isValue(); }
87 bool isCacheableGetter() const { return isCacheable() && isAccessor(); }
88 bool isCacheableCustom() const { return isCacheable() && isCustom(); }
89
90 void disableCaching()
91 {
92 m_cacheability = CachingDisallowed;
93 }
94
95 unsigned attributes() const { return m_attributes; }
96
97 PropertyOffset cachedOffset() const
98 {
99 ASSERT(isCacheable());
100 return m_offset;
101 }
102
103 GetterSetter* getterSetter() const
104 {
105 ASSERT(isAccessor());
106 return m_data.getter.getterSetter;
107 }
108
109 GetValueFunc customGetter() const
110 {
111 ASSERT(isCacheableCustom());
112 return m_data.custom.getValue;
113 }
114
115 JSObject* slotBase() const
116 {
117 ASSERT(m_propertyType != TypeUnset);
118 return m_slotBase;
119 }
120
121 WatchpointSet* watchpointSet() const
122 {
123 return m_watchpointSet;
124 }
125
126 void setValue(JSObject* slotBase, unsigned attributes, JSValue value)
127 {
128 ASSERT(value);
129 m_data.value = JSValue::encode(value);
130 m_attributes = attributes;
131
132 ASSERT(slotBase);
133 m_slotBase = slotBase;
134 m_propertyType = TypeValue;
135 m_offset = invalidOffset;
136 }
137
138 void setValue(JSObject* slotBase, unsigned attributes, JSValue value, PropertyOffset offset)
139 {
140 ASSERT(value);
141 m_data.value = JSValue::encode(value);
142 m_attributes = attributes;
143
144 ASSERT(slotBase);
145 m_slotBase = slotBase;
146 m_propertyType = TypeValue;
147 m_offset = offset;
148 }
149
150 void setValue(JSString*, unsigned attributes, JSValue value)
151 {
152 ASSERT(value);
153 m_data.value = JSValue::encode(value);
154 m_attributes = attributes;
155
156 m_slotBase = 0;
157 m_propertyType = TypeValue;
158 m_offset = invalidOffset;
159 }
160
161 void setCustom(JSObject* slotBase, unsigned attributes, GetValueFunc getValue)
162 {
163 ASSERT(getValue);
164 m_data.custom.getValue = getValue;
165 m_attributes = attributes;
166
167 ASSERT(slotBase);
168 m_slotBase = slotBase;
169 m_propertyType = TypeCustom;
170 m_offset = invalidOffset;
171 }
172
173 void setCacheableCustom(JSObject* slotBase, unsigned attributes, GetValueFunc getValue)
174 {
175 ASSERT(getValue);
176 m_data.custom.getValue = getValue;
177 m_attributes = attributes;
178
179 ASSERT(slotBase);
180 m_slotBase = slotBase;
181 m_propertyType = TypeCustom;
182 m_offset = !invalidOffset;
183 }
184
185 void setGetterSlot(JSObject* slotBase, unsigned attributes, GetterSetter* getterSetter)
186 {
187 ASSERT(getterSetter);
188 m_data.getter.getterSetter = getterSetter;
189 m_attributes = attributes;
190
191 ASSERT(slotBase);
192 m_slotBase = slotBase;
193 m_propertyType = TypeGetter;
194 m_offset = invalidOffset;
195 }
196
197 void setCacheableGetterSlot(JSObject* slotBase, unsigned attributes, GetterSetter* getterSetter, PropertyOffset offset)
198 {
199 ASSERT(getterSetter);
200 m_data.getter.getterSetter = getterSetter;
201 m_attributes = attributes;
202
203 ASSERT(slotBase);
204 m_slotBase = slotBase;
205 m_propertyType = TypeGetter;
206 m_offset = offset;
207 }
208
209 void setThisValue(JSValue thisValue)
210 {
211 m_thisValue = thisValue;
212 }
213
214 void setUndefined()
215 {
216 m_data.value = JSValue::encode(jsUndefined());
217 m_attributes = ReadOnly | DontDelete | DontEnum;
218
219 m_slotBase = 0;
220 m_propertyType = TypeValue;
221 m_offset = invalidOffset;
222 }
223
224 void setWatchpointSet(WatchpointSet& set)
225 {
226 m_watchpointSet = &set;
227 }
228
229 private:
230 JS_EXPORT_PRIVATE JSValue functionGetter(ExecState*) const;
231
232 unsigned m_attributes;
233 union {
234 EncodedJSValue value;
235 struct {
236 GetterSetter* getterSetter;
237 } getter;
238 struct {
239 GetValueFunc getValue;
240 } custom;
241 } m_data;
242
243 PropertyType m_propertyType;
244 PropertyOffset m_offset;
245 JSValue m_thisValue;
246 JSObject* m_slotBase;
247 WatchpointSet* m_watchpointSet;
248 CacheabilityType m_cacheability;
249 };
250
251 ALWAYS_INLINE JSValue PropertySlot::getValue(ExecState* exec, PropertyName propertyName) const
252 {
253 if (m_propertyType == TypeValue)
254 return JSValue::decode(m_data.value);
255 if (m_propertyType == TypeGetter)
256 return functionGetter(exec);
257 return JSValue::decode(m_data.custom.getValue(exec, slotBase(), JSValue::encode(m_thisValue), propertyName));
258 }
259
260 ALWAYS_INLINE JSValue PropertySlot::getValue(ExecState* exec, unsigned propertyName) const
261 {
262 if (m_propertyType == TypeValue)
263 return JSValue::decode(m_data.value);
264 if (m_propertyType == TypeGetter)
265 return functionGetter(exec);
266 return JSValue::decode(m_data.custom.getValue(exec, slotBase(), JSValue::encode(m_thisValue), Identifier::from(exec, propertyName)));
267 }
268
269 } // namespace JSC
270
271 #endif // PropertySlot_h