1/* 2 * Copyright (C) 2005, 2007, 2008 Apple Inc. All rights reserved. 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Library General Public 6 * License as published by the Free Software Foundation; either 7 * version 2 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Library General Public License for more details. 13 * 14 * You should have received a copy of the GNU Library General Public License 15 * along with this library; see the file COPYING.LIB. If not, write to 16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 17 * Boston, MA 02110-1301, USA. 18 * 19 */ 20 21#ifndef PropertySlot_h 22#define PropertySlot_h 23 24#include "JSCJSValue.h" 25#include "PropertyName.h" 26#include "PropertyOffset.h" 27#include "Register.h" 28#include <wtf/Assertions.h> 29 30namespace JSC { 31 32class ExecState; 33class GetterSetter; 34class JSObject; 35 36// ECMA 262-3 8.6.1 37// Property attributes 38enum Attribute { 39 None = 0, 40 ReadOnly = 1 << 1, // property can be only read, not written 41 DontEnum = 1 << 2, // property doesn't appear in (for .. in ..) 42 DontDelete = 1 << 3, // property can't be deleted 43 Function = 1 << 4, // property is a function - only used by static hashtables 44 Accessor = 1 << 5, // property is a getter/setter 45 CustomAccessor = 1 << 6, 46 Builtin = 1 << 7, // property is a builtin function - only used by static hashtables 47 ConstantInteger = 1 << 8, // property is a constant integer - only used by static hashtables 48 BuiltinOrFunction = Builtin | Function, // helper only used by static hashtables 49 BuiltinOrFunctionOrConstant = Builtin | Function | ConstantInteger, // helper only used by static hashtables 50}; 51 52class PropertySlot { 53 enum PropertyType { 54 TypeUnset, 55 TypeValue, 56 TypeGetter, 57 TypeCustom 58 }; 59 60 enum CacheabilityType { 61 CachingDisallowed, 62 CachingAllowed 63 }; 64 65public: 66 explicit PropertySlot(const JSValue thisValue) 67 : m_propertyType(TypeUnset) 68 , m_offset(invalidOffset) 69 , m_thisValue(thisValue) 70 , m_watchpointSet(nullptr) 71 , m_cacheability(CachingAllowed) 72 { 73 } 74 75 typedef EncodedJSValue (*GetValueFunc)(ExecState*, JSObject* slotBase, EncodedJSValue thisValue, PropertyName); 76 77 JSValue getValue(ExecState*, PropertyName) const; 78 JSValue getValue(ExecState*, unsigned propertyName) const; 79 80 bool isCacheable() const { return m_cacheability == CachingAllowed && m_offset != invalidOffset; } 81 bool isValue() const { return m_propertyType == TypeValue; } 82 bool isAccessor() const { return m_propertyType == TypeGetter; } 83 bool isCustom() const { return m_propertyType == TypeCustom; } 84 bool isCacheableValue() const { return isCacheable() && isValue(); } 85 bool isCacheableGetter() const { return isCacheable() && isAccessor(); } 86 bool isCacheableCustom() const { return isCacheable() && isCustom(); } 87 88 void disableCaching() 89 { 90 m_cacheability = CachingDisallowed; 91 } 92 93 unsigned attributes() const { return m_attributes; } 94 95 PropertyOffset cachedOffset() const 96 { 97 ASSERT(isCacheable()); 98 return m_offset; 99 } 100 101 GetterSetter* getterSetter() const 102 { 103 ASSERT(isAccessor()); 104 return m_data.getter.getterSetter; 105 } 106 107 GetValueFunc customGetter() const 108 { 109 ASSERT(isCacheableCustom()); 110 return m_data.custom.getValue; 111 } 112 113 JSObject* slotBase() const 114 { 115 ASSERT(m_propertyType != TypeUnset); 116 return m_slotBase; 117 } 118 119 WatchpointSet* watchpointSet() const 120 { 121 return m_watchpointSet; 122 } 123 124 void setValue(JSObject* slotBase, unsigned attributes, JSValue value) 125 { 126 ASSERT(value); 127 m_data.value = JSValue::encode(value); 128 m_attributes = attributes; 129 130 ASSERT(slotBase); 131 m_slotBase = slotBase; 132 m_propertyType = TypeValue; 133 m_offset = invalidOffset; 134 } 135 136 void setValue(JSObject* slotBase, unsigned attributes, JSValue value, PropertyOffset offset) 137 { 138 ASSERT(value); 139 m_data.value = JSValue::encode(value); 140 m_attributes = attributes; 141 142 ASSERT(slotBase); 143 m_slotBase = slotBase; 144 m_propertyType = TypeValue; 145 m_offset = offset; 146 } 147 148 void setValue(JSString*, unsigned attributes, JSValue value) 149 { 150 ASSERT(value); 151 m_data.value = JSValue::encode(value); 152 m_attributes = attributes; 153 154 m_slotBase = 0; 155 m_propertyType = TypeValue; 156 m_offset = invalidOffset; 157 } 158 159 void setCustom(JSObject* slotBase, unsigned attributes, GetValueFunc getValue) 160 { 161 ASSERT(getValue); 162 m_data.custom.getValue = getValue; 163 m_attributes = attributes; 164 165 ASSERT(slotBase); 166 m_slotBase = slotBase; 167 m_propertyType = TypeCustom; 168 m_offset = invalidOffset; 169 } 170 171 void setCacheableCustom(JSObject* slotBase, unsigned attributes, GetValueFunc getValue) 172 { 173 ASSERT(getValue); 174 m_data.custom.getValue = getValue; 175 m_attributes = attributes; 176 177 ASSERT(slotBase); 178 m_slotBase = slotBase; 179 m_propertyType = TypeCustom; 180 m_offset = !invalidOffset; 181 } 182 183 void setGetterSlot(JSObject* slotBase, unsigned attributes, GetterSetter* getterSetter) 184 { 185 ASSERT(getterSetter); 186 m_data.getter.getterSetter = getterSetter; 187 m_attributes = attributes; 188 189 ASSERT(slotBase); 190 m_slotBase = slotBase; 191 m_propertyType = TypeGetter; 192 m_offset = invalidOffset; 193 } 194 195 void setCacheableGetterSlot(JSObject* slotBase, unsigned attributes, GetterSetter* getterSetter, PropertyOffset offset) 196 { 197 ASSERT(getterSetter); 198 m_data.getter.getterSetter = getterSetter; 199 m_attributes = attributes; 200 201 ASSERT(slotBase); 202 m_slotBase = slotBase; 203 m_propertyType = TypeGetter; 204 m_offset = offset; 205 } 206 207 void setUndefined() 208 { 209 m_data.value = JSValue::encode(jsUndefined()); 210 m_attributes = ReadOnly | DontDelete | DontEnum; 211 212 m_slotBase = 0; 213 m_propertyType = TypeValue; 214 m_offset = invalidOffset; 215 } 216 217 void setWatchpointSet(WatchpointSet& set) 218 { 219 m_watchpointSet = &set; 220 } 221 222private: 223 JS_EXPORT_PRIVATE JSValue functionGetter(ExecState*) const; 224 225 unsigned m_attributes; 226 union { 227 EncodedJSValue value; 228 struct { 229 GetterSetter* getterSetter; 230 } getter; 231 struct { 232 GetValueFunc getValue; 233 } custom; 234 } m_data; 235 236 PropertyType m_propertyType; 237 PropertyOffset m_offset; 238 const JSValue m_thisValue; 239 JSObject* m_slotBase; 240 WatchpointSet* m_watchpointSet; 241 CacheabilityType m_cacheability; 242}; 243 244} // namespace JSC 245 246#endif // PropertySlot_h 247