Ignore:
Timestamp:
Dec 8, 2016, 10:52:51 PM (9 years ago)
Author:
[email protected]
Message:

WebAssembly: JSC::link* shouldn't need a CodeBlock
https://bugs.webkit.org/show_bug.cgi?id=165591

Reviewed by Keith Miller.

JSTests:

test that wasm -> JS works, including the IC

  • wasm/js-api/test_Instance.js:

(const.wasmModuleWhichImportJS):
(MonomorphicImport):
(Polyphic2Import):
(Polyphic3Import):
(VirtualImport):

Source/JavaScriptCore:

Allow linking without a CodeBlock, which WebAssembly's wasm -> JS stubs does. This needs to work for polymorphic and virtual calls. This patch adds corresponding tests for this.

  • assembler/LinkBuffer.cpp:

(JSC::shouldDumpDisassemblyFor): don't look at the tier option if there isn't a CodeBlock, only look at the global one. This is a WebAssembly function, so the tier information is irrelevant.

  • jit/Repatch.cpp:

(JSC::isWebAssemblyToJSCallee): this is used in the link* functions below
(JSC::linkFor):
(JSC::linkVirtualFor):
(JSC::linkPolymorphicCall):

  • runtime/Options.h: add an option to change the maximum number of polymorphic calls in stubs from wasm to JS, which will come in handy when we try to tune performance or try merging some of the WebAssembly stubs
  • wasm/WasmBinding.cpp:

