Changeset 277929 in webkit


Ignore:
Timestamp:
May 22, 2021, 11:23:48 PM (4 years ago)
Author:
mark.lam@apple.com
Message:

Use singleton thunks for virtual calls.
https://bugs.webkit.org/show_bug.cgi?id=226149
rdar://problem/78357604

Reviewed by Yusuke Suzuki.

Change virtualThunkFor() to return 1 of 6 possible singleton thunks.
These thunks are cached via vm.jitStubs->ctiStubs().

This change saves us ~16M of executable JIT memory (for the unique thunks) on a
single run of Speedometer2. On an M1 Mac, switching to singleton thunks here also
appears to be a 1.012x speed up on Speedometer2. Performance is neutral on
JetStream2.

  • jit/JITThunks.cpp:

(JSC::JITThunks::ctiInternalFunctionCall):
(JSC::JITThunks::ctiInternalFunctionConstruct):

  • jit/JITThunks.h:
  • jit/ThunkGenerators.cpp:

(JSC::virtualThunkFor):
(JSC::virtualThunkForRegularCall):
(JSC::virtualThunkForRegularConstruct):
(JSC::virtualThunkForTailCall):
(JSC::virtualThunkForTailConstruct):
(JSC::virtualThunkForConstructCall):
(JSC::virtualThunkForConstructConstruct):

  • runtime/VM.cpp:

(JSC::VM::getCTIInternalFunctionTrampolineFor):

  • runtime/VM.h:
