Title: [271186] trunk
Revision
271186
Author
[email protected]
Date
2021-01-05 19:03:43 -0800 (Tue, 05 Jan 2021)

Log Message

[JSC] DFG/FTL DirectCall need to respect Wasm IC
https://bugs.webkit.org/show_bug.cgi?id=220339

Reviewed by Saam Barati.

We found that Wasm IC for fast calls are not used in several places.

    1. LLInt calls
    2. DFG/FTL DirectCall
    3. Virtual calls

We noticed this because of r271112. r271112 made wasm function loading from exports constant-folded in DFG/FTL.
And it emits DirectCall instead of Call in DFG/FTL. Then, we missed Wasm IC and get large performance regression
in JetStream2 richard-wasm.

In this patch, we use Wasm IC as much as possible. The key thing of this wasm IC is that it relies on callee.
So, if the place is just checking Executable, then we should not go to that IC. Fortunately, the above three checks
callee before using code pointer obtained for Wasm IC.

    1. LLInt call fast path first checks callee.
    2. DFG/FTL DirectCall requires callee is constant for wasm functions.
    3. Virtual calls are not storing generated codePtr.

* dfg/DFGOperations.cpp:
(JSC::DFG::JSC_DEFINE_JIT_OPERATION):
* jit/JITOperations.cpp:
(JSC::virtualForWithFunction):
* llint/LLIntSlowPaths.cpp:
(JSC::LLInt::setUpCall):

Modified Paths

Diff

Modified: trunk/JSTests/stress/sampling-profiler/samplingProfiler.js (271185 => 271186)


--- trunk/JSTests/stress/sampling-profiler/samplingProfiler.js	2021-01-06 02:27:58 UTC (rev 271185)
+++ trunk/JSTests/stress/sampling-profiler/samplingProfiler.js	2021-01-06 03:03:43 UTC (rev 271186)
@@ -43,11 +43,13 @@
         stackTrace = [...stackTrace];
     
     let node = tree;
+    let prev = null;
     for (let i = stackTrace.length; i--; ) {
+        prev = node;
         node = node.children[stackTrace[i]];
         if (!node) {
             if (verbose)
-                print("failing on " + i + " : " + stackTrace[i]);
+                print("failing on " + i + " : " + stackTrace[i], " ", JSON.stringify(Object.getOwnPropertyNames(prev.children)));
             return false;
         }
     }

Modified: trunk/JSTests/stress/sampling-profiler-wasm-name-section.js (271185 => 271186)


--- trunk/JSTests/stress/sampling-profiler-wasm-name-section.js	2021-01-06 02:27:58 UTC (rev 271185)
+++ trunk/JSTests/stress/sampling-profiler-wasm-name-section.js	2021-01-06 03:03:43 UTC (rev 271186)
@@ -69,5 +69,5 @@
     var wasmEntry = function() {
         return instance.exports._parrot(1);
     };
-    runTest(wasmEntry, ["_silly", "(unknown)", "<?>.wasm-function[_eggs]", "<?>.wasm-function[_bacon]", "<?>.wasm-function[_spam]", "<?>.wasm-function[_parrot]", "wasm-stub", "24", "wasmEntry"]);
+    runTest(wasmEntry, ["_silly", "(unknown)", "<?>.wasm-function[_eggs]", "<?>.wasm-function[_bacon]", "<?>.wasm-function[_spam]", "<?>.wasm-function[_parrot]", "(unknown)", "wasmEntry"]);
 }

Modified: trunk/JSTests/stress/sampling-profiler-wasm.js (271185 => 271186)


--- trunk/JSTests/stress/sampling-profiler-wasm.js	2021-01-06 02:27:58 UTC (rev 271185)
+++ trunk/JSTests/stress/sampling-profiler-wasm.js	2021-01-06 03:03:43 UTC (rev 271186)
@@ -8,5 +8,5 @@
     var wasmEntry = function() {
         return instance.exports.loop(10000000);
     };
-    runTest(wasmEntry, ["<?>.wasm-function[0]", "wasm-stub", "0", "wasmEntry"]);
+    runTest(wasmEntry, ["<?>.wasm-function[0]", "(unknown)", "wasmEntry"]);
 }

Modified: trunk/JSTests/wasm/function-tests/nameSection.js (271185 => 271186)


--- trunk/JSTests/wasm/function-tests/nameSection.js	2021-01-06 02:27:58 UTC (rev 271185)
+++ trunk/JSTests/wasm/function-tests/nameSection.js	2021-01-06 03:03:43 UTC (rev 271186)
@@ -69,4 +69,4 @@
 assert.eq(stacktrace[3], "<?>.wasm-function[_bacon]@[wasm code]");
 assert.eq(stacktrace[4], "<?>.wasm-function[_spam]@[wasm code]");
 assert.eq(stacktrace[5], "<?>.wasm-function[_parrot]@[wasm code]");
-assert.eq(stacktrace[6], "wasm-stub@[wasm code]"); // wasm entry
+assert.eq(stacktrace[6], "wasm-stub@[native code]"); // wasm entry

Modified: trunk/Source/_javascript_Core/ChangeLog (271185 => 271186)


