]>
Commit | Line | Data |
---|---|---|
9dae56ea A |
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 | ||
93a37866 A |
24 | #include "JSCJSValue.h" |
25 | #include "PropertyName.h" | |
26 | #include "PropertyOffset.h" | |
9dae56ea A |
27 | #include "Register.h" |
28 | #include <wtf/Assertions.h> | |
9dae56ea A |
29 | |
30 | namespace JSC { | |
31 | ||
81345200 A |
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 | |
ed1e77d3 A |
49 | BuiltinOrFunctionOrAccessor = Builtin | Function | Accessor, // helper only used by static hashtables |
50 | BuiltinOrFunctionOrAccessorOrConstant = Builtin | Function | Accessor | ConstantInteger, // helper only used by static hashtables | |
81345200 A |
51 | }; |
52 | ||
53 | class PropertySlot { | |
54 | enum PropertyType { | |
55 | TypeUnset, | |
56 | TypeValue, | |
57 | TypeGetter, | |
58 | TypeCustom | |
9dae56ea A |
59 | }; |
60 | ||
81345200 A |
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; } | |
ed1e77d3 | 82 | bool isUnset() const { return m_propertyType == TypeUnset; } |
81345200 A |
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 | ||
ed1e77d3 A |
209 | void setThisValue(JSValue thisValue) |
210 | { | |
211 | m_thisValue = thisValue; | |
212 | } | |
213 | ||
81345200 A |
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; | |
ed1e77d3 | 245 | JSValue m_thisValue; |
81345200 A |
246 | JSObject* m_slotBase; |
247 | WatchpointSet* m_watchpointSet; | |
248 | CacheabilityType m_cacheability; | |
249 | }; | |
250 | ||
ed1e77d3 A |
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 | ||
9dae56ea A |
269 | } // namespace JSC |
270 | ||
271 | #endif // PropertySlot_h |