Title: [187505] trunk/Source/_javascript_Core
Revision
187505
Author
[email protected]
Date
2015-07-28 13:12:33 -0700 (Tue, 28 Jul 2015)

Log Message

Simplify call linking
https://bugs.webkit.org/show_bug.cgi?id=147363

Reviewed by Filip Pizlo.

Previously, we were passing both the CallLinkInfo and a
(CodeSpecializationKind, RegisterPreservationMode) pair to the
different call linking slow paths. However, the CallLinkInfo already
has all of that information, and we don't gain anything by having them
in additional static parameters - except possibly a very small
performance gain in presence of inlining. However since those are
already slow paths, this performance loss (if it exists) will not be
visible in practice.

This patch removes the various specialized thunks and JIT operations
for regular and polymorphic call linking with a single thunk and
operation for each case. Moreover, it removes the four specialized
virtual call thunks and operations with one virtual call thunk for each
call link info, allowing for better branch prediction by the CPU and
fixing a pre-existing FIXME.

* bytecode/CallLinkInfo.cpp:
(JSC::CallLinkInfo::unlink):
(JSC::CallLinkInfo::dummy): Deleted.
* bytecode/CallLinkInfo.h:
(JSC::CallLinkInfo::CallLinkInfo):
(JSC::CallLinkInfo::registerPreservationMode):
(JSC::CallLinkInfo::setUpCallFromFTL):
(JSC::CallLinkInfo::setSlowStub):
(JSC::CallLinkInfo::clearSlowStub):
(JSC::CallLinkInfo::slowStub):
* dfg/DFGDriver.cpp:
(JSC::DFG::compileImpl):
* dfg/DFGJITCompiler.cpp:
(JSC::DFG::JITCompiler::link):
* ftl/FTLJSCallBase.cpp:
(JSC::FTL::JSCallBase::link):
* jit/JITCall.cpp:
(JSC::JIT::compileCallEvalSlowCase):
(JSC::JIT::compileOpCall):
(JSC::JIT::compileOpCallSlowCase):
* jit/JITCall32_64.cpp:
(JSC::JIT::compileCallEvalSlowCase):
(JSC::JIT::compileOpCall):
(JSC::JIT::compileOpCallSlowCase):
* jit/JITOperations.cpp:
* jit/JITOperations.h:
(JSC::operationLinkFor): Deleted.
(JSC::operationVirtualFor): Deleted.
(JSC::operationLinkPolymorphicCallFor): Deleted.
* jit/Repatch.cpp:
(JSC::generateByIdStub):
(JSC::linkSlowFor):
(JSC::linkFor):
(JSC::revertCall):
(JSC::unlinkFor):
(JSC::linkVirtualFor):
(JSC::linkPolymorphicCall):
* jit/Repatch.h:
* jit/ThunkGenerators.cpp:
(JSC::linkCallThunkGenerator):
(JSC::linkPolymorphicCallThunkGenerator):
(JSC::virtualThunkFor):
(JSC::linkForThunkGenerator): Deleted.
(JSC::linkConstructThunkGenerator): Deleted.
(JSC::linkCallThatPreservesRegsThunkGenerator): Deleted.
(JSC::linkConstructThatPreservesRegsThunkGenerator): Deleted.
(JSC::linkPolymorphicCallForThunkGenerator): Deleted.
(JSC::linkPolymorphicCallThatPreservesRegsThunkGenerator): Deleted.
(JSC::virtualForThunkGenerator): Deleted.
(JSC::virtualCallThunkGenerator): Deleted.
(JSC::virtualConstructThunkGenerator): Deleted.
(JSC::virtualCallThatPreservesRegsThunkGenerator): Deleted.
(JSC::virtualConstructThatPreservesRegsThunkGenerator): Deleted.
* jit/ThunkGenerators.h:
(JSC::linkThunkGeneratorFor): Deleted.
(JSC::linkPolymorphicCallThunkGeneratorFor): Deleted.
(JSC::virtualThunkGeneratorFor): Deleted.

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (187504 => 187505)


--- trunk/Source/_javascript_Core/ChangeLog	2015-07-28 20:10:03 UTC (rev 187504)
+++ trunk/Source/_javascript_Core/ChangeLog	2015-07-28 20:12:33 UTC (rev 187505)
@@ -1,5 +1,86 @@
 2015-07-28  Basile Clement  <[email protected]>
 
+        Simplify call linking
+        https://bugs.webkit.org/show_bug.cgi?id=147363
+
+        Reviewed by Filip Pizlo.
+
+        Previously, we were passing both the CallLinkInfo and a
+        (CodeSpecializationKind, RegisterPreservationMode) pair to the
+        different call linking slow paths. However, the CallLinkInfo already
+        has all of that information, and we don't gain anything by having them
+        in additional static parameters - except possibly a very small
+        performance gain in presence of inlining. However since those are
+        already slow paths, this performance loss (if it exists) will not be
+        visible in practice.
+
+        This patch removes the various specialized thunks and JIT operations
+        for regular and polymorphic call linking with a single thunk and
+        operation for each case. Moreover, it removes the four specialized
+        virtual call thunks and operations with one virtual call thunk for each
+        call link info, allowing for better branch prediction by the CPU and
+        fixing a pre-existing FIXME.
+
+        * bytecode/CallLinkInfo.cpp:
+        (JSC::CallLinkInfo::unlink):
+        (JSC::CallLinkInfo::dummy): Deleted.
+        * bytecode/CallLinkInfo.h:
+        (JSC::CallLinkInfo::CallLinkInfo):
+        (JSC::CallLinkInfo::registerPreservationMode):
+        (JSC::CallLinkInfo::setUpCallFromFTL):
+        (JSC::CallLinkInfo::setSlowStub):
+        (JSC::CallLinkInfo::clearSlowStub):
+        (JSC::CallLinkInfo::slowStub):
+        * dfg/DFGDriver.cpp:
+        (JSC::DFG::compileImpl):
+        * dfg/DFGJITCompiler.cpp:
+        (JSC::DFG::JITCompiler::link):
+        * ftl/FTLJSCallBase.cpp:
+        (JSC::FTL::JSCallBase::link):
+        * jit/JITCall.cpp:
+        (JSC::JIT::compileCallEvalSlowCase):
+        (JSC::JIT::compileOpCall):
+        (JSC::JIT::compileOpCallSlowCase):
+        * jit/JITCall32_64.cpp:
+        (JSC::JIT::compileCallEvalSlowCase):
+        (JSC::JIT::compileOpCall):
+        (JSC::JIT::compileOpCallSlowCase):
+        * jit/JITOperations.cpp:
+        * jit/JITOperations.h:
+        (JSC::operationLinkFor): Deleted.
+        (JSC::operationVirtualFor): Deleted.
+        (JSC::operationLinkPolymorphicCallFor): Deleted.
+        * jit/Repatch.cpp:
+        (JSC::generateByIdStub):
+        (JSC::linkSlowFor):
+        (JSC::linkFor):
+        (JSC::revertCall):
+        (JSC::unlinkFor):
+        (JSC::linkVirtualFor):
+        (JSC::linkPolymorphicCall):
+        * jit/Repatch.h:
+        * jit/ThunkGenerators.cpp:
+        (JSC::linkCallThunkGenerator):
+        (JSC::linkPolymorphicCallThunkGenerator):
+        (JSC::virtualThunkFor):
+        (JSC::linkForThunkGenerator): Deleted.
+        (JSC::linkConstructThunkGenerator): Deleted.
+        (JSC::linkCallThatPreservesRegsThunkGenerator): Deleted.
+        (JSC::linkConstructThatPreservesRegsThunkGenerator): Deleted.
+        (JSC::linkPolymorphicCallForThunkGenerator): Deleted.
+        (JSC::linkPolymorphicCallThatPreservesRegsThunkGenerator): Deleted.
+        (JSC::virtualForThunkGenerator): Deleted.
+        (JSC::virtualCallThunkGenerator): Deleted.
+        (JSC::virtualConstructThunkGenerator): Deleted.
+        (JSC::virtualCallThatPreservesRegsThunkGenerator): Deleted.
+        (JSC::virtualConstructThatPreservesRegsThunkGenerator): Deleted.
+        * jit/ThunkGenerators.h:
+        (JSC::linkThunkGeneratorFor): Deleted.
+        (JSC::linkPolymorphicCallThunkGeneratorFor): Deleted.
+        (JSC::virtualThunkGeneratorFor): Deleted.
+
+2015-07-28  Basile Clement  <[email protected]>
+
         stress/math-pow-with-constants.js fails in cloop
         https://bugs.webkit.org/show_bug.cgi?id=147167
 

