Ignore:
Timestamp:
Mar 4, 2010, 5:33:54 PM (15 years ago)
Author:
[email protected]
Message:

2010-03-03 Oliver Hunt <[email protected]>

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 <[email protected]>

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 <[email protected]>

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):
File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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) {
Note: See TracChangeset for help on using the changeset viewer.