Title: [291875] trunk/Source/_javascript_Core
Revision
291875
Author
ysuz...@apple.com
Date
2022-03-25 12:08:48 -0700 (Fri, 25 Mar 2022)

Log Message

[JSC] Use Data CallIC in unlinked DFG
https://bugs.webkit.org/show_bug.cgi?id=238176

Reviewed by Saam Barati.

This patch enables Data CallIC when Options::useDataICInOptimizingJIT() is true
to pave the way to introducing unlinked DFG.

The most complicated part is DFG tail call handling. We load CallLinkInfo in one
non-callee-save register, and we set up CallFrameShuffleData to keep this value
in the same register even after call frame shuffling for the tail call. This must
be non-callee-save register since callee-save registers are restored to values
of the one-level upper caller for the tail-call.

We also clean up CallLinkInfo code so that many functions work well with DataIC.
Currently, direct calls are not supported, and we will not emit direct calls when
unlinked DFG is used.

* bytecode/AccessCase.cpp:
(JSC::AccessCase::generateImpl):
* bytecode/CallLinkInfo.cpp:
(JSC::BaselineCallLinkInfo::initialize):
(JSC::OptimizingCallLinkInfo::emitFastPath):
(JSC::OptimizingCallLinkInfo::emitTailCallFastPath):
(JSC::OptimizingCallLinkInfo::slowPathStart):
(JSC::OptimizingCallLinkInfo::emitDirectFastPath):
(JSC::OptimizingCallLinkInfo::emitDirectTailCallFastPath):
* bytecode/CallLinkInfo.h:
(JSC::CallLinkInfo::isDataIC const):
(JSC::CallLinkInfo::useDataIC const):
(JSC::CallLinkInfo::CallLinkInfo):
(JSC::CallLinkInfo::setUsesDataICs): Deleted.
* bytecode/Repatch.cpp:
(JSC::linkPolymorphicCall):
* dfg/DFGCommonData.h:
(JSC::DFG::CommonData::addCallLinkInfo):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::emitCall):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::emitCall):
* dfg/DFGStrengthReductionPhase.cpp:
(JSC::DFG::StrengthReductionPhase::handleNode):
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileCompareStrictEq):
* jit/CCallHelpers.h:
(JSC::CCallHelpers::prepareForTailCallSlow):
* wasm/js/WasmToJS.cpp:
(JSC::Wasm::wasmToJS):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (291874 => 291875)


--- trunk/Source/_javascript_Core/ChangeLog	2022-03-25 19:00:11 UTC (rev 291874)
+++ trunk/Source/_javascript_Core/ChangeLog	2022-03-25 19:08:48 UTC (rev 291875)
@@ -1,3 +1,54 @@
+2022-03-24  Yusuke Suzuki  <ysuz...@apple.com>
+
+        [JSC] Use Data CallIC in unlinked DFG
+        https://bugs.webkit.org/show_bug.cgi?id=238176
+
+        Reviewed by Saam Barati.
+
+        This patch enables Data CallIC when Options::useDataICInOptimizingJIT() is true
+        to pave the way to introducing unlinked DFG.
+
+        The most complicated part is DFG tail call handling. We load CallLinkInfo in one
+        non-callee-save register, and we set up CallFrameShuffleData to keep this value
+        in the same register even after call frame shuffling for the tail call. This must
+        be non-callee-save register since callee-save registers are restored to values
+        of the one-level upper caller for the tail-call.
+
+        We also clean up CallLinkInfo code so that many functions work well with DataIC.
+        Currently, direct calls are not supported, and we will not emit direct calls when
+        unlinked DFG is used.
+
+        * bytecode/AccessCase.cpp:
+        (JSC::AccessCase::generateImpl):
+        * bytecode/CallLinkInfo.cpp:
+        (JSC::BaselineCallLinkInfo::initialize):
+        (JSC::OptimizingCallLinkInfo::emitFastPath):
+        (JSC::OptimizingCallLinkInfo::emitTailCallFastPath):
+        (JSC::OptimizingCallLinkInfo::slowPathStart):
+        (JSC::OptimizingCallLinkInfo::emitDirectFastPath):
+        (JSC::OptimizingCallLinkInfo::emitDirectTailCallFastPath):
+        * bytecode/CallLinkInfo.h:
+        (JSC::CallLinkInfo::isDataIC const):
+        (JSC::CallLinkInfo::useDataIC const):
+        (JSC::CallLinkInfo::CallLinkInfo):
+        (JSC::CallLinkInfo::setUsesDataICs): Deleted.
+        * bytecode/Repatch.cpp:
+        (JSC::linkPolymorphicCall):
+        * dfg/DFGCommonData.h:
+        (JSC::DFG::CommonData::addCallLinkInfo):
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::emitCall):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::emitCall):
+        * dfg/DFGStrengthReductionPhase.cpp:
+        (JSC::DFG::StrengthReductionPhase::handleNode):
+        * ftl/FTLLowerDFGToB3.cpp:
+        (JSC::FTL::DFG::LowerDFGToB3::compileCompareStrictEq):
+        * jit/CCallHelpers.h:
+        (JSC::CCallHelpers::prepareForTailCallSlow):
+        * wasm/js/WasmToJS.cpp:
+        (JSC::Wasm::wasmToJS):
+
 2022-03-25  Keith Miller  <keith_mil...@apple.com>
 
         Remove unused JITOperation, operationTryOSREnterAtCatch.

