]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - runtime/PropertySlot.h
JavaScriptCore-7600.1.4.17.5.tar.gz
[apple/javascriptcore.git] / runtime / PropertySlot.h
index 15d90342ae7d401939239ba19b08ac09aae79fd7..f46048803b913095a9cd5643239b1f0944198ae9 100644 (file)
 #ifndef PropertySlot_h
 #define PropertySlot_h
 
-#include "Identifier.h"
-#include "JSValue.h"
+#include "JSCJSValue.h"
+#include "PropertyName.h"
+#include "PropertyOffset.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)
-
-    class PropertySlot {
-    public:
-        PropertySlot()
-        {
-            clearBase();
-            clearOffset();
-            clearValue();
-        }
-
-        explicit PropertySlot(const JSValue base)
-            : m_slotBase(base)
-        {
-            clearOffset();
-            clearValue();
-        }
-
-        typedef JSValue (*GetValueFunc)(ExecState*, const Identifier&, const PropertySlot&);
-
-        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();
-            return m_getValue(exec, propertyName, *this);
-        }
-
-        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();
-            return m_getValue(exec, Identifier::from(exec, propertyName), *this);
-        }
-
-        bool isCacheable() const { return m_offset != WTF::notFound; }
-        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;
-        }
-        
-        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_slotBase = slotBase;
-        }
-
-        void setCustomIndex(JSValue slotBase, unsigned index, GetValueFunc getValue)
-        {
-            ASSERT(slotBase);
-            ASSERT(getValue);
-            m_getValue = getValue;
-            m_slotBase = slotBase;
-            m_data.index = index;
-        }
-        
-        void setGetterSlot(JSObject* getterFunc)
-        {
-            ASSERT(getterFunc);
-            m_getValue = functionGetter;
-            m_data.getterFunc = getterFunc;
-        }
-        
-        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 = WTF::notFound;
-        }
-
-        unsigned index() const { return m_data.index; }
-
-    private:
-        static JSValue functionGetter(ExecState*, const Identifier&, const PropertySlot&);
-
-        GetValueFunc m_getValue;
-        
-        JSValue m_slotBase;
-        union {
-            JSObject* getterFunc;
-            JSValue* valueSlot;
-            Register* registerSlot;
-            unsigned index;
-        } m_data;
-
-        JSValue m_value;
-
-        size_t m_offset;
+class ExecState;
+class GetterSetter;
+class JSObject;
+
+// ECMA 262-3 8.6.1
+// Property attributes
+enum Attribute {
+    None              = 0,
+    ReadOnly          = 1 << 1,  // property can be only read, not written
+    DontEnum          = 1 << 2,  // property doesn't appear in (for .. in ..)
+    DontDelete        = 1 << 3,  // property can't be deleted
+    Function          = 1 << 4,  // property is a function - only used by static hashtables
+    Accessor          = 1 << 5,  // property is a getter/setter
+    CustomAccessor    = 1 << 6,
+    Builtin           = 1 << 7, // property is a builtin function - only used by static hashtables
+    ConstantInteger   = 1 << 8, // property is a constant integer - only used by static hashtables
+    BuiltinOrFunction = Builtin | Function, // helper only used by static hashtables
+    BuiltinOrFunctionOrConstant = Builtin | Function | ConstantInteger, // helper only used by static hashtables
+};
+
+class PropertySlot {
+    enum PropertyType {
+        TypeUnset,
+        TypeValue,
+        TypeGetter,
+        TypeCustom
     };
 
+    enum CacheabilityType {
+        CachingDisallowed,
+        CachingAllowed
+    };
+
+public:
+    explicit PropertySlot(const JSValue thisValue)
+        : m_propertyType(TypeUnset)
+        , m_offset(invalidOffset)
+        , m_thisValue(thisValue)
+        , m_watchpointSet(nullptr)
+        , m_cacheability(CachingAllowed)
+    {
+    }
+
+    typedef EncodedJSValue (*GetValueFunc)(ExecState*, JSObject* slotBase, EncodedJSValue thisValue, PropertyName);
+
+    JSValue getValue(ExecState*, PropertyName) const;
+    JSValue getValue(ExecState*, unsigned propertyName) const;
+
+    bool isCacheable() const { return m_cacheability == CachingAllowed && m_offset != invalidOffset; }
+    bool isValue() const { return m_propertyType == TypeValue; }
+    bool isAccessor() const { return m_propertyType == TypeGetter; }
+    bool isCustom() const { return m_propertyType == TypeCustom; }
+    bool isCacheableValue() const { return isCacheable() && isValue(); }
+    bool isCacheableGetter() const { return isCacheable() && isAccessor(); }
+    bool isCacheableCustom() const { return isCacheable() && isCustom(); }
+
+    void disableCaching()
+    {
+        m_cacheability = CachingDisallowed;
+    }
+
+    unsigned attributes() const { return m_attributes; }
+
+    PropertyOffset cachedOffset() const
+    {
+        ASSERT(isCacheable());
+        return m_offset;
+    }
+
+    GetterSetter* getterSetter() const
+    {
+        ASSERT(isAccessor());
+        return m_data.getter.getterSetter;
+    }
+
+    GetValueFunc customGetter() const
+    {
+        ASSERT(isCacheableCustom());
+        return m_data.custom.getValue;
+    }
+
+    JSObject* slotBase() const
+    {
+        ASSERT(m_propertyType != TypeUnset);
+        return m_slotBase;
+    }
+
+    WatchpointSet* watchpointSet() const
+    {
+        return m_watchpointSet;
+    }
+
+    void setValue(JSObject* slotBase, unsigned attributes, JSValue value)
+    {
+        ASSERT(value);
+        m_data.value = JSValue::encode(value);
+        m_attributes = attributes;
+
+        ASSERT(slotBase);
+        m_slotBase = slotBase;
+        m_propertyType = TypeValue;
+        m_offset = invalidOffset;
+    }
+    
+    void setValue(JSObject* slotBase, unsigned attributes, JSValue value, PropertyOffset offset)
+    {
+        ASSERT(value);
+        m_data.value = JSValue::encode(value);
+        m_attributes = attributes;
+
+        ASSERT(slotBase);
+        m_slotBase = slotBase;
+        m_propertyType = TypeValue;
+        m_offset = offset;
+    }
+
+    void setValue(JSString*, unsigned attributes, JSValue value)
+    {
+        ASSERT(value);
+        m_data.value = JSValue::encode(value);
+        m_attributes = attributes;
+
+        m_slotBase = 0;
+        m_propertyType = TypeValue;
+        m_offset = invalidOffset;
+    }
+
+    void setCustom(JSObject* slotBase, unsigned attributes, GetValueFunc getValue)
+    {
+        ASSERT(getValue);
+        m_data.custom.getValue = getValue;
+        m_attributes = attributes;
+
+        ASSERT(slotBase);
+        m_slotBase = slotBase;
+        m_propertyType = TypeCustom;
+        m_offset = invalidOffset;
+    }
+    
+    void setCacheableCustom(JSObject* slotBase, unsigned attributes, GetValueFunc getValue)
+    {
+        ASSERT(getValue);
+        m_data.custom.getValue = getValue;
+        m_attributes = attributes;
+
+        ASSERT(slotBase);
+        m_slotBase = slotBase;
+        m_propertyType = TypeCustom;
+        m_offset = !invalidOffset;
+    }
+
+    void setGetterSlot(JSObject* slotBase, unsigned attributes, GetterSetter* getterSetter)
+    {
+        ASSERT(getterSetter);
+        m_data.getter.getterSetter = getterSetter;
+        m_attributes = attributes;
+
+        ASSERT(slotBase);
+        m_slotBase = slotBase;
+        m_propertyType = TypeGetter;
+        m_offset = invalidOffset;
+    }
+
+    void setCacheableGetterSlot(JSObject* slotBase, unsigned attributes, GetterSetter* getterSetter, PropertyOffset offset)
+    {
+        ASSERT(getterSetter);
+        m_data.getter.getterSetter = getterSetter;
+        m_attributes = attributes;
+
+        ASSERT(slotBase);
+        m_slotBase = slotBase;
+        m_propertyType = TypeGetter;
+        m_offset = offset;
+    }
+
+    void setUndefined()
+    {
+        m_data.value = JSValue::encode(jsUndefined());
+        m_attributes = ReadOnly | DontDelete | DontEnum;
+
+        m_slotBase = 0;
+        m_propertyType = TypeValue;
+        m_offset = invalidOffset;
+    }
+
+    void setWatchpointSet(WatchpointSet& set)
+    {
+        m_watchpointSet = &set;
+    }
+
+private:
+    JS_EXPORT_PRIVATE JSValue functionGetter(ExecState*) const;
+
+    unsigned m_attributes;
+    union {
+        EncodedJSValue value;
+        struct {
+            GetterSetter* getterSetter;
+        } getter;
+        struct {
+            GetValueFunc getValue;
+        } custom;
+    } m_data;
+
+    PropertyType m_propertyType;
+    PropertyOffset m_offset;
+    const JSValue m_thisValue;
+    JSObject* m_slotBase;
+    WatchpointSet* m_watchpointSet;
+    CacheabilityType m_cacheability;
+};
+
 } // namespace JSC
 
 #endif // PropertySlot_h