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 "Identifier.h" 25 #include "JSValue.h" 26 #include "Register.h" 27 #include <wtf/Assertions.h> 28 #include <wtf/NotFound.h> 29 30 namespace JSC { 31 32 class ExecState; 33 class JSObject; 34 35 #define JSC_VALUE_MARKER 0 36 #define INDEX_GETTER_MARKER reinterpret_cast<GetValueFunc>(2) 37 #define GETTER_FUNCTION_MARKER reinterpret_cast<GetValueFunc>(3) 38 39 class PropertySlot { 40 public: 41 enum CachedPropertyType { 42 Uncacheable, 43 Getter, 44 Custom, 45 Value 46 }; 47 PropertySlot()48 PropertySlot() 49 : m_cachedPropertyType(Uncacheable) 50 { 51 clearBase(); 52 clearOffset(); 53 clearValue(); 54 } 55 PropertySlot(const JSValue base)56 explicit PropertySlot(const JSValue base) 57 : m_slotBase(base) 58 , m_cachedPropertyType(Uncacheable) 59 { 60 clearOffset(); 61 clearValue(); 62 } 63 64 typedef JSValue (*GetValueFunc)(ExecState*, JSValue slotBase, const Identifier&); 65 typedef JSValue (*GetIndexValueFunc)(ExecState*, JSValue slotBase, unsigned); 66 getValue(ExecState * exec,const Identifier & propertyName)67 JSValue getValue(ExecState* exec, const Identifier& propertyName) const 68 { 69 if (m_getValue == JSC_VALUE_MARKER) 70 return m_value; 71 if (m_getValue == INDEX_GETTER_MARKER) 72 return m_getIndexValue(exec, slotBase(), index()); 73 if (m_getValue == GETTER_FUNCTION_MARKER) 74 return functionGetter(exec); 75 return m_getValue(exec, slotBase(), propertyName); 76 } 77 getValue(ExecState * exec,unsigned propertyName)78 JSValue getValue(ExecState* exec, unsigned propertyName) const 79 { 80 if (m_getValue == JSC_VALUE_MARKER) 81 return m_value; 82 if (m_getValue == INDEX_GETTER_MARKER) 83 return m_getIndexValue(exec, m_slotBase, m_data.index); 84 if (m_getValue == GETTER_FUNCTION_MARKER) 85 return functionGetter(exec); 86 return m_getValue(exec, slotBase(), Identifier::from(exec, propertyName)); 87 } 88 cachedPropertyType()89 CachedPropertyType cachedPropertyType() const { return m_cachedPropertyType; } isCacheable()90 bool isCacheable() const { return m_cachedPropertyType != Uncacheable; } isCacheableValue()91 bool isCacheableValue() const { return m_cachedPropertyType == Value; } cachedOffset()92 size_t cachedOffset() const 93 { 94 ASSERT(isCacheable()); 95 return m_offset; 96 } 97 setValue(JSValue slotBase,JSValue value)98 void setValue(JSValue slotBase, JSValue value) 99 { 100 ASSERT(value); 101 clearOffset(); 102 m_getValue = JSC_VALUE_MARKER; 103 m_slotBase = slotBase; 104 m_value = value; 105 } 106 setValue(JSValue slotBase,JSValue value,size_t offset)107 void setValue(JSValue slotBase, JSValue value, size_t offset) 108 { 109 ASSERT(value); 110 m_getValue = JSC_VALUE_MARKER; 111 m_slotBase = slotBase; 112 m_value = value; 113 m_offset = offset; 114 m_cachedPropertyType = Value; 115 } 116 setValue(JSValue value)117 void setValue(JSValue value) 118 { 119 ASSERT(value); 120 clearBase(); 121 clearOffset(); 122 m_getValue = JSC_VALUE_MARKER; 123 m_value = value; 124 } 125 setCustom(JSValue slotBase,GetValueFunc getValue)126 void setCustom(JSValue slotBase, GetValueFunc getValue) 127 { 128 ASSERT(slotBase); 129 ASSERT(getValue); 130 m_getValue = getValue; 131 m_getIndexValue = 0; 132 m_slotBase = slotBase; 133 } 134 setCacheableCustom(JSValue slotBase,GetValueFunc getValue)135 void setCacheableCustom(JSValue slotBase, GetValueFunc getValue) 136 { 137 ASSERT(slotBase); 138 ASSERT(getValue); 139 m_getValue = getValue; 140 m_getIndexValue = 0; 141 m_slotBase = slotBase; 142 m_cachedPropertyType = Custom; 143 } 144 setCustomIndex(JSValue slotBase,unsigned index,GetIndexValueFunc getIndexValue)145 void setCustomIndex(JSValue slotBase, unsigned index, GetIndexValueFunc getIndexValue) 146 { 147 ASSERT(slotBase); 148 ASSERT(getIndexValue); 149 m_getValue = INDEX_GETTER_MARKER; 150 m_getIndexValue = getIndexValue; 151 m_slotBase = slotBase; 152 m_data.index = index; 153 } 154 setGetterSlot(JSObject * getterFunc)155 void setGetterSlot(JSObject* getterFunc) 156 { 157 ASSERT(getterFunc); 158 m_thisValue = m_slotBase; 159 m_getValue = GETTER_FUNCTION_MARKER; 160 m_data.getterFunc = getterFunc; 161 } 162 setCacheableGetterSlot(JSValue slotBase,JSObject * getterFunc,unsigned offset)163 void setCacheableGetterSlot(JSValue slotBase, JSObject* getterFunc, unsigned offset) 164 { 165 ASSERT(getterFunc); 166 m_getValue = GETTER_FUNCTION_MARKER; 167 m_thisValue = m_slotBase; 168 m_slotBase = slotBase; 169 m_data.getterFunc = getterFunc; 170 m_offset = offset; 171 m_cachedPropertyType = Getter; 172 } 173 setUndefined()174 void setUndefined() 175 { 176 setValue(jsUndefined()); 177 } 178 slotBase()179 JSValue slotBase() const 180 { 181 return m_slotBase; 182 } 183 setBase(JSValue base)184 void setBase(JSValue base) 185 { 186 ASSERT(m_slotBase); 187 ASSERT(base); 188 m_slotBase = base; 189 } 190 clearBase()191 void clearBase() 192 { 193 #ifndef NDEBUG 194 m_slotBase = JSValue(); 195 #endif 196 } 197 clearValue()198 void clearValue() 199 { 200 #ifndef NDEBUG 201 m_value = JSValue(); 202 #endif 203 } 204 clearOffset()205 void clearOffset() 206 { 207 // Clear offset even in release builds, in case this PropertySlot has been used before. 208 // (For other data members, we don't need to clear anything because reuse would meaningfully overwrite them.) 209 m_offset = 0; 210 m_cachedPropertyType = Uncacheable; 211 } 212 index()213 unsigned index() const { return m_data.index; } 214 thisValue()215 JSValue thisValue() const { return m_thisValue; } 216 customGetter()217 GetValueFunc customGetter() const 218 { 219 ASSERT(m_cachedPropertyType == Custom); 220 return m_getValue; 221 } 222 private: 223 JSValue functionGetter(ExecState*) const; 224 225 GetValueFunc m_getValue; 226 GetIndexValueFunc m_getIndexValue; 227 228 JSValue m_slotBase; 229 union { 230 JSObject* getterFunc; 231 unsigned index; 232 } m_data; 233 234 JSValue m_value; 235 JSValue m_thisValue; 236 237 size_t m_offset; 238 CachedPropertyType m_cachedPropertyType; 239 }; 240 241 } // namespace JSC 242 243 #endif // PropertySlot_h 244