Changeset 55002 in webkit


Ignore:
Timestamp:
Feb 18, 2010 10:23:25 PM (14 years ago)
Author:
oliver@apple.com
Message:

2010-02-18 Oliver Hunt <oliver@apple.com>

Reviewed by Gavin Barraclough.

Improve interpreter getter performance
https://bugs.webkit.org/show_bug.cgi?id=35138

Improve the performance of getter dispatch by making it possible
for the interpreter to cache the GetterSetter object lookup.

To do this we simply need to make PropertySlot aware of getters
as a potentially cacheable property, and record the base and this
objects for a getter access. This allows us to use more-or-less
identical code to that used by the normal get_by_id caching, with
the dispatch being the only actual difference.

I'm holding off of implementing this in the JIT until I do some
cleanup to try and making coding in the JIT not be as horrible
as it is currently.

  • bytecode/CodeBlock.cpp: (JSC::CodeBlock::dump): (JSC::CodeBlock::derefStructures): (JSC::CodeBlock::refStructures):
  • bytecode/Opcode.h:
  • interpreter/Interpreter.cpp: (JSC::Interpreter::resolveGlobal): (JSC::Interpreter::tryCacheGetByID): (JSC::Interpreter::privateExecute):
  • jit/JIT.cpp: (JSC::JIT::privateCompileMainPass):
  • jit/JITStubs.cpp: (JSC::JITThunks::tryCacheGetByID): (JSC::DEFINE_STUB_FUNCTION):
  • runtime/JSObject.cpp: (JSC::JSObject::fillGetterPropertySlot):
  • runtime/PropertySlot.cpp: (JSC::PropertySlot::functionGetter):
  • runtime/PropertySlot.h: (JSC::PropertySlot::isGetter): (JSC::PropertySlot::isCacheable): (JSC::PropertySlot::isCacheableValue): (JSC::PropertySlot::setValueSlot): (JSC::PropertySlot::setGetterSlot): (JSC::PropertySlot::setCacheableGetterSlot): (JSC::PropertySlot::clearOffset): (JSC::PropertySlot::thisValue):