Modified: trunk/Source/_javascript_Core/bytecode/CallLinkInfo.cpp (187504 => 187505)


--- trunk/Source/_javascript_Core/bytecode/CallLinkInfo.cpp	2015-07-28 20:10:03 UTC (rev 187504)
+++ trunk/Source/_javascript_Core/bytecode/CallLinkInfo.cpp	2015-07-28 20:12:33 UTC (rev 187505)
@@ -55,10 +55,7 @@
         return;
     }
     
-    unlinkFor(
-        repatchBuffer, *this,
-        (m_callType == Construct || m_callType == ConstructVarargs)? CodeForConstruct : CodeForCall,
-        m_isFTL ? MustPreserveRegisters : RegisterPreservationNotRequired);
+    unlinkFor(repatchBuffer, *this);
 
     // It will be on a list if the callee has a code block.
     if (isOnList())
@@ -104,12 +101,6 @@
     }
 }
 
-CallLinkInfo& CallLinkInfo::dummy()
-{
-    static NeverDestroyed<CallLinkInfo> dummy;
-    return dummy;
-}
-
 } // namespace JSC
 #endif // ENABLE(JIT)
 

Modified: trunk/Source/_javascript_Core/bytecode/CallLinkInfo.h (187504 => 187505)


--- trunk/Source/_javascript_Core/bytecode/CallLinkInfo.h	2015-07-28 20:10:03 UTC (rev 187504)
+++ trunk/Source/_javascript_Core/bytecode/CallLinkInfo.h	2015-07-28 20:12:33 UTC (rev 187505)
@@ -57,7 +57,7 @@
     }
     
     CallLinkInfo()
-        : m_isFTL(false)
+        : m_registerPreservationMode(static_cast<unsigned>(RegisterPreservationNotRequired))
         , m_hasSeenShouldRepatch(false)
         , m_hasSeenClosure(false)
         , m_clearedByGC(false)
@@ -84,6 +84,11 @@
         return specializationKindFor(static_cast<CallType>(m_callType));
     }
 
+    RegisterPreservationMode registerPreservationMode() const
+    {
+        return static_cast<RegisterPreservationMode>(m_registerPreservationMode);
+    }
+
     bool isLinked() { return m_stub || m_callee; }
     void unlink(RepatchBuffer&);
 
@@ -106,7 +111,7 @@
         CodeLocationNearCall callReturnLocation, CodeLocationDataLabelPtr hotPathBegin,
         CodeLocationNearCall hotPathOther, unsigned calleeGPR)
     {
-        m_isFTL = true;
+        m_registerPreservationMode = static_cast<unsigned>(MustPreserveRegisters);
         m_callType = callType;
         m_codeOrigin = codeOrigin;
         m_callReturnLocation = callReturnLocation;
@@ -178,6 +183,21 @@
         return m_stub.get();
     }
 