--- trunk/Source/_javascript_Core/ChangeLog	2021-01-06 02:27:58 UTC (rev 271185)
+++ trunk/Source/_javascript_Core/ChangeLog	2021-01-06 03:03:43 UTC (rev 271186)
@@ -1,5 +1,37 @@
 2021-01-05  Yusuke Suzuki  <[email protected]>
 
+        [JSC] DFG/FTL DirectCall need to respect Wasm IC
+        https://bugs.webkit.org/show_bug.cgi?id=220339
+
+        Reviewed by Saam Barati.
+
+        We found that Wasm IC for fast calls are not used in several places.
+
+            1. LLInt calls
+            2. DFG/FTL DirectCall
+            3. Virtual calls
+
+        We noticed this because of r271112. r271112 made wasm function loading from exports constant-folded in DFG/FTL.
+        And it emits DirectCall instead of Call in DFG/FTL. Then, we missed Wasm IC and get large performance regression
+        in JetStream2 richard-wasm.
+
+        In this patch, we use Wasm IC as much as possible. The key thing of this wasm IC is that it relies on callee.
+        So, if the place is just checking Executable, then we should not go to that IC. Fortunately, the above three checks
+        callee before using code pointer obtained for Wasm IC.
+
+            1. LLInt call fast path first checks callee.
+            2. DFG/FTL DirectCall requires callee is constant for wasm functions.
+            3. Virtual calls are not storing generated codePtr.
+
+        * dfg/DFGOperations.cpp:
+        (JSC::DFG::JSC_DEFINE_JIT_OPERATION):
+        * jit/JITOperations.cpp:
+        (JSC::virtualForWithFunction):
+        * llint/LLIntSlowPaths.cpp:
+        (JSC::LLInt::setUpCall):
+
+2021-01-05  Yusuke Suzuki  <[email protected]>
+
         [WASM] [BigInt] Add I64 to BigInt conversion
         https://bugs.webkit.org/show_bug.cgi?id=213528
 

Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.cpp (271185 => 271186)


--- trunk/Source/_javascript_Core/dfg/DFGOperations.cpp	2021-01-06 02:27:58 UTC (rev 271185)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.cpp	2021-01-06 03:03:43 UTC (rev 271186)
@@ -3550,9 +3550,13 @@
 
     MacroAssemblerCodePtr<JSEntryPtrTag> codePtr;
     CodeBlock* codeBlock = nullptr;