Modified: trunk/Source/_javascript_Core/bytecode/AccessCase.cpp (291874 => 291875)


--- trunk/Source/_javascript_Core/bytecode/AccessCase.cpp	2022-03-25 19:00:11 UTC (rev 291874)
+++ trunk/Source/_javascript_Core/bytecode/AccessCase.cpp	2022-03-25 19:08:48 UTC (rev 291875)
@@ -1999,7 +1999,7 @@
             state.setSpillStateForJSGetterSetter(spillState);
 
             RELEASE_ASSERT(!access.callLinkInfo());
-            auto* callLinkInfo = state.m_callLinkInfos.add(stubInfo.codeOrigin);
+            auto* callLinkInfo = state.m_callLinkInfos.add(stubInfo.codeOrigin, codeBlock->useDataIC() ? CallLinkInfo::UseDataIC::Yes : CallLinkInfo::UseDataIC::No);
             access.m_callLinkInfo = callLinkInfo;
 
             // FIXME: If we generated a polymorphic call stub that jumped back to the getter
@@ -2074,7 +2074,7 @@
                         virtualRegisterForArgumentIncludingThis(1).offset() * sizeof(Register)));
             }
 
-            auto slowCase = access.callLinkInfo()->emitFastPath(jit, loadedValueGPR, loadedValueGPR == GPRInfo::regT2 ? GPRInfo::regT0 : GPRInfo::regT2, JITCode::isOptimizingJIT(codeBlock->jitType()) ? CallLinkInfo::UseDataIC::No : CallLinkInfo::UseDataIC::Yes);
+            auto slowCase = access.callLinkInfo()->emitFastPath(jit, loadedValueGPR, loadedValueGPR == GPRInfo::regT2 ? GPRInfo::regT0 : GPRInfo::regT2);
             auto doneLocation = jit.label();
 
             if (m_type == Getter)

Modified: trunk/Source/_javascript_Core/bytecode/CallLinkInfo.cpp (291874 => 291875)


--- trunk/Source/_javascript_Core/bytecode/CallLinkInfo.cpp	2022-03-25 19:00:11 UTC (rev 291874)
+++ trunk/Source/_javascript_Core/bytecode/CallLinkInfo.cpp	2022-03-25 19:08:48 UTC (rev 291875)
@@ -314,6 +314,8 @@
     UNUSED_PARAM(frameShuffleData);
     m_type = static_cast<unsigned>(Type::Baseline);
     ASSERT(Type::Baseline == type());
+    m_useDataIC = static_cast<unsigned>(UseDataIC::Yes);
+    ASSERT(UseDataIC::Yes == useDataIC());
     m_codeOrigin = CodeOrigin(bytecodeIndex);
     m_callType = callType;
 #if ENABLE(JIT)
@@ -322,7 +324,6 @@
         m_frameShuffleData = makeUnique<CallFrameShuffleData>(*frameShuffleData);
     }
 #endif
-    setUsesDataICs(UseDataIC::Yes);
     setSlowPathCallDestination(vm.getCTILinkCall().code());
     // If JIT is disabled, we should not support dynamically generated call IC.
     if (!Options::useJIT())
@@ -424,10 +425,9 @@
     jit.call(CCallHelpers::Address(GPRInfo::regT2, offsetOfSlowPathCallDestination()), JSEntryPtrTag);
 }
 