+    void setSlowStub(PassRefPtr<JITStubRoutine> newSlowStub)
+    {
+        m_slowStub = newSlowStub;
+    }
+
+    void clearSlowStub()
+    {
+        m_slowStub = nullptr;
+    }
+
+    JITStubRoutine* slowStub()
+    {
+        return m_slowStub.get();
+    }
+
     bool seenOnce()
     {
         return m_hasSeenShouldRepatch;
@@ -260,8 +280,6 @@
 
     void visitWeak(RepatchBuffer&);
 
-    static CallLinkInfo& dummy();
-
 private:
     CodeLocationNearCall m_callReturnLocation;
     CodeLocationDataLabelPtr m_hotPathBegin;
@@ -269,7 +287,8 @@
     JITWriteBarrier<JSFunction> m_callee;
     WriteBarrier<JSFunction> m_lastSeenCallee;
     RefPtr<PolymorphicCallStubRoutine> m_stub;
-    bool m_isFTL : 1;
+    RefPtr<JITStubRoutine> m_slowStub;
+    unsigned m_registerPreservationMode : 1; // Real type is RegisterPreservationMode
     bool m_hasSeenShouldRepatch : 1;
     bool m_hasSeenClosure : 1;
     bool m_clearedByGC : 1;

Modified: trunk/Source/_javascript_Core/dfg/DFGDriver.cpp (187504 => 187505)


--- trunk/Source/_javascript_Core/dfg/DFGDriver.cpp	2015-07-28 20:10:03 UTC (rev 187504)
+++ trunk/Source/_javascript_Core/dfg/DFGDriver.cpp	2015-07-28 20:12:33 UTC (rev 187505)
@@ -81,19 +81,8 @@
     // make sure that all JIT code generation does finalization on the main thread.
     vm.getCTIStub(osrExitGenerationThunkGenerator);
     vm.getCTIStub(throwExceptionFromCallSlowPathGenerator);
-    if (mode == DFGMode) {
-        vm.getCTIStub(linkCallThunkGenerator);
-        vm.getCTIStub(linkConstructThunkGenerator);
-        vm.getCTIStub(linkPolymorphicCallThunkGenerator);
-        vm.getCTIStub(virtualCallThunkGenerator);
-        vm.getCTIStub(virtualConstructThunkGenerator);
-    } else {
-        vm.getCTIStub(linkCallThatPreservesRegsThunkGenerator);
-        vm.getCTIStub(linkConstructThatPreservesRegsThunkGenerator);
-        vm.getCTIStub(linkPolymorphicCallThatPreservesRegsThunkGenerator);
-        vm.getCTIStub(virtualCallThatPreservesRegsThunkGenerator);
-        vm.getCTIStub(virtualConstructThatPreservesRegsThunkGenerator);
-    }
+    vm.getCTIStub(linkCallThunkGenerator);
+    vm.getCTIStub(linkPolymorphicCallThunkGenerator);
     
     if (vm.typeProfiler())
         vm.typeProfilerLog()->processLogEntries(ASCIILiteral("Preparing for DFG compilation."));

Modified: trunk/Source/_javascript_Core/dfg/DFGJITCompiler.cpp (187504 => 187505)


--- trunk/Source/_javascript_Core/dfg/DFGJITCompiler.cpp	2015-07-28 20:10:03 UTC (rev 187504)
+++ trunk/Source/_javascript_Core/dfg/DFGJITCompiler.cpp	2015-07-28 20:12:33 UTC (rev 187505)
@@ -244,10 +244,7 @@
     for (unsigned i = 0; i < m_jsCalls.size(); ++i) {
         JSCallRecord& record = m_jsCalls[i];
         CallLinkInfo& info = *record.m_info;
-        ThunkGenerator generator = linkThunkGeneratorFor(
-            info.specializationKind(),
-            RegisterPreservationNotRequired);
-        linkBuffer.link(record.m_slowCall, FunctionPtr(m_vm->getCTIStub(generator).code().executableAddress()));
+        linkBuffer.link(record.m_slowCall, FunctionPtr(m_vm->getCTIStub(linkCallThunkGenerator).code().executableAddress()));
         info.setCallLocations(linkBuffer.locationOfNearCall(record.m_slowCall),
             linkBuffer.locationOf(record.m_targetToCheck),
             linkBuffer.locationOfNearCall(record.m_fastCall));

Modified: trunk/Source/_javascript_Core/ftl/FTLJSCallBase.cpp (187504 => 187505)


--- trunk/Source/_javascript_Core/ftl/FTLJSCallBase.cpp	2015-07-28 20:10:03 UTC (rev 187504)
+++ trunk/Source/_javascript_Core/ftl/FTLJSCallBase.cpp	2015-07-28 20:12:33 UTC (rev 187505)
@@ -69,11 +69,8 @@
 
 void JSCallBase::link(VM& vm, LinkBuffer& linkBuffer)
 {
-    ThunkGenerator generator = linkThunkGeneratorFor(
-        CallLinkInfo::specializationKindFor(m_type), MustPreserveRegisters);
-    
     linkBuffer.link(
-        m_slowCall, FunctionPtr(vm.getCTIStub(generator).code().executableAddress()));
+        m_slowCall, FunctionPtr(vm.getCTIStub(linkCallThunkGenerator).code().executableAddress()));
 
     m_callLinkInfo->setUpCallFromFTL(m_type, m_origin, linkBuffer.locationOfNearCall(m_slowCall),
         linkBuffer.locationOf(m_targetToCheck), linkBuffer.locationOfNearCall(m_fastCall),

Modified: trunk/Source/_javascript_Core/jit/JITCall.cpp (187504 => 187505)


--- trunk/Source/_javascript_Core/jit/JITCall.cpp	2015-07-28 20:10:03 UTC (rev 187504)
+++ trunk/Source/_javascript_Core/jit/JITCall.cpp	2015-07-28 20:12:33 UTC (rev 187505)
@@ -106,14 +106,19 @@
 
 void JIT::compileCallEvalSlowCase(Instruction* instruction, Vector<SlowCaseEntry>::iterator& iter)
 {
+    CallLinkInfo* info = m_codeBlock->addCallLinkInfo();
+    info->setUpCall(CallLinkInfo::Call, CodeOrigin(m_bytecodeOffset), regT0);
+
     linkSlowCase(iter);
     int registerOffset = -instruction[4].u.operand;
 
     addPtr(TrustedImm32(registerOffset * sizeof(Register) + sizeof(CallerFrameAndPC)), callFrameRegister, stackPointerRegister);
 
     load64(Address(stackPointerRegister, sizeof(Register) * JSStack::Callee - sizeof(CallerFrameAndPC)), regT0);
-    move(TrustedImmPtr(&CallLinkInfo::dummy()), regT2);
-    emitNakedCall(m_vm->getCTIStub(virtualCallThunkGenerator).code());
+    move(TrustedImmPtr(info), regT2);
+    MacroAssemblerCodeRef virtualThunk = virtualThunkFor(m_vm, *info);
+    info->setSlowStub(createJITStubRoutine(virtualThunk, *m_vm, nullptr, true));
+    emitNakedCall(virtualThunk.code());
     addPtr(TrustedImm32(stackPointerOffsetFor(m_codeBlock) * sizeof(Register)), callFrameRegister, stackPointerRegister);
     checkStackPointerAlignment();
 
@@ -124,8 +129,6 @@
 
 void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned callLinkInfoIndex)
 {
-    CallLinkInfo* info = m_codeBlock->addCallLinkInfo();
-
     int callee = instruction[2].u.operand;
 
     /* Caller always:
@@ -143,6 +146,9 @@
     COMPILE_ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_construct), call_and_construct_opcodes_must_be_same_length);
     COMPILE_ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_call_varargs), call_and_call_varargs_opcodes_must_be_same_length);
     COMPILE_ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_construct_varargs), call_and_construct_varargs_opcodes_must_be_same_length);
+    CallLinkInfo* info;
+    if (opcodeID != op_call_eval)
+        info = m_codeBlock->addCallLinkInfo();
     if (opcodeID == op_call_varargs || opcodeID == op_construct_varargs)
         compileSetupVarargsFrame(instruction, info);
     else {
@@ -202,12 +208,8 @@
 
     linkSlowCase(iter);
 
-    ThunkGenerator generator = linkThunkGeneratorFor(
-        (opcodeID == op_construct || opcodeID == op_construct_varargs) ? CodeForConstruct : CodeForCall,
-        RegisterPreservationNotRequired);
-    
     move(TrustedImmPtr(m_callCompilationInfo[callLinkInfoIndex].callLinkInfo), regT2);
-    m_callCompilationInfo[callLinkInfoIndex].callReturnLocation = emitNakedCall(m_vm->getCTIStub(generator).code());
+    m_callCompilationInfo[callLinkInfoIndex].callReturnLocation = emitNakedCall(m_vm->getCTIStub(linkCallThunkGenerator).code());
 
     addPtr(TrustedImm32(stackPointerOffsetFor(m_codeBlock) * sizeof(Register)), callFrameRegister, stackPointerRegister);
     checkStackPointerAlignment();

Modified: trunk/Source/_javascript_Core/jit/JITCall32_64.cpp (187504 => 187505)


--- trunk/Source/_javascript_Core/jit/JITCall32_64.cpp	2015-07-28 20:10:03 UTC (rev 187504)
+++ trunk/Source/_javascript_Core/jit/JITCall32_64.cpp	2015-07-28 20:12:33 UTC (rev 187505)
@@ -166,6 +166,9 @@
 
 void JIT::compileCallEvalSlowCase(Instruction* instruction, Vector<SlowCaseEntry>::iterator& iter)
 {
+    CallLinkInfo* info = m_codeBlock->addCallLinkInfo();
+    info->setUpCall(CallLinkInfo::Call, CodeOrigin(m_bytecodeOffset), regT0);
+
     linkSlowCase(iter);
 
     int registerOffset = -instruction[4].u.operand;
@@ -174,10 +177,12 @@
 
     loadPtr(Address(stackPointerRegister, sizeof(Register) * JSStack::Callee - sizeof(CallerFrameAndPC)), regT0);
     loadPtr(Address(stackPointerRegister, sizeof(Register) * JSStack::Callee - sizeof(CallerFrameAndPC)), regT1);
-    move(TrustedImmPtr(&CallLinkInfo::dummy()), regT2);
+    move(TrustedImmPtr(info), regT2);
 
     emitLoad(JSStack::Callee, regT1, regT0);
-    emitNakedCall(m_vm->getCTIStub(virtualCallThunkGenerator).code());
+    MacroAssemblerCodeRef virtualThunk = virtualThunkFor(m_vm, *info);
+    info->setSlowStub(createJITStubRoutine(virtualThunk, *m_vm, nullptr, true));
+    emitNakedCall(virtualThunk.code());
     addPtr(TrustedImm32(stackPointerOffsetFor(m_codeBlock) * sizeof(Register)), callFrameRegister, stackPointerRegister);
     checkStackPointerAlignment();
 
@@ -188,7 +193,6 @@
 
 void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned callLinkInfoIndex)
 {
-    CallLinkInfo* info = m_codeBlock->addCallLinkInfo();
     int callee = instruction[2].u.operand;
 
     /* Caller always:
@@ -203,7 +207,9 @@
         - Caller initializes ReturnPC; CodeBlock.
         - Caller restores callFrameRegister after return.
     */
-    
+    CallLinkInfo* info;
+    if (opcodeID != op_call_eval)
+        info = m_codeBlock->addCallLinkInfo();
     if (opcodeID == op_call_varargs || opcodeID == op_construct_varargs)
         compileSetupVarargsFrame(instruction, info);
     else {
@@ -268,12 +274,8 @@
     linkSlowCase(iter);
     linkSlowCase(iter);
 
-    ThunkGenerator generator = linkThunkGeneratorFor(
-        (opcodeID == op_construct || opcodeID == op_construct_varargs) ? CodeForConstruct : CodeForCall,
-        RegisterPreservationNotRequired);
-    
     move(TrustedImmPtr(m_callCompilationInfo[callLinkInfoIndex].callLinkInfo), regT2);
-    m_callCompilationInfo[callLinkInfoIndex].callReturnLocation = emitNakedCall(m_vm->getCTIStub(generator).code());
+    m_callCompilationInfo[callLinkInfoIndex].callReturnLocation = emitNakedCall(m_vm->getCTIStub(linkCallThunkGenerator).code());
 
     addPtr(TrustedImm32(stackPointerOffsetFor(m_codeBlock) * sizeof(Register)), callFrameRegister, stackPointerRegister);
     checkStackPointerAlignment();

Modified: trunk/Source/_javascript_Core/jit/JITOperations.cpp (187504 => 187505)


--- trunk/Source/_javascript_Core/jit/JITOperations.cpp	2015-07-28 20:10:03 UTC (rev 187504)
+++ trunk/Source/_javascript_Core/jit/JITOperations.cpp	2015-07-28 20:12:33 UTC (rev 187505)
@@ -752,12 +752,11 @@
     return vm->getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress();
 }
 
-inline char* linkFor(
-    ExecState* execCallee, CallLinkInfo* callLinkInfo, CodeSpecializationKind kind,
-    RegisterPreservationMode registers)
+char* JIT_OPERATION operationLinkCall(ExecState* execCallee, CallLinkInfo* callLinkInfo)
 {
     ExecState* exec = execCallee->callerFrame();
     VM* vm = &exec->vm();
+    CodeSpecializationKind kind = callLinkInfo->specializationKind();
     NativeCallFrameTracer tracer(vm, exec);
     
     JSValue calleeAsValue = execCallee->calleeAsValue();
@@ -776,7 +775,7 @@
     MacroAssemblerCodePtr codePtr;
     CodeBlock* codeBlock = 0;
     if (executable->isHostFunction())
-        codePtr = executable->entrypointFor(*vm, kind, MustCheckArity, registers);
+        codePtr = executable->entrypointFor(*vm, kind, MustCheckArity, callLinkInfo->registerPreservationMode());
     else {
         FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable);
 
@@ -796,42 +795,22 @@
             arity = MustCheckArity;
         else
             arity = ArityCheckNotRequired;
-        codePtr = functionExecutable->entrypointFor(*vm, kind, arity, registers);
+        codePtr = functionExecutable->entrypointFor(*vm, kind, arity, callLinkInfo->registerPreservationMode());
     }
     if (!callLinkInfo->seenOnce())
         callLinkInfo->setSeen();
     else
-        linkFor(execCallee, *callLinkInfo, codeBlock, callee, codePtr, kind, registers);
+        linkFor(execCallee, *callLinkInfo, codeBlock, callee, codePtr);
     
     return reinterpret_cast<char*>(codePtr.executableAddress());
 }
 
-char* JIT_OPERATION operationLinkCall(ExecState* execCallee, CallLinkInfo* callLinkInfo)
-{
-    return linkFor(execCallee, callLinkInfo, CodeForCall, RegisterPreservationNotRequired);
-}
-
-char* JIT_OPERATION operationLinkConstruct(ExecState* execCallee, CallLinkInfo* callLinkInfo)
-{
-    return linkFor(execCallee, callLinkInfo, CodeForConstruct, RegisterPreservationNotRequired);
-}
-
-char* JIT_OPERATION operationLinkCallThatPreservesRegs(ExecState* execCallee, CallLinkInfo* callLinkInfo)
-{
-    return linkFor(execCallee, callLinkInfo, CodeForCall, MustPreserveRegisters);
-}
-
-char* JIT_OPERATION operationLinkConstructThatPreservesRegs(ExecState* execCallee, CallLinkInfo* callLinkInfo)
-{
-    return linkFor(execCallee, callLinkInfo, CodeForConstruct, MustPreserveRegisters);
-}
-
 inline char* virtualForWithFunction(
-    ExecState* execCallee, CodeSpecializationKind kind, RegisterPreservationMode registers,
-    JSCell*& calleeAsFunctionCell)
+    ExecState* execCallee, CallLinkInfo* callLinkInfo, JSCell*& calleeAsFunctionCell)
 {
     ExecState* exec = execCallee->callerFrame();
     VM* vm = &exec->vm();
+    CodeSpecializationKind kind = callLinkInfo->specializationKind();
     NativeCallFrameTracer tracer(vm, exec);
 
     JSValue calleeAsValue = execCallee->calleeAsValue();
@@ -857,56 +836,26 @@
         }
     }
     return reinterpret_cast<char*>(executable->entrypointFor(
-        *vm, kind, MustCheckArity, registers).executableAddress());
+        *vm, kind, MustCheckArity, callLinkInfo->registerPreservationMode()).executableAddress());
 }
 
