Title: [249069] trunk
Revision
249069
Author
justin_mich...@apple.com
Date
2019-08-23 14:33:08 -0700 (Fri, 23 Aug 2019)

Log 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/_javascript_Core:

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):

Modified Paths

Diff

Modified: trunk/JSTests/ChangeLog (249068 => 249069)


--- trunk/JSTests/ChangeLog	2019-08-23 21:21:51 UTC (rev 249068)
+++ trunk/JSTests/ChangeLog	2019-08-23 21:33:08 UTC (rev 249069)
@@ -1,3 +1,13 @@
+2019-08-23  Justin Michaud  <justin_mich...@apple.com>
+
+        [WASM-References] Do not overwrite argument registers in jsCallEntrypoint
+        https://bugs.webkit.org/show_bug.cgi?id=200952
+
+        Reviewed by Saam Barati.
+
+        * wasm/references/func_ref.js:
+        (assert.throws):
+
 2019-08-22  Justin Michaud  <justin_mich...@apple.com>
 
         Add missing exception check in canonicalizeLocaleList

Modified: trunk/JSTests/wasm/references/func_ref.js (249068 => 249069)


--- trunk/JSTests/wasm/references/func_ref.js	2019-08-23 21:21:51 UTC (rev 249068)
+++ trunk/JSTests/wasm/references/func_ref.js	2019-08-23 21:33:08 UTC (rev 249069)
@@ -448,3 +448,62 @@
         }
     }
 }
+
+{
+    const $1 = new WebAssembly.Instance(new WebAssembly.Module((new Builder())
+      .Type().End()
+      .Import().End()
+      .Function().End()
+      .Export()
+          .Function("test")
+      .End()
+      .Code()
+        .Function("test", { params: ["i32", "funcref"], ret: "i32" })
+          .GetLocal(0)
+        .End()
+      .End().WebAssembly().get()), { });
+
+    const myfun = makeExportedFunction(1337);
+    assert.eq(myfun(), 1337)
+    assert.eq(42, $1.exports.test(42, myfun))
+    assert.throws(() => $1.exports.test(42, () => 5), Error, "Funcref must be an exported wasm function (evaluating 'func(...args)')")
+}
+
+{
+    const $1 = new WebAssembly.Instance(new WebAssembly.Module((new Builder())
+      .Type().End()
+      .Import().End()
+      .Function().End()
+      .Export()
+          .Function("test")
+      .End()
+      .Code()
+        .Function("test", { params: ["i32", "funcref"], ret: "i32" })
+          .GetLocal(0)
+          .If("i32")
+          .Block("i32", (b) =>
+            b.GetLocal(0)
+            .GetLocal(1)
+            .Call(0)
+          )
+          .Else()
+          .Block("i32", (b) =>
+            b.GetLocal(0)
+          )
+          .End()
+        .End()
+      .End().WebAssembly().get()), { });
+
+    const myfun = makeExportedFunction(1337);
+    function foo(b) {
+        $1.exports.test(b, myfun)
+    }
+    noInline(foo);
+
+    for (let i = 0; i < 100; ++i)
+        foo(0);
+
+    assert.throws(() => $1.exports.test(42, () => 5), Error, "Funcref must be an exported wasm function (evaluating 'func(...args)')")
+    assert.throws(() => $1.exports.test(42, myfun), RangeError, "Maximum call stack size exceeded.")
+    assert.throws(() => foo(1), RangeError, "Maximum call stack size exceeded.")
+}

Modified: trunk/Source/_javascript_Core/ChangeLog (249068 => 249069)


--- trunk/Source/_javascript_Core/ChangeLog	2019-08-23 21:21:51 UTC (rev 249068)
+++ trunk/Source/_javascript_Core/ChangeLog	2019-08-23 21:33:08 UTC (rev 249069)
@@ -1,3 +1,17 @@
+2019-08-23  Justin Michaud  <justin_mich...@apple.com>
+
+        [WASM-References] Do not overwrite argument registers in jsCallEntrypoint
+        https://bugs.webkit.org/show_bug.cgi?id=200952
+
+        Reviewed by Saam Barati.
+
+        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):
+
 2019-08-23  Ross Kirsling  <ross.kirsl...@sony.com>
 
         JSC should have public API for unhandled promise rejections

Modified: trunk/Source/_javascript_Core/wasm/js/WebAssemblyFunction.cpp (249068 => 249069)


--- trunk/Source/_javascript_Core/wasm/js/WebAssemblyFunction.cpp	2019-08-23 21:21:51 UTC (rev 249068)
+++ trunk/Source/_javascript_Core/wasm/js/WebAssemblyFunction.cpp	2019-08-23 21:33:08 UTC (rev 249069)
@@ -266,12 +266,13 @@
     }
 
     GPRReg scratchGPR = Wasm::wasmCallingConventionAir().prologueScratch(1);
