Changeset 249069 in webkit


Ignore:
Timestamp:
Aug 23, 2019 2:33:08 PM (5 years ago)
Author:
Justin Michaud
Message:

[WASM-References] Do not overwrite argument registers in jsCallEntrypoint
https://bugs.webkit.org/show_bug.cgi?id=200952

Reviewed by Saam Barati.

JSTests:

  • wasm/references/func_ref.js:

(assert.throws):

Source/JavaScriptCore:

The c call that we emitted was incorrect. If we had an int argument that was supposed to be placed in GPR0 by this loop,
we would clobber it while making the call (among many other possible registers). To fix this, we just inline the call
to isWebassemblyHostFunction.

  • wasm/js/WebAssemblyFunction.cpp:

(JSC::WebAssemblyFunction::jsCallEntrypointSlow):

Location:
trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r249020 r249069  
     12019-08-23  Justin Michaud  <justin_michaud@apple.com>
     2
     3        [WASM-References] Do not overwrite argument registers in jsCallEntrypoint
     4        https://bugs.webkit.org/show_bug.cgi?id=200952
     5
     6        Reviewed by Saam Barati.
     7
     8        * wasm/references/func_ref.js:
     9        (assert.throws):
     10
    1112019-08-22  Justin Michaud  <justin_michaud@apple.com>
    212
  • trunk/JSTests/wasm/references/func_ref.js

    r247036 r249069  
    449449    }
    450450}
     451
     452{
     453    const $1 = new WebAssembly.Instance(new WebAssembly.Module((new Builder())
     454      .Type().End()
     455      .Import().End()
     456      .Function().End()
     457      .Export()
     458          .Function("test")
     459      .End()
     460      .Code()
     461        .Function("test", { params: ["i32", "funcref"], ret: "i32" })
     462          .GetLocal(0)
     463        .End()
     464      .End().WebAssembly().get()), { });
     465
     466    const myfun = makeExportedFunction(1337);
     467    assert.eq(myfun(), 1337)
     468    assert.eq(42, $1.exports.test(42, myfun))
     469    assert.throws(() => $1.exports.test(42, () => 5), Error, "Funcref must be an exported wasm function (evaluating 'func(...args)')")
     470}
     471
     472{
     473    const $1 = new WebAssembly.Instance(new WebAssembly.Module((new Builder())
     474      .Type().End()
     475      .Import().End()
     476      .Function().End()
     477      .Export()
     478          .Function("test")
     479      .End()
     480      .Code()
     481        .Function("test", { params: ["i32", "funcref"], ret: "i32" })
     482          .GetLocal(0)
     483          .If("i32")
     484          .Block("i32", (b) =>
     485            b.GetLocal(0)
     486            .GetLocal(1)
     487            .Call(0)
     488          )
     489          .Else()
     490          .Block("i32", (b) =>
     491            b.GetLocal(0)
     492          )
     493          .End()
     494        .End()
     495      .End().WebAssembly().get()), { });
     496
     497    const myfun = makeExportedFunction(1337);
     498    function foo(b) {
     499        $1.exports.test(b, myfun)
     500    }
     501    noInline(foo);
     502
     503    for (let i = 0; i < 100; ++i)
     504        foo(0);
     505
     506    assert.throws(() => $1.exports.test(42, () => 5), Error, "Funcref must be an exported wasm function (evaluating 'func(...args)')")
     507    assert.throws(() => $1.exports.test(42, myfun), RangeError, "Maximum call stack size exceeded.")
     508    assert.throws(() => foo(1), RangeError, "Maximum call stack size exceeded.")
     509}
  • trunk/Source/JavaScriptCore/ChangeLog

    r249058 r249069  
     12019-08-23  Justin Michaud  <justin_michaud@apple.com>
     2
     3        [WASM-References] Do not overwrite argument registers in jsCallEntrypoint
     4        https://bugs.webkit.org/show_bug.cgi?id=200952
     5
     6        Reviewed by Saam Barati.
     7
     8        The c call that we emitted was incorrect. If we had an int argument that was supposed to be placed in GPR0 by this loop,
     9        we would clobber it while making the call (among many other possible registers). To fix this, we just inline the call
     10        to isWebassemblyHostFunction.
     11
     12        * wasm/js/WebAssemblyFunction.cpp:
     13        (JSC::WebAssemblyFunction::jsCallEntrypointSlow):
     14
    1152019-08-23  Ross Kirsling  <ross.kirsling@sony.com>
    216
  • trunk/Source/JavaScriptCore/wasm/js/WebAssemblyFunction.cpp

    r246596 r249069  
    267267
    268268    GPRReg scratchGPR = Wasm::wasmCallingConventionAir().prologueScratch(1);
    269     GPRReg scratch2GPR = Wasm::wasmCallingConventionAir().prologueScratch(0);
    270     jit.loadPtr(vm.addressOfSoftStackLimit(), scratch2GPR);
     269    bool stackLimitGPRIsClobbered = false;
     270    GPRReg stackLimitGPR = Wasm::wasmCallingConventionAir().prologueScratch(0);
     271    jit.loadPtr(vm.addressOfSoftStackLimit(), stackLimitGPR);
    271272
    272273    CCallHelpers::JumpList slowPath;
    273274    slowPath.append(jit.branchPtr(CCallHelpers::Above, MacroAssembler::stackPointerRegister, GPRInfo::callFrameRegister));
    274     slowPath.append(jit.branchPtr(CCallHelpers::Below, MacroAssembler::stackPointerRegister, scratch2GPR));
     275    slowPath.append(jit.branchPtr(CCallHelpers::Below, MacroAssembler::stackPointerRegister, stackLimitGPR));
    275276
    276277    // Ensure:
     
    311312                break;
    312313            case Wasm::Funcref: {
    313                 // FIXME: Emit this inline <https://bugs.webkit.org/show_bug.cgi?id=198506>.
    314                 bool (*shouldThrow)(Wasm::Instance*, JSValue) = [] (Wasm::Instance* wasmInstance, JSValue arg) -> bool {
    315                     JSWebAssemblyInstance* instance = wasmInstance->owner<JSWebAssemblyInstance>();
    316                     JSGlobalObject* globalObject = instance->globalObject();
    317                     VM& vm = globalObject->vm();
    318                     return !isWebAssemblyHostFunction(vm, arg) && !arg.isNull();
    319                 };
    320                 jit.move(CCallHelpers::TrustedImmPtr(&instance()->instance()), GPRInfo::argumentGPR0);
    321                 jit.load64(CCallHelpers::Address(GPRInfo::callFrameRegister, jsOffset), GPRInfo::argumentGPR1);
    322                 jit.setupArguments<decltype(shouldThrow)>(GPRInfo::argumentGPR0, GPRInfo::argumentGPR1);
    323                 auto call = jit.call(OperationPtrTag);
    324 
    325                 jit.addLinkTask([=] (LinkBuffer& linkBuffer) {
    326                     linkBuffer.link(call, FunctionPtr<OperationPtrTag>(shouldThrow));
    327                 });
    328 
    329                 slowPath.append(jit.branchTest32(CCallHelpers::NonZero, GPRInfo::returnValueGPR));
    330 
     314                // Ensure we have a WASM exported function.
     315                jit.load64(CCallHelpers::Address(GPRInfo::callFrameRegister, jsOffset), scratchGPR);
     316                auto isNull = jit.branchIfNull(scratchGPR);
     317                slowPath.append(jit.branchIfNotCell(scratchGPR));
     318
     319                stackLimitGPRIsClobbered = true;
     320                jit.emitLoadStructure(vm, scratchGPR, scratchGPR, stackLimitGPR);
     321                jit.loadPtr(CCallHelpers::Address(scratchGPR, Structure::classInfoOffset()), scratchGPR);
     322
     323                static_assert(std::is_final<WebAssemblyFunction>::value, "We do not check for subtypes below");
     324                static_assert(std::is_final<WebAssemblyWrapperFunction>::value, "We do not check for subtypes below");
     325
     326                auto isWasmFunction = jit.branchPtr(CCallHelpers::Equal, scratchGPR, CCallHelpers::TrustedImmPtr(WebAssemblyFunction::info()));
     327                slowPath.append(jit.branchPtr(CCallHelpers::NotEqual, scratchGPR, CCallHelpers::TrustedImmPtr(WebAssemblyWrapperFunction::info())));
     328
     329                isWasmFunction.link(&jit);
     330                isNull.link(&jit);
    331331                FALLTHROUGH;
    332332            }
     
    433433        jit.storePtr(scratchGPR, vm.wasmContext.pointerToInstance());
    434434    }
    435     // This contains the cached stack limit still.
    436     jit.storePtr(scratch2GPR, CCallHelpers::Address(scratchGPR, Wasm::Instance::offsetOfCachedStackLimit()));
     435    if (stackLimitGPRIsClobbered)
     436        jit.loadPtr(vm.addressOfSoftStackLimit(), stackLimitGPR);
     437    jit.storePtr(stackLimitGPR, CCallHelpers::Address(scratchGPR, Wasm::Instance::offsetOfCachedStackLimit()));
    437438
    438439    if (!!moduleInformation.memory) {
    439440        GPRReg baseMemory = pinnedRegs.baseMemoryPointer;
    440         GPRReg scratchOrSize = scratch2GPR;
     441        GPRReg scratchOrSize = stackLimitGPR;
    441442        auto mode = instance()->memoryMode();
    442443
Note: See TracChangeset for help on using the changeset viewer.