Ignore:
Timestamp:
Feb 24, 2010, 1:02:40 AM (15 years ago)
Author:
[email protected]
Message:

2010-02-24 Oliver Hunt <[email protected]>

Reviewed by Gavin Barraclough.

Speed up getter performance in the jit
https://bugs.webkit.org/show_bug.cgi?id=35332

Implement getter lookup caching in the interpreter.
The getter stubs are generated through basically the
same code paths as the normal get_by_id caching.
Instead of simply loading a property and returning,
we load the getter slot, and pass the getter, base value
and return address to a shared stub used for getter
dispatch.

  • 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/GetterSetter.h:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/jit/JITPropertyAccess.cpp

    r55027 r55185  
    3333
    3434#include "CodeBlock.h"
     35#include "GetterSetter.h"
    3536#include "JITInlineMethods.h"
    3637#include "JITStubCall.h"
     
    696697}
    697698
    698 void JIT::privateCompileGetByIdProto(StructureStubInfo* stubInfo, Structure* structure, Structure* prototypeStructure, size_t cachedOffset, ReturnAddressPtr returnAddress, CallFrame* callFrame)
     699void JIT::privateCompileGetByIdProto(StructureStubInfo* stubInfo, Structure* structure, Structure* prototypeStructure, bool isGetter, size_t cachedOffset, ReturnAddressPtr returnAddress, CallFrame* callFrame)
    699700{
    700701    // The prototype object definitely exists (if this stub exists the CodeBlock is referencing a Structure that is
     
    714715#endif
    715716
    716     // Checks out okay! - getDirectOffset
    717     compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset);
    718 
     717    // Checks out okay!
     718    if (isGetter) {
     719        compileGetDirectOffset(protoObject, regT1, regT1, cachedOffset);
     720        JITStubCall stubCall(this, cti_op_get_by_id_getter_stub);
     721        stubCall.addArgument(regT1);
     722        stubCall.addArgument(regT0);
     723        stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress()));
     724        stubCall.call();
     725    } else
     726        compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset);
    719727    Jump success = jump();
    720 
    721728    LinkBuffer patchBuffer(this, m_codeBlock->executablePool());
    722729
     
    729736    patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(patchOffsetGetByIdPutResult));
    730737
     738    if (isGetter) {
     739        for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter) {
     740            if (iter->to)
     741                patchBuffer.link(iter->from, FunctionPtr(iter->to));
     742        }
     743    }
    731744    // Track the stub we have created so that it will be deleted later.
    732745    CodeLocationLabel entryLabel = patchBuffer.finalizeCodeAddendum();
     
    742755}
    743756
    744 void JIT::privateCompileGetByIdSelfList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* polymorphicStructures, int currentIndex, Structure* structure, size_t cachedOffset)
     757void JIT::privateCompileGetByIdSelfList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* polymorphicStructures, int currentIndex, Structure* structure, bool isGetter, size_t cachedOffset)
    745758{
    746759    Jump failureCase = checkStructure(regT0, structure);
    747     compileGetDirectOffset(regT0, regT0, structure, cachedOffset);
     760    if (isGetter) {
     761        compileGetDirectOffset(regT0, regT1, structure, cachedOffset);
     762        JITStubCall stubCall(this, cti_op_get_by_id_getter_stub);
     763        stubCall.addArgument(regT1);
     764        stubCall.addArgument(regT0);
     765        stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress()));
     766        stubCall.call();
     767    } else
     768        compileGetDirectOffset(regT0, regT0, structure, cachedOffset);
    748769    Jump success = jump();
    749770
    750771    LinkBuffer patchBuffer(this, m_codeBlock->executablePool());
     772
     773    if (isGetter) {
     774        for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter) {
     775            if (iter->to)
     776                patchBuffer.link(iter->from, FunctionPtr(iter->to));
     777        }
     778    }
    751779
    752780    // Use the patch information to link the failure cases back to the original slow case routine.
     
    771799}
    772800
    773 void JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructures, int currentIndex, Structure* structure, Structure* prototypeStructure, size_t cachedOffset, CallFrame* callFrame)
     801void JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructures, int currentIndex, Structure* structure, Structure* prototypeStructure, bool isGetter, size_t cachedOffset, CallFrame* callFrame)
    774802{
    775803    // The prototype object definitely exists (if this stub exists the CodeBlock is referencing a Structure that is
     
    789817#endif
    790818
    791     // Checks out okay! - getDirectOffset
    792     compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset);
     819    // Checks out okay!
     820    if (isGetter) {
     821        compileGetDirectOffset(protoObject, regT1, regT1, cachedOffset);
     822        JITStubCall stubCall(this, cti_op_get_by_id_getter_stub);
     823        stubCall.addArgument(regT1);
     824        stubCall.addArgument(regT0);
     825        stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress()));
     826        stubCall.call();
     827    } else
     828        compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset);
    793829
    794830    Jump success = jump();
    795831
    796832    LinkBuffer patchBuffer(this, m_codeBlock->executablePool());
     833
     834    if (isGetter) {
     835        for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter) {
     836            if (iter->to)
     837                patchBuffer.link(iter->from, FunctionPtr(iter->to));
     838        }
     839    }
    797840
    798841    // Use the patch information to link the failure cases back to the original slow case routine.
     
    816859}
    817860
    818 void JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructures, int currentIndex, Structure* structure, StructureChain* chain, size_t count, size_t cachedOffset, CallFrame* callFrame)
     861void JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructures, int currentIndex, Structure* structure, StructureChain* chain, size_t count, bool isGetter, size_t cachedOffset, CallFrame* callFrame)
    819862{
    820863    ASSERT(count);
    821    
    822864    JumpList bucketsOfFail;
    823865
     
    843885    }
    844886    ASSERT(protoObject);
    845 
    846     compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset);
     887   
     888    if (isGetter) {
     889        compileGetDirectOffset(protoObject, regT1, regT1, cachedOffset);
     890        JITStubCall stubCall(this, cti_op_get_by_id_getter_stub);
     891        stubCall.addArgument(regT1);
     892        stubCall.addArgument(regT0);
     893        stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress()));
     894        stubCall.call();
     895    } else
     896        compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset);
    847897    Jump success = jump();
    848898
    849899    LinkBuffer patchBuffer(this, m_codeBlock->executablePool());
     900   
     901    if (isGetter) {
     902        for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter) {
     903            if (iter->to)
     904                patchBuffer.link(iter->from, FunctionPtr(iter->to));
     905        }
     906    }
    850907
    851908    // Use the patch information to link the failure cases back to the original slow case routine.
     
    870927}
    871928
    872 void JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* structure, StructureChain* chain, size_t count, size_t cachedOffset, ReturnAddressPtr returnAddress, CallFrame* callFrame)
     929void JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* structure, StructureChain* chain, size_t count, bool isGetter, size_t cachedOffset, ReturnAddressPtr returnAddress, CallFrame* callFrame)
    873930{
    874931    ASSERT(count);
    875    
     932
    876933    JumpList bucketsOfFail;
    877934
     
    896953    }
    897954    ASSERT(protoObject);
    898 
    899     compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset);
     955   
     956    if (isGetter) {
     957        compileGetDirectOffset(protoObject, regT1, regT1, cachedOffset);
     958        JITStubCall stubCall(this, cti_op_get_by_id_getter_stub);
     959        stubCall.addArgument(regT1);
     960        stubCall.addArgument(regT0);
     961        stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress()));
     962        stubCall.call();
     963    } else
     964        compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset);
    900965    Jump success = jump();
    901966
    902967    LinkBuffer patchBuffer(this, m_codeBlock->executablePool());
     968
     969    if (isGetter) {
     970        for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter) {
     971            if (iter->to)
     972                patchBuffer.link(iter->from, FunctionPtr(iter->to));
     973        }
     974    }
    903975
    904976    // Use the patch information to link the failure cases back to the original slow case routine.
Note: See TracChangeset for help on using the changeset viewer.