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_SLOT_MARKER 0
     36 #define JSC_REGISTER_SLOT_MARKER reinterpret_cast<GetValueFunc>(1)
     37 
     38     class PropertySlot {
     39     public:
     40         PropertySlot()
     41         {
     42             clearBase();
     43             clearOffset();
     44             clearValue();
     45         }
     46 
     47         explicit PropertySlot(const JSValue base)
     48             : m_slotBase(base)
     49         {
     50             clearOffset();
     51             clearValue();
     52         }
     53 
     54         typedef JSValue (*GetValueFunc)(ExecState*, const Identifier&, const PropertySlot&);
     55 
     56         JSValue getValue(ExecState* exec, const Identifier& propertyName) const
     57         {
     58             if (m_getValue == JSC_VALUE_SLOT_MARKER)
     59                 return *m_data.valueSlot;
     60             if (m_getValue == JSC_REGISTER_SLOT_MARKER)
     61                 return (*m_data.registerSlot).jsValue();
     62             return m_getValue(exec, propertyName, *this);
     63         }
     64 
     65         JSValue getValue(ExecState* exec, unsigned propertyName) const
     66         {
     67             if (m_getValue == JSC_VALUE_SLOT_MARKER)
     68                 return *m_data.valueSlot;
     69             if (m_getValue == JSC_REGISTER_SLOT_MARKER)
     70                 return (*m_data.registerSlot).jsValue();
     71             return m_getValue(exec, Identifier::from(exec, propertyName), *this);
     72         }
     73 
     74         bool isCacheable() const { return m_offset != WTF::notFound; }
     75         size_t cachedOffset() const
     76         {
     77             ASSERT(isCacheable());
     78             return m_offset;
     79         }
     80 
     81         void setValueSlot(JSValue* valueSlot)
     82         {
     83             ASSERT(valueSlot);
     84             clearBase();
     85             clearOffset();
     86             m_getValue = JSC_VALUE_SLOT_MARKER;
     87             m_data.valueSlot = valueSlot;
     88         }
     89 
     90         void setValueSlot(JSValue slotBase, JSValue* valueSlot)
     91         {
     92             ASSERT(valueSlot);
     93             m_getValue = JSC_VALUE_SLOT_MARKER;
     94             m_slotBase = slotBase;
     95             m_data.valueSlot = valueSlot;
     96         }
     97 
     98         void setValueSlot(JSValue slotBase, JSValue* valueSlot, size_t offset)
     99         {
    100             ASSERT(valueSlot);
    101             m_getValue = JSC_VALUE_SLOT_MARKER;
    102             m_slotBase = slotBase;
    103             m_data.valueSlot = valueSlot;
    104             m_offset = offset;
    105         }
    106 
    107         void setValue(JSValue value)
    108         {
    109             ASSERT(value);
    110             clearBase();
    111             clearOffset();
    112             m_getValue = JSC_VALUE_SLOT_MARKER;
    113             m_value = value;
    114             m_data.valueSlot = &m_value;
    115         }
    116 
    117         void setRegisterSlot(Register* registerSlot)
    118         {
    119             ASSERT(registerSlot);
    120             clearBase();
    121             clearOffset();
    122             m_getValue = JSC_REGISTER_SLOT_MARKER;
    123             m_data.registerSlot = registerSlot;
    124         }
    125 
    126         void setCustom(JSValue slotBase, GetValueFunc getValue)
    127         {
    128             ASSERT(slotBase);
    129             ASSERT(getValue);
    130             m_getValue = getValue;
    131             m_slotBase = slotBase;
    132         }
    133 
    134         void setCustomIndex(JSValue slotBase, unsigned index, GetValueFunc getValue)
    135         {
    136             ASSERT(slotBase);
    137             ASSERT(getValue);
    138             m_getValue = getValue;
    139             m_slotBase = slotBase;
    140             m_data.index = index;
    141         }
    142 
    143         void setGetterSlot(JSObject* getterFunc)
    144         {
    145             ASSERT(getterFunc);
    146             m_getValue = functionGetter;
    147             m_data.getterFunc = getterFunc;
    148         }
    149 
    150         void setUndefined()
    151         {
    152             setValue(jsUndefined());
    153         }
    154 
    155         JSValue slotBase() const
    156         {
    157             return m_slotBase;
    158         }
    159 
    160         void setBase(JSValue base)
    161         {
    162             ASSERT(m_slotBase);
    163             ASSERT(base);
    164             m_slotBase = base;
    165         }
    166 
    167         void clearBase()
    168         {
    169 #ifndef NDEBUG
    170             m_slotBase = JSValue();
    171 #endif
    172         }
    173 
    174         void clearValue()
    175         {
    176 #ifndef NDEBUG
    177             m_value = JSValue();
    178 #endif
    179         }
    180 
    181         void clearOffset()
    182         {
    183             // Clear offset even in release builds, in case this PropertySlot has been used before.
    184             // (For other data members, we don't need to clear anything because reuse would meaningfully overwrite them.)
    185             m_offset = WTF::notFound;
    186         }
    187 
    188         unsigned index() const { return m_data.index; }
    189 
    190     private:
    191         static JSValue functionGetter(ExecState*, const Identifier&, const PropertySlot&);
    192 
    193         GetValueFunc m_getValue;
    194 
    195         JSValue m_slotBase;
    196         union {
    197             JSObject* getterFunc;
    198             JSValue* valueSlot;
    199             Register* registerSlot;
    200             unsigned index;
    201         } m_data;
    202 
    203         JSValue m_value;
    204 
    205         size_t m_offset;
    206     };
    207 
    208 } // namespace JSC
    209 
    210 #endif // PropertySlot_h
    211