18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/*
28e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  Copyright (C) 2005, 2007, 2008 Apple Inc. All rights reserved.
38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  This library is free software; you can redistribute it and/or
5231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block *  modify it under the terms of the GNU Library General Public
68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  License as published by the Free Software Foundation; either
78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  version 2 of the License, or (at your option) any later version.
88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  This library is distributed in the hope that it will be useful,
108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  but WITHOUT ANY WARRANTY; without even the implied warranty of
118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  Library General Public License for more details.
138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  You should have received a copy of the GNU Library General Public License
158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  along with this library; see the file COPYING.LIB.  If not, write to
168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  Boston, MA 02110-1301, USA.
188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */
208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#ifndef PropertySlot_h
228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#define PropertySlot_h
238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Identifier.h"
258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "JSValue.h"
268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Register.h"
278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <wtf/Assertions.h>
288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <wtf/NotFound.h>
298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace JSC {
318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    class ExecState;
338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    class JSObject;
348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#define JSC_VALUE_MARKER 0
368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#define INDEX_GETTER_MARKER reinterpret_cast<GetValueFunc>(2)
378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#define GETTER_FUNCTION_MARKER reinterpret_cast<GetValueFunc>(3)
388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
39cad810f21b803229eb11403f9209855525a25d57Steve Block    class PropertySlot {
40cad810f21b803229eb11403f9209855525a25d57Steve Block    public:
418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        enum CachedPropertyType {
42231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            Uncacheable,
43231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            Getter,
448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            Custom,
45d0825bca7fe65beaee391d30da42e937db621564Steve Block            Value
462bde8e466a4451c7319e3a072d118917957d6554Steve Block        };
472bde8e466a4451c7319e3a072d118917957d6554Steve Block
482bde8e466a4451c7319e3a072d118917957d6554Steve Block        PropertySlot()
49d0825bca7fe65beaee391d30da42e937db621564Steve Block            : m_cachedPropertyType(Uncacheable)
50231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        {
51231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            clearBase();
528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            clearOffset();
53231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            clearValue();
548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
55e78cbe89e6f337f2f1fe40315be88f742b547151Steve Block
56231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        explicit PropertySlot(const JSValue base)
57231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            : m_slotBase(base)
588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            , m_cachedPropertyType(Uncacheable)
59231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        {
60231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            clearOffset();
61231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            clearValue();
62231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        }
63231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        typedef JSValue (*GetValueFunc)(ExecState*, JSValue slotBase, const Identifier&);
65d0825bca7fe65beaee391d30da42e937db621564Steve Block        typedef JSValue (*GetIndexValueFunc)(ExecState*, JSValue slotBase, unsigned);
6668513a70bcd92384395513322f1b801e7bf9c729Steve Block
67692e5dbf12901edacf14812a6fae25462920af42Steve Block        JSValue getValue(ExecState* exec, const Identifier& propertyName) const
68d0825bca7fe65beaee391d30da42e937db621564Steve Block        {
698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (m_getValue == JSC_VALUE_MARKER)
708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return m_value;
718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (m_getValue == INDEX_GETTER_MARKER)
72dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                return m_getIndexValue(exec, slotBase(), index());
738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (m_getValue == GETTER_FUNCTION_MARKER)
748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return functionGetter(exec);
758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return m_getValue(exec, slotBase(), propertyName);
768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        JSValue getValue(ExecState* exec, unsigned propertyName) const
798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        {
808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (m_getValue == JSC_VALUE_MARKER)
818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return m_value;
8268513a70bcd92384395513322f1b801e7bf9c729Steve Block            if (m_getValue == INDEX_GETTER_MARKER)
8368513a70bcd92384395513322f1b801e7bf9c729Steve Block                return m_getIndexValue(exec, m_slotBase, m_data.index);
8468513a70bcd92384395513322f1b801e7bf9c729Steve Block            if (m_getValue == GETTER_FUNCTION_MARKER)
8568513a70bcd92384395513322f1b801e7bf9c729Steve Block                return functionGetter(exec);
8668513a70bcd92384395513322f1b801e7bf9c729Steve Block            return m_getValue(exec, slotBase(), Identifier::from(exec, propertyName));
8768513a70bcd92384395513322f1b801e7bf9c729Steve Block        }
8868513a70bcd92384395513322f1b801e7bf9c729Steve Block
8968513a70bcd92384395513322f1b801e7bf9c729Steve Block        CachedPropertyType cachedPropertyType() const { return m_cachedPropertyType; }
9068513a70bcd92384395513322f1b801e7bf9c729Steve Block        bool isCacheable() const { return m_cachedPropertyType != Uncacheable; }
9168513a70bcd92384395513322f1b801e7bf9c729Steve Block        bool isCacheableValue() const { return m_cachedPropertyType == Value; }
9268513a70bcd92384395513322f1b801e7bf9c729Steve Block        size_t cachedOffset() const
93d0825bca7fe65beaee391d30da42e937db621564Steve Block        {
948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            ASSERT(isCacheable());
95d0825bca7fe65beaee391d30da42e937db621564Steve Block            return m_offset;
968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        void setValue(JSValue slotBase, JSValue value)
998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        {
1008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            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        JSValue thisValue() const { return m_thisValue; }
216
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