Location:
trunk/JavaScriptCore
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/ChangeLog

    r54988 r55002  
     12010-02-18  Oliver Hunt  <oliver@apple.com>
     2
     3        Reviewed by Gavin Barraclough.
     4
     5        Improve interpreter getter performance
     6        https://bugs.webkit.org/show_bug.cgi?id=35138
     7
     8        Improve the performance of getter dispatch by making it possible
     9        for the interpreter to cache the GetterSetter object lookup.
     10
     11        To do this we simply need to make PropertySlot aware of getters
     12        as a potentially cacheable property, and record the base and this
     13        objects for a getter access.  This allows us to use more-or-less
     14        identical code to that used by the normal get_by_id caching, with
     15        the dispatch being the only actual difference.
     16
     17        I'm holding off of implementing this in the JIT until I do some
     18        cleanup to try and making coding in the JIT not be as horrible
     19        as it is currently.
     20
     21        * bytecode/CodeBlock.cpp:
     22        (JSC::CodeBlock::dump):
     23        (JSC::CodeBlock::derefStructures):
     24        (JSC::CodeBlock::refStructures):
     25        * bytecode/Opcode.h:
     26        * interpreter/Interpreter.cpp:
     27        (JSC::Interpreter::resolveGlobal):
     28        (JSC::Interpreter::tryCacheGetByID):
     29        (JSC::Interpreter::privateExecute):
     30        * jit/JIT.cpp:
     31        (JSC::JIT::privateCompileMainPass):
     32        * jit/JITStubs.cpp:
     33        (JSC::JITThunks::tryCacheGetByID):
     34        (JSC::DEFINE_STUB_FUNCTION):
     35        * runtime/JSObject.cpp:
     36        (JSC::JSObject::fillGetterPropertySlot):
     37        * runtime/PropertySlot.cpp:
     38        (JSC::PropertySlot::functionGetter):
     39        * runtime/PropertySlot.h:
     40        (JSC::PropertySlot::isGetter):
     41        (JSC::PropertySlot::isCacheable):
     42        (JSC::PropertySlot::isCacheableValue):
     43        (JSC::PropertySlot::setValueSlot):
     44        (JSC::PropertySlot::setGetterSlot):
     45        (JSC::PropertySlot::setCacheableGetterSlot):
     46        (JSC::PropertySlot::clearOffset):
     47        (JSC::PropertySlot::thisValue):
     48
    1492010-02-17  Geoffrey Garen  <ggaren@apple.com>
    250
  • trunk/JavaScriptCore/bytecode/CodeBlock.cpp

    r54789 r55002  
    766766            break;
    767767        }
     768        case op_get_by_id_getter_self: {
     769            printGetByIdOp(exec, location, it, "get_by_id_getter_self");
     770            break;
     771        }
     772        case op_get_by_id_getter_self_list: {
     773            printGetByIdOp(exec, location, it, "get_by_id_getter_self_list");
     774            break;
     775        }
     776        case op_get_by_id_getter_proto: {
     777            printGetByIdOp(exec, location, it, "get_by_id_getter_proto");
     778            break;
     779        }
     780        case op_get_by_id_getter_proto_list: {
     781            printGetByIdOp(exec, location, it, "get_by_id_getter_proto_list");
     782            break;
     783        }
     784        case op_get_by_id_getter_chain: {
     785            printGetByIdOp(exec, location, it, "get_by_id_getter_chain");
     786            break;
     787        }
    768788        case op_get_by_id_generic: {
    769789            printGetByIdOp(exec, location, it, "get_by_id_generic");
     
    13561376    Interpreter* interpreter = m_globalData->interpreter;
    13571377
    1358     if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self)) {
     1378    if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_self)) {
    13591379        vPC[4].u.structure->deref();
    13601380        return;
    13611381    }
    1362     if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto)) {
     1382    if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_proto)) {
    13631383        vPC[4].u.structure->deref();
    13641384        vPC[5].u.structure->deref();
    13651385        return;
    13661386    }
    1367     if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain)) {
     1387    if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_chain)) {
    13681388        vPC[4].u.structure->deref();
    13691389        vPC[5].u.structureChain->deref();
     
    13861406    }
    13871407    if ((vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto_list))
    1388         || (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self_list))) {
     1408        || (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self_list))
     1409        || (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_proto_list))
     1410        || (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_self_list))) {
    13891411        PolymorphicAccessStructureList* polymorphicStructures = vPC[4].u.polymorphicStructures;
    13901412        polymorphicStructures->derefStructures(vPC[5].u.operand);
     
    14011423    Interpreter* interpreter = m_globalData->interpreter;
    14021424
    1403     if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self)) {
     1425    if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_self)) {
    14041426        vPC[4].u.structure->ref();
    14051427        return;
    14061428    }
    1407     if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto)) {
     1429    if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_proto)) {
    14081430        vPC[4].u.structure->ref();
    14091431        vPC[5].u.structure->ref();
    14101432        return;
    14111433    }
    1412     if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain)) {
     1434    if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_chain)) {
    14131435        vPC[4].u.structure->ref();
    14141436        vPC[5].u.structureChain->ref();
  • trunk/JavaScriptCore/bytecode/Opcode.h

    r53891 r55002  
    105105        macro(op_get_by_id_proto_list, 8) \
    106106        macro(op_get_by_id_chain, 8) \
     107        macro(op_get_by_id_getter_self, 8) \
     108        macro(op_get_by_id_getter_self_list, 8) \
     109        macro(op_get_by_id_getter_proto, 8) \
     110        macro(op_get_by_id_getter_proto_list, 8) \
     111        macro(op_get_by_id_getter_chain, 8) \
    107112        macro(op_get_by_id_generic, 8) \
    108113        macro(op_get_array_length, 8) \
  • trunk/JavaScriptCore/interpreter/Interpreter.cpp

    r54843 r55002  
    4141#include "EvalCodeCache.h"
    4242#include "ExceptionHelpers.h"
     43#include "GetterSetter.h"
    4344#include "GlobalEvalFunction.h"
    4445#include "JSActivation.h"
     
    170171    if (globalObject->getPropertySlot(callFrame, ident, slot)) {
    171172        JSValue result = slot.getValue(callFrame, ident);
    172         if (slot.isCacheable() && !globalObject->structure()->isUncacheableDictionary() && slot.slotBase() == globalObject) {
     173        if (slot.isCacheableValue() && !globalObject->structure()->isUncacheableDictionary() && slot.slotBase() == globalObject) {
    173174            if (vPC[4].u.structure)
    174175                vPC[4].u.structure->deref();
     
    10301031
    10311032    if (slot.slotBase() == baseValue) {
    1032         vPC[0] = getOpcode(op_get_by_id_self);
     1033        vPC[0] = slot.isGetter() ? getOpcode(op_get_by_id_getter_self) : getOpcode(op_get_by_id_self);
    10331034        vPC[5] = slot.cachedOffset();
    10341035
     
    10571058        ASSERT(!baseObject->structure()->isUncacheableDictionary());
    10581059
    1059         vPC[0] = getOpcode(op_get_by_id_proto);
     1060        vPC[0] = slot.isGetter() ? getOpcode(op_get_by_id_getter_proto) : getOpcode(op_get_by_id_proto);
    10601061        vPC[5] = baseObject->structure();
    10611062        vPC[6] = offset;
     
    10721073    }
    10731074
    1074     vPC[0] = getOpcode(op_get_by_id_chain);
     1075    vPC[0] = slot.isGetter() ? getOpcode(op_get_by_id_getter_chain) : getOpcode(op_get_by_id_chain);
    10751076    vPC[4] = structure;
    10761077    vPC[5] = structure->prototypeChain(callFrame);
     
    21622163        NEXT_INSTRUCTION();
    21632164    }
     2165#if HAVE(COMPUTED_GOTO)
     2166    goto *(&&skip_id_getter_proto);
     2167#endif
     2168    DEFINE_OPCODE(op_get_by_id_getter_proto) {
     2169        /* op_get_by_id_getter_proto dst(r) base(r) property(id) structure(sID) prototypeStructure(sID) offset(n) nop(n)
     2170         
     2171         Cached property access: Attempts to get a cached getter property from the
     2172         value base's prototype. If the cache misses, op_get_by_id_getter_proto
     2173         reverts to op_get_by_id.
     2174         */
     2175        int base = vPC[2].u.operand;
     2176        JSValue baseValue = callFrame->r(base).jsValue();
     2177       
     2178        if (LIKELY(baseValue.isCell())) {
     2179            JSCell* baseCell = asCell(baseValue);
     2180            Structure* structure = vPC[4].u.structure;
     2181           
     2182            if (LIKELY(baseCell->structure() == structure)) {
     2183                ASSERT(structure->prototypeForLookup(callFrame).isObject());
     2184                JSObject* protoObject = asObject(structure->prototypeForLookup(callFrame));
     2185                Structure* prototypeStructure = vPC[5].u.structure;
     2186               
     2187                if (LIKELY(protoObject->structure() == prototypeStructure)) {
     2188                    int dst = vPC[1].u.operand;
     2189                    int offset = vPC[6].u.operand;
     2190                    if (GetterSetter* getterSetter = asGetterSetter(protoObject->getDirectOffset(offset).asCell())) {
     2191                        JSObject* getter = getterSetter->getter();
     2192                        CallData callData;
     2193                        CallType callType = getter->getCallData(callData);
     2194                        JSValue result = call(callFrame, getter, callType, callData, asObject(baseCell), ArgList());
     2195                        CHECK_FOR_EXCEPTION();
     2196                        callFrame->r(dst) = result;
     2197                    } else
     2198                        callFrame->r(dst) = jsUndefined();
     2199                    vPC += OPCODE_LENGTH(op_get_by_id_getter_proto);
     2200                    NEXT_INSTRUCTION();
     2201                }
     2202            }
     2203        }
     2204        uncacheGetByID(callFrame->codeBlock(), vPC);
     2205        NEXT_INSTRUCTION();
     2206    }
     2207#if HAVE(COMPUTED_GOTO)
     2208    skip_id_getter_proto:
     2209#endif
    21642210    DEFINE_OPCODE(op_get_by_id_self_list) {
    21652211        // Polymorphic self access caching currently only supported when JITting.
     
    21762222        NEXT_INSTRUCTION();
    21772223    }
     2224    DEFINE_OPCODE(op_get_by_id_getter_self_list) {
     2225        // Polymorphic self access caching currently only supported when JITting.
     2226        ASSERT_NOT_REACHED();
     2227        // This case of the switch must not be empty, else (op_get_by_id_self_list == op_get_by_id_chain)!
     2228        vPC += OPCODE_LENGTH(op_get_by_id_self_list);
     2229        NEXT_INSTRUCTION();
     2230    }
     2231    DEFINE_OPCODE(op_get_by_id_getter_proto_list) {
     2232        // Polymorphic prototype access caching currently only supported when JITting.
     2233        ASSERT_NOT_REACHED();
     2234        // This case of the switch must not be empty, else (op_get_by_id_proto_list == op_get_by_id_chain)!
     2235        vPC += OPCODE_LENGTH(op_get_by_id_proto_list);
     2236        NEXT_INSTRUCTION();
     2237    }
    21782238    DEFINE_OPCODE(op_get_by_id_chain) {
    21792239        /* op_get_by_id_chain dst(r) base(r) property(id) structure(sID) structureChain(chain) count(n) offset(n)
     
    22222282        NEXT_INSTRUCTION();
    22232283    }
     2284#if HAVE(COMPUTED_GOTO)
     2285    goto *(&&skip_id_getter_self);
     2286#endif
     2287    DEFINE_OPCODE(op_get_by_id_getter_self) {
     2288        /* op_get_by_id_self dst(r) base(r) property(id) structure(sID) offset(n) nop(n) nop(n)
     2289         
     2290         Cached property access: Attempts to get a cached property from the
     2291         value base. If the cache misses, op_get_by_id_getter_self reverts to
     2292         op_get_by_id.
     2293         */
     2294        int base = vPC[2].u.operand;
     2295        JSValue baseValue = callFrame->r(base).jsValue();
     2296       
     2297        if (LIKELY(baseValue.isCell())) {
     2298            JSCell* baseCell = asCell(baseValue);
     2299            Structure* structure = vPC[4].u.structure;
     2300           
     2301            if (LIKELY(baseCell->structure() == structure)) {
     2302                ASSERT(baseCell->isObject());
     2303                JSObject* baseObject = asObject(baseCell);
     2304                int dst = vPC[1].u.operand;
     2305                int offset = vPC[5].u.operand;
     2306
     2307                if (GetterSetter* getterSetter = asGetterSetter(baseObject->getDirectOffset(offset).asCell())) {
     2308                    JSObject* getter = getterSetter->getter();
     2309                    CallData callData;
     2310                    CallType callType = getter->getCallData(callData);
     2311                    JSValue result = call(callFrame, getter, callType, callData, baseObject, ArgList());
     2312                    CHECK_FOR_EXCEPTION();
     2313                    callFrame->r(dst) = result;
     2314                } else
     2315                    callFrame->r(dst) = jsUndefined();
     2316
     2317                vPC += OPCODE_LENGTH(op_get_by_id_getter_self);
     2318                NEXT_INSTRUCTION();
     2319            }
     2320        }
     2321        uncacheGetByID(callFrame->codeBlock(), vPC);
     2322        NEXT_INSTRUCTION();
     2323    }
     2324#if HAVE(COMPUTED_GOTO)
     2325    skip_id_getter_self:
     2326#endif
    22242327    DEFINE_OPCODE(op_get_by_id_generic) {
    22252328        /* op_get_by_id_generic dst(r) base(r) property(id) nop(sID) nop(n) nop(n) nop(n)
     
    22422345        NEXT_INSTRUCTION();
    22432346    }
     2347#if HAVE(COMPUTED_GOTO)
     2348    goto *(&&skip_id_getter_chain);
     2349#endif
     2350    DEFINE_OPCODE(op_get_by_id_getter_chain) {
     2351        /* op_get_by_id_getter_chain dst(r) base(r) property(id) structure(sID) structureChain(chain) count(n) offset(n)
     2352         
     2353         Cached property access: Attempts to get a cached property from the
     2354         value base's prototype chain. If the cache misses, op_get_by_id_getter_chain
     2355         reverts to op_get_by_id.
     2356         */
     2357        int base = vPC[2].u.operand;
     2358        JSValue baseValue = callFrame->r(base).jsValue();
     2359       
     2360        if (LIKELY(baseValue.isCell())) {
     2361            JSCell* baseCell = asCell(baseValue);
     2362            Structure* structure = vPC[4].u.structure;
     2363           
     2364            if (LIKELY(baseCell->structure() == structure)) {
     2365                RefPtr<Structure>* it = vPC[5].u.structureChain->head();
     2366                size_t count = vPC[6].u.operand;
     2367                RefPtr<Structure>* end = it + count;
     2368               
     2369                while (true) {
     2370                    JSObject* baseObject = asObject(baseCell->structure()->prototypeForLookup(callFrame));
     2371                   
     2372                    if (UNLIKELY(baseObject->structure() != (*it).get()))
     2373                        break;
     2374                   
     2375                    if (++it == end) {
     2376                        int dst = vPC[1].u.operand;
     2377                        int offset = vPC[7].u.operand;
     2378                        if (GetterSetter* getterSetter = asGetterSetter(baseObject->getDirectOffset(offset).asCell())) {
     2379                            JSObject* getter = getterSetter->getter();
     2380                            CallData callData;
     2381                            CallType callType = getter->getCallData(callData);
     2382                            JSValue result = call(callFrame, getter, callType, callData, asObject(baseCell), ArgList());
     2383                            CHECK_FOR_EXCEPTION();
     2384                            callFrame->r(dst) = result;
     2385                        } else
     2386                            callFrame->r(dst) = jsUndefined();
     2387                        vPC += OPCODE_LENGTH(op_get_by_id_getter_chain);
     2388                        NEXT_INSTRUCTION();
     2389                    }
     2390                   
     2391                    // Update baseCell, so that next time around the loop we'll pick up the prototype's prototype.
     2392                    baseCell = baseObject;
     2393                }
     2394            }
     2395        }
     2396        uncacheGetByID(callFrame->codeBlock(), vPC);
     2397        NEXT_INSTRUCTION();
     2398    }
     2399#if HAVE(COMPUTED_GOTO)
     2400    skip_id_getter_chain:
     2401#endif
    22442402    DEFINE_OPCODE(op_get_array_length) {
    22452403        /* op_get_array_length dst(r) base(r) property(id) nop(sID) nop(n) nop(n) nop(n)
  • trunk/JavaScriptCore/jit/JIT.cpp

    r54747 r55002  
    323323        case op_get_by_id_self:
    324324        case op_get_by_id_self_list:
     325        case op_get_by_id_getter_chain:
     326        case op_get_by_id_getter_proto:
     327        case op_get_by_id_getter_proto_list:
     328        case op_get_by_id_getter_self:
     329        case op_get_by_id_getter_self_list:
    325330        case op_get_string_length:
    326331        case op_put_by_id_generic:
  • trunk/JavaScriptCore/jit/JITStubs.cpp

    r54843 r55002  
    857857
    858858    // Uncacheable: give up.
    859     if (!slot.isCacheable()) {
     859    if (!slot.isCacheableValue()) {
    860860        ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_generic));
    861861        return;
    862862    }
     863    ASSERT(!slot.isGetter());
    863864
    864865    JSCell* baseCell = asCell(baseValue);
     
    12901291    // be an object.  (Assertion to ensure asObject() call below is safe, which comes after
    12911292    // an isCacheable() chceck.
    1292     ASSERT(!slot.isCacheable() || slot.slotBase().isObject());
     1293    ASSERT(!slot.isCacheableValue() || slot.slotBase().isObject());
    12931294
    12941295    // Check that:
     
    13011302    JSObject* slotBaseObject;
    13021303    if (baseValue.isCell()
    1303         && slot.isCacheable()
     1304        && slot.isCacheableValue()
    13041305        && !(structure = asCell(baseValue)->structure())->isUncacheableDictionary()
    13051306        && (slotBaseObject = asObject(slot.slotBase()))->getPropertySpecificValue(callFrame, ident, specific)
     
    13751376
    13761377    if (baseValue.isCell()
    1377         && slot.isCacheable()
     1378        && slot.isCacheableValue()
    13781379        && !asCell(baseValue)->structure()->isUncacheableDictionary()
    13791380        && slot.slotBase() == baseValue) {
     
    14481449    CHECK_FOR_EXCEPTION();
    14491450
    1450     if (!baseValue.isCell() || !slot.isCacheable() || asCell(baseValue)->structure()->isDictionary()) {
     1451    if (!baseValue.isCell() || !slot.isCacheableValue() || asCell(baseValue)->structure()->isDictionary()) {
    14511452        ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail));
    14521453        return JSValue::encode(result);
     
    23042305    if (globalObject->getPropertySlot(callFrame, ident, slot)) {
    23052306        JSValue result = slot.getValue(callFrame, ident);
    2306         if (slot.isCacheable() && !globalObject->structure()->isUncacheableDictionary() && slot.slotBase() == globalObject) {
     2307        if (slot.isCacheableValue() && !globalObject->structure()->isUncacheableDictionary() && slot.slotBase() == globalObject) {
    23072308            GlobalResolveInfo& globalResolveInfo = callFrame->codeBlock()->globalResolveInfo(globalResolveInfoIndex);
    23082309            if (globalResolveInfo.structure)
  • trunk/JavaScriptCore/runtime/JSObject.cpp

    r53170 r55002  
    517517NEVER_INLINE void JSObject::fillGetterPropertySlot(PropertySlot& slot, JSValue* location)
    518518{
    519     if (JSObject* getterFunction = asGetterSetter(*location)->getter())
    520         slot.setGetterSlot(getterFunction);
    521     else
     519    if (JSObject* getterFunction = asGetterSetter(*location)->getter()) {
     520        if (!structure()->isDictionary())
     521            slot.setCacheableGetterSlot(this, getterFunction, offsetForLocation(location));
     522        else
     523            slot.setGetterSlot(getterFunction);
     524    } else
    522525        slot.setUndefined();
    523526}
  • trunk/JavaScriptCore/runtime/PropertySlot.cpp

    r47236 r55002  
    3636    CallType callType = slot.m_data.getterFunc->getCallData(callData);
    3737    if (callType == CallTypeHost)
    38         return callData.native.function(exec, slot.m_data.getterFunc, slot.slotBase(), exec->emptyList());
     38        return callData.native.function(exec, slot.m_data.getterFunc, slot.thisValue(), exec->emptyList());
    3939    ASSERT(callType == CallTypeJS);
    4040    // FIXME: Can this be done more efficiently using the callData?
    41     return asFunction(slot.m_data.getterFunc)->call(exec, slot.slotBase(), exec->emptyList());
     41    return asFunction(slot.m_data.getterFunc)->call(exec, slot.thisValue(), exec->emptyList());
    4242}
    4343
  • trunk/JavaScriptCore/runtime/PropertySlot.h

    r46598 r55002  
    7272        }
    7373
    74         bool isCacheable() const { return m_offset != WTF::notFound; }
     74        bool isGetter() const { return m_isGetter; }
     75        bool isCacheable() const { return m_isCacheable; }
     76        bool isCacheableValue() const { return m_isCacheable && !m_isGetter; }
    7577        size_t cachedOffset() const
    7678        {
     
    103105            m_data.valueSlot = valueSlot;
    104106            m_offset = offset;
     107            m_isCacheable = true;
     108            m_isGetter = false;
    105109        }
    106110       
     
    140144            m_data.index = index;
    141145        }
    142        
     146
    143147        void setGetterSlot(JSObject* getterFunc)
     148        {
     149            ASSERT(getterFunc);
     150            m_thisValue = m_slotBase;
     151            m_getValue = functionGetter;
     152            m_data.getterFunc = getterFunc;
     153            m_isGetter = true;
     154        }
     155
     156        void setCacheableGetterSlot(JSValue slotBase, JSObject* getterFunc, unsigned offset)
    144157        {
    145158            ASSERT(getterFunc);
    146159            m_getValue = functionGetter;
     160            m_thisValue = m_slotBase;
     161            m_slotBase = slotBase;
    147162            m_data.getterFunc = getterFunc;
    148         }
    149        
     163            m_offset = offset;
     164            m_isCacheable = true;
     165            m_isGetter = true;
     166        }
     167
    150168        void setUndefined()
    151169        {
     
    183201            // Clear offset even in release builds, in case this PropertySlot has been used before.
    184202            // (For other data members, we don't need to clear anything because reuse would meaningfully overwrite them.)
    185             m_offset = WTF::notFound;
     203            m_offset = 0;
     204            m_isCacheable = false;
     205            m_isGetter = false;
    186206        }
    187207
    188208        unsigned index() const { return m_data.index; }
    189209
     210        JSValue thisValue() const { return m_thisValue; }
    190211    private:
    191212        static JSValue functionGetter(ExecState*, const Identifier&, const PropertySlot&);
     
    202223
    203224        JSValue m_value;
     225        JSValue m_thisValue;
    204226
    205227        size_t m_offset;
     228        bool m_isCacheable : 1;
     229        bool m_isGetter : 1;
    206230    };
    207231
Note: See TracChangeset for help on using the changeset viewer.