Changeset 38688 in webkit


Ignore:
Timestamp:
Nov 21, 2008 7:34:43 PM (15 years ago)
Author:
barraclough@apple.com
Message:

2008-11-21 Gavin Barraclough <barraclough@apple.com>

Reviewed by Oliver Hunt.

Add (really) polymorphic caching for get by id self.
Very similar to caching of prototype accesses, described below.

Oh, also, probably shouldn't have been leaking those structure list objects.


4% preogression on deltablue.

  • bytecode/CodeBlock.cpp: (JSC::CodeBlock::dump): (JSC::CodeBlock::derefStructures): (JSC::PrototypeStructureList::derefStructures):
  • bytecode/Instruction.h:
  • bytecode/Opcode.h:
  • interpreter/Interpreter.cpp: (JSC::Interpreter::privateExecute): (JSC::Interpreter::cti_op_get_by_id_self_fail):
  • jit/JIT.cpp: (JSC::JIT::privateCompileMainPass): (JSC::JIT::privateCompileGetByIdSelfList): (JSC::JIT::patchGetByIdSelf):
  • jit/JIT.h: (JSC::JIT::compileGetByIdSelfList):
Location:
trunk/JavaScriptCore
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/ChangeLog

    r38682 r38688  
     12008-11-21  Gavin Barraclough  <barraclough@apple.com>
     2
     3        Reviewed by Oliver Hunt.
     4
     5        Add (really) polymorphic caching for get by id self.
     6        Very similar to caching of prototype accesses, described below.
     7
     8        Oh, also, probably shouldn't have been leaking those structure list objects.
     9       
     10        4% preogression on deltablue.
     11
     12        * bytecode/CodeBlock.cpp:
     13        (JSC::CodeBlock::dump):
     14        (JSC::CodeBlock::derefStructures):
     15        (JSC::PrototypeStructureList::derefStructures):
     16        * bytecode/Instruction.h:
     17        * bytecode/Opcode.h:
     18        * interpreter/Interpreter.cpp:
     19        (JSC::Interpreter::privateExecute):
     20        (JSC::Interpreter::cti_op_get_by_id_self_fail):
     21        * jit/JIT.cpp:
     22        (JSC::JIT::privateCompileMainPass):
     23        (JSC::JIT::privateCompileGetByIdSelfList):
     24        (JSC::JIT::patchGetByIdSelf):
     25        * jit/JIT.h:
     26        (JSC::JIT::compileGetByIdSelfList):
     27
    1282008-11-21  Geoffrey Garen  <ggaren@apple.com>
    229
  • trunk/JavaScriptCore/bytecode/CodeBlock.cpp

    r38652 r38688  
    643643            break;
    644644        }
     645        case op_get_by_id_self_list: {
     646            printGetByIdOp(location, it, identifiers, "get_by_id_self_list");
     647            break;
     648        }
    645649        case op_get_by_id_proto: {
    646650            printGetByIdOp(location, it, identifiers, "get_by_id_proto");
     
    10241028        return;
    10251029    }
    1026     if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto_list)) {
    1027         PrototypeStructureList* prototypeStructures = vPC[4].u.prototypeStructure;
    1028         int count = vPC[5].u.operand;
    1029         for (int i = 0; i < count; ++i) {
    1030             PrototypeStructureList::ProtoStubInfo& info = prototypeStructures->list[i];
    1031             ASSERT(info.base);
    1032             ASSERT(info.proto);
    1033             ASSERT(info.stubRoutine);
    1034             info.base->deref();
    1035             info.proto->deref();
    1036             WTF::fastFreeExecutable(info.stubRoutine);
    1037         }
     1030    if ((vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto_list))
     1031        || (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self_list))) {
     1032        PolymorphicAccessStructureList* polymorphicStructures = vPC[4].u.polymorphicStructures;
     1033        polymorphicStructures->derefStructures(vPC[5].u.operand);
     1034        delete polymorphicStructures;
    10381035        return;
    10391036    }
  • trunk/JavaScriptCore/bytecode/Instruction.h

    r38652 r38688  
    3434#include <wtf/VectorTraits.h>
    3535
    36 #define PROTOTYPE_LIST_CACHE_SIZE 4
     36#define POLYMORPHIC_LIST_CACHE_SIZE 4
    3737
    3838namespace JSC {
     
    4343
    4444    // Structure used by op_get_by_id_proto_list instruction to hold data off the main opcode stream.
    45     struct PrototypeStructureList {
    46         struct ProtoStubInfo {
     45    struct PolymorphicAccessStructureList {
     46        struct PolymorphicStubInfo {
    4747            Structure* base;
    4848            Structure* proto;
     
    5757                stubRoutine = _stubRoutine;
    5858            }
    59         } list[PROTOTYPE_LIST_CACHE_SIZE];
     59        } list[POLYMORPHIC_LIST_CACHE_SIZE];
    6060       
    61         PrototypeStructureList(Structure* firstBase, Structure* firstProto, int cachedOffset, void* stubRoutine)
     61        PolymorphicAccessStructureList(Structure* firstBase, Structure* firstProto, int cachedOffset, void* stubRoutine)
    6262        {
    6363            list[0].set(firstBase, firstProto, cachedOffset, stubRoutine);
     64        }
     65
     66        void derefStructures(int count)
     67        {
     68            for (int i = 0; i < count; ++i) {
     69                PolymorphicStubInfo& info = list[i];
     70
     71                ASSERT(info.base);
     72                info.base->deref();
     73
     74                if (info.proto)
     75                    info.proto->deref();
     76
     77                if (info.stubRoutine)
     78                    WTF::fastFreeExecutable(info.stubRoutine);
     79            }
    6480        }
    6581    };
     
    7894        Instruction(StructureChain* structureChain) { u.structureChain = structureChain; }
    7995        Instruction(JSCell* jsCell) { u.jsCell = jsCell; }
    80         Instruction(PrototypeStructureList* prototypeStructure) { u.prototypeStructure = prototypeStructure; }
     96        Instruction(PolymorphicAccessStructureList* polymorphicStructures) { u.polymorphicStructures = polymorphicStructures; }
    8197
    8298        union {
     
    87103            JSCell* jsCell;
    88104            ResultType::Type resultType;
    89             PrototypeStructureList* prototypeStructure;
     105            PolymorphicAccessStructureList* polymorphicStructures;
    90106        } u;
    91107    };
  • trunk/JavaScriptCore/bytecode/Opcode.h

    r38652 r38688  
    102102        macro(op_get_by_id) \
    103103        macro(op_get_by_id_self) \
     104        macro(op_get_by_id_self_list) \
    104105        macro(op_get_by_id_proto) \
    105106        macro(op_get_by_id_proto_list) \
  • trunk/JavaScriptCore/interpreter/Interpreter.cpp

    r38652 r38688  
    25872587        NEXT_INSTRUCTION();
    25882588    }
     2589    DEFINE_OPCODE(op_get_by_id_self_list) {
     2590        // Polymorphic self access caching currently only supported when JITting.
     2591        ASSERT_NOT_REACHED();
     2592        // This case of the switch must not be empty, else (op_get_by_id_self_list == op_get_by_id_chain)!
     2593        vPC += 8;
     2594        NEXT_INSTRUCTION();
     2595    }
    25892596    DEFINE_OPCODE(op_get_by_id_proto_list) {
    25902597        // Polymorphic prototype access caching currently only supported when JITting.
     
    45944601    JSValue* result = baseValue->get(callFrame, ident, slot);
    45954602
    4596     CHECK_FOR_EXCEPTION_AT_END();
     4603    CHECK_FOR_EXCEPTION();
     4604
     4605    if (baseValue->isObject()
     4606        && slot.isCacheable()
     4607        && !asCell(baseValue)->structure()->isDictionary()
     4608        && slot.slotBase() == baseValue) {
     4609
     4610        CodeBlock* codeBlock = callFrame->codeBlock();
     4611        unsigned vPCIndex = codeBlock->ctiReturnAddressVPCMap.get(CTI_RETURN_ADDRESS);
     4612        Instruction* vPC = codeBlock->instructions.begin() + vPCIndex;
     4613
     4614        ASSERT(slot.slotBase()->isObject());
     4615
     4616        StructureStubInfo* stubInfo = &codeBlock->getStubInfo(CTI_RETURN_ADDRESS);
     4617
     4618        PolymorphicAccessStructureList* polymorphicStructureList;
     4619        int listIndex = 1;
     4620
     4621        if (vPC[0].u.opcode == ARG_globalData->interpreter->getOpcode(op_get_by_id_self)) {
     4622            ASSERT(!stubInfo->stubRoutine);
     4623            polymorphicStructureList = new PolymorphicAccessStructureList(vPC[4].u.structure, 0, vPC[5].u.operand, 0);
     4624
     4625            vPC[0] = ARG_globalData->interpreter->getOpcode(op_get_by_id_self_list);
     4626            vPC[4] = polymorphicStructureList;
     4627            vPC[5] = 2;
     4628        } else {
     4629            polymorphicStructureList = vPC[4].u.polymorphicStructures;
     4630            listIndex = vPC[5].u.operand;
     4631
     4632            vPC[5] = listIndex + 1;
     4633        }
     4634
     4635        JIT::compileGetByIdSelfList(callFrame->scopeChain()->globalData, codeBlock, stubInfo, polymorphicStructureList, listIndex, asCell(baseValue)->structure(), slot.cachedOffset());
     4636
     4637        if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1))
     4638            ctiRepatchCallByReturnAddress(CTI_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_get_by_id_generic));
     4639    } else {
     4640        ctiRepatchCallByReturnAddress(CTI_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_get_by_id_generic));
     4641    }
    45974642    return result;
    45984643}
     
    46354680        StructureStubInfo* stubInfo = &codeBlock->getStubInfo(CTI_RETURN_ADDRESS);
    46364681
    4637         PrototypeStructureList* prototypeStructureList;
     4682        PolymorphicAccessStructureList* prototypeStructureList;
    46384683        int listIndex = 1;
    46394684
    46404685        if (vPC[0].u.opcode == ARG_globalData->interpreter->getOpcode(op_get_by_id_proto)) {
    4641             prototypeStructureList = new PrototypeStructureList(vPC[4].u.structure, vPC[5].u.structure, vPC[6].u.operand, stubInfo->stubRoutine);
     4686            prototypeStructureList = new PolymorphicAccessStructureList(vPC[4].u.structure, vPC[5].u.structure, vPC[6].u.operand, stubInfo->stubRoutine);
    46424687            stubInfo->stubRoutine = 0;
    46434688
     
    46464691            vPC[5] = 2;
    46474692        } else {
    4648             prototypeStructureList = vPC[4].u.prototypeStructure;
     4693            prototypeStructureList = vPC[4].u.polymorphicStructures;
    46494694            listIndex = vPC[5].u.operand;
    46504695
     
    46544699        JIT::compileGetByIdProtoList(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, prototypeStructureList, listIndex, structure, slotBaseObject->structure(), slot.cachedOffset());
    46554700
    4656         if (listIndex == (PROTOTYPE_LIST_CACHE_SIZE - 1))
     4701        if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1))
    46574702            ctiRepatchCallByReturnAddress(CTI_RETURN_ADDRESS, reinterpret_cast<void*>(cti_op_get_by_id_proto_list_full));
    46584703    } else {
  • trunk/JavaScriptCore/jit/JIT.cpp

    r38669 r38688  
    23602360        case op_get_by_id_proto_list:
    23612361        case op_get_by_id_self:
     2362        case op_get_by_id_self_list:
    23622363        case op_get_string_length:
    23632364        case op_put_by_id_generic:
     
    32313232
    32323233#if USE(CTI_REPATCH_PIC)
    3233 void JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, PrototypeStructureList* prototypeStructures, int currentIndex, Structure* structure, Structure* prototypeStructure, size_t cachedOffset, CallFrame* callFrame)
     3234void JIT::privateCompileGetByIdSelfList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* polymorphicStructures, int currentIndex, Structure* structure, size_t cachedOffset)
     3235{
     3236    JmpSrc failureCase = checkStructure(X86::eax, structure);
     3237    __ movl_mr(FIELD_OFFSET(JSObject, m_propertyStorage), X86::eax, X86::eax);
     3238    __ movl_mr(cachedOffset * sizeof(JSValue*), X86::eax, X86::eax);
     3239    JmpSrc success = __ jmp();
     3240
     3241    void* code = __ executableCopy();
     3242    ASSERT(code);
     3243
     3244    // Use the repatch information to link the failure cases back to the original slow case routine.
     3245    void* lastProtoBegin = polymorphicStructures->list[currentIndex - 1].stubRoutine;
     3246    if (!lastProtoBegin)
     3247        lastProtoBegin = reinterpret_cast<char*>(stubInfo->callReturnLocation) - repatchOffsetGetByIdSlowCaseCall;
     3248
     3249    X86Assembler::link(code, failureCase, lastProtoBegin);
     3250
     3251    // On success return back to the hot patch code, at a point it will perform the store to dest for us.
     3252    intptr_t successDest = reinterpret_cast<intptr_t>(stubInfo->hotPathBegin) + repatchOffsetGetByIdPropertyMapOffset;
     3253    X86Assembler::link(code, success, reinterpret_cast<void*>(successDest));
     3254
     3255    structure->ref();
     3256    polymorphicStructures->list[currentIndex].set(structure, 0, cachedOffset, 0/*code*/);
     3257
     3258    // Finally repatch the jump to slow case back in the hot path to jump here instead.
     3259    intptr_t jmpLocation = reinterpret_cast<intptr_t>(stubInfo->hotPathBegin) + repatchOffsetGetByIdBranchToSlowCase;
     3260    X86Assembler::repatchBranchOffset(jmpLocation, code);
     3261}
     3262
     3263void JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructures, int currentIndex, Structure* structure, Structure* prototypeStructure, size_t cachedOffset, CallFrame* callFrame)
    32343264{
    32353265    // The prototype object definitely exists (if this stub exists the CodeBlock is referencing a Structure that is
     
    36673697    // We don't want to repatch more than once - in future go to cti_op_get_by_id_generic.
    36683698    // Should probably go to Interpreter::cti_op_get_by_id_fail, but that doesn't do anything interesting right now.
    3669     ctiRepatchCallByReturnAddress(returnAddress, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_generic));
     3699    ctiRepatchCallByReturnAddress(returnAddress, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_self_fail));
    36703700
    36713701    // Repatch the offset into the propoerty map to load from, then repatch the Structure to look for.
  • trunk/JavaScriptCore/jit/JIT.h

    r38652 r38688  
    110110    struct Instruction;
    111111    struct OperandTypes;
    112     struct PrototypeStructureList;
     112    struct PolymorphicAccessStructureList;
    113113    struct StructureStubInfo;
    114114
     
    321321
    322322#if USE(CTI_REPATCH_PIC)
    323         static void compileGetByIdProtoList(JSGlobalData* globalData, CallFrame* callFrame, CodeBlock* codeBlock, StructureStubInfo* stubInfo, PrototypeStructureList* prototypeStructureList, int currentIndex, Structure* structure, Structure* prototypeStructure, size_t cachedOffset)
     323        static void compileGetByIdSelfList(JSGlobalData* globalData, CodeBlock* codeBlock, StructureStubInfo* stubInfo, PolymorphicAccessStructureList* polymorphicStructures, int currentIndex, Structure* structure, size_t cachedOffset)
     324        {
     325            JIT jit(globalData, codeBlock);
     326            jit.privateCompileGetByIdSelfList(stubInfo, polymorphicStructures, currentIndex, structure, cachedOffset);
     327        }
     328        static void compileGetByIdProtoList(JSGlobalData* globalData, CallFrame* callFrame, CodeBlock* codeBlock, StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructureList, int currentIndex, Structure* structure, Structure* prototypeStructure, size_t cachedOffset)
    324329        {
    325330            JIT jit(globalData, codeBlock);
     
    380385        void privateCompileGetByIdProto(Structure*, Structure* prototypeStructure, size_t cachedOffset, void* returnAddress, CallFrame* callFrame);
    381386#if USE(CTI_REPATCH_PIC)
    382         void privateCompileGetByIdProtoList(StructureStubInfo*, PrototypeStructureList*, int, Structure*, Structure* prototypeStructure, size_t cachedOffset, CallFrame* callFrame);
     387        void privateCompileGetByIdSelfList(StructureStubInfo*, PolymorphicAccessStructureList*, int, Structure*, size_t cachedOffset);
     388        void privateCompileGetByIdProtoList(StructureStubInfo*, PolymorphicAccessStructureList*, int, Structure*, Structure* prototypeStructure, size_t cachedOffset, CallFrame* callFrame);
    383389#endif
    384390        void privateCompileGetByIdChain(Structure*, StructureChain*, size_t count, size_t cachedOffset, void* returnAddress, CallFrame* callFrame);
Note: See TracChangeset for help on using the changeset viewer.