-    if (executable->isHostFunction())
-        codePtr = executable->entrypointFor(kind, MustCheckArity);
-    else {
+    if (executable->isHostFunction()) {
+        // jsToWasmICCodePtr assumes that callee is always the same since DirectCall does not check callee.
+        // But for wasm functions, we already ensured that callee is constant when emitting DirectCall.
+        codePtr = jsToWasmICCodePtr(vm, kind, callee);
+        if (!codePtr)
+            codePtr = executable->entrypointFor(kind, MustCheckArity);
+    } else {
         FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
 
         RELEASE_ASSERT(isCall(kind) || functionExecutable->constructAbility() != ConstructAbility::CannotConstruct);

Modified: trunk/Source/_javascript_Core/dfg/DFGStrengthReductionPhase.cpp (271185 => 271186)


--- trunk/Source/_javascript_Core/dfg/DFGStrengthReductionPhase.cpp	2021-01-06 02:27:58 UTC (rev 271185)
+++ trunk/Source/_javascript_Core/dfg/DFGStrengthReductionPhase.cpp	2021-01-06 03:03:43 UTC (rev 271186)
@@ -917,7 +917,8 @@
             ExecutableBase* executable = nullptr;
             Edge callee = m_graph.varArgChild(m_node, 0);
             CallVariant callVariant;
-            if (JSFunction* function = callee->dynamicCastConstant<JSFunction*>(vm())) {
+            JSFunction* function = callee->dynamicCastConstant<JSFunction*>(vm());
+            if (function) {
                 executable = function->executable();
                 callVariant = CallVariant(function);
             } else if (callee->isFunctionAllocation()) {
@@ -927,6 +928,15 @@
             
             if (!executable)
                 break;
+
+            // If this is wasm function, and callee is not an constant,
+            // we should not use DirectCall since it will emit Wasm IC based on the assumption that the callee is constant.
+            // Currently, there is no way to reach to this condition (since no function-allocation node generates WebAssemblyFunction),
+            // but this is good guard for the future extension.
+            if (executable->intrinsic() == WasmFunctionIntrinsic) {
+                if (!function)
+                    break;
+            }
             
             if (FunctionExecutable* functionExecutable = jsDynamicCast<FunctionExecutable*>(vm(), executable)) {
                 if (m_node->op() == Construct && functionExecutable->constructAbility() == ConstructAbility::CannotConstruct)

Modified: trunk/Source/_javascript_Core/jit/JITOperations.cpp (271185 => 271186)


--- trunk/Source/_javascript_Core/jit/JITOperations.cpp	2021-01-06 02:27:58 UTC (rev 271185)
+++ trunk/Source/_javascript_Core/jit/JITOperations.cpp	2021-01-06 03:03:43 UTC (rev 271186)
@@ -1389,8 +1389,14 @@
                 reinterpret_cast<void*>(KeepTheFrame));
         }
     }
-    return encodeResult(executable->entrypointFor(
-        kind, MustCheckArity).executableAddress(),
+
+    MacroAssemblerCodePtr<JSEntryPtrTag> codePtr;
+    if (executable->isHostFunction())
+        codePtr = jsToWasmICCodePtr(vm, kind, function);
+    if (!codePtr)
+        codePtr = executable->entrypointFor(kind, MustCheckArity);
+
+    return encodeResult(codePtr.executableAddress(),
         reinterpret_cast<void*>(callLinkInfo->callMode() == CallMode::Tail ? ReuseTheFrame : KeepTheFrame));
 }
 

Modified: trunk/Source/_javascript_Core/llint/LLIntSlowPaths.cpp (271185 => 271186)


--- trunk/Source/_javascript_Core/llint/LLIntSlowPaths.cpp	2021-01-06 02:27:58 UTC (rev 271185)
+++ trunk/Source/_javascript_Core/llint/LLIntSlowPaths.cpp	2021-01-06 03:03:43 UTC (rev 271186)
@@ -60,6 +60,7 @@
 #include "ObjectPropertyConditionSet.h"
 #include "ProtoCallFrameInlines.h"
 #include "RegExpObject.h"
+#include "Repatch.h"
 #include "ShadowChicken.h"
 #include "SuperSampler.h"
 #include "VMInlines.h"
@@ -1736,9 +1737,13 @@
 
     MacroAssemblerCodePtr<JSEntryPtrTag> codePtr;
     CodeBlock* codeBlock = nullptr;
-    if (executable->isHostFunction())
-        codePtr = executable->entrypointFor(kind, MustCheckArity);
-    else {
+    if (executable->isHostFunction()) {
+#if ENABLE(JIT)
+        codePtr = jsToWasmICCodePtr(vm, kind, callee);
+#endif
+        if (!codePtr)
+            codePtr = executable->entrypointFor(kind, MustCheckArity);
+    } else {
         FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
 
         if (!isCall(kind) && functionExecutable->constructAbility() == ConstructAbility::CannotConstruct)

Modified: trunk/Source/_javascript_Core/runtime/Intrinsic.cpp (271185 => 271186)


--- trunk/Source/_javascript_Core/runtime/Intrinsic.cpp	2021-01-06 02:27:58 UTC (rev 271185)
+++ trunk/Source/_javascript_Core/runtime/Intrinsic.cpp	2021-01-06 03:03:43 UTC (rev 271186)
@@ -337,6 +337,8 @@
         return "DataViewSetFloat32";
     case DataViewSetFloat64:
         return "DataViewSetFloat64";
+    case WasmFunctionIntrinsic:
+        return "WasmFunctionIntrinsic";
     }
     RELEASE_ASSERT_NOT_REACHED();
     return nullptr;

Modified: trunk/Source/_javascript_Core/runtime/Intrinsic.h (271185 => 271186)


--- trunk/Source/_javascript_Core/runtime/Intrinsic.h	2021-01-06 02:27:58 UTC (rev 271185)
+++ trunk/Source/_javascript_Core/runtime/Intrinsic.h	2021-01-06 03:03:43 UTC (rev 271186)
@@ -192,6 +192,8 @@
     DataViewSetUint32,
     DataViewSetFloat32,
     DataViewSetFloat64,
+
+    WasmFunctionIntrinsic,
 };
 
 Optional<IterationKind> interationKindForIntrinsic(Intrinsic);

Modified: trunk/Source/_javascript_Core/wasm/js/WebAssemblyFunction.cpp (271185 => 271186)


--- trunk/Source/_javascript_Core/wasm/js/WebAssemblyFunction.cpp	2021-01-06 02:27:58 UTC (rev 271185)
+++ trunk/Source/_javascript_Core/wasm/js/WebAssemblyFunction.cpp	2021-01-06 03:03:43 UTC (rev 271186)
@@ -434,7 +434,7 @@
 
 WebAssemblyFunction* WebAssemblyFunction::create(VM& vm, JSGlobalObject* globalObject, Structure* structure, unsigned length, const String& name, JSWebAssemblyInstance* instance, Wasm::Callee& jsEntrypoint, Wasm::WasmToWasmImportableFunction::LoadLocation wasmToWasmEntrypointLoadLocation, Wasm::SignatureIndex signatureIndex)
 {
-    NativeExecutable* executable = vm.getHostFunction(callWebAssemblyFunction, NoIntrinsic, callHostFunctionAsConstructor, nullptr, name);
+    NativeExecutable* executable = vm.getHostFunction(callWebAssemblyFunction, WasmFunctionIntrinsic, callHostFunctionAsConstructor, nullptr, name);
     WebAssemblyFunction* function = new (NotNull, allocateCell<WebAssemblyFunction>(vm.heap)) WebAssemblyFunction(vm, executable, globalObject, structure, jsEntrypoint, wasmToWasmEntrypointLoadLocation, signatureIndex);
     function->finishCreation(vm, executable, length, name, instance);
     return function;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to