Changeset 153454 in webkit


Ignore:
Timestamp:
Jul 29, 2013 6:15:18 PM (11 years ago)
Author:
barraclough@apple.com
Message:

Some cleanup in PropertySlot
https://bugs.webkit.org/show_bug.cgi?id=119189

Reviewed by Geoff Garen.

PropertySlot represents a property in one of four states - value, getter, custom, or custom-index.
The state is currently tracked redundantly by two mechanisms - the custom getter function (m_getValue)
is set to a special value to indicate the type (other than custom), and the type is also tracked by
an enum - but only if cacheable. Cacheability can typically be determined by the value of m_offset
(this is invalidOffset if not cacheable).

  • Internally, always track the type of the property using an enum value, PropertyType.
  • Use m_offset to indicate cacheable.
  • Keep the external interface (CachedPropertyType) unchanged.
  • Better pack data into the m_data union.

Performance neutral.

  • dfg/DFGRepatch.cpp:

(JSC::DFG::tryCacheGetByID):
(JSC::DFG::tryBuildGetByIDList):

  • cachedPropertyType() -> isCacheable*()
  • jit/JITPropertyAccess.cpp:

(JSC::JIT::privateCompileGetByIdProto):
(JSC::JIT::privateCompileGetByIdSelfList):
(JSC::JIT::privateCompileGetByIdProtoList):
(JSC::JIT::privateCompileGetByIdChainList):
(JSC::JIT::privateCompileGetByIdChain):

  • cachedPropertyType() -> isCacheable*()
  • jit/JITPropertyAccess32_64.cpp:

(JSC::JIT::privateCompileGetByIdProto):
(JSC::JIT::privateCompileGetByIdSelfList):
(JSC::JIT::privateCompileGetByIdProtoList):
(JSC::JIT::privateCompileGetByIdChainList):
(JSC::JIT::privateCompileGetByIdChain):

  • cachedPropertyType() -> isCacheable*()
  • jit/JITStubs.cpp:

(JSC::tryCacheGetByID):

  • cachedPropertyType() -> isCacheable*()
  • llint/LLIntSlowPaths.cpp:

(JSC::LLInt::LLINT_SLOW_PATH_DECL):

  • cachedPropertyType() -> isCacheable*()
  • runtime/PropertySlot.cpp:

(JSC::PropertySlot::functionGetter):

  • refactoring described above.
  • runtime/PropertySlot.h:

(JSC::PropertySlot::PropertySlot):
(JSC::PropertySlot::getValue):
(JSC::PropertySlot::isCacheable):
(JSC::PropertySlot::isCacheableValue):
(JSC::PropertySlot::isCacheableGetter):
(JSC::PropertySlot::isCacheableCustom):
(JSC::PropertySlot::cachedOffset):
(JSC::PropertySlot::customGetter):
(JSC::PropertySlot::setValue):
(JSC::PropertySlot::setCustom):
(JSC::PropertySlot::setCacheableCustom):
(JSC::PropertySlot::setCustomIndex):
(JSC::PropertySlot::setGetterSlot):
(JSC::PropertySlot::setCacheableGetterSlot):
(JSC::PropertySlot::setUndefined):
(JSC::PropertySlot::slotBase):
(JSC::PropertySlot::setBase):

  • refactoring described above.