-inline char* virtualFor(
-    ExecState* execCallee, CodeSpecializationKind kind, RegisterPreservationMode registers)
-{
-    JSCell* calleeAsFunctionCellIgnored;
-    return virtualForWithFunction(execCallee, kind, registers, calleeAsFunctionCellIgnored);
-}
-
 char* JIT_OPERATION operationLinkPolymorphicCall(ExecState* execCallee, CallLinkInfo* callLinkInfo)
 {
+    ASSERT(callLinkInfo->specializationKind() == CodeForCall);
     JSCell* calleeAsFunctionCell;
-    char* result = virtualForWithFunction(execCallee, CodeForCall, RegisterPreservationNotRequired, calleeAsFunctionCell);
+    char* result = virtualForWithFunction(execCallee, callLinkInfo, calleeAsFunctionCell);
 
-    linkPolymorphicCall(execCallee, *callLinkInfo, CallVariant(calleeAsFunctionCell), RegisterPreservationNotRequired);
+    linkPolymorphicCall(execCallee, *callLinkInfo, CallVariant(calleeAsFunctionCell));
     
     return result;
 }
 
-char* JIT_OPERATION operationVirtualCall(ExecState* execCallee, CallLinkInfo*)
-{    
-    return virtualFor(execCallee, CodeForCall, RegisterPreservationNotRequired);
-}
-
-char* JIT_OPERATION operationVirtualConstruct(ExecState* execCallee, CallLinkInfo*)
+char* JIT_OPERATION operationVirtualCall(ExecState* execCallee, CallLinkInfo* callLinkInfo)
 {
-    return virtualFor(execCallee, CodeForConstruct, RegisterPreservationNotRequired);
+    JSCell* calleeAsFunctionCellIgnored;
+    return virtualForWithFunction(execCallee, callLinkInfo, calleeAsFunctionCellIgnored);
 }
 
