<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[238376] trunk/Source/JavaScriptCore</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/238376">238376</a></dd>
<dt>Author</dt> <dd>yusukesuzuki@slowstart.org</dd>
<dt>Date</dt> <dd>2018-11-19 08:49:43 -0800 (Mon, 19 Nov 2018)</dd>
</dl>

<h3>Log Message</h3>
<pre>[WebAssembly] I64 arguments / return value check should be moved from callWebAssemblyFunction to JSToWasm wrapper
https://bugs.webkit.org/show_bug.cgi?id=190512

Reviewed by Keith Miller.

This patch moves I64 arguments / return value check from callWebAssemblyFunction to JSToWasm wrapper. Since this
check can be done when compiling the function, we should encode the result into the generated wrapper instead of
checking every time we call callWebAssemblyFunction. This change is also one of the steps removing callWebAssemblyFunction
entirely.

* wasm/WasmExceptionType.h:
* wasm/js/JSToWasm.cpp:
(JSC::Wasm::createJSToWasmWrapper):
* wasm/js/WebAssemblyFunction.cpp:
(JSC::callWebAssemblyFunction):
* wasm/js/WebAssemblyWrapperFunction.cpp:
(JSC::callWebAssemblyWrapperFunction):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmWasmExceptionTypeh">trunk/Source/JavaScriptCore/wasm/WasmExceptionType.h</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsJSToWasmcpp">trunk/Source/JavaScriptCore/wasm/js/JSToWasm.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsWebAssemblyFunctioncpp">trunk/Source/JavaScriptCore/wasm/js/WebAssemblyFunction.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorewasmjsWebAssemblyWrapperFunctioncpp">trunk/Source/JavaScriptCore/wasm/js/WebAssemblyWrapperFunction.cpp</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (238375 => 238376)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog    2018-11-19 16:31:22 UTC (rev 238375)
+++ trunk/Source/JavaScriptCore/ChangeLog       2018-11-19 16:49:43 UTC (rev 238376)
</span><span class="lines">@@ -1,3 +1,23 @@
</span><ins>+2018-11-19  Yusuke Suzuki  <yusukesuzuki@slowstart.org>
+
+        [WebAssembly] I64 arguments / return value check should be moved from callWebAssemblyFunction to JSToWasm wrapper
+        https://bugs.webkit.org/show_bug.cgi?id=190512
+
+        Reviewed by Keith Miller.
+
+        This patch moves I64 arguments / return value check from callWebAssemblyFunction to JSToWasm wrapper. Since this
+        check can be done when compiling the function, we should encode the result into the generated wrapper instead of
+        checking every time we call callWebAssemblyFunction. This change is also one of the steps removing callWebAssemblyFunction
+        entirely.
+
+        * wasm/WasmExceptionType.h:
+        * wasm/js/JSToWasm.cpp:
+        (JSC::Wasm::createJSToWasmWrapper):
+        * wasm/js/WebAssemblyFunction.cpp:
+        (JSC::callWebAssemblyFunction):
+        * wasm/js/WebAssemblyWrapperFunction.cpp:
+        (JSC::callWebAssemblyWrapperFunction):
+
</ins><span class="cx"> 2018-11-12  Yusuke Suzuki  <yusukesuzuki@slowstart.org>
</span><span class="cx"> 
</span><span class="cx">         Consider removing double load for accessing the instructions from LLInt
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmWasmExceptionTypeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/WasmExceptionType.h (238375 => 238376)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/WasmExceptionType.h     2018-11-19 16:31:22 UTC (rev 238375)
+++ trunk/Source/JavaScriptCore/wasm/WasmExceptionType.h        2018-11-19 16:49:43 UTC (rev 238376)
</span><span class="lines">@@ -40,7 +40,9 @@
</span><span class="cx">     macro(Unreachable, "Unreachable code should not be executed") \
</span><span class="cx">     macro(DivisionByZero, "Division by zero") \
</span><span class="cx">     macro(IntegerOverflow, "Integer overflow") \
</span><del>-    macro(StackOverflow, "Stack overflow")
</del><ins>+    macro(StackOverflow, "Stack overflow") \
+    macro(I64ArgumentType, "WebAssembly function with an i64 argument can't be called from JavaScript") \
+    macro(I64ReturnType, "WebAssembly function that returns i64 can't be called from JavaScript")
</ins><span class="cx"> 
</span><span class="cx"> enum class ExceptionType : uint32_t {
</span><span class="cx"> #define MAKE_ENUM(enumName, error) enumName,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsJSToWasmcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/JSToWasm.cpp (238375 => 238376)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/JSToWasm.cpp 2018-11-19 16:31:22 UTC (rev 238375)
+++ trunk/Source/JavaScriptCore/wasm/js/JSToWasm.cpp    2018-11-19 16:49:43 UTC (rev 238376)
</span><span class="lines">@@ -30,9 +30,12 @@
</span><span class="cx"> 
</span><span class="cx"> #include "CCallHelpers.h"
</span><span class="cx"> #include "JSWebAssemblyInstance.h"
</span><ins>+#include "JSWebAssemblyRuntimeError.h"
+#include "MaxFrameExtentForSlowPathCall.h"
</ins><span class="cx"> #include "WasmCallingConvention.h"
</span><span class="cx"> #include "WasmContextInlines.h"
</span><span class="cx"> #include "WasmSignatureInlines.h"
</span><ins>+#include "WasmToJS.h"
</ins><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace Wasm {
</span><span class="cx"> 
</span><span class="lines">@@ -70,9 +73,12 @@
</span><span class="cx">     totalFrameSize -= sizeof(CallerFrameAndPC);
</span><span class="cx">     unsigned numGPRs = 0;
</span><span class="cx">     unsigned numFPRs = 0;
</span><ins>+    bool argumentsIncludeI64 = false;
</ins><span class="cx">     for (unsigned i = 0; i < signature.argumentCount(); i++) {
</span><span class="cx">         switch (signature.argument(i)) {
</span><span class="cx">         case Wasm::I64:
</span><ins>+            argumentsIncludeI64 = true;
+            FALLTHROUGH;
</ins><span class="cx">         case Wasm::I32:
</span><span class="cx">             if (numGPRs >= wasmCallingConvention().m_gprArgs.size())
</span><span class="cx">                 totalFrameSize += sizeof(void*);
</span><span class="lines">@@ -102,6 +108,36 @@
</span><span class="cx">         jit.storePtr(reg, CCallHelpers::Address(GPRInfo::callFrameRegister, offset));
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    if (argumentsIncludeI64 || signature.returnType() == Wasm::I64) {
+        if (Context::useFastTLS())
+            jit.loadWasmContextInstance(GPRInfo::argumentGPR2);
+        else {
+            // vmEntryToWasm passes the JSWebAssemblyInstance corresponding to Wasm::Context*'s
+            // instance as the first JS argument when we're not using fast TLS to hold the
+            // Wasm::Context*'s instance.
+            jit.loadPtr(CCallHelpers::Address(GPRInfo::callFrameRegister, CallFrameSlot::thisArgument * sizeof(EncodedJSValue)), GPRInfo::argumentGPR2);
+            jit.loadPtr(CCallHelpers::Address(GPRInfo::argumentGPR2, JSWebAssemblyInstance::offsetOfPoisonedInstance()), GPRInfo::argumentGPR2);
+            jit.move(CCallHelpers::TrustedImm64(JSWebAssemblyInstancePoison::key()), GPRInfo::argumentGPR0);
+            jit.xor64(GPRInfo::argumentGPR0, GPRInfo::argumentGPR2);
+        }
+
+        jit.loadPtr(CCallHelpers::Address(GPRInfo::argumentGPR2, Instance::offsetOfPointerToTopEntryFrame()), GPRInfo::argumentGPR0);
+        jit.loadPtr(CCallHelpers::Address(GPRInfo::argumentGPR0), GPRInfo::argumentGPR0);
+        jit.copyCalleeSavesToEntryFrameCalleeSavesBuffer(GPRInfo::argumentGPR0);
+        jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);
+        jit.move(CCallHelpers::TrustedImm32(static_cast<int32_t>(argumentsIncludeI64 ? ExceptionType::I64ArgumentType : ExceptionType::I64ReturnType)), GPRInfo::argumentGPR1);
+
+        CCallHelpers::Call call = jit.call(OperationPtrTag);
+
+        jit.jump(GPRInfo::returnValueGPR, ExceptionHandlerPtrTag);
+        jit.breakpoint(); // We should not reach this.
+
+        jit.addLinkTask([=] (LinkBuffer& linkBuffer) {
+            linkBuffer.link(call, FunctionPtr<OperationPtrTag>(wasmToJSException));
+        });
+        return result;
+    }
+
</ins><span class="cx">     GPRReg wasmContextInstanceGPR = pinnedRegs.wasmContextInstancePointer;
</span><span class="cx"> 
</span><span class="cx">     {
</span><span class="lines">@@ -200,7 +236,6 @@
</span><span class="cx">         unlinkedWasmToWasmCalls->append({ linkBuffer.locationOfNearCall<WasmEntryPtrTag>(call), functionIndexSpace });
</span><span class="cx">     });
</span><span class="cx"> 
</span><del>-
</del><span class="cx">     for (const RegisterAtOffset& regAtOffset : registersToSpill) {
</span><span class="cx">         GPRReg reg = regAtOffset.reg().gpr();
</span><span class="cx">         ASSERT(reg != GPRInfo::returnValueGPR);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsWebAssemblyFunctioncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/WebAssemblyFunction.cpp (238375 => 238376)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/WebAssemblyFunction.cpp      2018-11-19 16:31:22 UTC (rev 238375)
+++ trunk/Source/JavaScriptCore/wasm/js/WebAssemblyFunction.cpp 2018-11-19 16:49:43 UTC (rev 238376)
</span><span class="lines">@@ -55,32 +55,13 @@
</span><span class="cx"> {
</span><span class="cx">     VM& vm = exec->vm();
</span><span class="cx">     auto scope = DECLARE_THROW_SCOPE(vm);
</span><del>-    WebAssemblyFunction* wasmFunction = jsDynamicCast<WebAssemblyFunction*>(vm, exec->jsCallee());
-    if (!wasmFunction)
-        return JSValue::encode(throwException(exec, scope, createTypeError(exec, "expected a WebAssembly function", defaultSourceAppender, runtimeTypeForValue(vm, exec->jsCallee()))));
</del><ins>+    WebAssemblyFunction* wasmFunction = jsCast<WebAssemblyFunction*>(exec->jsCallee());
</ins><span class="cx">     Wasm::SignatureIndex signatureIndex = wasmFunction->signatureIndex();
</span><span class="cx">     const Wasm::Signature& signature = Wasm::SignatureInformation::get(signatureIndex);
</span><span class="cx"> 
</span><span class="cx">     // Make sure that the memory we think we are going to run with matches the one we expect.
</span><span class="cx">     ASSERT(wasmFunction->instance()->instance().codeBlock()->isSafeToRun(wasmFunction->instance()->memory()->memory().mode()));
</span><del>-    {
-        // Check if we have a disallowed I64 use.
</del><span class="cx"> 
</span><del>-        for (unsigned argIndex = 0; argIndex < signature.argumentCount(); ++argIndex) {
-            if (signature.argument(argIndex) == Wasm::I64) {
-                JSWebAssemblyRuntimeError* error = JSWebAssemblyRuntimeError::create(exec, vm, exec->lexicalGlobalObject()->WebAssemblyRuntimeErrorStructure(),
-                    "WebAssembly function with an i64 argument can't be called from JavaScript");
-                return JSValue::encode(throwException(exec, scope, error));
-            }
-        }
-
-        if (signature.returnType() == Wasm::I64) {
-            JSWebAssemblyRuntimeError* error = JSWebAssemblyRuntimeError::create(exec, vm, exec->lexicalGlobalObject()->WebAssemblyRuntimeErrorStructure(),
-                "WebAssembly function that returns i64 can't be called from JavaScript");
-            return JSValue::encode(throwException(exec, scope, error));
-        }
-    }
-
</del><span class="cx">     std::optional<TraceScope> traceScope;
</span><span class="cx">     if (Options::useTracePoints())
</span><span class="cx">         traceScope.emplace(WebAssemblyExecuteStart, WebAssemblyExecuteEnd);
</span><span class="lines">@@ -99,6 +80,9 @@
</span><span class="cx">         case Wasm::I32:
</span><span class="cx">             arg = JSValue::decode(arg.toInt32(exec));
</span><span class="cx">             break;
</span><ins>+        case Wasm::I64:
+            arg = JSValue();
+            break;
</ins><span class="cx">         case Wasm::F32:
</span><span class="cx">             arg = JSValue::decode(bitwise_cast<uint32_t>(arg.toFloat(exec)));
</span><span class="cx">             break;
</span><span class="lines">@@ -106,7 +90,6 @@
</span><span class="cx">             arg = JSValue::decode(bitwise_cast<uint64_t>(arg.toNumber(exec)));
</span><span class="cx">             break;
</span><span class="cx">         case Wasm::Void:
</span><del>-        case Wasm::I64:
</del><span class="cx">         case Wasm::Func:
</span><span class="cx">         case Wasm::Anyfunc:
</span><span class="cx">             RELEASE_ASSERT_NOT_REACHED();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorewasmjsWebAssemblyWrapperFunctioncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/wasm/js/WebAssemblyWrapperFunction.cpp (238375 => 238376)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/wasm/js/WebAssemblyWrapperFunction.cpp       2018-11-19 16:31:22 UTC (rev 238375)
+++ trunk/Source/JavaScriptCore/wasm/js/WebAssemblyWrapperFunction.cpp  2018-11-19 16:49:43 UTC (rev 238376)
</span><span class="lines">@@ -42,10 +42,7 @@
</span><span class="cx"> {
</span><span class="cx">     VM& vm = exec->vm();
</span><span class="cx">     auto scope = DECLARE_THROW_SCOPE(vm);
</span><del>-    WebAssemblyWrapperFunction* wasmFunction = jsDynamicCast<WebAssemblyWrapperFunction*>(vm, exec->jsCallee());
-    if (!wasmFunction)
-        return JSValue::encode(throwException(exec, scope, createTypeError(exec, "expected a WebAssembly function")));
-
</del><ins>+    WebAssemblyWrapperFunction* wasmFunction = jsCast<WebAssemblyWrapperFunction*>(exec->jsCallee());
</ins><span class="cx">     CallData callData;
</span><span class="cx">     JSObject* function = wasmFunction->function();
</span><span class="cx">     CallType callType = function->methodTable(vm)->getCallData(function, callData);
</span></span></pre>
</div>
</div>

</body>
</html>