Location:
trunk/Source/JavaScriptCore
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r153410 r153454  
     12013-07-29  Gavin Barraclough  <barraclough@apple.com>
     2
     3        Some cleanup in PropertySlot
     4        https://bugs.webkit.org/show_bug.cgi?id=119189
     5
     6        Reviewed by Geoff Garen.
     7
     8        PropertySlot represents a property in one of four states - value, getter, custom, or custom-index.
     9        The state is currently tracked redundantly by two mechanisms - the custom getter function (m_getValue)
     10        is set to a special value to indicate the type (other than custom), and the type is also tracked by
     11        an enum - but only if cacheable. Cacheability can typically be determined by the value of m_offset
     12        (this is invalidOffset if not cacheable).
     13
     14            * Internally, always track the type of the property using an enum value, PropertyType.
     15            * Use m_offset to indicate cacheable.
     16            * Keep the external interface (CachedPropertyType) unchanged.
     17            * Better pack data into the m_data union.
     18
     19        Performance neutral.
     20
     21        * dfg/DFGRepatch.cpp:
     22        (JSC::DFG::tryCacheGetByID):
     23        (JSC::DFG::tryBuildGetByIDList):
     24            - cachedPropertyType() -> isCacheable*()
     25        * jit/JITPropertyAccess.cpp:
     26        (JSC::JIT::privateCompileGetByIdProto):
     27        (JSC::JIT::privateCompileGetByIdSelfList):
     28        (JSC::JIT::privateCompileGetByIdProtoList):
     29        (JSC::JIT::privateCompileGetByIdChainList):
     30        (JSC::JIT::privateCompileGetByIdChain):
     31            - cachedPropertyType() -> isCacheable*()
     32        * jit/JITPropertyAccess32_64.cpp:
     33        (JSC::JIT::privateCompileGetByIdProto):
     34        (JSC::JIT::privateCompileGetByIdSelfList):
     35        (JSC::JIT::privateCompileGetByIdProtoList):
     36        (JSC::JIT::privateCompileGetByIdChainList):
     37        (JSC::JIT::privateCompileGetByIdChain):
     38            - cachedPropertyType() -> isCacheable*()
     39        * jit/JITStubs.cpp:
     40        (JSC::tryCacheGetByID):
     41            - cachedPropertyType() -> isCacheable*()
     42        * llint/LLIntSlowPaths.cpp:
     43        (JSC::LLInt::LLINT_SLOW_PATH_DECL):
     44            - cachedPropertyType() -> isCacheable*()
     45        * runtime/PropertySlot.cpp:
     46        (JSC::PropertySlot::functionGetter):
     47            - refactoring described above.
     48        * runtime/PropertySlot.h:
     49        (JSC::PropertySlot::PropertySlot):
     50        (JSC::PropertySlot::getValue):
     51        (JSC::PropertySlot::isCacheable):
     52        (JSC::PropertySlot::isCacheableValue):
     53        (JSC::PropertySlot::isCacheableGetter):
     54        (JSC::PropertySlot::isCacheableCustom):
     55        (JSC::PropertySlot::cachedOffset):
     56        (JSC::PropertySlot::customGetter):
     57        (JSC::PropertySlot::setValue):
     58        (JSC::PropertySlot::setCustom):
     59        (JSC::PropertySlot::setCacheableCustom):
     60        (JSC::PropertySlot::setCustomIndex):
     61        (JSC::PropertySlot::setGetterSlot):
     62        (JSC::PropertySlot::setCacheableGetterSlot):
     63        (JSC::PropertySlot::setUndefined):
     64        (JSC::PropertySlot::slotBase):
     65        (JSC::PropertySlot::setBase):
     66            - refactoring described above.
     67
    1682013-07-28  Oliver Hunt  <oliver@apple.com>
    269
  • trunk/Source/JavaScriptCore/dfg/DFGRepatch.cpp

    r153381 r153454  
    325325    // Optimize self access.
    326326    if (slot.slotBase() == baseValue) {
    327         if ((slot.cachedPropertyType() != PropertySlot::Value)
     327        if (!slot.isCacheableValue()
    328328            || !MacroAssembler::isCompactPtrAlignedAddressOffset(maxOffsetRelativeToPatchedStorage(slot.cachedOffset()))) {
    329329            dfgRepatchCall(codeBlock, stubInfo.callReturnLocation, operationGetByIdBuildList);
     
    340340   
    341341    // FIXME: optimize getters and setters
    342     if (slot.cachedPropertyType() != PropertySlot::Value)
     342    if (!slot.isCacheableValue())
    343343        return false;
    344344   
     
    439439            // non-Value cached properties require planting calls, which requires registers to have been flushed. Thus,
    440440            // if registers were not flushed, don't do non-Value caching.
    441             if (slot.cachedPropertyType() != PropertySlot::Value)
     441            if (!slot.isCacheableValue())
    442442                return false;
    443443        }
     
    476476        MacroAssembler::Jump success;
    477477       
    478         if (slot.cachedPropertyType() == PropertySlot::Getter
    479             || slot.cachedPropertyType() == PropertySlot::Custom) {
    480             if (slot.cachedPropertyType() == PropertySlot::Getter) {
     478        if (slot.isCacheableGetter() || slot.isCacheableCustom()) {
     479            if (slot.isCacheableGetter()) {
    481480                ASSERT(scratchGPR != InvalidGPRReg);
    482481                ASSERT(baseGPR != scratchGPR);
     
    568567                *vm,
    569568                codeBlock->ownerExecutable(),
    570                 slot.cachedPropertyType() == PropertySlot::Getter
    571                 || slot.cachedPropertyType() == PropertySlot::Custom);
     569                slot.isCacheableGetter() || slot.isCacheableCustom());
    572570       
    573571        polymorphicStructureList->list[listIndex].set(*vm, codeBlock->ownerExecutable(), stubRoutine, structure, isDirect);
     
    577575    }
    578576   
    579     if (baseValue.asCell()->structure()->typeInfo().prohibitsPropertyCaching()
    580         || slot.cachedPropertyType() != PropertySlot::Value)
     577    if (baseValue.asCell()->structure()->typeInfo().prohibitsPropertyCaching() || !slot.isCacheableValue())
    581578        return false;
    582579
  • trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp

    r153231 r153454  
    857857   
    858858    // Checks out okay!
    859     if (slot.cachedPropertyType() == PropertySlot::Getter) {
     859    if (slot.isCacheableGetter()) {
    860860        needsStubLink = true;
    861861        compileGetDirectOffset(protoObject, regT1, cachedOffset);
     
    865865        stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress()));
    866866        stubCall.call();
    867     } else if (slot.cachedPropertyType() == PropertySlot::Custom) {
     867    } else if (slot.isCacheableCustom()) {
    868868        needsStubLink = true;
    869869        JITStubCall stubCall(this, cti_op_get_by_id_custom_stub);
     
    918918    bool needsStubLink = false;
    919919    bool isDirect = false;
    920     if (slot.cachedPropertyType() == PropertySlot::Getter) {
     920    if (slot.isCacheableGetter()) {
    921921        needsStubLink = true;
    922922        compileGetDirectOffset(regT0, regT1, cachedOffset);
     
    926926        stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress()));
    927927        stubCall.call();
    928     } else if (slot.cachedPropertyType() == PropertySlot::Custom) {
     928    } else if (slot.isCacheableCustom()) {
    929929        needsStubLink = true;
    930930        JITStubCall stubCall(this, cti_op_get_by_id_custom_stub);
     
    992992    bool needsStubLink = false;
    993993    bool isDirect = false;
    994     if (slot.cachedPropertyType() == PropertySlot::Getter) {
     994    if (slot.isCacheableGetter()) {
    995995        needsStubLink = true;
    996996        compileGetDirectOffset(protoObject, regT1, cachedOffset);
     
    10001000        stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress()));
    10011001        stubCall.call();
    1002     } else if (slot.cachedPropertyType() == PropertySlot::Custom) {
     1002    } else if (slot.isCacheableCustom()) {
    10031003        needsStubLink = true;
    10041004        JITStubCall stubCall(this, cti_op_get_by_id_custom_stub);
     
    10711071    bool needsStubLink = false;
    10721072    bool isDirect = false;
    1073     if (slot.cachedPropertyType() == PropertySlot::Getter) {
     1073    if (slot.isCacheableGetter()) {
    10741074        needsStubLink = true;
    10751075        compileGetDirectOffset(protoObject, regT1, cachedOffset);
     
    10791079        stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress()));
    10801080        stubCall.call();
    1081     } else if (slot.cachedPropertyType() == PropertySlot::Custom) {
     1081    } else if (slot.isCacheableCustom()) {
    10821082        needsStubLink = true;
    10831083        JITStubCall stubCall(this, cti_op_get_by_id_custom_stub);
     
    11491149
    11501150    bool needsStubLink = false;
    1151     if (slot.cachedPropertyType() == PropertySlot::Getter) {
     1151    if (slot.isCacheableGetter()) {
    11521152        needsStubLink = true;
    11531153        compileGetDirectOffset(protoObject, regT1, cachedOffset);
     
    11571157        stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress()));
    11581158        stubCall.call();
    1159     } else if (slot.cachedPropertyType() == PropertySlot::Custom) {
     1159    } else if (slot.isCacheableCustom()) {
    11601160        needsStubLink = true;
    11611161        JITStubCall stubCall(this, cti_op_get_by_id_custom_stub);
  • trunk/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp

    r153231 r153454  
    819819    bool needsStubLink = false;
    820820    // Checks out okay!
    821     if (slot.cachedPropertyType() == PropertySlot::Getter) {
     821    if (slot.isCacheableGetter()) {
    822822        needsStubLink = true;
    823823        compileGetDirectOffset(protoObject, regT2, regT1, cachedOffset);
     
    827827        stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress()));
    828828        stubCall.call();
    829     } else if (slot.cachedPropertyType() == PropertySlot::Custom) {
     829    } else if (slot.isCacheableCustom()) {
    830830        needsStubLink = true;
    831831        JITStubCall stubCall(this, cti_op_get_by_id_custom_stub);
     
    885885    bool needsStubLink = false;
    886886    bool isDirect = false;
    887     if (slot.cachedPropertyType() == PropertySlot::Getter) {
     887    if (slot.isCacheableGetter()) {
    888888        needsStubLink = true;
    889889        compileGetDirectOffset(regT0, regT2, regT1, cachedOffset);
     
    893893        stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress()));
    894894        stubCall.call();
    895     } else if (slot.cachedPropertyType() == PropertySlot::Custom) {
     895    } else if (slot.isCacheableCustom()) {
    896896        needsStubLink = true;
    897897        JITStubCall stubCall(this, cti_op_get_by_id_custom_stub);
     
    959959    bool needsStubLink = false;
    960960    bool isDirect = false;
    961     if (slot.cachedPropertyType() == PropertySlot::Getter) {
     961    if (slot.isCacheableGetter()) {
    962962        needsStubLink = true;
    963963        compileGetDirectOffset(protoObject, regT2, regT1, cachedOffset);
     
    967967        stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress()));
    968968        stubCall.call();
    969     } else if (slot.cachedPropertyType() == PropertySlot::Custom) {
     969    } else if (slot.isCacheableCustom()) {
    970970        needsStubLink = true;
    971971        JITStubCall stubCall(this, cti_op_get_by_id_custom_stub);
     
    10381038    bool needsStubLink = false;
    10391039    bool isDirect = false;
    1040     if (slot.cachedPropertyType() == PropertySlot::Getter) {
     1040    if (slot.isCacheableGetter()) {
    10411041        needsStubLink = true;
    10421042        compileGetDirectOffset(protoObject, regT2, regT1, cachedOffset);
     
    10461046        stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress()));
    10471047        stubCall.call();
    1048     } else if (slot.cachedPropertyType() == PropertySlot::Custom) {
     1048    } else if (slot.isCacheableCustom()) {
    10491049        needsStubLink = true;
    10501050        JITStubCall stubCall(this, cti_op_get_by_id_custom_stub);
     
    11161116   
    11171117    bool needsStubLink = false;
    1118     if (slot.cachedPropertyType() == PropertySlot::Getter) {
     1118    if (slot.isCacheableGetter()) {
    11191119        needsStubLink = true;
    11201120        compileGetDirectOffset(protoObject, regT2, regT1, cachedOffset);
     
    11241124        stubCall.addArgument(TrustedImmPtr(stubInfo->callReturnLocation.executableAddress()));
    11251125        stubCall.call();
    1126     } else if (slot.cachedPropertyType() == PropertySlot::Custom) {
     1126    } else if (slot.isCacheableCustom()) {
    11271127        needsStubLink = true;
    11281128        JITStubCall stubCall(this, cti_op_get_by_id_custom_stub);
  • trunk/Source/JavaScriptCore/jit/JITStubs.cpp

    r153237 r153454  
    221221    if (slot.slotBase() == baseValue) {
    222222        RELEASE_ASSERT(stubInfo->accessType == access_unset);
    223         if ((slot.cachedPropertyType() != PropertySlot::Value)
    224             || !MacroAssembler::isCompactPtrAlignedAddressOffset(maxOffsetRelativeToPatchedStorage(slot.cachedOffset())))
     223        if (!slot.isCacheableValue() || !MacroAssembler::isCompactPtrAlignedAddressOffset(maxOffsetRelativeToPatchedStorage(slot.cachedOffset())))
    225224            ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_self_fail));
    226225        else {
     
    256255        }
    257256       
    258         stubInfo->initGetByIdProto(callFrame->vm(), codeBlock->ownerExecutable(), structure, slotBaseObject->structure(), slot.cachedPropertyType() == PropertySlot::Value);
     257        stubInfo->initGetByIdProto(callFrame->vm(), codeBlock->ownerExecutable(), structure, slotBaseObject->structure(), slot.isCacheableValue());
    259258
    260259        ASSERT(!structure->isDictionary());
     
    273272
    274273    StructureChain* prototypeChain = structure->prototypeChain(callFrame);
    275     stubInfo->initGetByIdChain(callFrame->vm(), codeBlock->ownerExecutable(), structure, prototypeChain, count, slot.cachedPropertyType() == PropertySlot::Value);
     274    stubInfo->initGetByIdChain(callFrame->vm(), codeBlock->ownerExecutable(), structure, prototypeChain, count, slot.isCacheableValue());
    276275    JIT::compileGetByIdChain(callFrame->scope()->vm(), callFrame, codeBlock, stubInfo, structure, prototypeChain, count, propertyName, slot, offset, returnAddress);
    277276}
  • trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp

    r153360 r153454  
    516516        && slot.isCacheable()
    517517        && slot.slotBase() == baseValue
    518         && slot.cachedPropertyType() == PropertySlot::Value) {
     518        && slot.isCacheableValue()) {
    519519       
    520520        JSCell* baseCell = baseValue.asCell();
  • trunk/Source/JavaScriptCore/runtime/PropertySlot.cpp

    r153145 r153454  
    2929JSValue PropertySlot::functionGetter(ExecState* exec) const
    3030{
    31     return callGetter(exec, m_thisValue, m_data.getterSetter);
     31    return callGetter(exec, JSValue::decode(m_data.getter.thisValue), m_data.getter.getterSetter);
    3232}
    3333
  • trunk/Source/JavaScriptCore/runtime/PropertySlot.h

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