-char* JIT_OPERATION operationLinkPolymorphicCallThatPreservesRegs(ExecState* execCallee, CallLinkInfo* callLinkInfo)
-{
-    JSCell* calleeAsFunctionCell;
-    char* result = virtualForWithFunction(execCallee, CodeForCall, MustPreserveRegisters, calleeAsFunctionCell);
-
-    linkPolymorphicCall(execCallee, *callLinkInfo, CallVariant(calleeAsFunctionCell), MustPreserveRegisters);
-    
-    return result;
-}
-
-char* JIT_OPERATION operationVirtualCallThatPreservesRegs(ExecState* execCallee, CallLinkInfo*)
-{    
-    return virtualFor(execCallee, CodeForCall, MustPreserveRegisters);
-}
-
-char* JIT_OPERATION operationVirtualConstructThatPreservesRegs(ExecState* execCallee, CallLinkInfo*)
-{
-    return virtualFor(execCallee, CodeForConstruct, MustPreserveRegisters);
-}
-
 size_t JIT_OPERATION operationCompareLess(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
 {
     VM* vm = &exec->vm();

Modified: trunk/Source/_javascript_Core/jit/JITOperations.h (187504 => 187505)


--- trunk/Source/_javascript_Core/jit/JITOperations.h	2015-07-28 20:10:03 UTC (rev 187504)
+++ trunk/Source/_javascript_Core/jit/JITOperations.h	2015-07-28 20:12:33 UTC (rev 187505)
@@ -267,13 +267,6 @@
 char* JIT_OPERATION operationLinkCall(ExecState*, CallLinkInfo*) WTF_INTERNAL;
 char* JIT_OPERATION operationLinkPolymorphicCall(ExecState*, CallLinkInfo*) WTF_INTERNAL;
 char* JIT_OPERATION operationVirtualCall(ExecState*, CallLinkInfo*) WTF_INTERNAL;
-char* JIT_OPERATION operationVirtualConstruct(ExecState*, CallLinkInfo*) WTF_INTERNAL;
-char* JIT_OPERATION operationLinkConstruct(ExecState*, CallLinkInfo*) WTF_INTERNAL;
-char* JIT_OPERATION operationLinkCallThatPreservesRegs(ExecState*, CallLinkInfo*) WTF_INTERNAL;
-char* JIT_OPERATION operationLinkPolymorphicCallThatPreservesRegs(ExecState*, CallLinkInfo*) WTF_INTERNAL;
-char* JIT_OPERATION operationVirtualCallThatPreservesRegs(ExecState*, CallLinkInfo*) WTF_INTERNAL;
-char* JIT_OPERATION operationVirtualConstructThatPreservesRegs(ExecState*, CallLinkInfo*) WTF_INTERNAL;
-char* JIT_OPERATION operationLinkConstructThatPreservesRegs(ExecState*, CallLinkInfo*) WTF_INTERNAL;
 
 size_t JIT_OPERATION operationCompareLess(ExecState*, EncodedJSValue, EncodedJSValue) WTF_INTERNAL;
 size_t JIT_OPERATION operationCompareLessEq(ExecState*, EncodedJSValue, EncodedJSValue) WTF_INTERNAL;
@@ -356,68 +349,6 @@
 
 } // extern "C"
 
-inline P_JITOperation_ECli operationLinkFor(
-    CodeSpecializationKind kind, RegisterPreservationMode registers)
-{
-    switch (kind) {
-    case CodeForCall:
-        switch (registers) {
-        case RegisterPreservationNotRequired:
-            return operationLinkCall;
-        case MustPreserveRegisters:
-            return operationLinkCallThatPreservesRegs;
-        }
-        break;
-    case CodeForConstruct:
-        switch (registers) {
-        case RegisterPreservationNotRequired:
-            return operationLinkConstruct;
-        case MustPreserveRegisters:
-            return operationLinkConstructThatPreservesRegs;
-        }
-        break;
-    }
-    RELEASE_ASSERT_NOT_REACHED();
-    return 0;
-}
-
-inline P_JITOperation_ECli operationVirtualFor(
-    CodeSpecializationKind kind, RegisterPreservationMode registers)
-{
-    switch (kind) {
-    case CodeForCall:
-        switch (registers) {
-        case RegisterPreservationNotRequired:
-            return operationVirtualCall;
-        case MustPreserveRegisters:
-            return operationVirtualCallThatPreservesRegs;
-        }
-        break;
-    case CodeForConstruct:
-        switch (registers) {
-        case RegisterPreservationNotRequired:
-            return operationVirtualConstruct;
-        case MustPreserveRegisters:
-            return operationVirtualConstructThatPreservesRegs;
-        }
-        break;
-    }
-    RELEASE_ASSERT_NOT_REACHED();
-    return 0;
-}
-
-inline P_JITOperation_ECli operationLinkPolymorphicCallFor(RegisterPreservationMode registers)
-{
-    switch (registers) {
-    case RegisterPreservationNotRequired:
-        return operationLinkPolymorphicCall;
-    case MustPreserveRegisters:
-        return operationLinkPolymorphicCallThatPreservesRegs;
-    }
-    RELEASE_ASSERT_NOT_REACHED();
-    return 0;
-}
-
 } // namespace JSC
 
 #endif // ENABLE(JIT)

Modified: trunk/Source/_javascript_Core/jit/Repatch.cpp (187504 => 187505)


--- trunk/Source/_javascript_Core/jit/Repatch.cpp	2015-07-28 20:10:03 UTC (rev 187504)
+++ trunk/Source/_javascript_Core/jit/Repatch.cpp	2015-07-28 20:12:33 UTC (rev 187505)
@@ -586,10 +586,8 @@
             patchBuffer.locationOf(addressOfLinkFunctionCheck),
             patchBuffer.locationOfNearCall(fastPathCall));
 
-        ThunkGenerator generator = linkThunkGeneratorFor(
-            CodeForCall, RegisterPreservationNotRequired);
         patchBuffer.link(
-            slowPathCall, CodeLocationLabel(vm->getCTIStub(generator).code()));
+            slowPathCall, CodeLocationLabel(vm->getCTIStub(linkCallThunkGenerator).code()));
     }
     
     MacroAssemblerCodeRef code = FINALIZE_CODE_FOR(
@@ -1601,23 +1599,29 @@
 }
 
 static void linkSlowFor(
-    RepatchBuffer& repatchBuffer, VM* vm, CallLinkInfo& callLinkInfo, ThunkGenerator generator)
+    RepatchBuffer& repatchBuffer, VM*, CallLinkInfo& callLinkInfo, MacroAssemblerCodeRef codeRef)
 {
     repatchBuffer.relink(
-        callLinkInfo.callReturnLocation(), vm->getCTIStub(generator).code());
+        callLinkInfo.callReturnLocation(), codeRef.code());
 }
 
 static void linkSlowFor(
-    RepatchBuffer& repatchBuffer, VM* vm, CallLinkInfo& callLinkInfo,
-    CodeSpecializationKind kind, RegisterPreservationMode registers)
+    RepatchBuffer& repatchBuffer, VM* vm, CallLinkInfo& callLinkInfo, ThunkGenerator generator)
 {
-    linkSlowFor(repatchBuffer, vm, callLinkInfo, virtualThunkGeneratorFor(kind, registers));
+    linkSlowFor(repatchBuffer, vm, callLinkInfo, vm->getCTIStub(generator));
 }
 
