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
30namespace JSC {
31
32 class ExecState;
33 class JSObject;
34
35#define JSC_VALUE_SLOT_MARKER 0
36#define JSC_REGISTER_SLOT_MARKER reinterpret_cast<GetValueFunc>(1)
37
38 class PropertySlot {
39 public:
40 PropertySlot()
41 {
42 clearBase();
43 clearOffset();
44 clearValue();
45 }
46
47 explicit PropertySlot(const JSValue base)
48 : m_slotBase(base)
49 {
50 clearOffset();
51 clearValue();
52 }
53
54 typedef JSValue (*GetValueFunc)(ExecState*, const Identifier&, const PropertySlot&);
55
56 JSValue getValue(ExecState* exec, const Identifier& propertyName) const
57 {
58 if (m_getValue == JSC_VALUE_SLOT_MARKER)
59 return *m_data.valueSlot;
60 if (m_getValue == JSC_REGISTER_SLOT_MARKER)
61 return (*m_data.registerSlot).jsValue();
62 return m_getValue(exec, propertyName, *this);
63 }
64
65 JSValue getValue(ExecState* exec, unsigned propertyName) const
66 {
67 if (m_getValue == JSC_VALUE_SLOT_MARKER)
68 return *m_data.valueSlot;
69 if (m_getValue == JSC_REGISTER_SLOT_MARKER)
70 return (*m_data.registerSlot).jsValue();
71 return m_getValue(exec, Identifier::from(exec, propertyName), *this);
72 }
73
74 bool isCacheable() const { return m_offset != WTF::notFound; }
75 size_t cachedOffset() const
76 {
77 ASSERT(isCacheable());
78 return m_offset;
79 }
80
81 void setValueSlot(JSValue* valueSlot)
82 {
83 ASSERT(valueSlot);
84 clearBase();
85 clearOffset();
86 m_getValue = JSC_VALUE_SLOT_MARKER;
87 m_data.valueSlot = valueSlot;
88 }
89
90 void setValueSlot(JSValue slotBase, JSValue* valueSlot)
91 {
92 ASSERT(valueSlot);
93 m_getValue = JSC_VALUE_SLOT_MARKER;
94 m_slotBase = slotBase;
95 m_data.valueSlot = valueSlot;
96 }
97
98 void setValueSlot(JSValue slotBase, JSValue* valueSlot, size_t offset)
99 {
100 ASSERT(valueSlot);
101 m_getValue = JSC_VALUE_SLOT_MARKER;
102 m_slotBase = slotBase;
103 m_data.valueSlot = valueSlot;
104 m_offset = offset;
105 }
106
107 void setValue(JSValue value)
108 {
109 ASSERT(value);
110 clearBase();
111 clearOffset();
112 m_getValue = JSC_VALUE_SLOT_MARKER;
113 m_value = value;
114 m_data.valueSlot = &m_value;
115 }
116
117 void setRegisterSlot(Register* registerSlot)
118 {
119 ASSERT(registerSlot);
120 clearBase();
121 clearOffset();
122 m_getValue = JSC_REGISTER_SLOT_MARKER;
123 m_data.registerSlot = registerSlot;
124 }
125
126 void setCustom(JSValue slotBase, GetValueFunc getValue)
127 {
128 ASSERT(slotBase);
129 ASSERT(getValue);
130 m_getValue = getValue;
131 m_slotBase = slotBase;
132 }
133
134 void setCustomIndex(JSValue slotBase, unsigned index, GetValueFunc getValue)
135 {
136 ASSERT(slotBase);
137 ASSERT(getValue);
138 m_getValue = getValue;
139 m_slotBase = slotBase;
140 m_data.index = index;
141 }
142
143 void setGetterSlot(JSObject* getterFunc)
144 {
145 ASSERT(getterFunc);
146 m_getValue = functionGetter;
147 m_data.getterFunc = getterFunc;
148 }
149
150 void setUndefined()
151 {
152 setValue(jsUndefined());
153 }
154
155 JSValue slotBase() const
156 {
157 return m_slotBase;
158 }
159
160 void setBase(JSValue base)
161 {
162 ASSERT(m_slotBase);
163 ASSERT(base);
164 m_slotBase = base;
165 }
166
167 void clearBase()
168 {
169#ifndef NDEBUG
170 m_slotBase = JSValue();
171#endif
172 }
173
174 void clearValue()
175 {
176#ifndef NDEBUG
177 m_value = JSValue();
178#endif
179 }
180
181 void clearOffset()
182 {
183 // Clear offset even in release builds, in case this PropertySlot has been used before.
184 // (For other data members, we don't need to clear anything because reuse would meaningfully overwrite them.)
185 m_offset = WTF::notFound;
186 }
187
188 unsigned index() const { return m_data.index; }
189
190 private:
191 static JSValue functionGetter(ExecState*, const Identifier&, const PropertySlot&);
192
193 GetValueFunc m_getValue;
194
195 JSValue m_slotBase;
196 union {
197 JSObject* getterFunc;
198 JSValue* valueSlot;
199 Register* registerSlot;
200 unsigned index;
201 } m_data;
202
203 JSValue m_value;
204
205 size_t m_offset;
206 };
207
208} // namespace JSC
209
210#endif // PropertySlot_h
211