]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - runtime/PropertySlot.h
JavaScriptCore-621.1.tar.gz
[apple/javascriptcore.git] / runtime / PropertySlot.h
index 1dd1afafea8c2350bccf19b7c557defd342b0c7a..de9ddc99822a633f024e96362188d9d5c4ab6bc0 100644 (file)
@@ -23,7 +23,6 @@
 
 #include "Identifier.h"
 #include "JSValue.h"
-#include "JSImmediate.h"
 #include "Register.h"
 #include <wtf/Assertions.h>
 #include <wtf/NotFound.h>
@@ -35,69 +34,82 @@ namespace JSC {
 
 #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_offset(WTF::notFound)
+            : m_cachedPropertyType(Uncacheable)
         {
             clearBase();
+            clearOffset();
             clearValue();
         }
 
-        explicit PropertySlot(const JSValuePtr base)
+        explicit PropertySlot(const JSValue base)
             : m_slotBase(base)
-            , m_offset(WTF::notFound)
+            , m_cachedPropertyType(Uncacheable)
         {
+            clearOffset();
             clearValue();
         }
 
-        typedef JSValuePtr (*GetValueFunc)(ExecState*, const Identifier&, const PropertySlot&);
+        typedef JSValue (*GetValueFunc)(ExecState*, JSValue slotBase, const Identifier&);
+        typedef JSValue (*GetIndexValueFunc)(ExecState*, JSValue slotBase, unsigned);
 
-        JSValuePtr getValue(ExecState* exec, const Identifier& propertyName) const
+        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(exec);
-            return m_getValue(exec, propertyName, *this);
+                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);
         }
 
-        JSValuePtr getValue(ExecState* exec, unsigned propertyName) const
+        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(exec);
-            return m_getValue(exec, Identifier::from(exec, propertyName), *this);
+                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));
         }
 
-        bool isCacheable() const { return m_offset != WTF::notFound; }
+        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 putValue(JSValuePtr value)
-        { 
-            if (m_getValue == JSC_VALUE_SLOT_MARKER) {
-                *m_data.valueSlot = value;
-                return;
-            }
-            ASSERT(m_getValue == JSC_REGISTER_SLOT_MARKER);
-            *m_data.registerSlot = JSValuePtr(value);
-        }
-
-        void setValueSlot(JSValuePtr* valueSlot) 
+        void setValueSlot(JSValue* valueSlot) 
         {
             ASSERT(valueSlot);
-            m_getValue = JSC_VALUE_SLOT_MARKER;
             clearBase();
+            clearOffset();
+            m_getValue = JSC_VALUE_SLOT_MARKER;
             m_data.valueSlot = valueSlot;
         }
         
-        void setValueSlot(JSValuePtr slotBase, JSValuePtr* valueSlot)
+        void setValueSlot(JSValue slotBase, JSValue* valueSlot)
         {
             ASSERT(valueSlot);
             m_getValue = JSC_VALUE_SLOT_MARKER;
@@ -105,20 +117,22 @@ namespace JSC {
             m_data.valueSlot = valueSlot;
         }
         
-        void setValueSlot(JSValuePtr slotBase, JSValuePtr* valueSlot, size_t offset)
+        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(JSValuePtr value)
+        void setValue(JSValue value)
         {
             ASSERT(value);
-            m_getValue = JSC_VALUE_SLOT_MARKER;
             clearBase();
+            clearOffset();
+            m_getValue = JSC_VALUE_SLOT_MARKER;
             m_value = value;
             m_data.valueSlot = &m_value;
         }
@@ -126,48 +140,71 @@ namespace JSC {
         void setRegisterSlot(Register* registerSlot)
         {
             ASSERT(registerSlot);
-            m_getValue = JSC_REGISTER_SLOT_MARKER;
             clearBase();
+            clearOffset();
+            m_getValue = JSC_REGISTER_SLOT_MARKER;
             m_data.registerSlot = registerSlot;
         }
 
-        void setCustom(JSValuePtr slotBase, GetValueFunc getValue)
+        void setCustom(JSValue slotBase, GetValueFunc getValue)
         {
             ASSERT(slotBase);
             ASSERT(getValue);
             m_getValue = getValue;
+            m_getIndexValue = 0;
             m_slotBase = slotBase;
         }
-
-        void setCustomIndex(JSValuePtr slotBase, unsigned index, GetValueFunc getValue)
+        
+        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_getValue = functionGetter;
+            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()
         {
-            clearBase();
             setValue(jsUndefined());
         }
 
-        JSValuePtr slotBase() const
+        JSValue slotBase() const
         {
-            ASSERT(m_slotBase);
             return m_slotBase;
         }
 
-        void setBase(JSValuePtr base)
+        void setBase(JSValue base)
         {
             ASSERT(m_slotBase);
             ASSERT(base);
@@ -177,35 +214,53 @@ namespace JSC {
         void clearBase()
         {
 #ifndef NDEBUG
-            m_slotBase = noValue();
+            m_slotBase = JSValue();
 #endif
         }
 
         void clearValue()
         {
 #ifndef NDEBUG
-            m_value = noValue();
+            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:
-        static JSValuePtr functionGetter(ExecState*, const Identifier&, const PropertySlot&);
+        JSValue functionGetter(ExecState*) const;
 
         GetValueFunc m_getValue;
+        GetIndexValueFunc m_getIndexValue;
         
-        JSValuePtr m_slotBase;
+        JSValue m_slotBase;
         union {
             JSObject* getterFunc;
-            JSValuePtr* valueSlot;
+            JSValue* valueSlot;
             Register* registerSlot;
             unsigned index;
         } m_data;
 
-        JSValuePtr m_value;
+        JSValue m_value;
+        JSValue m_thisValue;
 
         size_t m_offset;
+        CachedPropertyType m_cachedPropertyType;
     };
 
 } // namespace JSC