+static void linkSlowFor(
+    RepatchBuffer& repatchBuffer, VM* vm, CallLinkInfo& callLinkInfo)
+{
+    MacroAssemblerCodeRef virtualThunk = virtualThunkFor(vm, callLinkInfo);
+    linkSlowFor(repatchBuffer, vm, callLinkInfo, virtualThunk);
+    callLinkInfo.setSlowStub(createJITStubRoutine(virtualThunk, *vm, nullptr, true));
+}
+
 void linkFor(
     ExecState* exec, CallLinkInfo& callLinkInfo, CodeBlock* calleeCodeBlock,
-    JSFunction* callee, MacroAssemblerCodePtr codePtr, CodeSpecializationKind kind,
-    RegisterPreservationMode registers)
+    JSFunction* callee, MacroAssemblerCodePtr codePtr)
 {
     ASSERT(!callLinkInfo.stub());
     
@@ -1637,61 +1641,55 @@
     if (calleeCodeBlock)
         calleeCodeBlock->linkIncomingCall(exec->callerFrame(), &callLinkInfo);
     
-    if (kind == CodeForCall) {
+    if (callLinkInfo.specializationKind() == CodeForCall) {
         linkSlowFor(
-            repatchBuffer, vm, callLinkInfo, linkPolymorphicCallThunkGeneratorFor(registers));
+            repatchBuffer, vm, callLinkInfo, linkPolymorphicCallThunkGenerator);
         return;
     }
     
-    ASSERT(kind == CodeForConstruct);
-    linkSlowFor(repatchBuffer, vm, callLinkInfo, CodeForConstruct, registers);
+    ASSERT(callLinkInfo.specializationKind() == CodeForConstruct);
+    linkSlowFor(repatchBuffer, vm, callLinkInfo);
 }
 
 void linkSlowFor(
-    ExecState* exec, CallLinkInfo& callLinkInfo, CodeSpecializationKind kind,
-    RegisterPreservationMode registers)
+    ExecState* exec, CallLinkInfo& callLinkInfo)
 {
     CodeBlock* callerCodeBlock = exec->callerFrame()->codeBlock();
     VM* vm = callerCodeBlock->vm();
     
     RepatchBuffer repatchBuffer(callerCodeBlock);
     
-    linkSlowFor(repatchBuffer, vm, callLinkInfo, kind, registers);
+    linkSlowFor(repatchBuffer, vm, callLinkInfo);
 }
 
 static void revertCall(
-    RepatchBuffer& repatchBuffer, VM* vm, CallLinkInfo& callLinkInfo, ThunkGenerator generator)
+    RepatchBuffer& repatchBuffer, VM* vm, CallLinkInfo& callLinkInfo, MacroAssemblerCodeRef codeRef)
 {
     repatchBuffer.revertJumpReplacementToBranchPtrWithPatch(
         RepatchBuffer::startOfBranchPtrWithPatchOnRegister(callLinkInfo.hotPathBegin()),
         static_cast<MacroAssembler::RegisterID>(callLinkInfo.calleeGPR()), 0);
-    linkSlowFor(repatchBuffer, vm, callLinkInfo, generator);
+    linkSlowFor(repatchBuffer, vm, callLinkInfo, codeRef);
     callLinkInfo.clearSeen();
     callLinkInfo.clearCallee();
     callLinkInfo.clearStub();
+    callLinkInfo.clearSlowStub();
     if (callLinkInfo.isOnList())
         callLinkInfo.remove();
 }
 
 void unlinkFor(
-    RepatchBuffer& repatchBuffer, CallLinkInfo& callLinkInfo,
-    CodeSpecializationKind kind, RegisterPreservationMode registers)
+    RepatchBuffer& repatchBuffer, CallLinkInfo& callLinkInfo)
 {
     if (Options::showDisassembly())
         dataLog("Unlinking call from ", callLinkInfo.callReturnLocation(), " in request from ", pointerDump(repatchBuffer.codeBlock()), "\n");
     
-    revertCall(
-        repatchBuffer, repatchBuffer.codeBlock()->vm(), callLinkInfo,
-        linkThunkGeneratorFor(kind, registers));
+    VM* vm = repatchBuffer.codeBlock()->vm();
+    revertCall(repatchBuffer, vm, callLinkInfo, vm->getCTIStub(linkCallThunkGenerator));
 }
 
 void linkVirtualFor(
-    ExecState* exec, CallLinkInfo& callLinkInfo,
-    CodeSpecializationKind kind, RegisterPreservationMode registers)
+    ExecState* exec, CallLinkInfo& callLinkInfo)
 {
-    // FIXME: We could generate a virtual call stub here. This would lead to faster virtual calls
-    // by eliminating the branch prediction bottleneck inside the shared virtual call thunk.
-    
     CodeBlock* callerCodeBlock = exec->callerFrame()->codeBlock();
     VM* vm = callerCodeBlock->vm();
     
@@ -1699,7 +1697,9 @@
         dataLog("Linking virtual call at ", *callerCodeBlock, " ", exec->callerFrame()->codeOrigin(), "\n");
     
     RepatchBuffer repatchBuffer(callerCodeBlock);
-    revertCall(repatchBuffer, vm, callLinkInfo, virtualThunkGeneratorFor(kind, registers));
+    MacroAssemblerCodeRef virtualThunk = virtualThunkFor(vm, callLinkInfo);
+    revertCall(repatchBuffer, vm, callLinkInfo, virtualThunk);
+    callLinkInfo.setSlowStub(createJITStubRoutine(virtualThunk, *vm, nullptr, true));
 }
 
 namespace {
@@ -1710,13 +1710,12 @@
 } // annonymous namespace
 
 void linkPolymorphicCall(
-    ExecState* exec, CallLinkInfo& callLinkInfo, CallVariant newVariant,
-    RegisterPreservationMode registers)
+    ExecState* exec, CallLinkInfo& callLinkInfo, CallVariant newVariant)
 {
     // Currently we can't do anything for non-function callees.
     // https://bugs.webkit.org/show_bug.cgi?id=140685
     if (!newVariant || !newVariant.executable()) {
-        linkVirtualFor(exec, callLinkInfo, CodeForCall, registers);
+        linkVirtualFor(exec, callLinkInfo);
         return;
     }
     
@@ -1759,7 +1758,7 @@
             // If we cannot handle a callee, assume that it's better for this whole thing to be a
             // virtual call.
             if (exec->argumentCountIncludingThis() < static_cast<size_t>(codeBlock->numParameters()) || callLinkInfo.callType() == CallLinkInfo::CallVarargs || callLinkInfo.callType() == CallLinkInfo::ConstructVarargs) {
-                linkVirtualFor(exec, callLinkInfo, CodeForCall, registers);
+                linkVirtualFor(exec, callLinkInfo);
                 return;
             }
         }
@@ -1774,7 +1773,7 @@
     else
         maxPolymorphicCallVariantListSize = Options::maxPolymorphicCallVariantListSize();
     if (list.size() > maxPolymorphicCallVariantListSize) {
-        linkVirtualFor(exec, callLinkInfo, CodeForCall, registers);
+        linkVirtualFor(exec, callLinkInfo);
         return;
     }
     
