Changeset 55564 in webkit


Ignore:
Timestamp:
Mar 4, 2010 5:33:54 PM (14 years ago)
Author:
oliver@apple.com
Message:

2010-03-03 Oliver Hunt <oliver@apple.com>

Reviewed by Gavin Barraclough.

Allow static property getters to interact with JSCs caching
https://bugs.webkit.org/show_bug.cgi?id=35716

Add new opcodes for handling cached lookup of static value getters.
More or less the same as with JS getters, all that changes is that
instead of calling through a JSFunction we always know that we have
a C function to call.

For the patching routines in the JIT we now need to pass a few
new parameters to allow us to pass enough information to the stub
function to allow us to call the C function correctly. Logically
this shouldn't actually be necessary as all of these functions ignore
the identifier, but removing the ident parameter would require
somewhat involved changes to the way we implement getOwnPropertySlot,
etc.

  • bytecode/CodeBlock.cpp: (JSC::CodeBlock::dump): (JSC::CodeBlock::derefStructures): (JSC::CodeBlock::refStructures):
  • bytecode/Instruction.h: (JSC::Instruction::Instruction): (JSC::Instruction::):
  • bytecode/Opcode.h:
  • interpreter/Interpreter.cpp: (JSC::Interpreter::tryCacheGetByID): (JSC::Interpreter::privateExecute):
  • jit/JIT.cpp: (JSC::JIT::privateCompileMainPass):
  • jit/JIT.h: (JSC::JIT::compileGetByIdProto): (JSC::JIT::compileGetByIdSelfList): (JSC::JIT::compileGetByIdProtoList): (JSC::JIT::compileGetByIdChainList): (JSC::JIT::compileGetByIdChain):
  • jit/JITPropertyAccess.cpp: (JSC::JIT::privateCompileGetByIdProto): (JSC::JIT::privateCompileGetByIdSelfList): (JSC::JIT::privateCompileGetByIdProtoList): (JSC::JIT::privateCompileGetByIdChainList): (JSC::JIT::privateCompileGetByIdChain):
  • jit/JITPropertyAccess32_64.cpp: (JSC::JIT::privateCompileGetByIdProto): (JSC::JIT::privateCompileGetByIdSelfList): (JSC::JIT::privateCompileGetByIdProtoList): (JSC::JIT::privateCompileGetByIdChainList): (JSC::JIT::privateCompileGetByIdChain):
  • jit/JITStubs.cpp: (JSC::JITThunks::tryCacheGetByID): (JSC::DEFINE_STUB_FUNCTION):
  • jit/JITStubs.h: (JSC::):
  • runtime/JSFunction.cpp: (JSC::JSFunction::getOwnPropertySlot):
  • runtime/Lookup.h: (JSC::getStaticPropertySlot): (JSC::getStaticValueSlot):
  • runtime/PropertySlot.h: (JSC::PropertySlot::): (JSC::PropertySlot::PropertySlot): (JSC::PropertySlot::cachedPropertyType): (JSC::PropertySlot::isCacheable): (JSC::PropertySlot::isCacheableValue): (JSC::PropertySlot::setValueSlot): (JSC::PropertySlot::setCacheableCustom): (JSC::PropertySlot::setGetterSlot): (JSC::PropertySlot::setCacheableGetterSlot): (JSC::PropertySlot::clearOffset): (JSC::PropertySlot::customGetter):

2010-03-03 Oliver Hunt <oliver@apple.com>

Reviewed by Gavin Barraclough.

Allow static property getters to interact with JSCs caching
https://bugs.webkit.org/show_bug.cgi?id=35716

Add tests to ensure nothing horrifying happens to static property
getters if they're in a path where we end up caching lookups.

  • fast/js/pic/cached-named-property-getter-expected.txt: Added.
  • fast/js/pic/cached-named-property-getter.html: Added.

2010-03-03 Oliver Hunt <oliver@apple.com>

Reviewed by Gavin Barraclough.

Allow static property getters to interact with JSCs caching
https://bugs.webkit.org/show_bug.cgi?id=35716

Update the obviously safe getters to allow caching

Test: fast/js/pic/cached-named-property-getter.html

  • bridge/runtime_array.cpp: (JSC::RuntimeArray::getOwnPropertySlot):
  • bridge/runtime_method.cpp: (JSC::RuntimeMethod::getOwnPropertySlot):
