+ 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;
+};
+