@@ -1874,7 +1873,7 @@
         ASSERT(variant.executable()->hasJITCodeForCall());
         MacroAssemblerCodePtr codePtr =
             variant.executable()->generatedJITCodeForCall()->addressForCall(
-                *vm, variant.executable(), ArityCheckNotRequired, registers);
+                *vm, variant.executable(), ArityCheckNotRequired, callLinkInfo.registerPreservationMode());
         
         if (fastCounts) {
             stubJit.add32(
@@ -1900,7 +1899,7 @@
         
     LinkBuffer patchBuffer(*vm, stubJit, callerCodeBlock, JITCompilationCanFail);
     if (patchBuffer.didFailToAllocate()) {
-        linkVirtualFor(exec, callLinkInfo, CodeForCall, registers);
+        linkVirtualFor(exec, callLinkInfo);
         return;
     }
     
@@ -1913,7 +1912,7 @@
         patchBuffer.link(done, callLinkInfo.callReturnLocation().labelAtOffset(0));
     else
         patchBuffer.link(done, callLinkInfo.hotPathOther().labelAtOffset(0));
-    patchBuffer.link(slow, CodeLocationLabel(vm->getCTIStub(linkPolymorphicCallThunkGeneratorFor(registers)).code()));
+    patchBuffer.link(slow, CodeLocationLabel(vm->getCTIStub(linkPolymorphicCallThunkGenerator).code()));
     
     RefPtr<PolymorphicCallStubRoutine> stubRoutine = adoptRef(new PolymorphicCallStubRoutine(
         FINALIZE_CODE_FOR(
@@ -1929,8 +1928,10 @@
     repatchBuffer.replaceWithJump(
         RepatchBuffer::startOfBranchPtrWithPatchOnRegister(callLinkInfo.hotPathBegin()),
         CodeLocationLabel(stubRoutine->code().code()));
-    // This is weird. The original slow path should no longer be reachable.
-    linkSlowFor(repatchBuffer, vm, callLinkInfo, CodeForCall, registers);
+    // The original slow path is unreachable on 64-bits, but still
+    // reachable on 32-bits since a non-cell callee will always
+    // trigger the slow path
+    linkSlowFor(repatchBuffer, vm, callLinkInfo);
     
     // If there had been a previous stub routine, that one will die as soon as the GC runs and sees
     // that it's no longer on stack.

Modified: trunk/Source/_javascript_Core/jit/Repatch.h (187504 => 187505)


--- trunk/Source/_javascript_Core/jit/Repatch.h	2015-07-28 20:10:03 UTC (rev 187504)
+++ trunk/Source/_javascript_Core/jit/Repatch.h	2015-07-28 20:12:33 UTC (rev 187505)
@@ -40,11 +40,11 @@
 void repatchPutByID(ExecState*, JSValue, Structure*, const Identifier&, const PutPropertySlot&, StructureStubInfo&, PutKind);
 void buildPutByIdList(ExecState*, JSValue, Structure*, const Identifier&, const PutPropertySlot&, StructureStubInfo&, PutKind);
 void repatchIn(ExecState*, JSCell*, const Identifier&, bool wasFound, const PropertySlot&, StructureStubInfo&);
-void linkFor(ExecState*, CallLinkInfo&, CodeBlock*, JSFunction* callee, MacroAssemblerCodePtr, CodeSpecializationKind, RegisterPreservationMode);
-void linkSlowFor(ExecState*, CallLinkInfo&, CodeSpecializationKind, RegisterPreservationMode);
-void unlinkFor(RepatchBuffer&, CallLinkInfo&, CodeSpecializationKind, RegisterPreservationMode);
-void linkVirtualFor(ExecState*, CallLinkInfo&, CodeSpecializationKind, RegisterPreservationMode);
-void linkPolymorphicCall(ExecState*, CallLinkInfo&, CallVariant, RegisterPreservationMode);
+void linkFor(ExecState*, CallLinkInfo&, CodeBlock*, JSFunction* callee, MacroAssemblerCodePtr);
+void linkSlowFor(ExecState*, CallLinkInfo&);
+void unlinkFor(RepatchBuffer&, CallLinkInfo&);
+void linkVirtualFor(ExecState*, CallLinkInfo&);
+void linkPolymorphicCall(ExecState*, CallLinkInfo&, CallVariant);
 void resetGetByID(RepatchBuffer&, StructureStubInfo&);
 void resetPutByID(RepatchBuffer&, StructureStubInfo&);
 void resetIn(RepatchBuffer&, StructureStubInfo&);

Modified: trunk/Source/_javascript_Core/jit/ThunkGenerators.cpp (187504 => 187505)


--- trunk/Source/_javascript_Core/jit/ThunkGenerators.cpp	2015-07-28 20:10:03 UTC (rev 187504)
+++ trunk/Source/_javascript_Core/jit/ThunkGenerators.cpp	2015-07-28 20:12:33 UTC (rev 187505)
@@ -99,8 +99,7 @@
     jit.jump(GPRInfo::returnValueGPR);
 }
 
-static MacroAssemblerCodeRef linkForThunkGenerator(
-    VM* vm, CodeSpecializationKind kind, RegisterPreservationMode registers)
+MacroAssemblerCodeRef linkCallThunkGenerator(VM* vm)
 {
     // The return address is on the stack or in the link register. We will hence
     // save the return address to the call frame while we make a C++ function call
@@ -110,60 +109,26 @@
     
     CCallHelpers jit(vm);
     
-    slowPathFor(jit, vm, operationLinkFor(kind, registers));
+    slowPathFor(jit, vm, operationLinkCall);
     
     LinkBuffer patchBuffer(*vm, jit, GLOBAL_THUNK_ID);
-    return FINALIZE_CODE(
-        patchBuffer,
-        ("Link %s%s slow path thunk", kind == CodeForCall ? "call" : "construct", registers == MustPreserveRegisters ? " that preserves registers" : ""));
+    return FINALIZE_CODE(patchBuffer, ("Link call slow path thunk"));
 }
 
-MacroAssemblerCodeRef linkCallThunkGenerator(VM* vm)
+// For closure optimizations, we only include calls, since if you're using closures for
+// object construction then you're going to lose big time anyway.
+MacroAssemblerCodeRef linkPolymorphicCallThunkGenerator(VM* vm)
 {
-    return linkForThunkGenerator(vm, CodeForCall, RegisterPreservationNotRequired);
-}
-
-MacroAssemblerCodeRef linkConstructThunkGenerator(VM* vm)
-{
-    return linkForThunkGenerator(vm, CodeForConstruct, RegisterPreservationNotRequired);
-}
-
-MacroAssemblerCodeRef linkCallThatPreservesRegsThunkGenerator(VM* vm)
-{
-    return linkForThunkGenerator(vm, CodeForCall, MustPreserveRegisters);
-}
-
-MacroAssemblerCodeRef linkConstructThatPreservesRegsThunkGenerator(VM* vm)
-{
-    return linkForThunkGenerator(vm, CodeForConstruct, MustPreserveRegisters);
-}
-
-static MacroAssemblerCodeRef linkPolymorphicCallForThunkGenerator(
-    VM* vm, RegisterPreservationMode registers)
-{
     CCallHelpers jit(vm);
     
-    slowPathFor(jit, vm, operationLinkPolymorphicCallFor(registers));
+    slowPathFor(jit, vm, operationLinkPolymorphicCall);
     
     LinkBuffer patchBuffer(*vm, jit, GLOBAL_THUNK_ID);
-    return FINALIZE_CODE(patchBuffer, ("Link polymorphic call %s slow path thunk", registers == MustPreserveRegisters ? " that preserves registers" : ""));
+    return FINALIZE_CODE(patchBuffer, ("Link polymorphic call slow path thunk"));
 }
 
-// For closure optimizations, we only include calls, since if you're using closures for
-// object construction then you're going to lose big time anyway.
-MacroAssemblerCodeRef linkPolymorphicCallThunkGenerator(VM* vm)
+MacroAssemblerCodeRef virtualThunkFor(VM* vm, CallLinkInfo& callLinkInfo)
 {
-    return linkPolymorphicCallForThunkGenerator(vm, RegisterPreservationNotRequired);
-}
-
-MacroAssemblerCodeRef linkPolymorphicCallThatPreservesRegsThunkGenerator(VM* vm)
-{
-    return linkPolymorphicCallForThunkGenerator(vm, MustPreserveRegisters);
-}
-
-static MacroAssemblerCodeRef virtualForThunkGenerator(
-    VM* vm, CodeSpecializationKind kind, RegisterPreservationMode registers)
-{
     // The callee is in regT0 (for JSVALUE32_64, the tag is in regT1).
     // The return address is on the stack, or in the link register. We will hence
     // jump to the callee, or save the return address to the call frame while we
@@ -208,7 +173,8 @@
         GPRInfo::regT4);
     jit.loadPtr(
         CCallHelpers::Address(
-            GPRInfo::regT4, ExecutableBase::offsetOfJITCodeWithArityCheckFor(kind, registers)),
+            GPRInfo::regT4, ExecutableBase::offsetOfJITCodeWithArityCheckFor(
+                callLinkInfo.specializationKind(), callLinkInfo.registerPreservationMode())),
         GPRInfo::regT4);
     slowCase.append(jit.branchTestPtr(CCallHelpers::Zero, GPRInfo::regT4));
     
@@ -223,34 +189,17 @@
     
     // Here we don't know anything, so revert to the full slow path.
     
-    slowPathFor(jit, vm, operationVirtualFor(kind, registers));
+    slowPathFor(jit, vm, operationVirtualCall);
     
     LinkBuffer patchBuffer(*vm, jit, GLOBAL_THUNK_ID);
     return FINALIZE_CODE(
         patchBuffer,
-        ("Virtual %s%s slow path thunk", kind == CodeForCall ? "call" : "construct", registers == MustPreserveRegisters ? " that preserves registers" : ""));
+        ("Virtual %s%s slow path thunk at CodePtr(%p)",
+        callLinkInfo.specializationKind() == CodeForCall ? "call" : "construct",
+        callLinkInfo.registerPreservationMode() == MustPreserveRegisters ? " that preserves registers" : "",
+        callLinkInfo.callReturnLocation().dataLocation()));
 }
 
-MacroAssemblerCodeRef virtualCallThunkGenerator(VM* vm)
-{
-    return virtualForThunkGenerator(vm, CodeForCall, RegisterPreservationNotRequired);
-}
-
-MacroAssemblerCodeRef virtualConstructThunkGenerator(VM* vm)
-{
-    return virtualForThunkGenerator(vm, CodeForConstruct, RegisterPreservationNotRequired);
-}
-
-MacroAssemblerCodeRef virtualCallThatPreservesRegsThunkGenerator(VM* vm)
-{
-    return virtualForThunkGenerator(vm, CodeForCall, MustPreserveRegisters);
-}
-
-MacroAssemblerCodeRef virtualConstructThatPreservesRegsThunkGenerator(VM* vm)
-{
-    return virtualForThunkGenerator(vm, CodeForConstruct, MustPreserveRegisters);
-}
-
 enum ThunkEntryType { EnterViaCall, EnterViaJump };
 
 static MacroAssemblerCodeRef nativeForGenerator(VM* vm, CodeSpecializationKind kind, ThunkEntryType entryType = EnterViaCall)

Modified: trunk/Source/_javascript_Core/jit/ThunkGenerators.h (187504 => 187505)


--- trunk/Source/_javascript_Core/jit/ThunkGenerators.h	2015-07-28 20:10:03 UTC (rev 187504)
+++ trunk/Source/_javascript_Core/jit/ThunkGenerators.h	2015-07-28 20:12:33 UTC (rev 187505)
@@ -33,83 +33,15 @@
 #if ENABLE(JIT)
 namespace JSC {
 
+class CallLinkInfo;
+
 MacroAssemblerCodeRef throwExceptionFromCallSlowPathGenerator(VM*);
 
 MacroAssemblerCodeRef linkCallThunkGenerator(VM*);
-MacroAssemblerCodeRef linkConstructThunkGenerator(VM*);
-MacroAssemblerCodeRef linkCallThatPreservesRegsThunkGenerator(VM*);
-MacroAssemblerCodeRef linkConstructThatPreservesRegsThunkGenerator(VM*);
-
-inline ThunkGenerator linkThunkGeneratorFor(
-    CodeSpecializationKind kind, RegisterPreservationMode registers)
-{
-    switch (kind) {
-    case CodeForCall:
-        switch (registers) {
-        case RegisterPreservationNotRequired:
-            return linkCallThunkGenerator;
-        case MustPreserveRegisters:
-            return linkCallThatPreservesRegsThunkGenerator;
-        }
-        break;
-    case CodeForConstruct:
-        switch (registers) {
-        case RegisterPreservationNotRequired:
-            return linkConstructThunkGenerator;
-        case MustPreserveRegisters:
-            return linkConstructThatPreservesRegsThunkGenerator;
-        }
-        break;
-    }
-    RELEASE_ASSERT_NOT_REACHED();
-    return 0;
-}
-
 MacroAssemblerCodeRef linkPolymorphicCallThunkGenerator(VM*);
-MacroAssemblerCodeRef linkPolymorphicCallThatPreservesRegsThunkGenerator(VM*);
 
-inline ThunkGenerator linkPolymorphicCallThunkGeneratorFor(RegisterPreservationMode registers)
-{
-    switch (registers) {
-    case RegisterPreservationNotRequired:
-        return linkPolymorphicCallThunkGenerator;
-    case MustPreserveRegisters:
-        return linkPolymorphicCallThatPreservesRegsThunkGenerator;
-    }
-    RELEASE_ASSERT_NOT_REACHED();
-    return 0;
-}
+MacroAssemblerCodeRef virtualThunkFor(VM*, CallLinkInfo&);
 
-MacroAssemblerCodeRef virtualCallThunkGenerator(VM*);
-MacroAssemblerCodeRef virtualConstructThunkGenerator(VM*);
-MacroAssemblerCodeRef virtualCallThatPreservesRegsThunkGenerator(VM*);
-MacroAssemblerCodeRef virtualConstructThatPreservesRegsThunkGenerator(VM*);
-
-inline ThunkGenerator virtualThunkGeneratorFor(
-    CodeSpecializationKind kind, RegisterPreservationMode registers)
-{
-    switch (kind) {
-    case CodeForCall:
-        switch (registers) {
-        case RegisterPreservationNotRequired:
-            return virtualCallThunkGenerator;
-        case MustPreserveRegisters:
-            return virtualCallThatPreservesRegsThunkGenerator;
-        }
-        break;
-    case CodeForConstruct:
-        switch (registers) {
-        case RegisterPreservationNotRequired:
-            return virtualConstructThunkGenerator;
-        case MustPreserveRegisters:
-            return virtualConstructThatPreservesRegsThunkGenerator;
-        }
-        break;
-    }
-    RELEASE_ASSERT_NOT_REACHED();
-    return 0;
-}
-
 MacroAssemblerCodeRef nativeCallGenerator(VM*);
 MacroAssemblerCodeRef nativeConstructGenerator(VM*);
 MacroAssemblerCodeRef nativeTailCallGenerator(VM*);
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to