• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
PropertySlot()48         PropertySlot()
49             : m_cachedPropertyType(Uncacheable)
50         {
51             clearBase();
52             clearOffset();
53             clearValue();
54         }
55 
PropertySlot(const JSValue base)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 
getValue(ExecState * exec,const Identifier & propertyName)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 
getValue(ExecState * exec,unsigned propertyName)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 
cachedPropertyType()89         CachedPropertyType cachedPropertyType() const { return m_cachedPropertyType; }
isCacheable()90         bool isCacheable() const { return m_cachedPropertyType != Uncacheable; }
isCacheableValue()91         bool isCacheableValue() const { return m_cachedPropertyType == Value; }
cachedOffset()92         size_t cachedOffset() const
93         {
94             ASSERT(isCacheable());
95             return m_offset;
96         }
97 
setValue(JSValue slotBase,JSValue value)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 
setValue(JSValue slotBase,JSValue value,size_t offset)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 
setValue(JSValue value)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 
setCustom(JSValue slotBase,GetValueFunc getValue)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 
setCacheableCustom(JSValue slotBase,GetValueFunc getValue)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 
setCustomIndex(JSValue slotBase,unsigned index,GetIndexValueFunc getIndexValue)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 
setGetterSlot(JSObject * getterFunc)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 
setCacheableGetterSlot(JSValue slotBase,JSObject * getterFunc,unsigned offset)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 
setUndefined()174         void setUndefined()
175         {
176             setValue(jsUndefined());
177         }
178 
slotBase()179         JSValue slotBase() const
180         {
181             return m_slotBase;
182         }
183 
setBase(JSValue base)184         void setBase(JSValue base)
185         {
186             ASSERT(m_slotBase);
187             ASSERT(base);
188             m_slotBase = base;
189         }
190 
clearBase()191         void clearBase()
192         {
193 #ifndef NDEBUG
194             m_slotBase = JSValue();
195 #endif
196         }
197 
clearValue()198         void clearValue()
199         {
200 #ifndef NDEBUG
201             m_value = JSValue();
202 #endif
203         }
204 
clearOffset()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 
index()213         unsigned index() const { return m_data.index; }
214 
thisValue()215         JSValue thisValue() const { return m_thisValue; }
216 
customGetter()217         GetValueFunc customGetter() const
218         {
219             ASSERT(m_cachedPropertyType == Custom);
220             return m_getValue;
221         }
222     private:
223         JSValue functionGetter(ExecState*) const;
224 
225         GetValueFunc m_getValue;
226         GetIndexValueFunc m_getIndexValue;
227 
228         JSValue m_slotBase;
229         union {
230             JSObject* getterFunc;
231             unsigned index;
232         } m_data;
233 
234         JSValue m_value;
235         JSValue m_thisValue;
236 
237         size_t m_offset;
238         CachedPropertyType m_cachedPropertyType;
239     };
240 
241 } // namespace JSC
242 
243 #endif // PropertySlot_h
244