-    GPRReg scratch2GPR = Wasm::wasmCallingConventionAir().prologueScratch(0);
-    jit.loadPtr(vm.addressOfSoftStackLimit(), scratch2GPR);
+    bool stackLimitGPRIsClobbered = false;
+    GPRReg stackLimitGPR = Wasm::wasmCallingConventionAir().prologueScratch(0);
+    jit.loadPtr(vm.addressOfSoftStackLimit(), stackLimitGPR);
 
     CCallHelpers::JumpList slowPath;
     slowPath.append(jit.branchPtr(CCallHelpers::Above, MacroAssembler::stackPointerRegister, GPRInfo::callFrameRegister));
-    slowPath.append(jit.branchPtr(CCallHelpers::Below, MacroAssembler::stackPointerRegister, scratch2GPR));
+    slowPath.append(jit.branchPtr(CCallHelpers::Below, MacroAssembler::stackPointerRegister, stackLimitGPR));
 
     // Ensure:
     // argCountPlusThis - 1 >= signature.argumentCount()
@@ -310,24 +311,23 @@
                 }
                 break;
             case Wasm::Funcref: {
-                // FIXME: Emit this inline <https://bugs.webkit.org/show_bug.cgi?id=198506>.
-                bool (*shouldThrow)(Wasm::Instance*, JSValue) = [] (Wasm::Instance* wasmInstance, JSValue arg) -> bool {
-                    JSWebAssemblyInstance* instance = wasmInstance->owner<JSWebAssemblyInstance>();
-                    JSGlobalObject* globalObject = instance->globalObject();
-                    VM& vm = globalObject->vm();
-                    return !isWebAssemblyHostFunction(vm, arg) && !arg.isNull();
-                };
-                jit.move(CCallHelpers::TrustedImmPtr(&instance()->instance()), GPRInfo::argumentGPR0);
-                jit.load64(CCallHelpers::Address(GPRInfo::callFrameRegister, jsOffset), GPRInfo::argumentGPR1);
-                jit.setupArguments<decltype(shouldThrow)>(GPRInfo::argumentGPR0, GPRInfo::argumentGPR1);
-                auto call = jit.call(OperationPtrTag);
+                // Ensure we have a WASM exported function.
+                jit.load64(CCallHelpers::Address(GPRInfo::callFrameRegister, jsOffset), scratchGPR);
+                auto isNull = jit.branchIfNull(scratchGPR);
+                slowPath.append(jit.branchIfNotCell(scratchGPR));
 
-                jit.addLinkTask([=] (LinkBuffer& linkBuffer) {
-                    linkBuffer.link(call, FunctionPtr<OperationPtrTag>(shouldThrow));
-                });
+                stackLimitGPRIsClobbered = true;
+                jit.emitLoadStructure(vm, scratchGPR, scratchGPR, stackLimitGPR);
+                jit.loadPtr(CCallHelpers::Address(scratchGPR, Structure::classInfoOffset()), scratchGPR);
 
-                slowPath.append(jit.branchTest32(CCallHelpers::NonZero, GPRInfo::returnValueGPR));
+                static_assert(std::is_final<WebAssemblyFunction>::value, "We do not check for subtypes below");
+                static_assert(std::is_final<WebAssemblyWrapperFunction>::value, "We do not check for subtypes below");
 
+                auto isWasmFunction = jit.branchPtr(CCallHelpers::Equal, scratchGPR, CCallHelpers::TrustedImmPtr(WebAssemblyFunction::info()));
+                slowPath.append(jit.branchPtr(CCallHelpers::NotEqual, scratchGPR, CCallHelpers::TrustedImmPtr(WebAssemblyWrapperFunction::info())));
+
+                isWasmFunction.link(&jit);
+                isNull.link(&jit);
                 FALLTHROUGH;
             }
             case Wasm::Anyref: {
@@ -432,12 +432,13 @@
         jit.move(scratchGPR, pinnedRegs.wasmContextInstancePointer);
         jit.storePtr(scratchGPR, vm.wasmContext.pointerToInstance());
     }
-    // This contains the cached stack limit still.
-    jit.storePtr(scratch2GPR, CCallHelpers::Address(scratchGPR, Wasm::Instance::offsetOfCachedStackLimit()));
+    if (stackLimitGPRIsClobbered)
+        jit.loadPtr(vm.addressOfSoftStackLimit(), stackLimitGPR);
+    jit.storePtr(stackLimitGPR, CCallHelpers::Address(scratchGPR, Wasm::Instance::offsetOfCachedStackLimit()));
 
     if (!!moduleInformation.memory) {
         GPRReg baseMemory = pinnedRegs.baseMemoryPointer;
-        GPRReg scratchOrSize = scratch2GPR;
+        GPRReg scratchOrSize = stackLimitGPR;
         auto mode = instance()->memoryMode();
 
         if (isARM64E()) {
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to