JavaScriptCore/runtime/PropertySlot.h
changeset 0 4f2f89ce4247
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/JavaScriptCore/runtime/PropertySlot.h	Fri Sep 17 09:02:29 2010 +0300
@@ -0,0 +1,268 @@
+/*
+ *  Copyright (C) 2005, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public License
+ *  along with this library; see the file COPYING.LIB.  If not, write to
+ *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef PropertySlot_h
+#define PropertySlot_h
+
+#include "Identifier.h"
+#include "JSValue.h"
+#include "Register.h"
+#include <wtf/Assertions.h>
+#include <wtf/NotFound.h>
+
+namespace JSC {
+
+    class ExecState;
+    class JSObject;
+
+#define JSC_VALUE_SLOT_MARKER 0
+#define JSC_REGISTER_SLOT_MARKER reinterpret_cast<GetValueFunc>(1)
+#define INDEX_GETTER_MARKER reinterpret_cast<GetValueFunc>(2)
+#define GETTER_FUNCTION_MARKER reinterpret_cast<GetValueFunc>(3)
+
+    class PropertySlot {
+    public:
+        enum CachedPropertyType {
+            Uncacheable,
+            Getter,
+            Custom,
+            Value
+        };
+
+        PropertySlot()
+            : m_cachedPropertyType(Uncacheable)
+        {
+            clearBase();
+            clearOffset();
+            clearValue();
+        }
+
+        explicit PropertySlot(const JSValue base)
+            : m_slotBase(base)
+            , m_cachedPropertyType(Uncacheable)
+        {
+            clearOffset();
+            clearValue();
+        }
+
+        typedef JSValue (*GetValueFunc)(ExecState*, JSValue slotBase, const Identifier&);
+        typedef JSValue (*GetIndexValueFunc)(ExecState*, JSValue slotBase, unsigned);
+
+        JSValue getValue(ExecState* exec, const Identifier& propertyName) const
+        {
+            if (m_getValue == JSC_VALUE_SLOT_MARKER)
+                return *m_data.valueSlot;
+            if (m_getValue == JSC_REGISTER_SLOT_MARKER)
+                return (*m_data.registerSlot).jsValue();
+            if (m_getValue == INDEX_GETTER_MARKER)
+                return m_getIndexValue(exec, slotBase(), index());
+            if (m_getValue == GETTER_FUNCTION_MARKER)
+                return functionGetter(exec);
+            return m_getValue(exec, slotBase(), propertyName);
+        }
+
+        JSValue getValue(ExecState* exec, unsigned propertyName) const
+        {
+            if (m_getValue == JSC_VALUE_SLOT_MARKER)
+                return *m_data.valueSlot;
+            if (m_getValue == JSC_REGISTER_SLOT_MARKER)
+                return (*m_data.registerSlot).jsValue();
+            if (m_getValue == INDEX_GETTER_MARKER)
+                return m_getIndexValue(exec, m_slotBase, m_data.index);
+            if (m_getValue == GETTER_FUNCTION_MARKER)
+                return functionGetter(exec);
+            return m_getValue(exec, slotBase(), Identifier::from(exec, propertyName));
+        }
+
+        CachedPropertyType cachedPropertyType() const { return m_cachedPropertyType; }
+        bool isCacheable() const { return m_cachedPropertyType != Uncacheable; }
+        bool isCacheableValue() const { return m_cachedPropertyType == Value; }
+        size_t cachedOffset() const
+        {
+            ASSERT(isCacheable());
+            return m_offset;
+        }
+
+        void setValueSlot(JSValue* valueSlot) 
+        {
+            ASSERT(valueSlot);
+            clearBase();
+            clearOffset();
+            m_getValue = JSC_VALUE_SLOT_MARKER;
+            m_data.valueSlot = valueSlot;
+        }
+        
+        void setValueSlot(JSValue slotBase, JSValue* valueSlot)
+        {
+            ASSERT(valueSlot);
+            m_getValue = JSC_VALUE_SLOT_MARKER;
+            m_slotBase = slotBase;
+            m_data.valueSlot = valueSlot;
+        }
+        
+        void setValueSlot(JSValue slotBase, JSValue* valueSlot, size_t offset)
+        {
+            ASSERT(valueSlot);
+            m_getValue = JSC_VALUE_SLOT_MARKER;
+            m_slotBase = slotBase;
+            m_data.valueSlot = valueSlot;
+            m_offset = offset;
+            m_cachedPropertyType = Value;
+        }
+        
+        void setValue(JSValue value)
+        {
+            ASSERT(value);
+            clearBase();
+            clearOffset();
+            m_getValue = JSC_VALUE_SLOT_MARKER;
+            m_value = value;
+            m_data.valueSlot = &m_value;
+        }
+
+        void setRegisterSlot(Register* registerSlot)
+        {
+            ASSERT(registerSlot);
+            clearBase();
+            clearOffset();
+            m_getValue = JSC_REGISTER_SLOT_MARKER;
+            m_data.registerSlot = registerSlot;
+        }
+
+        void setCustom(JSValue slotBase, GetValueFunc getValue)
+        {
+            ASSERT(slotBase);
+            ASSERT(getValue);
+            m_getValue = getValue;
+            m_getIndexValue = 0;
+            m_slotBase = slotBase;
+        }
+        
+        void setCacheableCustom(JSValue slotBase, GetValueFunc getValue)
+        {
+            ASSERT(slotBase);
+            ASSERT(getValue);
+            m_getValue = getValue;
+            m_getIndexValue = 0;
+            m_slotBase = slotBase;
+            m_cachedPropertyType = Custom;
+        }
+
+        void setCustomIndex(JSValue slotBase, unsigned index, GetIndexValueFunc getIndexValue)
+        {
+            ASSERT(slotBase);
+            ASSERT(getIndexValue);
+            m_getValue = INDEX_GETTER_MARKER;
+            m_getIndexValue = getIndexValue;
+            m_slotBase = slotBase;
+            m_data.index = index;
+        }
+
+        void setGetterSlot(JSObject* getterFunc)
+        {
+            ASSERT(getterFunc);
+            m_thisValue = m_slotBase;
+            m_getValue = GETTER_FUNCTION_MARKER;
+            m_data.getterFunc = getterFunc;
+        }
+
+        void setCacheableGetterSlot(JSValue slotBase, JSObject* getterFunc, unsigned offset)
+        {
+            ASSERT(getterFunc);
+            m_getValue = GETTER_FUNCTION_MARKER;
+            m_thisValue = m_slotBase;
+            m_slotBase = slotBase;
+            m_data.getterFunc = getterFunc;
+            m_offset = offset;
+            m_cachedPropertyType = Getter;
+        }
+
+        void setUndefined()
+        {
+            setValue(jsUndefined());
+        }
+
+        JSValue slotBase() const
+        {
+            return m_slotBase;
+        }
+
+        void setBase(JSValue base)
+        {
+            ASSERT(m_slotBase);
+            ASSERT(base);
+            m_slotBase = base;
+        }
+
+        void clearBase()
+        {
+#ifndef NDEBUG
+            m_slotBase = JSValue();
+#endif
+        }
+
+        void clearValue()
+        {
+#ifndef NDEBUG
+            m_value = JSValue();
+#endif
+        }
+
+        void clearOffset()
+        {
+            // Clear offset even in release builds, in case this PropertySlot has been used before.
+            // (For other data members, we don't need to clear anything because reuse would meaningfully overwrite them.)
+            m_offset = 0;
+            m_cachedPropertyType = Uncacheable;
+        }
+
+        unsigned index() const { return m_data.index; }
+
+        JSValue thisValue() const { return m_thisValue; }
+
+        GetValueFunc customGetter() const
+        {
+            ASSERT(m_cachedPropertyType == Custom);
+            return m_getValue;
+        }
+    private:
+        JSValue functionGetter(ExecState*) const;
+
+        GetValueFunc m_getValue;
+        GetIndexValueFunc m_getIndexValue;
+        
+        JSValue m_slotBase;
+        union {
+            JSObject* getterFunc;
+            JSValue* valueSlot;
+            Register* registerSlot;
+            unsigned index;
+        } m_data;
+
+        JSValue m_value;
+        JSValue m_thisValue;
+
+        size_t m_offset;
+        CachedPropertyType m_cachedPropertyType;
+    };
+
+} // namespace JSC
+
+#endif // PropertySlot_h