-CCallHelpers::JumpList OptimizingCallLinkInfo::emitFastPath(CCallHelpers& jit, GPRReg calleeGPR, GPRReg callLinkInfoGPR, UseDataIC useDataIC)
+CCallHelpers::JumpList OptimizingCallLinkInfo::emitFastPath(CCallHelpers& jit, GPRReg calleeGPR, GPRReg callLinkInfoGPR)
 {
     RELEASE_ASSERT(!isTailCall());
-    setUsesDataICs(useDataIC);
 
     if (isDataIC()) {
         RELEASE_ASSERT(callLinkInfoGPR != GPRReg::InvalidGPRReg);
@@ -435,15 +435,22 @@
         setCallLinkInfoGPR(callLinkInfoGPR);
     }
 
-    return emitFastPathImpl(this, jit, calleeGPR, callLinkInfoGPR, useDataIC, isTailCall(), nullptr);
+    return emitFastPathImpl(this, jit, calleeGPR, callLinkInfoGPR, useDataIC(), isTailCall(), nullptr);
 }
 
-MacroAssembler::JumpList OptimizingCallLinkInfo::emitTailCallFastPath(CCallHelpers& jit, GPRReg calleeGPR, ScopedLambda<void()>&& prepareForTailCall)
+MacroAssembler::JumpList OptimizingCallLinkInfo::emitTailCallFastPath(CCallHelpers& jit, GPRReg calleeGPR, GPRReg callLinkInfoGPR, ScopedLambda<void()>&& prepareForTailCall)
 {
     RELEASE_ASSERT(isTailCall());
-    setUsesDataICs(UseDataIC::No);
-    return emitFastPathImpl(this, jit, calleeGPR, InvalidGPRReg, UseDataIC::No, isTailCall(), WTFMove(prepareForTailCall));
+
+    if (isDataIC()) {
+        RELEASE_ASSERT(callLinkInfoGPR != GPRReg::InvalidGPRReg);
+        jit.move(CCallHelpers::TrustedImmPtr(this), callLinkInfoGPR);
+        setCallLinkInfoGPR(callLinkInfoGPR);
+    }
+
+    return emitFastPathImpl(this, jit, calleeGPR, callLinkInfoGPR, useDataIC(), isTailCall(), WTFMove(prepareForTailCall));
 }