(JSC::Wasm::importStubGenerator): remove the breakpoint since the code now works

  • wasm/js/WebAssemblyToJSCallee.h:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/jit/Repatch.cpp

    r209433 r209597  
    4545#include "JITInlines.h"
    4646#include "JSCInlines.h"
     47#include "JSWebAssembly.h"
    4748#include "LinkBuffer.h"
    4849#include "PolymorphicAccess.h"
     
    557558}
    558559
     560static bool isWebAssemblyToJSCallee(VM& vm, JSCell* callee)
     561{
     562#if ENABLE(WEBASSEMBLY)
     563    // The WebAssembly -> JS stub sets it caller frame's callee to a singleton which lives on the VM.
     564    return callee == vm.webAssemblyToJSCallee.get();
     565#else
     566    UNUSED_PARAM(vm);
     567    UNUSED_PARAM(callee);
     568    return false;
     569#endif // ENABLE(WEBASSEMBLY)
     570}
     571
     572static JSCell* webAssemblyOwner(VM& vm)
     573{
     574#if ENABLE(WEBASSEMBLY)
     575    // Each WebAssembly.Instance shares the stubs from their WebAssembly.Module, which are therefore the appropriate owner.
     576    return vm.topJSWebAssemblyInstance->module();
     577#else
     578    UNUSED_PARAM(vm);
     579    RELEASE_ASSERT_NOT_REACHED();
     580    return nullptr;
     581#endif // ENABLE(WEBASSEMBLY)
     582}
     583
    559584void linkFor(
    560585    ExecState* exec, CallLinkInfo& callLinkInfo, CodeBlock* calleeCodeBlock,
     
    562587{
    563588    ASSERT(!callLinkInfo.stub());
    564    
    565     CodeBlock* callerCodeBlock = exec->callerFrame()->codeBlock();
    566 
    567     VM* vm = callerCodeBlock->vm();
    568    
     589
     590    CallFrame* callerFrame = exec->callerFrame();
     591    VM& vm = callerFrame->vm();
     592    CodeBlock* callerCodeBlock = callerFrame->codeBlock();
     593
     594    // WebAssembly -> JS stubs don't have a valid CodeBlock.
     595    JSCell* owner = isWebAssemblyToJSCallee(vm, callerFrame->callee()) ? webAssemblyOwner(vm) : callerCodeBlock;
     596    ASSERT(owner);
     597
    569598    ASSERT(!callLinkInfo.isLinked());
    570     callLinkInfo.setCallee(exec->callerFrame()->vm(), callerCodeBlock, callee);
    571     callLinkInfo.setLastSeenCallee(exec->callerFrame()->vm(), callerCodeBlock, callee);
     599    callLinkInfo.setCallee(vm, owner, callee);
     600    callLinkInfo.setLastSeenCallee(vm, owner, callee);
    572601    if (shouldDumpDisassemblyFor(callerCodeBlock))
    573602        dataLog("Linking call in ", *callerCodeBlock, " at ", callLinkInfo.codeOrigin(), " to ", pointerDump(calleeCodeBlock), ", entrypoint at ", codePtr, "\n");
    574603    MacroAssembler::repatchNearCall(callLinkInfo.hotPathOther(), CodeLocationLabel(codePtr));
    575    
     604
    576605    if (calleeCodeBlock)
    577         calleeCodeBlock->linkIncomingCall(exec->callerFrame(), &callLinkInfo);
    578    
     606        calleeCodeBlock->linkIncomingCall(callerFrame, &callLinkInfo);
     607
    579608    if (callLinkInfo.specializationKind() == CodeForCall && callLinkInfo.allowStubs()) {
    580         linkSlowFor(vm, callLinkInfo, linkPolymorphicCallThunkGenerator);
     609        linkSlowFor(&vm, callLinkInfo, linkPolymorphicCallThunkGenerator);
    581610        return;
    582611    }
    583612   
    584     linkSlowFor(vm, callLinkInfo);
     613    linkSlowFor(&vm, callLinkInfo);
    585614}
    586615
     
    646675}
    647676
    648 void linkVirtualFor(
    649     ExecState* exec, CallLinkInfo& callLinkInfo)
    650 {
    651     CodeBlock* callerCodeBlock = exec->callerFrame()->codeBlock();
    652     VM* vm = callerCodeBlock->vm();
     677void linkVirtualFor(ExecState* exec, CallLinkInfo& callLinkInfo)
     678{
     679    CallFrame* callerFrame = exec->callerFrame();
     680    VM& vm = callerFrame->vm();
     681    CodeBlock* callerCodeBlock = callerFrame->codeBlock();
    653682
    654683    if (shouldDumpDisassemblyFor(callerCodeBlock))
    655         dataLog("Linking virtual call at ", *callerCodeBlock, " ", exec->callerFrame()->codeOrigin(), "\n");
    656    
    657     MacroAssemblerCodeRef virtualThunk = virtualThunkFor(vm, callLinkInfo);
    658     revertCall(vm, callLinkInfo, virtualThunk);
    659     callLinkInfo.setSlowStub(createJITStubRoutine(virtualThunk, *vm, nullptr, true));
     684        dataLog("Linking virtual call at ", *callerCodeBlock, " ", callerFrame->codeOrigin(), "\n");
     685
     686    MacroAssemblerCodeRef virtualThunk = virtualThunkFor(&vm, callLinkInfo);
     687    revertCall(&vm, callLinkInfo, virtualThunk);
     688    callLinkInfo.setSlowStub(createJITStubRoutine(virtualThunk, vm, nullptr, true));
    660689}
    661690
     
    678707        return;
    679708    }
    680    
    681     CodeBlock* callerCodeBlock = exec->callerFrame()->codeBlock();
    682     VM* vm = callerCodeBlock->vm();
    683    
     709
     710    CallFrame* callerFrame = exec->callerFrame();
     711    VM& vm = callerFrame->vm();
     712    CodeBlock* callerCodeBlock = callerFrame->codeBlock();
     713    bool isWebAssembly = isWebAssemblyToJSCallee(vm, callerFrame->callee());
     714
     715    // WebAssembly -> JS stubs don't have a valid CodeBlock.
     716    JSCell* owner = isWebAssembly ? webAssemblyOwner(vm) : callerCodeBlock;
     717    ASSERT(owner);
     718
    684719    CallVariantList list;
    685720    if (PolymorphicCallStubRoutine* stub = callLinkInfo.stub())
     
    710745    for (CallVariant variant : list) {
    711746        CodeBlock* codeBlock;
    712         if (variant.executable()->isHostFunction())
     747        if (isWebAssembly || variant.executable()->isHostFunction())
    713748            codeBlock = nullptr;
    714749        else {
     
    728763    // If we are over the limit, just use a normal virtual call.
    729764    unsigned maxPolymorphicCallVariantListSize;
    730     if (callerCodeBlock->jitType() == JITCode::topTierJIT())
     765    if (isWebAssembly)
     766        maxPolymorphicCallVariantListSize = Options::maxPolymorphicCallVariantListSizeForWebAssemblyToJS();
     767    else if (callerCodeBlock->jitType() == JITCode::topTierJIT())
    731768        maxPolymorphicCallVariantListSize = Options::maxPolymorphicCallVariantListSizeForTopTier();
    732769    else
    733770        maxPolymorphicCallVariantListSize = Options::maxPolymorphicCallVariantListSize();
     771
    734772    if (list.size() > maxPolymorphicCallVariantListSize) {
    735773        linkVirtualFor(exec, callLinkInfo);
     
    739777    GPRReg calleeGPR = static_cast<GPRReg>(callLinkInfo.calleeGPR());
    740778   
    741     CCallHelpers stubJit(vm, callerCodeBlock);
     779    CCallHelpers stubJit(&vm, callerCodeBlock);
    742780   
    743781    CCallHelpers::JumpList slowPath;
     
    788826    std::unique_ptr<uint32_t[]> fastCounts;
    789827   
    790     if (callerCodeBlock->jitType() != JITCode::topTierJIT())
     828    if (!isWebAssembly && callerCodeBlock->jitType() != JITCode::topTierJIT())
    791829        fastCounts = std::make_unique<uint32_t[]>(callCases.size());
    792830   
     
    885923    AssemblyHelpers::Jump slow = stubJit.jump();
    886924       
    887     LinkBuffer patchBuffer(*vm, stubJit, callerCodeBlock, JITCompilationCanFail);
     925    LinkBuffer patchBuffer(vm, stubJit, owner, JITCompilationCanFail);
    888926    if (patchBuffer.didFailToAllocate()) {
    889927        linkVirtualFor(exec, callLinkInfo);
     
    899937            callToCodePtr.call, FunctionPtr(isTailCall ? callToCodePtr.codePtr.dataLocation() : callToCodePtr.codePtr.executableAddress()));
    900938    }
    901     if (JITCode::isOptimizingJIT(callerCodeBlock->jitType()))
     939    if (isWebAssembly || JITCode::isOptimizingJIT(callerCodeBlock->jitType()))
    902940        patchBuffer.link(done, callLinkInfo.callReturnLocation().labelAtOffset(0));
    903941    else
    904942        patchBuffer.link(done, callLinkInfo.hotPathOther().labelAtOffset(0));
    905     patchBuffer.link(slow, CodeLocationLabel(vm->getCTIStub(linkPolymorphicCallThunkGenerator).code()));
     943    patchBuffer.link(slow, CodeLocationLabel(vm.getCTIStub(linkPolymorphicCallThunkGenerator).code()));
    906944   
    907945    auto stubRoutine = adoptRef(*new PolymorphicCallStubRoutine(
     
    909947            callerCodeBlock, patchBuffer,
    910948            ("Polymorphic call stub for %s, return point %p, targets %s",
    911                 toCString(*callerCodeBlock).data(), callLinkInfo.callReturnLocation().labelAtOffset(0).executableAddress(),
     949                isWebAssembly ? "WebAssembly" : toCString(*callerCodeBlock).data(), callLinkInfo.callReturnLocation().labelAtOffset(0).executableAddress(),
    912950                toCString(listDump(callCases)).data())),
    913         *vm, callerCodeBlock, exec->callerFrame(), callLinkInfo, callCases,
     951        vm, owner, exec->callerFrame(), callLinkInfo, callCases,
    914952        WTFMove(fastCounts)));
    915953   
     
    920958    // reachable on 32-bits since a non-cell callee will always
    921959    // trigger the slow path
    922     linkSlowFor(vm, callLinkInfo);
     960    linkSlowFor(&vm, callLinkInfo);
    923961   
    924962    // If there had been a previous stub routine, that one will die as soon as the GC runs and sees
Note: See TracChangeset for help on using the changeset viewer.