Home | History | Annotate | Download | only in runtime
      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 
     48         PropertySlot()
     49             : m_cachedPropertyType(Uncacheable)
     50         {
     51             clearBase();
     52             clearOffset();
     53             clearValue();
     54         }
     55 
     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 
     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 
     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 
     89         CachedPropertyType cachedPropertyType() const { return m_cachedPropertyType; }
     90         bool isCacheable() const { return m_cachedPropertyType != Uncacheable; }
     91         bool isCacheableValue() const { return m_cachedPropertyType == Value; }
     92         size_t cachedOffset() const
     93         {
     94             ASSERT(isCacheable());
     95             return m_offset;
     96         }
     97 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    174         void setUndefined()
    175         {
    176             setValue(jsUndefined());
    177         }
    178 
    179         JSValue slotBase() const
    180         {
    181             return m_slotBase;
    182         }
    183 
    184         void setBase(JSValue base)
    185         {
    186             ASSERT(m_slotBase);
    187             ASSERT(base);
    188             m_slotBase = base;
    189         }
    190 
    191         void clearBase()
    192         {
    193 #ifndef NDEBUG
    194             m_slotBase = JSValue();
    195 #endif
    196         }
    197 
    198         void clearValue()
    199         {
    200 #ifndef NDEBUG
    201             m_value = JSValue();
    202 #endif
    203         }
    204 
    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 
    213         unsigned index() const { return m_data.index; }
    214 
    215         JSValue thisValue() const { return m_thisValue; }
    216 
    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