+
 void OptimizingCallLinkInfo::emitSlowPath(VM& vm, CCallHelpers& jit)
 {
     setSlowPathCallDestination(vm.getCTILinkCall().code());
@@ -453,7 +460,7 @@
 
 CodeLocationLabel<JSInternalPtrTag> OptimizingCallLinkInfo::slowPathStart()
 {
-    RELEASE_ASSERT(!isDataIC());
+    RELEASE_ASSERT(isDirect() && !isDataIC());
     return m_slowPathStart;
 }
 
@@ -465,9 +472,9 @@
 
 void OptimizingCallLinkInfo::emitDirectFastPath(CCallHelpers& jit)
 {
-    RELEASE_ASSERT(!isTailCall());
+    RELEASE_ASSERT(isDirect() && !isTailCall());
 
-    setUsesDataICs(UseDataIC::No);
+    ASSERT(UseDataIC::No == this->useDataIC());
 
     auto call = jit.nearCall();
     jit.addLinkTask([=, this] (LinkBuffer& linkBuffer) {
@@ -480,9 +487,9 @@
 
 void OptimizingCallLinkInfo::emitDirectTailCallFastPath(CCallHelpers& jit, ScopedLambda<void()>&& prepareForTailCall)
 {
-    RELEASE_ASSERT(isTailCall());
+    RELEASE_ASSERT(isDirect() && isTailCall());
 
-    setUsesDataICs(UseDataIC::No);
+    ASSERT(UseDataIC::No == this->useDataIC());
 
     auto fastPathStart = jit.label();
     jit.addLinkTask([=, this] (LinkBuffer& linkBuffer) {

Modified: trunk/Source/_javascript_Core/bytecode/CallLinkInfo.h (291874 => 291875)


--- trunk/Source/_javascript_Core/bytecode/CallLinkInfo.h	2022-03-25 19:00:11 UTC (rev 291874)
+++ trunk/Source/_javascript_Core/bytecode/CallLinkInfo.h	2022-03-25 19:08:48 UTC (rev 291875)
@@ -187,8 +187,8 @@
 
     void revertCallToStub();
 
-    bool isDataIC() const { return static_cast<UseDataIC>(m_useDataIC) == UseDataIC::Yes; }
-    void setUsesDataICs(UseDataIC useDataIC) { m_useDataIC = static_cast<unsigned>(useDataIC); }
+    bool isDataIC() const { return useDataIC() == UseDataIC::Yes; }
+    UseDataIC useDataIC() const { return static_cast<UseDataIC>(m_useDataIC); }
 
     bool allowStubs() const { return m_allowStubs; }
 
@@ -376,7 +376,7 @@
     Type type() const { return static_cast<Type>(m_type); }
 
 protected:
-    CallLinkInfo(Type type, CodeOrigin codeOrigin)
+    CallLinkInfo(Type type, CodeOrigin codeOrigin, UseDataIC useDataIC)
         : m_codeOrigin(codeOrigin)
         , m_hasSeenShouldRepatch(false)
         , m_hasSeenClosure(false)
@@ -385,17 +385,13 @@
         , m_allowStubs(true)
         , m_clearedByJettison(false)
         , m_callType(None)
-        , m_useDataIC(static_cast<unsigned>(UseDataIC::Yes))
+        , m_useDataIC(static_cast<unsigned>(useDataIC))
         , m_type(static_cast<unsigned>(type))
     {
         ASSERT(type == this->type());
+        ASSERT(useDataIC == this->useDataIC());
     }
 
-    CallLinkInfo(Type type)
-        : CallLinkInfo(type, CodeOrigin { })
-    {
-    }
-
 #if ENABLE(JIT)
     void setCallLinkInfoGPR(GPRReg);
 #endif
@@ -443,7 +439,7 @@
 class BaselineCallLinkInfo final : public CallLinkInfo {
 public:
     BaselineCallLinkInfo()
-        : CallLinkInfo(Type::Baseline)
+        : CallLinkInfo(Type::Baseline, CodeOrigin { }, UseDataIC::Yes)
     {
     }
 
@@ -477,8 +473,8 @@
 public:
     friend class CallLinkInfo;
 
-    OptimizingCallLinkInfo(CodeOrigin codeOrigin)
-        : CallLinkInfo(Type::Optimizing, codeOrigin)
+    OptimizingCallLinkInfo(CodeOrigin codeOrigin, UseDataIC useDataIC)
+        : CallLinkInfo(Type::Optimizing, codeOrigin, useDataIC)
     {
     }
 
@@ -510,8 +506,8 @@
     void setDirectCallTarget(CodeLocationLabel<JSEntryPtrTag>);
     void emitSlowPath(VM&, CCallHelpers&);
 
-    MacroAssembler::JumpList emitFastPath(CCallHelpers&, GPRReg calleeGPR, GPRReg callLinkInfoGPR, UseDataIC) WARN_UNUSED_RETURN;
-    MacroAssembler::JumpList emitTailCallFastPath(CCallHelpers&, GPRReg calleeGPR, ScopedLambda<void()>&& prepareForTailCall) WARN_UNUSED_RETURN;
+    MacroAssembler::JumpList emitFastPath(CCallHelpers&, GPRReg calleeGPR, GPRReg callLinkInfoGPR) WARN_UNUSED_RETURN;
+    MacroAssembler::JumpList emitTailCallFastPath(CCallHelpers&, GPRReg calleeGPR, GPRReg callLinkInfoGPR, ScopedLambda<void()>&& prepareForTailCall) WARN_UNUSED_RETURN;
 
 private:
     CodeLocationNearCall<JSInternalPtrTag> m_callLocation;

Modified: trunk/Source/_javascript_Core/bytecode/Repatch.cpp (291874 => 291875)


--- trunk/Source/_javascript_Core/bytecode/Repatch.cpp	2022-03-25 19:00:11 UTC (rev 291874)
+++ trunk/Source/_javascript_Core/bytecode/Repatch.cpp	2022-03-25 19:08:48 UTC (rev 291875)
@@ -1861,15 +1861,33 @@
     } else {
         // FIXME: We are not doing a real tail-call in this case. We leave stack entries in the caller, and we are not running prepareForTailCall, thus,
         // we will return to the caller after the callee finishes. We should make it a real tail-call for this slow path case.
-        if (callLinkInfo.isTailCall()) {
+        switch (callLinkInfo.type()) {
+        case CallLinkInfo::Type::Baseline: {
 #if ASSERT_ENABLED
             // It needs to be LLInt or Baseline since we are using returnFromBaselineGenerator.
             if (!isWebAssembly)
                 ASSERT(!JITCode::isOptimizingJIT(callerCodeBlock->jitType()));
 #endif
-            stubJit.move(CCallHelpers::TrustedImmPtr(vm.getCTIStub(JIT::returnFromBaselineGenerator).code().untaggedExecutableAddress()), GPRInfo::regT4);
+            if (callLinkInfo.isTailCall()) {
+                stubJit.move(CCallHelpers::TrustedImmPtr(vm.getCTIStub(JIT::returnFromBaselineGenerator).code().untaggedExecutableAddress()), GPRInfo::regT4);
+                stubJit.restoreReturnAddressBeforeReturn(GPRInfo::regT4);
+            }
+            break;
+        }
+        case CallLinkInfo::Type::Optimizing: {
+            // While Baseline / LLInt shares BaselineCallLinkInfo, OptimizingCallLinkInfo is exclusively used for one JIT code.
+            // Thus, we can safely use doneLocation.
+            if (!callLinkInfo.isTailCall()) {
+                // We were called from the fast path, get rid of any remnants of that
+                // which may exist. This really only matters for x86, which adjusts
+                // SP for calls.
+                stubJit.preserveReturnAddressAfterCall(GPRInfo::regT4);
+            }
+            stubJit.move(CCallHelpers::TrustedImmPtr(callLinkInfo.doneLocation().untaggedExecutableAddress()), GPRInfo::regT4);
             stubJit.restoreReturnAddressBeforeReturn(GPRInfo::regT4);
+            break;
         }
+        }
     }
 
     AssemblyHelpers::Jump slow = stubJit.jump();

Modified: trunk/Source/_javascript_Core/dfg/DFGCommonData.h (291874 => 291875)


--- trunk/Source/_javascript_Core/dfg/DFGCommonData.h	2022-03-25 19:00:11 UTC (rev 291874)
+++ trunk/Source/_javascript_Core/dfg/DFGCommonData.h	2022-03-25 19:08:48 UTC (rev 291875)
@@ -111,9 +111,9 @@
     
     void clearWatchpoints();
 
-    OptimizingCallLinkInfo* addCallLinkInfo(CodeOrigin codeOrigin)
+    OptimizingCallLinkInfo* addCallLinkInfo(CodeOrigin codeOrigin, CallLinkInfo::UseDataIC useDataIC = CallLinkInfo::UseDataIC::No)
     {
-        return m_callLinkInfos.add(codeOrigin);
+        return m_callLinkInfos.add(codeOrigin, useDataIC);
     }
 
     RefPtr<InlineCallFrameSet> inlineCallFrames;

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp (291874 => 291875)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp	2022-03-25 19:00:11 UTC (rev 291874)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT32_64.cpp	2022-03-25 19:08:48 UTC (rev 291875)
@@ -783,7 +783,7 @@
         isEmulatedTail ? *staticInlineCallFrame->getCallerSkippingTailCalls() : staticOrigin;
     CallSiteIndex callSite = m_jit.recordCallSiteAndGenerateExceptionHandlingOSRExitIfNeeded(dynamicOrigin, m_stream->size());
     
-    auto* info = m_jit.jitCode()->common.addCallLinkInfo(node->origin.semantic);
+    auto* info = m_jit.jitCode()->common.addCallLinkInfo(node->origin.semantic, CallLinkInfo::UseDataIC::No);
     info->setUpCall(callType, calleePayloadGPR);
     
     auto setResultAndResetStack = [&] () {
@@ -825,7 +825,10 @@
         // This is the part where we meant to make a normal call. Oops.
         m_jit.addPtr(TrustedImm32(requiredBytes), JITCompiler::stackPointerRegister);
         m_jit.loadValue(JITCompiler::calleeFrameSlot(CallFrameSlot::callee), JSValueRegs { GPRInfo::regT1, GPRInfo::regT0 });
-        m_jit.emitVirtualCall(vm(), globalObject, info);
+        m_jit.move(TrustedImmPtr(info), GPRInfo::regT2);
+        m_jit.move(TrustedImmPtr::weakPointer(m_graph, globalObject), GPRInfo::regT3);
+        m_jit.emitVirtualCallWithoutMovingGlobalObject(vm(), GPRInfo::regT2, CallMode::Regular);
+        ASSERT(info->callMode() == CallMode::Regular);
         
         done.link(&m_jit);
         setResultAndResetStack();
@@ -888,7 +891,7 @@
 
     CCallHelpers::JumpList slowCases;
     if (isTail) {
-        slowCases = info->emitTailCallFastPath(m_jit, calleePayloadGPR, scopedLambda<void()>([&]{
+        slowCases = info->emitTailCallFastPath(m_jit, calleePayloadGPR, InvalidGPRReg, scopedLambda<void()>([&]{
             if (node->op() == TailCall) {
                 info->setFrameShuffleData(shuffleData);
                 CallFrameShuffler(m_jit, shuffleData).prepareForTailCall();
@@ -898,7 +901,7 @@
             }
         }));
     } else
-        slowCases = info->emitFastPath(m_jit, calleePayloadGPR, InvalidGPRReg, CallLinkInfo::UseDataIC::No);
+        slowCases = info->emitFastPath(m_jit, calleePayloadGPR, InvalidGPRReg);
 
     JITCompiler::Jump done = m_jit.jump();
 

Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp (291874 => 291875)


--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2022-03-25 19:00:11 UTC (rev 291874)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT64.cpp	2022-03-25 19:08:48 UTC (rev 291875)
@@ -696,6 +696,7 @@
     }
 
     GPRReg calleeGPR = InvalidGPRReg;
+    GPRReg callLinkInfoGPR = InvalidGPRReg;
     CallFrameShuffleData shuffleData;
     
     JSGlobalObject* globalObject = m_graph.globalObjectFor(node->origin.semantic);
@@ -708,6 +709,8 @@
     
     unsigned numPassedArgs = 0;
     unsigned numAllocatedArgs = 0;
+
+    auto* callLinkInfo = m_jit.jitCode()->common.addCallLinkInfo(m_currentNode->origin.semantic, JITCode::useDataIC(JITType::DFGJIT) ? CallLinkInfo::UseDataIC::Yes : CallLinkInfo::UseDataIC::No);
     
     // Gotta load the arguments somehow. Varargs is trickier.
     if (isVarargs || isForwardVarargs) {
@@ -825,6 +828,17 @@
             Edge calleeEdge = m_jit.graph().child(node, 0);
             JSValueOperand callee(this, calleeEdge);
             calleeGPR = callee.gpr();
+
+            // callLinkInfoGPR must be non callee-save register. Otherwise, tail-call preparation will fill it
+            // with saved callee-save. Also, it should not be the same to calleeGPR and regT0 since both will
+            // be used later differently.
+            // We also do not keep GPRTemporary (it is immediately destroyed) because
+            // 1. We do not want to keep the register locked in the following sequence of the Call.
+            // 2. This must be the last register allocation from DFG register bank, so it is OK (otherwise, callee.use() is wrong).
+            if (callLinkInfo->isDataIC()) {
+                GPRTemporary callLinkInfoTemp(this, JITCompiler::selectScratchGPR(calleeGPR, GPRInfo::regT0));
+                callLinkInfoGPR = callLinkInfoTemp.gpr();
+            }
             if (!isDirect)
                 callee.use();
 
@@ -846,6 +860,8 @@
             for (unsigned i = numPassedArgs; i < numAllocatedArgs; ++i)
                 shuffleData.args[i] = ValueRecovery::constant(jsUndefined());
 
+            if (callLinkInfo->isDataIC())
+                shuffleData.registers[callLinkInfoGPR] = ValueRecovery::inGPR(callLinkInfoGPR, DataFormatJS);
             shuffleData.setupCalleeSaveRegisters(&RegisterAtOffsetList::dfgCalleeSaveRegisters());
         } else {
             m_jit.store32(MacroAssembler::TrustedImm32(numPassedArgs), JITCompiler::calleeFramePayloadSlot(CallFrameSlot::argumentCountIncludingThis));
@@ -868,6 +884,18 @@
         Edge calleeEdge = m_jit.graph().child(node, 0);
         JSValueOperand callee(this, calleeEdge);
         calleeGPR = callee.gpr();
+
+        // callLinkInfoGPR must be non callee-save register. Otherwise, tail-call preparation will fill it
+        // with saved callee-save. Also, it should not be the same to calleeGPR and regT0 since both will
+        // be used later differently.
+        // We also do not keep GPRTemporary (it is immediately destroyed) because
+        // 1. We do not want to keep the register locked in the following sequence of the Call.
+        // 2. This must be the last register allocation from DFG register bank, so it is OK (otherwise, callee.use() is wrong).
+        if (callLinkInfo->isDataIC()) {
+            GPRTemporary callLinkInfoTemp(this, JITCompiler::selectScratchGPR(calleeGPR, GPRInfo::regT0));
+            callLinkInfoGPR = callLinkInfoTemp.gpr();
+        }
+
         callee.use();
         m_jit.store64(calleeGPR, JITCompiler::calleeFrameSlot(CallFrameSlot::callee));
 
@@ -896,7 +924,6 @@
         m_jit.addPtr(TrustedImm32(m_jit.graph().stackPointerOffset() * sizeof(Register)), GPRInfo::callFrameRegister, JITCompiler::stackPointerRegister);
     };
     
-    auto* callLinkInfo = m_jit.jitCode()->common.addCallLinkInfo(m_currentNode->origin.semantic);
     callLinkInfo->setUpCall(callType, calleeGPR);
 
     if (node->op() == CallEval) {
@@ -925,7 +952,10 @@
         // This is the part where we meant to make a normal call. Oops.
         m_jit.addPtr(TrustedImm32(requiredBytes), JITCompiler::stackPointerRegister);
         m_jit.load64(JITCompiler::calleeFrameSlot(CallFrameSlot::callee), GPRInfo::regT0);
-        m_jit.emitVirtualCall(vm(), globalObject, callLinkInfo);
+        m_jit.move(TrustedImmPtr(callLinkInfo), GPRInfo::regT2);
+        m_jit.move(TrustedImmPtr::weakPointer(m_graph, globalObject), GPRInfo::regT3);
+        m_jit.emitVirtualCallWithoutMovingGlobalObject(vm(), GPRInfo::regT2, CallMode::Regular);
+        ASSERT(callLinkInfo->callMode() == CallMode::Regular);
         
         done.link(&m_jit);
         setResultAndResetStack();
@@ -985,17 +1015,17 @@
     
     CCallHelpers::JumpList slowCases;
     if (isTail) {
-        slowCases = callLinkInfo->emitTailCallFastPath(m_jit, calleeGPR, scopedLambda<void()>([&]{
+        slowCases = callLinkInfo->emitTailCallFastPath(m_jit, calleeGPR, callLinkInfoGPR, scopedLambda<void()>([&]{
             if (node->op() == TailCall) {
                 callLinkInfo->setFrameShuffleData(shuffleData);
                 CallFrameShuffler(m_jit, shuffleData).prepareForTailCall();
             } else {
                 m_jit.emitRestoreCalleeSaves();
-                m_jit.prepareForTailCallSlow();
+                m_jit.prepareForTailCallSlow(callLinkInfoGPR);
             }
         }));
     } else
-        slowCases = callLinkInfo->emitFastPath(m_jit, calleeGPR, InvalidGPRReg, CallLinkInfo::UseDataIC::No);
+        slowCases = callLinkInfo->emitFastPath(m_jit, calleeGPR, callLinkInfoGPR);
     JITCompiler::Jump done = m_jit.jump();
 
     slowCases.link(&m_jit);

Modified: trunk/Source/_javascript_Core/dfg/DFGStrengthReductionPhase.cpp (291874 => 291875)


--- trunk/Source/_javascript_Core/dfg/DFGStrengthReductionPhase.cpp	2022-03-25 19:00:11 UTC (rev 291874)
+++ trunk/Source/_javascript_Core/dfg/DFGStrengthReductionPhase.cpp	2022-03-25 19:08:48 UTC (rev 291875)
@@ -1021,6 +1021,12 @@
             if (!executable)
                 break;
 
+            if (m_graph.m_plan.isUnlinked())
+                break;
+
+            if (JITCode::useDataIC(m_graph.m_plan.isFTL() ? JITType::FTLJIT : JITType::DFGJIT))
+                break;
+
             // FIXME: Support wasm IC.
             // DirectCall to wasm function has suboptimal implementation. We avoid using DirectCall if we know that function is a wasm function.
             // https://bugs.webkit.org/show_bug.cgi?id=220339

Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp (291874 => 291875)


--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp	2022-03-25 19:00:11 UTC (rev 291874)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp	2022-03-25 19:08:48 UTC (rev 291875)
@@ -10282,7 +10282,7 @@
                 callLinkInfo->setUpCall(
                     nodeOp == Construct ? CallLinkInfo::Construct : CallLinkInfo::Call, GPRInfo::regT0);
 
-                auto slowPath = callLinkInfo->emitFastPath(jit, GPRInfo::regT0, InvalidGPRReg, CallLinkInfo::UseDataIC::No);
+                auto slowPath = callLinkInfo->emitFastPath(jit, GPRInfo::regT0, InvalidGPRReg);
                 CCallHelpers::Jump done = jit.jump();
 
                 slowPath.link(&jit);
@@ -10575,7 +10575,7 @@
                 auto* callLinkInfo = state->jitCode->common.addCallLinkInfo(codeOrigin);
                 callLinkInfo->setUpCall(CallLinkInfo::TailCall, GPRInfo::regT0);
 
-                auto slowPath = callLinkInfo->emitTailCallFastPath(jit, GPRInfo::regT0, scopedLambda<void()>([&]{
+                auto slowPath = callLinkInfo->emitTailCallFastPath(jit, GPRInfo::regT0, InvalidGPRReg, scopedLambda<void()>([&]{
                     callLinkInfo->setFrameShuffleData(shuffleData);
                     CallFrameShuffler(jit, shuffleData).prepareForTailCall();
                 }));
@@ -10918,12 +10918,12 @@
                 CCallHelpers::JumpList slowPath;
                 CCallHelpers::Jump done;
                 if (isTailCall) {
-                    slowPath = callLinkInfo->emitTailCallFastPath(jit, GPRInfo::regT0, scopedLambda<void()>([&]{
+                    slowPath = callLinkInfo->emitTailCallFastPath(jit, GPRInfo::regT0, InvalidGPRReg, scopedLambda<void()>([&]{
                         jit.emitRestoreCalleeSavesFor(state->jitCode->calleeSaveRegisters());
                         jit.prepareForTailCallSlow();
                     }));
                 } else {
-                    slowPath = callLinkInfo->emitFastPath(jit, GPRInfo::regT0, InvalidGPRReg, CallLinkInfo::UseDataIC::No);
+                    slowPath = callLinkInfo->emitFastPath(jit, GPRInfo::regT0, InvalidGPRReg);
                     done = jit.jump();
                 }
                 
@@ -11199,12 +11199,12 @@
                 CCallHelpers::JumpList slowPath;
                 CCallHelpers::Jump done;
                 if (isTailCall) {
-                    slowPath = callLinkInfo->emitTailCallFastPath(jit, GPRInfo::regT0, scopedLambda<void()>([&]{
+                    slowPath = callLinkInfo->emitTailCallFastPath(jit, GPRInfo::regT0, InvalidGPRReg, scopedLambda<void()>([&]{
                         jit.emitRestoreCalleeSavesFor(state->jitCode->calleeSaveRegisters());
                         jit.prepareForTailCallSlow();
                     }));
                 } else {
-                    slowPath = callLinkInfo->emitFastPath(jit, GPRInfo::regT0, InvalidGPRReg, CallLinkInfo::UseDataIC::No);
+                    slowPath = callLinkInfo->emitFastPath(jit, GPRInfo::regT0, InvalidGPRReg);
                     done = jit.jump();
                 }
                 

Modified: trunk/Source/_javascript_Core/jit/CCallHelpers.h (291874 => 291875)


--- trunk/Source/_javascript_Core/jit/CCallHelpers.h	2022-03-25 19:00:11 UTC (rev 291874)
+++ trunk/Source/_javascript_Core/jit/CCallHelpers.h	2022-03-25 19:08:48 UTC (rev 291875)
@@ -744,11 +744,11 @@
         farJump(GPRInfo::regT1, ExceptionHandlerPtrTag);
     }
 
-    void prepareForTailCallSlow(GPRReg calleeGPR = InvalidGPRReg)
+    void prepareForTailCallSlow(GPRReg preservedGPR = InvalidGPRReg)
     {
-        GPRReg temp1 = calleeGPR == GPRInfo::regT0 ? GPRInfo::regT3 : GPRInfo::regT0;
-        GPRReg temp2 = calleeGPR == GPRInfo::regT1 ? GPRInfo::regT3 : GPRInfo::regT1;
-        GPRReg temp3 = calleeGPR == GPRInfo::regT2 ? GPRInfo::regT3 : GPRInfo::regT2;
+        GPRReg temp1 = preservedGPR == GPRInfo::regT0 ? GPRInfo::regT3 : GPRInfo::regT0;
+        GPRReg temp2 = preservedGPR == GPRInfo::regT1 ? GPRInfo::regT3 : GPRInfo::regT1;
+        GPRReg temp3 = preservedGPR == GPRInfo::regT2 ? GPRInfo::regT3 : GPRInfo::regT2;
 
         GPRReg newFramePointer = temp1;
         GPRReg newFrameSizeGPR = temp2;

Modified: trunk/Source/_javascript_Core/wasm/js/WasmToJS.cpp (291874 => 291875)


--- trunk/Source/_javascript_Core/wasm/js/WasmToJS.cpp	2022-03-25 19:00:11 UTC (rev 291874)
+++ trunk/Source/_javascript_Core/wasm/js/WasmToJS.cpp	2022-03-25 19:08:48 UTC (rev 291875)
@@ -261,9 +261,9 @@
 
     // FIXME Tail call if the wasm return type is void and no registers were spilled. https://bugs.webkit.org/show_bug.cgi?id=165488
 
-    auto* callLinkInfo = callLinkInfos.add(CodeOrigin());
+    auto* callLinkInfo = callLinkInfos.add(CodeOrigin(), CallLinkInfo::UseDataIC::No);
     callLinkInfo->setUpCall(CallLinkInfo::Call, importJSCellGPRReg);
-    auto slowPath = callLinkInfo->emitFastPath(jit, importJSCellGPRReg, InvalidGPRReg, CallLinkInfo::UseDataIC::No);
+    auto slowPath = callLinkInfo->emitFastPath(jit, importJSCellGPRReg, InvalidGPRReg);
 
     JIT::Jump done = jit.jump();
     slowPath.link(&jit);
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to