⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 271186 in webkit


Ignore:
Timestamp:
Jan 5, 2021, 7:03:43 PM (6 years ago)
Author:
ysuzuki@apple.com
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):

Location:
trunk
Files:
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/stress/sampling-profiler-wasm-name-section.js

    r271112 r271186  
    7070        return instance.exports._parrot(1);
    7171    };
    72     runTest(wasmEntry, ["_silly", "(unknown)", "<?>.wasm-function[_eggs]", "<?>.wasm-function[_bacon]", "<?>.wasm-function[_spam]", "<?>.wasm-function[_parrot]", "wasm-stub", "24", "wasmEntry"]);
     72    runTest(wasmEntry, ["_silly", "(unknown)", "<?>.wasm-function[_eggs]", "<?>.wasm-function[_bacon]", "<?>.wasm-function[_spam]", "<?>.wasm-function[_parrot]", "(unknown)", "wasmEntry"]);
    7373}
  • trunk/JSTests/stress/sampling-profiler-wasm.js

    r271112 r271186  
    99        return instance.exports.loop(10000000);
    1010    };
    11     runTest(wasmEntry, ["<?>.wasm-function[0]", "wasm-stub", "0", "wasmEntry"]);
     11    runTest(wasmEntry, ["<?>.wasm-function[0]", "(unknown)", "wasmEntry"]);
    1212}
  • trunk/JSTests/stress/sampling-profiler/samplingProfiler.js

    r195376 r271186  
    4444   
    4545    let node = tree;
     46    let prev = null;
    4647    for (let i = stackTrace.length; i--; ) {
     48        prev = node;
    4749        node = node.children[stackTrace[i]];
    4850        if (!node) {
    4951            if (verbose)
    50                 print("failing on " + i + " : " + stackTrace[i]);
     52                print("failing on " + i + " : " + stackTrace[i], " ", JSON.stringify(Object.getOwnPropertyNames(prev.children)));
    5153            return false;
    5254        }
  • trunk/JSTests/wasm/function-tests/nameSection.js

    r246589 r271186  
    7070assert.eq(stacktrace[4], "<?>.wasm-function[_spam]@[wasm code]");
    7171assert.eq(stacktrace[5], "<?>.wasm-function[_parrot]@[wasm code]");
    72 assert.eq(stacktrace[6], "wasm-stub@[wasm code]"); // wasm entry
     72assert.eq(stacktrace[6], "wasm-stub@[native code]"); // wasm entry
  • trunk/Source/JavaScriptCore/ChangeLog

    r271168 r271186  
     12021-01-05  Yusuke Suzuki  <ysuzuki@apple.com>
     2
     3        [JSC] DFG/FTL DirectCall need to respect Wasm IC
     4        https://bugs.webkit.org/show_bug.cgi?id=220339
     5
     6        Reviewed by Saam Barati.
     7
     8        We found that Wasm IC for fast calls are not used in several places.
     9
     10            1. LLInt calls
     11            2. DFG/FTL DirectCall
     12            3. Virtual calls
     13
     14        We noticed this because of r271112. r271112 made wasm function loading from exports constant-folded in DFG/FTL.
     15        And it emits DirectCall instead of Call in DFG/FTL. Then, we missed Wasm IC and get large performance regression
     16        in JetStream2 richard-wasm.
     17
     18        In this patch, we use Wasm IC as much as possible. The key thing of this wasm IC is that it relies on callee.
     19        So, if the place is just checking Executable, then we should not go to that IC. Fortunately, the above three checks
     20        callee before using code pointer obtained for Wasm IC.
     21
     22            1. LLInt call fast path first checks callee.
     23            2. DFG/FTL DirectCall requires callee is constant for wasm functions.
     24            3. Virtual calls are not storing generated codePtr.
     25
     26        * dfg/DFGOperations.cpp:
     27        (JSC::DFG::JSC_DEFINE_JIT_OPERATION):
     28        * jit/JITOperations.cpp:
     29        (JSC::virtualForWithFunction):
     30        * llint/LLIntSlowPaths.cpp:
     31        (JSC::LLInt::setUpCall):
     32
    1332021-01-05  Yusuke Suzuki  <ysuzuki@apple.com>
    234
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp

    r270874 r271186  
    35513551    MacroAssemblerCodePtr<JSEntryPtrTag> codePtr;
    35523552    CodeBlock* codeBlock = nullptr;
    3553     if (executable->isHostFunction())
    3554         codePtr = executable->entrypointFor(kind, MustCheckArity);
    3555     else {
     3553    if (executable->isHostFunction()) {
     3554        // jsToWasmICCodePtr assumes that callee is always the same since DirectCall does not check callee.
     3555        // But for wasm functions, we already ensured that callee is constant when emitting DirectCall.
     3556        codePtr = jsToWasmICCodePtr(vm, kind, callee);
     3557        if (!codePtr)
     3558            codePtr = executable->entrypointFor(kind, MustCheckArity);
     3559    } else {
    35563560        FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
    35573561
  • trunk/Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp

    r261895 r271186  
    918918            Edge callee = m_graph.varArgChild(m_node, 0);
    919919            CallVariant callVariant;
    920             if (JSFunction* function = callee->dynamicCastConstant<JSFunction*>(vm())) {
     920            JSFunction* function = callee->dynamicCastConstant<JSFunction*>(vm());
     921            if (function) {
    921922                executable = function->executable();
    922923                callVariant = CallVariant(function);
     
    928929            if (!executable)
    929930                break;
     931
     932            // If this is wasm function, and callee is not an constant,
     933            // we should not use DirectCall since it will emit Wasm IC based on the assumption that the callee is constant.
     934            // Currently, there is no way to reach to this condition (since no function-allocation node generates WebAssemblyFunction),
     935            // but this is good guard for the future extension.
     936            if (executable->intrinsic() == WasmFunctionIntrinsic) {
     937                if (!function)
     938                    break;
     939            }
    930940           
    931941            if (FunctionExecutable* functionExecutable = jsDynamicCast<FunctionExecutable*>(vm(), executable)) {
  • trunk/Source/JavaScriptCore/jit/JITOperations.cpp

    r270874 r271186  
    13901390        }
    13911391    }
    1392     return encodeResult(executable->entrypointFor(
    1393         kind, MustCheckArity).executableAddress(),
     1392
     1393    MacroAssemblerCodePtr<JSEntryPtrTag> codePtr;
     1394    if (executable->isHostFunction())
     1395        codePtr = jsToWasmICCodePtr(vm, kind, function);
     1396    if (!codePtr)
     1397        codePtr = executable->entrypointFor(kind, MustCheckArity);
     1398
     1399    return encodeResult(codePtr.executableAddress(),
    13941400        reinterpret_cast<void*>(callLinkInfo->callMode() == CallMode::Tail ? ReuseTheFrame : KeepTheFrame));
    13951401}
  • trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp

    r269468 r271186  
    6161#include "ProtoCallFrameInlines.h"
    6262#include "RegExpObject.h"
     63#include "Repatch.h"
    6364#include "ShadowChicken.h"
    6465#include "SuperSampler.h"
     
    17371738    MacroAssemblerCodePtr<JSEntryPtrTag> codePtr;
    17381739    CodeBlock* codeBlock = nullptr;
    1739     if (executable->isHostFunction())
    1740         codePtr = executable->entrypointFor(kind, MustCheckArity);
    1741     else {
     1740    if (executable->isHostFunction()) {
     1741#if ENABLE(JIT)
     1742        codePtr = jsToWasmICCodePtr(vm, kind, callee);
     1743#endif
     1744        if (!codePtr)
     1745            codePtr = executable->entrypointFor(kind, MustCheckArity);
     1746    } else {
    17421747        FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
    17431748
  • trunk/Source/JavaScriptCore/runtime/Intrinsic.cpp

    r269531 r271186  
    338338    case DataViewSetFloat64:
    339339        return "DataViewSetFloat64";
     340    case WasmFunctionIntrinsic:
     341        return "WasmFunctionIntrinsic";
    340342    }
    341343    RELEASE_ASSERT_NOT_REACHED();
  • trunk/Source/JavaScriptCore/runtime/Intrinsic.h

    r269531 r271186  
    193193    DataViewSetFloat32,
    194194    DataViewSetFloat64,
     195
     196    WasmFunctionIntrinsic,
    195197};
    196198
  • trunk/Source/JavaScriptCore/wasm/js/WebAssemblyFunction.cpp

    r271168 r271186  
    435435WebAssemblyFunction* 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)
    436436{
    437     NativeExecutable* executable = vm.getHostFunction(callWebAssemblyFunction, NoIntrinsic, callHostFunctionAsConstructor, nullptr, name);
     437    NativeExecutable* executable = vm.getHostFunction(callWebAssemblyFunction, WasmFunctionIntrinsic, callHostFunctionAsConstructor, nullptr, name);
    438438    WebAssemblyFunction* function = new (NotNull, allocateCell<WebAssemblyFunction>(vm.heap)) WebAssemblyFunction(vm, executable, globalObject, structure, jsEntrypoint, wasmToWasmEntrypointLoadLocation, signatureIndex);
    439439    function->finishCreation(vm, executable, length, name, instance);
Note: See TracChangeset for help on using the changeset viewer.