Location:
trunk
Files:
2 added
18 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/ChangeLog

    r55521 r55564  
     12010-03-03  Oliver Hunt  <oliver@apple.com>
     2
     3        Reviewed by Gavin Barraclough.
     4
     5        Allow static property getters to interact with JSCs caching
     6        https://bugs.webkit.org/show_bug.cgi?id=35716
     7
     8        Add new opcodes for handling cached lookup of static value getters.
     9        More or less the same as with JS getters, all that changes is that
     10        instead of calling through a JSFunction we always know that we have
     11        a C function to call.
     12
     13        For the patching routines in the JIT we now need to pass a few
     14        new parameters to allow us to pass enough information to the stub
     15        function to allow us to call the C function correctly.  Logically
     16        this shouldn't actually be necessary as all of these functions ignore
     17        the identifier, but removing the ident parameter would require
     18        somewhat involved changes to the way we implement getOwnPropertySlot,
     19        etc.
     20
     21        * bytecode/CodeBlock.cpp:
     22        (JSC::CodeBlock::dump):
     23        (JSC::CodeBlock::derefStructures):
     24        (JSC::CodeBlock::refStructures):
     25        * bytecode/Instruction.h:
     26        (JSC::Instruction::Instruction):
     27        (JSC::Instruction::):
     28        * bytecode/Opcode.h:
     29        * interpreter/Interpreter.cpp:
     30        (JSC::Interpreter::tryCacheGetByID):
     31        (JSC::Interpreter::privateExecute):
     32        * jit/JIT.cpp:
     33        (JSC::JIT::privateCompileMainPass):
     34        * jit/JIT.h:
     35        (JSC::JIT::compileGetByIdProto):
     36        (JSC::JIT::compileGetByIdSelfList):
     37        (JSC::JIT::compileGetByIdProtoList):
     38        (JSC::JIT::compileGetByIdChainList):
     39        (JSC::JIT::compileGetByIdChain):
     40        * jit/JITPropertyAccess.cpp:
     41        (JSC::JIT::privateCompileGetByIdProto):
     42        (JSC::JIT::privateCompileGetByIdSelfList):
     43        (JSC::JIT::privateCompileGetByIdProtoList):
     44        (JSC::JIT::privateCompileGetByIdChainList):
     45        (JSC::JIT::privateCompileGetByIdChain):
     46        * jit/JITPropertyAccess32_64.cpp:
     47        (JSC::JIT::privateCompileGetByIdProto):
     48        (JSC::JIT::privateCompileGetByIdSelfList):
     49        (JSC::JIT::privateCompileGetByIdProtoList):
     50        (JSC::JIT::privateCompileGetByIdChainList):
     51        (JSC::JIT::privateCompileGetByIdChain):
     52        * jit/JITStubs.cpp:
     53        (JSC::JITThunks::tryCacheGetByID):
     54        (JSC::DEFINE_STUB_FUNCTION):
     55        * jit/JITStubs.h:
     56        (JSC::):
     57        * runtime/JSFunction.cpp:
     58        (JSC::JSFunction::getOwnPropertySlot):
     59        * runtime/Lookup.h:
     60        (JSC::getStaticPropertySlot):
     61        (JSC::getStaticValueSlot):
     62        * runtime/PropertySlot.h:
     63        (JSC::PropertySlot::):
     64        (JSC::PropertySlot::PropertySlot):
     65        (JSC::PropertySlot::cachedPropertyType):
     66        (JSC::PropertySlot::isCacheable):
     67        (JSC::PropertySlot::isCacheableValue):
     68        (JSC::PropertySlot::setValueSlot):
     69        (JSC::PropertySlot::setCacheableCustom):
     70        (JSC::PropertySlot::setGetterSlot):
     71        (JSC::PropertySlot::setCacheableGetterSlot):
     72        (JSC::PropertySlot::clearOffset):
     73        (JSC::PropertySlot::customGetter):
     74
    1752010-03-04  Shinichiro Hamaji  <hamaji@chromium.org>
    276
  • trunk/JavaScriptCore/bytecode/CodeBlock.cpp

    r55002 r55564  
    786786            break;
    787787        }
     788        case op_get_by_id_custom_self: {
     789            printGetByIdOp(exec, location, it, "get_by_id_custom_self");
     790            break;
     791        }
     792        case op_get_by_id_custom_self_list: {
     793            printGetByIdOp(exec, location, it, "get_by_id_custom_self_list");
     794            break;
     795        }
     796        case op_get_by_id_custom_proto: {
     797            printGetByIdOp(exec, location, it, "get_by_id_custom_proto");
     798            break;
     799        }
     800        case op_get_by_id_custom_proto_list: {
     801            printGetByIdOp(exec, location, it, "get_by_id_custom_proto_list");
     802            break;
     803        }
     804        case op_get_by_id_custom_chain: {
     805            printGetByIdOp(exec, location, it, "get_by_id_custom_chain");
     806            break;
     807        }
    788808        case op_get_by_id_generic: {
    789809            printGetByIdOp(exec, location, it, "get_by_id_generic");
     
    13761396    Interpreter* interpreter = m_globalData->interpreter;
    13771397
    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)) {
     1398    if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_self) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_custom_self)) {
    13791399        vPC[4].u.structure->deref();
    13801400        return;
     
    14231443    Interpreter* interpreter = m_globalData->interpreter;
    14241444
    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)) {
     1445    if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_self) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_custom_self)) {
    14261446        vPC[4].u.structure->ref();
    14271447        return;
  • trunk/JavaScriptCore/bytecode/Instruction.h

    r46854 r55564  
    3232#include "MacroAssembler.h"
    3333#include "Opcode.h"
     34#include "PropertySlot.h"
    3435#include "Structure.h"
    3536#include <wtf/VectorTraits.h>
     
    145146        Instruction(JSCell* jsCell) { u.jsCell = jsCell; }
    146147        Instruction(PolymorphicAccessStructureList* polymorphicStructures) { u.polymorphicStructures = polymorphicStructures; }
     148        Instruction(PropertySlot::GetValueFunc getterFunc) { u.getterFunc = getterFunc; }
    147149
    148150        union {
     
    153155            JSCell* jsCell;
    154156            PolymorphicAccessStructureList* polymorphicStructures;
     157            PropertySlot::GetValueFunc getterFunc;
    155158        } u;
    156159    };
  • trunk/JavaScriptCore/bytecode/Opcode.h

    r55002 r55564  
    110110        macro(op_get_by_id_getter_proto_list, 8) \
    111111        macro(op_get_by_id_getter_chain, 8) \
     112        macro(op_get_by_id_custom_self, 8) \
     113        macro(op_get_by_id_custom_self_list, 8) \
     114        macro(op_get_by_id_custom_proto, 8) \
     115        macro(op_get_by_id_custom_proto_list, 8) \
     116        macro(op_get_by_id_custom_chain, 8) \
    112117        macro(op_get_by_id_generic, 8) \
    113118        macro(op_get_array_length, 8) \
  • trunk/JavaScriptCore/interpreter/Interpreter.cpp

    r55181 r55564  
    10311031
    10321032    if (slot.slotBase() == baseValue) {
    1033         vPC[0] = slot.isGetter() ? getOpcode(op_get_by_id_getter_self) : getOpcode(op_get_by_id_self);
    1034         vPC[5] = slot.cachedOffset();
     1033        switch (slot.cachedPropertyType()) {
     1034        case PropertySlot::Getter:
     1035            vPC[0] = getOpcode(op_get_by_id_getter_self);
     1036            vPC[5] = slot.cachedOffset();
     1037            break;
     1038        case PropertySlot::Custom:
     1039            vPC[0] = getOpcode(op_get_by_id_custom_self);
     1040            vPC[5] = slot.customGetter();
     1041            break;
     1042        default:
     1043            vPC[0] = getOpcode(op_get_by_id_self);
     1044            vPC[5] = slot.cachedOffset();
     1045            break;
     1046        }
    10351047
    10361048        codeBlock->refStructures(vPC);
     
    10571069
    10581070        ASSERT(!baseObject->structure()->isUncacheableDictionary());
    1059 
    1060         vPC[0] = slot.isGetter() ? getOpcode(op_get_by_id_getter_proto) : getOpcode(op_get_by_id_proto);
     1071       
     1072        switch (slot.cachedPropertyType()) {
     1073        case PropertySlot::Getter:
     1074            vPC[0] = getOpcode(op_get_by_id_getter_proto);
     1075            vPC[6] = offset;
     1076            break;
     1077        case PropertySlot::Custom:
     1078            vPC[0] = getOpcode(op_get_by_id_custom_proto);
     1079            vPC[6] = slot.customGetter();
     1080            break;
     1081        default:
     1082            vPC[0] = getOpcode(op_get_by_id_proto);
     1083            vPC[6] = offset;
     1084            break;
     1085        }
    10611086        vPC[5] = baseObject->structure();
    1062         vPC[6] = offset;
    10631087
    10641088        codeBlock->refStructures(vPC);
     
    10731097    }
    10741098
    1075     vPC[0] = slot.isGetter() ? getOpcode(op_get_by_id_getter_chain) : getOpcode(op_get_by_id_chain);
     1099   
     1100    switch (slot.cachedPropertyType()) {
     1101    case PropertySlot::Getter:
     1102        vPC[0] = getOpcode(op_get_by_id_getter_chain);
     1103        vPC[7] = offset;
     1104        break;
     1105    case PropertySlot::Custom:
     1106        vPC[0] = getOpcode(op_get_by_id_custom_chain);
     1107        vPC[7] = slot.customGetter();
     1108        break;
     1109    default:
     1110        vPC[0] = getOpcode(op_get_by_id_chain);
     1111        vPC[7] = offset;
     1112        break;
     1113    }
    10761114    vPC[4] = structure;
    10771115    vPC[5] = structure->prototypeChain(callFrame);
    10781116    vPC[6] = count;
    1079     vPC[7] = offset;
    10801117    codeBlock->refStructures(vPC);
    10811118}
     
    22082245    skip_id_getter_proto:
    22092246#endif
     2247#if HAVE(COMPUTED_GOTO)
     2248    goto *(&&skip_id_custom_proto);
     2249#endif
     2250    DEFINE_OPCODE(op_get_by_id_custom_proto) {
     2251        /* op_get_by_id_custom_proto dst(r) base(r) property(id) structure(sID) prototypeStructure(sID) offset(n) nop(n)
     2252         
     2253         Cached property access: Attempts to use a cached named property getter
     2254         from the value base's prototype. If the cache misses, op_get_by_id_custom_proto
     2255         reverts to op_get_by_id.
     2256         */
     2257        int base = vPC[2].u.operand;
     2258        JSValue baseValue = callFrame->r(base).jsValue();
     2259       
     2260        if (LIKELY(baseValue.isCell())) {
     2261            JSCell* baseCell = asCell(baseValue);
     2262            Structure* structure = vPC[4].u.structure;
     2263           
     2264            if (LIKELY(baseCell->structure() == structure)) {
     2265                ASSERT(structure->prototypeForLookup(callFrame).isObject());
     2266                JSObject* protoObject = asObject(structure->prototypeForLookup(callFrame));
     2267                Structure* prototypeStructure = vPC[5].u.structure;
     2268               
     2269                if (LIKELY(protoObject->structure() == prototypeStructure)) {
     2270                    int dst = vPC[1].u.operand;
     2271                    int property = vPC[3].u.operand;
     2272                    Identifier& ident = callFrame->codeBlock()->identifier(property);
     2273                   
     2274                    PropertySlot::GetValueFunc getter = vPC[6].u.getterFunc;
     2275                    JSValue result = getter(callFrame, protoObject, ident);
     2276                    CHECK_FOR_EXCEPTION();
     2277                    callFrame->r(dst) = result;
     2278                    vPC += OPCODE_LENGTH(op_get_by_id_custom_proto);
     2279                    NEXT_INSTRUCTION();
     2280                }
     2281            }
     2282        }
     2283        uncacheGetByID(callFrame->codeBlock(), vPC);
     2284        NEXT_INSTRUCTION();
     2285    }
     2286#if HAVE(COMPUTED_GOTO)
     2287    skip_id_custom_proto:
     2288#endif
    22102289    DEFINE_OPCODE(op_get_by_id_self_list) {
    22112290        // Polymorphic self access caching currently only supported when JITting.
     
    22302309    }
    22312310    DEFINE_OPCODE(op_get_by_id_getter_proto_list) {
     2311        // Polymorphic prototype access caching currently only supported when JITting.
     2312        ASSERT_NOT_REACHED();
     2313        // This case of the switch must not be empty, else (op_get_by_id_proto_list == op_get_by_id_chain)!
     2314        vPC += OPCODE_LENGTH(op_get_by_id_proto_list);
     2315        NEXT_INSTRUCTION();
     2316    }
     2317    DEFINE_OPCODE(op_get_by_id_custom_self_list) {
     2318        // Polymorphic self access caching currently only supported when JITting.
     2319        ASSERT_NOT_REACHED();
     2320        // This case of the switch must not be empty, else (op_get_by_id_self_list == op_get_by_id_chain)!
     2321        vPC += OPCODE_LENGTH(op_get_by_id_custom_self_list);
     2322        NEXT_INSTRUCTION();
     2323    }
     2324    DEFINE_OPCODE(op_get_by_id_custom_proto_list) {
    22322325        // Polymorphic prototype access caching currently only supported when JITting.
    22332326        ASSERT_NOT_REACHED();
     
    23242417#if HAVE(COMPUTED_GOTO)
    23252418    skip_id_getter_self:
     2419#endif
     2420#if HAVE(COMPUTED_GOTO)
     2421    goto *(&&skip_id_custom_self);
     2422#endif
     2423    DEFINE_OPCODE(op_get_by_id_custom_self) {
     2424        /* op_get_by_id_custom_self dst(r) base(r) property(id) structure(sID) offset(n) nop(n) nop(n)
     2425         
     2426         Cached property access: Attempts to use a cached named property getter
     2427         from the value base. If the cache misses, op_get_by_id_custom_self reverts to
     2428         op_get_by_id.
     2429         */
     2430        int base = vPC[2].u.operand;
     2431        JSValue baseValue = callFrame->r(base).jsValue();
     2432       
     2433        if (LIKELY(baseValue.isCell())) {
     2434            JSCell* baseCell = asCell(baseValue);
     2435            Structure* structure = vPC[4].u.structure;
     2436           
     2437            if (LIKELY(baseCell->structure() == structure)) {
     2438                ASSERT(baseCell->isObject());
     2439                int dst = vPC[1].u.operand;
     2440                int property = vPC[3].u.operand;
     2441                Identifier& ident = callFrame->codeBlock()->identifier(property);
     2442
     2443                PropertySlot::GetValueFunc getter = vPC[5].u.getterFunc;
     2444                JSValue result = getter(callFrame, baseValue, ident);
     2445                CHECK_FOR_EXCEPTION();
     2446                callFrame->r(dst) = result;
     2447                vPC += OPCODE_LENGTH(op_get_by_id_custom_self);
     2448                NEXT_INSTRUCTION();
     2449            }
     2450        }
     2451        uncacheGetByID(callFrame->codeBlock(), vPC);
     2452        NEXT_INSTRUCTION();
     2453    }
     2454#if HAVE(COMPUTED_GOTO)
     2455skip_id_custom_self:
    23262456#endif
    23272457    DEFINE_OPCODE(op_get_by_id_generic) {
     
    23992529#if HAVE(COMPUTED_GOTO)
    24002530    skip_id_getter_chain:
     2531#endif
     2532#if HAVE(COMPUTED_GOTO)
     2533    goto *(&&skip_id_custom_chain);
     2534#endif
     2535    DEFINE_OPCODE(op_get_by_id_custom_chain) {
     2536        /* op_get_by_id_custom_chain dst(r) base(r) property(id) structure(sID) structureChain(chain) count(n) offset(n)
     2537         
     2538         Cached property access: Attempts to use a cached named property getter on the
     2539         value base's prototype chain. If the cache misses, op_get_by_id_custom_chain
     2540         reverts to op_get_by_id.
     2541         */
     2542        int base = vPC[2].u.operand;
     2543        JSValue baseValue = callFrame->r(base).jsValue();
     2544       
     2545        if (LIKELY(baseValue.isCell())) {
     2546            JSCell* baseCell = asCell(baseValue);
     2547            Structure* structure = vPC[4].u.structure;
     2548           
     2549            if (LIKELY(baseCell->structure() == structure)) {
     2550                RefPtr<Structure>* it = vPC[5].u.structureChain->head();
     2551                size_t count = vPC[6].u.operand;
     2552                RefPtr<Structure>* end = it + count;
     2553               
     2554                while (true) {
     2555                    JSObject* baseObject = asObject(baseCell->structure()->prototypeForLookup(callFrame));
     2556                   
     2557                    if (UNLIKELY(baseObject->structure() != (*it).get()))
     2558                        break;
     2559                   
     2560                    if (++it == end) {
     2561                        int dst = vPC[1].u.operand;
     2562                        int property = vPC[3].u.operand;
     2563                        Identifier& ident = callFrame->codeBlock()->identifier(property);
     2564                       
     2565                        PropertySlot::GetValueFunc getter = vPC[7].u.getterFunc;
     2566                        JSValue result = getter(callFrame, baseObject, ident);
     2567                        CHECK_FOR_EXCEPTION();
     2568                        callFrame->r(dst) = result;
     2569                        vPC += OPCODE_LENGTH(op_get_by_id_custom_chain);
     2570                        NEXT_INSTRUCTION();
     2571                    }
     2572                   
     2573                    // Update baseCell, so that next time around the loop we'll pick up the prototype's prototype.
     2574                    baseCell = baseObject;
     2575                }
     2576            }
     2577        }
     2578        uncacheGetByID(callFrame->codeBlock(), vPC);
     2579        NEXT_INSTRUCTION();
     2580    }
     2581#if HAVE(COMPUTED_GOTO)
     2582    skip_id_custom_chain:
    24012583#endif
    24022584    DEFINE_OPCODE(op_get_array_length) {
  • trunk/JavaScriptCore/jit/JIT.cpp

    r55002 r55564  
    328328        case op_get_by_id_getter_self:
    329329        case op_get_by_id_getter_self_list:
     330        case op_get_by_id_custom_chain:
     331        case op_get_by_id_custom_proto:
     332        case op_get_by_id_custom_proto_list:
     333        case op_get_by_id_custom_self:
     334        case op_get_by_id_custom_self_list:
    330335        case op_get_string_length:
    331336        case op_put_by_id_generic:
  • trunk/JavaScriptCore/jit/JIT.h

    r55185 r55564  
    284284        }
    285285
    286         static void compileGetByIdProto(JSGlobalData* globalData, CallFrame* callFrame, CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, Structure* prototypeStructure, bool isGetter, size_t cachedOffset, ReturnAddressPtr returnAddress)
     286        static void compileGetByIdProto(JSGlobalData* globalData, CallFrame* callFrame, CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, Structure* prototypeStructure, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset, ReturnAddressPtr returnAddress)
    287287        {
    288288            JIT jit(globalData, codeBlock);
    289             jit.privateCompileGetByIdProto(stubInfo, structure, prototypeStructure, isGetter, cachedOffset, returnAddress, callFrame);
    290         }
    291 
    292         static void compileGetByIdSelfList(JSGlobalData* globalData, CodeBlock* codeBlock, StructureStubInfo* stubInfo, PolymorphicAccessStructureList* polymorphicStructures, int currentIndex, Structure* structure, bool isGetter, size_t cachedOffset)
     289            jit.privateCompileGetByIdProto(stubInfo, structure, prototypeStructure, ident, slot, cachedOffset, returnAddress, callFrame);
     290        }
     291
     292        static void compileGetByIdSelfList(JSGlobalData* globalData, CodeBlock* codeBlock, StructureStubInfo* stubInfo, PolymorphicAccessStructureList* polymorphicStructures, int currentIndex, Structure* structure, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset)
    293293        {
    294294            JIT jit(globalData, codeBlock);
    295             jit.privateCompileGetByIdSelfList(stubInfo, polymorphicStructures, currentIndex, structure, isGetter, cachedOffset);
    296         }
    297         static void compileGetByIdProtoList(JSGlobalData* globalData, CallFrame* callFrame, CodeBlock* codeBlock, StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructureList, int currentIndex, Structure* structure, Structure* prototypeStructure, bool isGetter, size_t cachedOffset)
     295            jit.privateCompileGetByIdSelfList(stubInfo, polymorphicStructures, currentIndex, structure, ident, slot, cachedOffset);
     296        }
     297        static void compileGetByIdProtoList(JSGlobalData* globalData, CallFrame* callFrame, CodeBlock* codeBlock, StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructureList, int currentIndex, Structure* structure, Structure* prototypeStructure, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset)
    298298        {
    299299            JIT jit(globalData, codeBlock);
    300             jit.privateCompileGetByIdProtoList(stubInfo, prototypeStructureList, currentIndex, structure, prototypeStructure, isGetter, cachedOffset, callFrame);
    301         }
    302         static void compileGetByIdChainList(JSGlobalData* globalData, CallFrame* callFrame, CodeBlock* codeBlock, StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructureList, int currentIndex, Structure* structure, StructureChain* chain, size_t count, bool isGetter, size_t cachedOffset)
     300            jit.privateCompileGetByIdProtoList(stubInfo, prototypeStructureList, currentIndex, structure, prototypeStructure, ident, slot, cachedOffset, callFrame);
     301        }
     302        static void compileGetByIdChainList(JSGlobalData* globalData, CallFrame* callFrame, CodeBlock* codeBlock, StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructureList, int currentIndex, Structure* structure, StructureChain* chain, size_t count, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset)
    303303        {
    304304            JIT jit(globalData, codeBlock);
    305             jit.privateCompileGetByIdChainList(stubInfo, prototypeStructureList, currentIndex, structure, chain, count, isGetter, cachedOffset, callFrame);
    306         }
    307 
    308         static void compileGetByIdChain(JSGlobalData* globalData, CallFrame* callFrame, CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, StructureChain* chain, size_t count, bool isGetter, size_t cachedOffset, ReturnAddressPtr returnAddress)
     305            jit.privateCompileGetByIdChainList(stubInfo, prototypeStructureList, currentIndex, structure, chain, count, ident, slot, cachedOffset, callFrame);
     306        }
     307
     308        static void compileGetByIdChain(JSGlobalData* globalData, CallFrame* callFrame, CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, StructureChain* chain, size_t count, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset, ReturnAddressPtr returnAddress)
    309309        {
    310310            JIT jit(globalData, codeBlock);
    311             jit.privateCompileGetByIdChain(stubInfo, structure, chain, count, isGetter, cachedOffset, returnAddress, callFrame);
     311            jit.privateCompileGetByIdChain(stubInfo, structure, chain, count, ident, slot, cachedOffset, returnAddress, callFrame);
    312312        }
    313313       
     
    355355        void privateCompileSlowCases();
    356356        JITCode privateCompile();
    357         void privateCompileGetByIdProto(StructureStubInfo*, Structure*, Structure* prototypeStructure, bool isGetter, size_t cachedOffset, ReturnAddressPtr returnAddress, CallFrame* callFrame);
    358         void privateCompileGetByIdSelfList(StructureStubInfo*, PolymorphicAccessStructureList*, int, Structure*, bool isGetter, size_t cachedOffset);
    359         void privateCompileGetByIdProtoList(StructureStubInfo*, PolymorphicAccessStructureList*, int, Structure*, Structure* prototypeStructure, bool isGetter, size_t cachedOffset, CallFrame* callFrame);
    360         void privateCompileGetByIdChainList(StructureStubInfo*, PolymorphicAccessStructureList*, int, Structure*, StructureChain* chain, size_t count, bool isGetter, size_t cachedOffset, CallFrame* callFrame);
    361         void privateCompileGetByIdChain(StructureStubInfo*, Structure*, StructureChain*, size_t count, bool isGetter, size_t cachedOffset, ReturnAddressPtr returnAddress, CallFrame* callFrame);
     357        void privateCompileGetByIdProto(StructureStubInfo*, Structure*, Structure* prototypeStructure, const Identifier&, const PropertySlot&, size_t cachedOffset, ReturnAddressPtr returnAddress, CallFrame* callFrame);
     358        void privateCompileGetByIdSelfList(StructureStubInfo*, PolymorphicAccessStructureList*, int, Structure*, const Identifier&, const PropertySlot&, size_t cachedOffset);
     359        void privateCompileGetByIdProtoList(StructureStubInfo*, PolymorphicAccessStructureList*, int, Structure*, Structure* prototypeStructure, const Identifier&, const PropertySlot&, size_t cachedOffset, CallFrame* callFrame);
     360        void privateCompileGetByIdChainList(StructureStubInfo*, PolymorphicAccessStructureList*, int, Structure*, StructureChain* chain, size_t count, const Identifier&, const PropertySlot&, size_t cachedOffset, CallFrame* callFrame);
     361        void privateCompileGetByIdChain(StructureStubInfo*, Structure*, StructureChain*, size_t count, const Identifier&, const PropertySlot&, size_t cachedOffset, ReturnAddressPtr returnAddress, CallFrame* callFrame);
    362362        void privateCompilePutByIdTransition(StructureStubInfo*, Structure*, Structure*, size_t cachedOffset, StructureChain*, ReturnAddressPtr returnAddress);
    363363
  • trunk/JavaScriptCore/jit/JITPropertyAccess.cpp

    r55198 r55564  
    697697}
    698698
    699 void JIT::privateCompileGetByIdProto(StructureStubInfo* stubInfo, Structure* structure, Structure* prototypeStructure, bool isGetter, size_t cachedOffset, ReturnAddressPtr returnAddress, CallFrame* callFrame)
     699void JIT::privateCompileGetByIdProto(StructureStubInfo* stubInfo, Structure* structure, Structure* prototypeStructure, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset, ReturnAddressPtr returnAddress, CallFrame* callFrame)
    700700{
    701701    // The prototype object definitely exists (if this stub exists the CodeBlock is referencing a Structure that is
     
    715715#endif
    716716
     717    bool needsStubLink = false;
     718   
    717719    // Checks out okay!
    718     if (isGetter) {
     720    if (slot.cachedPropertyType() == PropertySlot::Getter) {
     721        needsStubLink = true;
    719722        compileGetDirectOffset(protoObject, regT1, regT1, cachedOffset);
    720723        JITStubCall stubCall(this, cti_op_get_by_id_getter_stub);
     
    723726        stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress()));
    724727        stubCall.call();
     728    } else if (slot.cachedPropertyType() == PropertySlot::Custom) {
     729        needsStubLink = true;
     730        JITStubCall stubCall(this, cti_op_get_by_id_custom_stub);
     731        stubCall.addArgument(ImmPtr(protoObject));
     732        stubCall.addArgument(ImmPtr(FunctionPtr(slot.customGetter()).executableAddress()));
     733        stubCall.addArgument(ImmPtr(const_cast<Identifier*>(&ident)));
     734        stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress()));
     735        stubCall.call();
    725736    } else
    726737        compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset);
     
    736747    patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(patchOffsetGetByIdPutResult));
    737748
    738     if (isGetter) {
     749    if (needsStubLink) {
    739750        for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter) {
    740751            if (iter->to)
     
    755766}
    756767
    757 void JIT::privateCompileGetByIdSelfList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* polymorphicStructures, int currentIndex, Structure* structure, bool isGetter, size_t cachedOffset)
     768void JIT::privateCompileGetByIdSelfList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* polymorphicStructures, int currentIndex, Structure* structure, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset)
    758769{
    759770    Jump failureCase = checkStructure(regT0, structure);
    760     if (isGetter) {
     771    bool needsStubLink = false;
     772    if (slot.cachedPropertyType() == PropertySlot::Getter) {
     773        needsStubLink = true;
    761774        if (!structure->isUsingInlineStorage()) {
    762775            move(regT0, regT1);
     
    769782        stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress()));
    770783        stubCall.call();
     784    } else if (slot.cachedPropertyType() == PropertySlot::Custom) {
     785        needsStubLink = true;
     786        JITStubCall stubCall(this, cti_op_get_by_id_custom_stub);
     787        stubCall.addArgument(regT0);
     788        stubCall.addArgument(ImmPtr(FunctionPtr(slot.customGetter()).executableAddress()));
     789        stubCall.addArgument(ImmPtr(const_cast<Identifier*>(&ident)));
     790        stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress()));
     791        stubCall.call();
    771792    } else
    772793        compileGetDirectOffset(regT0, regT0, structure, cachedOffset);
     
    775796    LinkBuffer patchBuffer(this, m_codeBlock->executablePool());
    776797
    777     if (isGetter) {
     798    if (needsStubLink) {
    778799        for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter) {
    779800            if (iter->to)
     
    803824}
    804825
    805 void JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructures, int currentIndex, Structure* structure, Structure* prototypeStructure, bool isGetter, size_t cachedOffset, CallFrame* callFrame)
     826void JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructures, int currentIndex, Structure* structure, Structure* prototypeStructure, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset, CallFrame* callFrame)
    806827{
    807828    // The prototype object definitely exists (if this stub exists the CodeBlock is referencing a Structure that is
     
    822843
    823844    // Checks out okay!
    824     if (isGetter) {
     845    bool needsStubLink = false;
     846    if (slot.cachedPropertyType() == PropertySlot::Getter) {
     847        needsStubLink = true;
    825848        compileGetDirectOffset(protoObject, regT1, regT1, cachedOffset);
    826849        JITStubCall stubCall(this, cti_op_get_by_id_getter_stub);
     
    829852        stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress()));
    830853        stubCall.call();
     854    } else if (slot.cachedPropertyType() == PropertySlot::Custom) {
     855        needsStubLink = true;
     856        JITStubCall stubCall(this, cti_op_get_by_id_custom_stub);
     857        stubCall.addArgument(ImmPtr(protoObject));
     858        stubCall.addArgument(ImmPtr(FunctionPtr(slot.customGetter()).executableAddress()));
     859        stubCall.addArgument(ImmPtr(const_cast<Identifier*>(&ident)));
     860        stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress()));
     861        stubCall.call();
    831862    } else
    832863        compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset);
     
    836867    LinkBuffer patchBuffer(this, m_codeBlock->executablePool());
    837868
    838     if (isGetter) {
     869    if (needsStubLink) {
    839870        for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter) {
    840871            if (iter->to)
     
    863894}
    864895
    865 void JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructures, int currentIndex, Structure* structure, StructureChain* chain, size_t count, bool isGetter, size_t cachedOffset, CallFrame* callFrame)
     896void JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructures, int currentIndex, Structure* structure, StructureChain* chain, size_t count, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset, CallFrame* callFrame)
    866897{
    867898    ASSERT(count);
     
    890921    ASSERT(protoObject);
    891922   
    892     if (isGetter) {
     923    bool needsStubLink = false;
     924    if (slot.cachedPropertyType() == PropertySlot::Getter) {
     925        needsStubLink = true;
    893926        compileGetDirectOffset(protoObject, regT1, regT1, cachedOffset);
    894927        JITStubCall stubCall(this, cti_op_get_by_id_getter_stub);
     
    897930        stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress()));
    898931        stubCall.call();
     932    } else if (slot.cachedPropertyType() == PropertySlot::Custom) {
     933        needsStubLink = true;
     934        JITStubCall stubCall(this, cti_op_get_by_id_custom_stub);
     935        stubCall.addArgument(ImmPtr(protoObject));
     936        stubCall.addArgument(ImmPtr(FunctionPtr(slot.customGetter()).executableAddress()));
     937        stubCall.addArgument(ImmPtr(const_cast<Identifier*>(&ident)));
     938        stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress()));
     939        stubCall.call();
    899940    } else
    900941        compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset);
     
    903944    LinkBuffer patchBuffer(this, m_codeBlock->executablePool());
    904945   
    905     if (isGetter) {
     946    if (needsStubLink) {
    906947        for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter) {
    907948            if (iter->to)
     
    931972}
    932973
    933 void JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* structure, StructureChain* chain, size_t count, bool isGetter, size_t cachedOffset, ReturnAddressPtr returnAddress, CallFrame* callFrame)
     974void JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* structure, StructureChain* chain, size_t count, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset, ReturnAddressPtr returnAddress, CallFrame* callFrame)
    934975{
    935976    ASSERT(count);
     
    957998    }
    958999    ASSERT(protoObject);
    959    
    960     if (isGetter) {
     1000
     1001    bool needsStubLink = false;
     1002    if (slot.cachedPropertyType() == PropertySlot::Getter) {
     1003        needsStubLink = true;
    9611004        compileGetDirectOffset(protoObject, regT1, regT1, cachedOffset);
    9621005        JITStubCall stubCall(this, cti_op_get_by_id_getter_stub);
     
    9651008        stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress()));
    9661009        stubCall.call();
     1010    } else if (slot.cachedPropertyType() == PropertySlot::Custom) {
     1011        needsStubLink = true;
     1012        JITStubCall stubCall(this, cti_op_get_by_id_custom_stub);
     1013        stubCall.addArgument(ImmPtr(protoObject));
     1014        stubCall.addArgument(ImmPtr(FunctionPtr(slot.customGetter()).executableAddress()));
     1015        stubCall.addArgument(ImmPtr(const_cast<Identifier*>(&ident)));
     1016        stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress()));
     1017        stubCall.call();
    9671018    } else
    9681019        compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset);
     
    9711022    LinkBuffer patchBuffer(this, m_codeBlock->executablePool());
    9721023
    973     if (isGetter) {
     1024    if (needsStubLink) {
    9741025        for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter) {
    9751026            if (iter->to)
  • trunk/JavaScriptCore/jit/JITPropertyAccess32_64.cpp

    r55198 r55564  
    719719}
    720720
    721 void JIT::privateCompileGetByIdProto(StructureStubInfo* stubInfo, Structure* structure, Structure* prototypeStructure, bool isGetter, size_t cachedOffset, ReturnAddressPtr returnAddress, CallFrame* callFrame)
     721void JIT::privateCompileGetByIdProto(StructureStubInfo* stubInfo, Structure* structure, Structure* prototypeStructure, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset, ReturnAddressPtr returnAddress, CallFrame* callFrame)
    722722{
    723723    // regT0 holds a JSCell*
     
    737737    Jump failureCases2 = branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), ImmPtr(prototypeStructure));
    738738#endif
    739    
     739    bool needsStubLink = false;
    740740    // Checks out okay!
    741     if (isGetter) {
     741    if (slot.cachedPropertyType() == PropertySlot::Getter) {
     742        needsStubLink = true;
    742743        compileGetDirectOffset(protoObject, regT2, regT2, regT1, cachedOffset);
    743744        JITStubCall stubCall(this, cti_op_get_by_id_getter_stub);
     
    746747        stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress()));
    747748        stubCall.call();
     749    } else if (slot.cachedPropertyType() == PropertySlot::Custom) {
     750        needsStubLink = true;
     751        JITStubCall stubCall(this, cti_op_get_by_id_custom_stub);
     752        stubCall.addArgument(ImmPtr(protoObject));
     753        stubCall.addArgument(ImmPtr(FunctionPtr(slot.customGetter()).executableAddress()));
     754        stubCall.addArgument(ImmPtr(const_cast<Identifier*>(&ident)));
     755        stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress()));
     756        stubCall.call();
    748757    } else
    749758        compileGetDirectOffset(protoObject, regT2, regT1, regT0, cachedOffset);
     
    761770    patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(patchOffsetGetByIdPutResult));
    762771
    763     if (isGetter) {
     772    if (needsStubLink) {
    764773        for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter) {
    765774            if (iter->to)
     
    782791
    783792
    784 void JIT::privateCompileGetByIdSelfList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* polymorphicStructures, int currentIndex, Structure* structure, bool isGetter, size_t cachedOffset)
     793void JIT::privateCompileGetByIdSelfList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* polymorphicStructures, int currentIndex, Structure* structure, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset)
    785794{
    786795    // regT0 holds a JSCell*
    787796    Jump failureCase = checkStructure(regT0, structure);
    788     if (isGetter) {
     797    bool needsStubLink = false;
     798    if (slot.cachedPropertyType() == PropertySlot::Getter) {
     799        needsStubLink = true;
    789800        if (!structure->isUsingInlineStorage()) {
    790801            move(regT0, regT1);
     
    797808        stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress()));
    798809        stubCall.call();
     810    } else if (slot.cachedPropertyType() == PropertySlot::Custom) {
     811        needsStubLink = true;
     812        JITStubCall stubCall(this, cti_op_get_by_id_custom_stub);
     813        stubCall.addArgument(regT0);
     814        stubCall.addArgument(ImmPtr(FunctionPtr(slot.customGetter()).executableAddress()));
     815        stubCall.addArgument(ImmPtr(const_cast<Identifier*>(&ident)));
     816        stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress()));
     817        stubCall.call();
    799818    } else
    800819        compileGetDirectOffset(regT0, regT1, regT0, structure, cachedOffset);
     
    803822   
    804823    LinkBuffer patchBuffer(this, m_codeBlock->executablePool());
    805     if (isGetter) {
     824    if (needsStubLink) {
    806825        for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter) {
    807826            if (iter->to)
     
    830849}
    831850
    832 void JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructures, int currentIndex, Structure* structure, Structure* prototypeStructure, bool isGetter, size_t cachedOffset, CallFrame* callFrame)
     851void JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructures, int currentIndex, Structure* structure, Structure* prototypeStructure, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset, CallFrame* callFrame)
    833852{
    834853    // regT0 holds a JSCell*
     
    850869#endif
    851870   
    852     if (isGetter) {
     871    bool needsStubLink = false;
     872    if (slot.cachedPropertyType() == PropertySlot::Getter) {
     873        needsStubLink = true;
    853874        compileGetDirectOffset(protoObject, regT2, regT2, regT1, cachedOffset);
    854875        JITStubCall stubCall(this, cti_op_get_by_id_getter_stub);
     
    857878        stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress()));
    858879        stubCall.call();
     880    } else if (slot.cachedPropertyType() == PropertySlot::Custom) {
     881        needsStubLink = true;
     882        JITStubCall stubCall(this, cti_op_get_by_id_custom_stub);
     883        stubCall.addArgument(ImmPtr(protoObject));
     884        stubCall.addArgument(ImmPtr(FunctionPtr(slot.customGetter()).executableAddress()));
     885        stubCall.addArgument(ImmPtr(const_cast<Identifier*>(&ident)));
     886        stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress()));
     887        stubCall.call();
    859888    } else
    860889        compileGetDirectOffset(protoObject, regT2, regT1, regT0, cachedOffset);
     
    863892   
    864893    LinkBuffer patchBuffer(this, m_codeBlock->executablePool());
    865     if (isGetter) {
     894    if (needsStubLink) {
    866895        for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter) {
    867896            if (iter->to)
     
    889918}
    890919
    891 void JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructures, int currentIndex, Structure* structure, StructureChain* chain, size_t count, bool isGetter, size_t cachedOffset, CallFrame* callFrame)
     920void JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructures, int currentIndex, Structure* structure, StructureChain* chain, size_t count, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset, CallFrame* callFrame)
    892921{
    893922    // regT0 holds a JSCell*
     
    917946    ASSERT(protoObject);
    918947   
    919     if (isGetter) {
     948    bool needsStubLink = false;
     949    if (slot.cachedPropertyType() == PropertySlot::Getter) {
     950        needsStubLink = true;
    920951        compileGetDirectOffset(protoObject, regT2, regT2, regT1, cachedOffset);
    921952        JITStubCall stubCall(this, cti_op_get_by_id_getter_stub);
     
    924955        stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress()));
    925956        stubCall.call();
     957    } else if (slot.cachedPropertyType() == PropertySlot::Custom) {
     958        needsStubLink = true;
     959        JITStubCall stubCall(this, cti_op_get_by_id_custom_stub);
     960        stubCall.addArgument(ImmPtr(protoObject));
     961        stubCall.addArgument(ImmPtr(FunctionPtr(slot.customGetter()).executableAddress()));
     962        stubCall.addArgument(ImmPtr(const_cast<Identifier*>(&ident)));
     963        stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress()));
     964        stubCall.call();
    926965    } else
    927966        compileGetDirectOffset(protoObject, regT2, regT1, regT0, cachedOffset);
     
    930969   
    931970    LinkBuffer patchBuffer(this, m_codeBlock->executablePool());
    932     if (isGetter) {
     971    if (needsStubLink) {
    933972        for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter) {
    934973            if (iter->to)
     
    957996}
    958997
    959 void JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* structure, StructureChain* chain, size_t count, bool isGetter, size_t cachedOffset, ReturnAddressPtr returnAddress, CallFrame* callFrame)
     998void JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* structure, StructureChain* chain, size_t count, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset, ReturnAddressPtr returnAddress, CallFrame* callFrame)
    960999{
    9611000    // regT0 holds a JSCell*
     
    9851024    ASSERT(protoObject);
    9861025   
    987     if (isGetter) {
     1026    bool needsStubLink = false;
     1027    if (slot.cachedPropertyType() == PropertySlot::Getter) {
     1028        needsStubLink = true;
    9881029        compileGetDirectOffset(protoObject, regT2, regT2, regT1, cachedOffset);
    9891030        JITStubCall stubCall(this, cti_op_get_by_id_getter_stub);
     
    9921033        stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress()));
    9931034        stubCall.call();
     1035    } else if (slot.cachedPropertyType() == PropertySlot::Custom) {
     1036        needsStubLink = true;
     1037        JITStubCall stubCall(this, cti_op_get_by_id_custom_stub);
     1038        stubCall.addArgument(ImmPtr(protoObject));
     1039        stubCall.addArgument(ImmPtr(FunctionPtr(slot.customGetter()).executableAddress()));
     1040        stubCall.addArgument(ImmPtr(const_cast<Identifier*>(&ident)));
     1041        stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress()));
     1042        stubCall.call();
    9941043    } else
    9951044        compileGetDirectOffset(protoObject, regT2, regT1, regT0, cachedOffset);
     
    9971046   
    9981047    LinkBuffer patchBuffer(this, m_codeBlock->executablePool());
    999     if (isGetter) {
     1048    if (needsStubLink) {
    10001049        for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter) {
    10011050            if (iter->to)
  • trunk/JavaScriptCore/jit/JITStubs.cpp

    r55185 r55564  
    876876        // set this up, so derefStructures can do it's job.
    877877        stubInfo->initGetByIdSelf(structure);
    878         if (slot.isGetter())
     878        if (slot.cachedPropertyType() != PropertySlot::Value)
    879879            ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_self_fail));
    880880        else
     
    905905        ASSERT(!structure->isDictionary());
    906906        ASSERT(!slotBaseObject->structure()->isDictionary());
    907         JIT::compileGetByIdProto(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, structure, slotBaseObject->structure(), slot.isGetter(), offset, returnAddress);
     907        JIT::compileGetByIdProto(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, structure, slotBaseObject->structure(), propertyName, slot, offset, returnAddress);
    908908        return;
    909909    }
     
    918918    StructureChain* prototypeChain = structure->prototypeChain(callFrame);
    919919    stubInfo->initGetByIdChain(structure, prototypeChain);
    920     JIT::compileGetByIdChain(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, structure, prototypeChain, count, slot.isGetter(), offset, returnAddress);
     920    JIT::compileGetByIdChain(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, structure, prototypeChain, count, propertyName, slot, offset, returnAddress);
    921921}
    922922
     
    14001400        }
    14011401
    1402         JIT::compileGetByIdSelfList(callFrame->scopeChain()->globalData, codeBlock, stubInfo, polymorphicStructureList, listIndex, asCell(baseValue)->structure(), slot.isGetter(), slot.cachedOffset());
     1402        JIT::compileGetByIdSelfList(callFrame->scopeChain()->globalData, codeBlock, stubInfo, polymorphicStructureList, listIndex, asCell(baseValue)->structure(), ident, slot, slot.cachedOffset());
    14031403
    14041404        if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1))
     
    14551455}
    14561456
     1457DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_custom_stub)
     1458{
     1459    STUB_INIT_STACK_FRAME(stackFrame);
     1460    CallFrame* callFrame = stackFrame.callFrame;
     1461    JSObject* slotBase = stackFrame.args[0].jsObject();
     1462    PropertySlot::GetValueFunc getter = reinterpret_cast<PropertySlot::GetValueFunc>(stackFrame.args[1].asPointer);
     1463    const Identifier& ident = stackFrame.args[2].identifier();
     1464    JSValue result = getter(callFrame, slotBase, ident);
     1465    if (callFrame->hadException())
     1466        returnToThrowTrampoline(&callFrame->globalData(), stackFrame.args[3].returnAddress(), STUB_RETURN_ADDRESS);
     1467   
     1468    return JSValue::encode(result);
     1469}
     1470
    14571471DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_proto_list)
    14581472{
     
    14961510        PolymorphicAccessStructureList* prototypeStructureList = getPolymorphicAccessStructureListSlot(stubInfo, listIndex);
    14971511
    1498         JIT::compileGetByIdProtoList(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, prototypeStructureList, listIndex, structure, slotBaseObject->structure(), slot.isGetter(), offset);
     1512        JIT::compileGetByIdProtoList(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, prototypeStructureList, listIndex, structure, slotBaseObject->structure(), propertyName, slot, offset);
    14991513
    15001514        if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1))
     
    15061520
    15071521        StructureChain* protoChain = structure->prototypeChain(callFrame);
    1508         JIT::compileGetByIdChainList(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, prototypeStructureList, listIndex, structure, protoChain, count, slot.isGetter(), offset);
     1522        JIT::compileGetByIdChainList(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, prototypeStructureList, listIndex, structure, protoChain, count, propertyName, slot, offset);
    15091523
    15101524        if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1))
  • trunk/JavaScriptCore/jit/JITStubs.h

    r55453 r55564  
    278278    EncodedJSValue JIT_STUB cti_op_get_by_id_method_check(STUB_ARGS_DECLARATION);
    279279    EncodedJSValue JIT_STUB cti_op_get_by_id_getter_stub(STUB_ARGS_DECLARATION);
     280    EncodedJSValue JIT_STUB cti_op_get_by_id_custom_stub(STUB_ARGS_DECLARATION);
    280281    EncodedJSValue JIT_STUB cti_op_get_by_id_proto_fail(STUB_ARGS_DECLARATION);
    281282    EncodedJSValue JIT_STUB cti_op_get_by_id_proto_list(STUB_ARGS_DECLARATION);
  • trunk/JavaScriptCore/runtime/JSFunction.cpp

    r55401 r55564  
    163163
    164164    if (propertyName == exec->propertyNames().arguments) {
    165         slot.setCustom(this, argumentsGetter);
     165        slot.setCacheableCustom(this, argumentsGetter);
    166166        return true;
    167167    }
    168168
    169169    if (propertyName == exec->propertyNames().length) {
    170         slot.setCustom(this, lengthGetter);
     170        slot.setCacheableCustom(this, lengthGetter);
    171171        return true;
    172172    }
    173173
    174174    if (propertyName == exec->propertyNames().caller) {
    175         slot.setCustom(this, callerGetter);
     175        slot.setCacheableCustom(this, callerGetter);
    176176        return true;
    177177    }
  • trunk/JavaScriptCore/runtime/Lookup.h

    r53320 r55564  
    182182            setUpStaticFunctionSlot(exec, entry, thisObj, propertyName, slot);
    183183        else
    184             slot.setCustom(thisObj, entry->propertyGetter());
     184            slot.setCacheableCustom(thisObj, entry->propertyGetter());
    185185
    186186        return true;
     
    259259        ASSERT(!(entry->attributes() & Function));
    260260
    261         slot.setCustom(thisObj, entry->propertyGetter());
     261        slot.setCacheableCustom(thisObj, entry->propertyGetter());
    262262        return true;
    263263    }
  • trunk/JavaScriptCore/runtime/PropertySlot.h

    r55401 r55564  
    4040    class PropertySlot {
    4141    public:
     42        enum CachedPropertyType {
     43            Uncacheable,
     44            Getter,
     45            Custom,
     46            Value
     47        };
     48
    4249        PropertySlot()
     50            : m_cachedPropertyType(Uncacheable)
    4351        {
    4452            clearBase();
     
    4957        explicit PropertySlot(const JSValue base)
    5058            : m_slotBase(base)
     59            , m_cachedPropertyType(Uncacheable)
    5160        {
    5261            clearOffset();
     
    8392        }
    8493
    85         bool isGetter() const { return m_isGetter; }
    86         bool isCacheable() const { return m_isCacheable; }
    87         bool isCacheableValue() const { return m_isCacheable && !m_isGetter; }
     94        CachedPropertyType cachedPropertyType() const { return m_cachedPropertyType; }
     95        bool isCacheable() const { return m_cachedPropertyType != Uncacheable; }
     96        bool isCacheableValue() const { return m_cachedPropertyType == Value; }
    8897        size_t cachedOffset() const
    8998        {
     
    116125            m_data.valueSlot = valueSlot;
    117126            m_offset = offset;
    118             m_isCacheable = true;
    119             m_isGetter = false;
     127            m_cachedPropertyType = Value;
    120128        }
    121129       
     
    147155            m_slotBase = slotBase;
    148156        }
     157       
     158        void setCacheableCustom(JSValue slotBase, GetValueFunc getValue)
     159        {
     160            ASSERT(slotBase);
     161            ASSERT(getValue);
     162            m_getValue = getValue;
     163            m_getIndexValue = 0;
     164            m_slotBase = slotBase;
     165            m_cachedPropertyType = Custom;
     166        }
    149167
    150168        void setCustomIndex(JSValue slotBase, unsigned index, GetIndexValueFunc getIndexValue)
     
    164182            m_getValue = GETTER_FUNCTION_MARKER;
    165183            m_data.getterFunc = getterFunc;
    166             m_isGetter = true;
    167184        }
    168185
     
    175192            m_data.getterFunc = getterFunc;
    176193            m_offset = offset;
    177             m_isCacheable = true;
    178             m_isGetter = true;
     194            m_cachedPropertyType = Getter;
    179195        }
    180196
     
    215231            // (For other data members, we don't need to clear anything because reuse would meaningfully overwrite them.)
    216232            m_offset = 0;
    217             m_isCacheable = false;
    218             m_isGetter = false;
     233            m_cachedPropertyType = Uncacheable;
    219234        }
    220235
     
    222237
    223238        JSValue thisValue() const { return m_thisValue; }
     239
     240        GetValueFunc customGetter() const
     241        {
     242            ASSERT(m_cachedPropertyType == Custom);
     243            return m_getValue;
     244        }
    224245    private:
    225246        JSValue functionGetter(ExecState*) const;
     
    240261
    241262        size_t m_offset;
    242         bool m_isCacheable : 1;
    243         bool m_isGetter : 1;
     263        CachedPropertyType m_cachedPropertyType;
    244264    };
    245265
  • trunk/LayoutTests/ChangeLog

    r55557 r55564  
     12010-03-03  Oliver Hunt  <oliver@apple.com>
     2
     3        Reviewed by Gavin Barraclough.
     4
     5        Allow static property getters to interact with JSCs caching
     6        https://bugs.webkit.org/show_bug.cgi?id=35716
     7
     8        Add tests to ensure nothing horrifying happens to static property
     9        getters if they're in a path where we end up caching lookups.
     10
     11        * fast/js/pic/cached-named-property-getter-expected.txt: Added.
     12        * fast/js/pic/cached-named-property-getter.html: Added.
     13
    1142010-03-04  James Robinson  <jamesr@chromium.org>
    215
  • trunk/WebCore/ChangeLog

    r55560 r55564  
     12010-03-03  Oliver Hunt  <oliver@apple.com>
     2
     3        Reviewed by Gavin Barraclough.
     4
     5        Allow static property getters to interact with JSCs caching
     6        https://bugs.webkit.org/show_bug.cgi?id=35716
     7
     8        Update the obviously safe getters to allow caching
     9
     10        Test: fast/js/pic/cached-named-property-getter.html
     11
     12        * bridge/runtime_array.cpp:
     13        (JSC::RuntimeArray::getOwnPropertySlot):
     14        * bridge/runtime_method.cpp:
     15        (JSC::RuntimeMethod::getOwnPropertySlot):
     16
    1172010-03-04  Mark Rowe  <mrowe@apple.com>
    218
  • trunk/WebCore/bridge/runtime_array.cpp

    r55401 r55564  
    7878{
    7979    if (propertyName == exec->propertyNames().length) {
    80         slot.setCustom(this, lengthGetter);
     80        slot.setCacheableCustom(this, lengthGetter);
    8181        return true;
    8282    }
  • trunk/WebCore/bridge/runtime_method.cpp

    r55401 r55564  
    6969{
    7070    if (propertyName == exec->propertyNames().length) {
    71         slot.setCustom(this, lengthGetter);
     71        slot.setCacheableCustom(this, lengthGetter);
    7272        return true;
    7373    }
Note: See TracChangeset for help on using the changeset viewer.