Location:
trunk/Source/JavaScriptCore
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r277928 r277929  
     12021-05-22  Mark Lam  <mark.lam@apple.com>
     2
     3        Use singleton thunks for virtual calls.
     4        https://bugs.webkit.org/show_bug.cgi?id=226149
     5        rdar://problem/78357604
     6
     7        Reviewed by Yusuke Suzuki.
     8
     9        Change virtualThunkFor() to return 1 of 6 possible singleton thunks.
     10        These thunks are cached via vm.jitStubs->ctiStubs().
     11
     12        This change saves us ~16M of executable JIT memory (for the unique thunks) on a
     13        single run of Speedometer2.  On an M1 Mac, switching to singleton thunks here also
     14        appears to be a 1.012x speed up on Speedometer2.  Performance is neutral on
     15        JetStream2.
     16
     17        * jit/JITThunks.cpp:
     18        (JSC::JITThunks::ctiInternalFunctionCall):
     19        (JSC::JITThunks::ctiInternalFunctionConstruct):
     20        * jit/JITThunks.h:
     21        * jit/ThunkGenerators.cpp:
     22        (JSC::virtualThunkFor):
     23        (JSC::virtualThunkForRegularCall):
     24        (JSC::virtualThunkForRegularConstruct):
     25        (JSC::virtualThunkForTailCall):
     26        (JSC::virtualThunkForTailConstruct):
     27        (JSC::virtualThunkForConstructCall):
     28        (JSC::virtualThunkForConstructConstruct):
     29        * runtime/VM.cpp:
     30        (JSC::VM::getCTIInternalFunctionTrampolineFor):
     31        * runtime/VM.h:
     32
    1332021-05-22  Mark Lam  <mark.lam@apple.com>
    234
  • trunk/Source/JavaScriptCore/jit/JITThunks.cpp

    r277920 r277929  
    118118}
    119119
    120 MacroAssemblerCodePtr<JITThunkPtrTag> JITThunks::ctiInternalFunctionCall(VM& vm)
    121 {
    122     ASSERT(Options::useJIT());
     120MacroAssemblerCodePtr<JITThunkPtrTag> JITThunks::ctiInternalFunctionCall(VM& vm, Optional<NoLockingNecessaryTag> noLockingNecessary)
     121{
     122    ASSERT(Options::useJIT());
     123    if (noLockingNecessary)
     124        return existingCTIStub(internalFunctionCallGenerator, NoLockingNecessary).code();
    123125    return ctiStub(vm, internalFunctionCallGenerator).code();
    124126}
    125127
    126 MacroAssemblerCodePtr<JITThunkPtrTag> JITThunks::ctiInternalFunctionConstruct(VM& vm)
    127 {
    128     ASSERT(Options::useJIT());
     128MacroAssemblerCodePtr<JITThunkPtrTag> JITThunks::ctiInternalFunctionConstruct(VM& vm, Optional<NoLockingNecessaryTag> noLockingNecessary)
     129{
     130    ASSERT(Options::useJIT());
     131    if (noLockingNecessary)
     132        return existingCTIStub(internalFunctionConstructGenerator, NoLockingNecessary).code();
    129133    return ctiStub(vm, internalFunctionConstructGenerator).code();
    130134}
  • trunk/Source/JavaScriptCore/jit/JITThunks.h

    r277882 r277929  
    6060    MacroAssemblerCodePtr<JITThunkPtrTag> ctiNativeTailCall(VM&);
    6161    MacroAssemblerCodePtr<JITThunkPtrTag> ctiNativeTailCallWithoutSavedTags(VM&);
    62     MacroAssemblerCodePtr<JITThunkPtrTag> ctiInternalFunctionCall(VM&);
    63     MacroAssemblerCodePtr<JITThunkPtrTag> ctiInternalFunctionConstruct(VM&);
     62    MacroAssemblerCodePtr<JITThunkPtrTag> ctiInternalFunctionCall(VM&, Optional<NoLockingNecessaryTag> = WTF::nullopt);
     63    MacroAssemblerCodePtr<JITThunkPtrTag> ctiInternalFunctionConstruct(VM&, Optional<NoLockingNecessaryTag> = WTF::nullopt);
    6464
    6565    MacroAssemblerCodeRef<JITThunkPtrTag> ctiStub(VM&, ThunkGenerator);
  • trunk/Source/JavaScriptCore/jit/ThunkGenerators.cpp

    r277928 r277929  
    264264// virtual calls by using the shuffler.
    265265// https://bugs.webkit.org/show_bug.cgi?id=148831
    266 MacroAssemblerCodeRef<JITStubRoutinePtrTag> virtualThunkFor(VM& vm, CallLinkInfo& callLinkInfo)
     266static MacroAssemblerCodeRef<JITThunkPtrTag> virtualThunkFor(VM& vm, CallMode mode, CodeSpecializationKind kind)
    267267{
    268268    // The callee is in regT0 (for JSVALUE32_64, the tag is in regT1).
     
    272272
    273273    CCallHelpers jit;
    274    
     274
     275    bool isTailCall = mode == CallMode::Tail;
     276
    275277    CCallHelpers::JumpList slowCase;
    276278   
     
    285287   
    286288#if USE(JSVALUE64)
    287     if (callLinkInfo.isTailCall()) {
     289    if (isTailCall) {
    288290        // Tail calls could have clobbered the GPRInfo::notCellMaskRegister because they
    289291        // restore callee saved registers before getthing here. So, let's materialize
     
    304306    hasExecutable.link(&jit);
    305307    jit.loadPtr(
    306         CCallHelpers::Address(
    307             GPRInfo::regT4, ExecutableBase::offsetOfJITCodeWithArityCheckFor(
    308                 callLinkInfo.specializationKind())),
     308        CCallHelpers::Address(GPRInfo::regT4, ExecutableBase::offsetOfJITCodeWithArityCheckFor(kind)),
    309309        GPRInfo::regT4);
    310310    slowCase.append(jit.branchTestPtr(CCallHelpers::Zero, GPRInfo::regT4));
     
    316316    JSInterfaceJIT::Label callCode(jit.label());
    317317    emitPointerValidation(jit, GPRInfo::regT4, JSEntryPtrTag);
    318     if (callLinkInfo.isTailCall()) {
     318    if (isTailCall) {
    319319        jit.preserveReturnAddressAfterCall(GPRInfo::regT0);
    320320        jit.prepareForTailCallSlow(GPRInfo::regT4);
     
    325325    notJSFunction.link(&jit);
    326326    slowCase.append(jit.branchIfNotType(GPRInfo::regT0, InternalFunctionType));
    327     void* executableAddress = vm.getCTIInternalFunctionTrampolineFor(callLinkInfo.specializationKind()).executableAddress();
     327    void* executableAddress = vm.getCTIInternalFunctionTrampolineFor(kind, NoLockingNecessary).executableAddress();
    328328    jit.move(CCallHelpers::TrustedImmPtr(executableAddress), GPRInfo::regT4);
    329329    jit.jump().linkTo(callCode, &jit);
     
    336336    LinkBuffer patchBuffer(jit, GLOBAL_THUNK_ID, LinkBuffer::Profile::VirtualThunk);
    337337    return FINALIZE_CODE(
    338         patchBuffer, JITStubRoutinePtrTag,
     338        patchBuffer, JITThunkPtrTag,
    339339        "Virtual %s slow path thunk",
    340         callLinkInfo.callMode() == CallMode::Regular ? "call" : callLinkInfo.callMode() == CallMode::Tail ? "tail call" : "construct");
     340        mode == CallMode::Regular ? "call" : mode == CallMode::Tail ? "tail call" : "construct");
     341}
     342
     343static MacroAssemblerCodeRef<JITThunkPtrTag> virtualThunkForRegularCall(VM& vm)
     344{
     345    return virtualThunkFor(vm, CallMode::Regular, CodeForCall);
     346}
     347
     348static MacroAssemblerCodeRef<JITThunkPtrTag> virtualThunkForRegularConstruct(VM& vm)
     349{
     350    return virtualThunkFor(vm, CallMode::Regular, CodeForConstruct);
     351}
     352
     353static MacroAssemblerCodeRef<JITThunkPtrTag> virtualThunkForTailCall(VM& vm)
     354{
     355    return virtualThunkFor(vm, CallMode::Tail, CodeForCall);
     356}
     357
     358static MacroAssemblerCodeRef<JITThunkPtrTag> virtualThunkForTailConstruct(VM& vm)
     359{
     360    return virtualThunkFor(vm, CallMode::Tail, CodeForConstruct);
     361}
     362
     363static MacroAssemblerCodeRef<JITThunkPtrTag> virtualThunkForConstructCall(VM& vm)
     364{
     365    return virtualThunkFor(vm, CallMode::Construct, CodeForCall);
     366}
     367
     368static MacroAssemblerCodeRef<JITThunkPtrTag> virtualThunkForConstructConstruct(VM& vm)
     369{
     370    return virtualThunkFor(vm, CallMode::Construct, CodeForConstruct);
     371}
     372
     373MacroAssemblerCodeRef<JITStubRoutinePtrTag> virtualThunkFor(VM& vm, CallLinkInfo& callLinkInfo)
     374{
     375    auto mode = callLinkInfo.callMode();
     376    auto kind = callLinkInfo.specializationKind();
     377    auto generator = [&] () -> ThunkGenerator {
     378        switch (mode) {
     379        case CallMode::Regular:
     380            if (kind == CodeForCall)
     381                return virtualThunkForRegularCall;
     382            return virtualThunkForRegularConstruct;
     383        case CallMode::Tail:
     384            if (kind == CodeForCall)
     385                return virtualThunkForTailCall;
     386            return virtualThunkForTailConstruct;
     387        case CallMode::Construct:
     388            if (kind == CodeForCall)
     389                return virtualThunkForConstructCall;
     390            return virtualThunkForConstructConstruct;
     391        }
     392    };
     393    return vm.getCTIStub(generator()).retagged<JITStubRoutinePtrTag>();
    341394}
    342395
  • trunk/Source/JavaScriptCore/runtime/VM.cpp

    r277909 r277929  
    889889}
    890890
    891 MacroAssemblerCodePtr<JSEntryPtrTag> VM::getCTIInternalFunctionTrampolineFor(CodeSpecializationKind kind)
    892 {
     891MacroAssemblerCodePtr<JSEntryPtrTag> VM::getCTIInternalFunctionTrampolineFor(CodeSpecializationKind kind, Optional<NoLockingNecessaryTag> noLockingNecessary)
     892{
     893    UNUSED_PARAM(noLockingNecessary);
    893894#if ENABLE(JIT)
    894895    if (Options::useJIT()) {
    895896        if (kind == CodeForCall)
    896             return jitStubs->ctiInternalFunctionCall(*this).retagged<JSEntryPtrTag>();
    897         return jitStubs->ctiInternalFunctionConstruct(*this).retagged<JSEntryPtrTag>();
     897            return jitStubs->ctiInternalFunctionCall(*this, noLockingNecessary).retagged<JSEntryPtrTag>();
     898        return jitStubs->ctiInternalFunctionConstruct(*this, noLockingNecessary).retagged<JSEntryPtrTag>();
    898899    }
    899900#endif
  • trunk/Source/JavaScriptCore/runtime/VM.h

    r277094 r277929  
    852852    NativeExecutable* getBoundFunction(bool isJSFunction, bool canConstruct);
    853853
    854     MacroAssemblerCodePtr<JSEntryPtrTag> getCTIInternalFunctionTrampolineFor(CodeSpecializationKind);
     854    MacroAssemblerCodePtr<JSEntryPtrTag> getCTIInternalFunctionTrampolineFor(CodeSpecializationKind, Optional<NoLockingNecessaryTag> = WTF::nullopt);
    855855
    856856    static ptrdiff_t exceptionOffset()
Note: See TracChangeset for help on using the changeset viewer.