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

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

<h3>Log Message</h3>
<pre>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.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCallLinkInfocpp">trunk/Source/JavaScriptCore/bytecode/CallLinkInfo.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCallLinkInfoh">trunk/Source/JavaScriptCore/bytecode/CallLinkInfo.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGDrivercpp">trunk/Source/JavaScriptCore/dfg/DFGDriver.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGJITCompilercpp">trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLJSCallBasecpp">trunk/Source/JavaScriptCore/ftl/FTLJSCallBase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITCallcpp">trunk/Source/JavaScriptCore/jit/JITCall.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITCall32_64cpp">trunk/Source/JavaScriptCore/jit/JITCall32_64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITOperationscpp">trunk/Source/JavaScriptCore/jit/JITOperations.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITOperationsh">trunk/Source/JavaScriptCore/jit/JITOperations.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitRepatchcpp">trunk/Source/JavaScriptCore/jit/Repatch.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitRepatchh">trunk/Source/JavaScriptCore/jit/Repatch.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitThunkGeneratorscpp">trunk/Source/JavaScriptCore/jit/ThunkGenerators.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitThunkGeneratorsh">trunk/Source/JavaScriptCore/jit/ThunkGenerators.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (187504 => 187505)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-07-28 20:10:03 UTC (rev 187504)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-07-28 20:12:33 UTC (rev 187505)
</span><span class="lines">@@ -1,5 +1,86 @@
</span><span class="cx"> 2015-07-28  Basile Clement  &lt;basile_clement@apple.com&gt;
</span><span class="cx"> 
</span><ins>+        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  &lt;basile_clement@apple.com&gt;
+
</ins><span class="cx">         stress/math-pow-with-constants.js fails in cloop
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=147167
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCallLinkInfocpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CallLinkInfo.cpp (187504 => 187505)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CallLinkInfo.cpp        2015-07-28 20:10:03 UTC (rev 187504)
+++ trunk/Source/JavaScriptCore/bytecode/CallLinkInfo.cpp        2015-07-28 20:12:33 UTC (rev 187505)
</span><span class="lines">@@ -55,10 +55,7 @@
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    unlinkFor(
-        repatchBuffer, *this,
-        (m_callType == Construct || m_callType == ConstructVarargs)? CodeForConstruct : CodeForCall,
-        m_isFTL ? MustPreserveRegisters : RegisterPreservationNotRequired);
</del><ins>+    unlinkFor(repatchBuffer, *this);
</ins><span class="cx"> 
</span><span class="cx">     // It will be on a list if the callee has a code block.
</span><span class="cx">     if (isOnList())
</span><span class="lines">@@ -104,12 +101,6 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-CallLinkInfo&amp; CallLinkInfo::dummy()
-{
-    static NeverDestroyed&lt;CallLinkInfo&gt; dummy;
-    return dummy;
-}
-
</del><span class="cx"> } // namespace JSC
</span><span class="cx"> #endif // ENABLE(JIT)
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCallLinkInfoh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CallLinkInfo.h (187504 => 187505)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CallLinkInfo.h        2015-07-28 20:10:03 UTC (rev 187504)
+++ trunk/Source/JavaScriptCore/bytecode/CallLinkInfo.h        2015-07-28 20:12:33 UTC (rev 187505)
</span><span class="lines">@@ -57,7 +57,7 @@
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     CallLinkInfo()
</span><del>-        : m_isFTL(false)
</del><ins>+        : m_registerPreservationMode(static_cast&lt;unsigned&gt;(RegisterPreservationNotRequired))
</ins><span class="cx">         , m_hasSeenShouldRepatch(false)
</span><span class="cx">         , m_hasSeenClosure(false)
</span><span class="cx">         , m_clearedByGC(false)
</span><span class="lines">@@ -84,6 +84,11 @@
</span><span class="cx">         return specializationKindFor(static_cast&lt;CallType&gt;(m_callType));
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    RegisterPreservationMode registerPreservationMode() const
+    {
+        return static_cast&lt;RegisterPreservationMode&gt;(m_registerPreservationMode);
+    }
+
</ins><span class="cx">     bool isLinked() { return m_stub || m_callee; }
</span><span class="cx">     void unlink(RepatchBuffer&amp;);
</span><span class="cx"> 
</span><span class="lines">@@ -106,7 +111,7 @@
</span><span class="cx">         CodeLocationNearCall callReturnLocation, CodeLocationDataLabelPtr hotPathBegin,
</span><span class="cx">         CodeLocationNearCall hotPathOther, unsigned calleeGPR)
</span><span class="cx">     {
</span><del>-        m_isFTL = true;
</del><ins>+        m_registerPreservationMode = static_cast&lt;unsigned&gt;(MustPreserveRegisters);
</ins><span class="cx">         m_callType = callType;
</span><span class="cx">         m_codeOrigin = codeOrigin;
</span><span class="cx">         m_callReturnLocation = callReturnLocation;
</span><span class="lines">@@ -178,6 +183,21 @@
</span><span class="cx">         return m_stub.get();
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    void setSlowStub(PassRefPtr&lt;JITStubRoutine&gt; newSlowStub)
+    {
+        m_slowStub = newSlowStub;
+    }
+
+    void clearSlowStub()
+    {
+        m_slowStub = nullptr;
+    }
+
+    JITStubRoutine* slowStub()
+    {
+        return m_slowStub.get();
+    }
+
</ins><span class="cx">     bool seenOnce()
</span><span class="cx">     {
</span><span class="cx">         return m_hasSeenShouldRepatch;
</span><span class="lines">@@ -260,8 +280,6 @@
</span><span class="cx"> 
</span><span class="cx">     void visitWeak(RepatchBuffer&amp;);
</span><span class="cx"> 
</span><del>-    static CallLinkInfo&amp; dummy();
-
</del><span class="cx"> private:
</span><span class="cx">     CodeLocationNearCall m_callReturnLocation;
</span><span class="cx">     CodeLocationDataLabelPtr m_hotPathBegin;
</span><span class="lines">@@ -269,7 +287,8 @@
</span><span class="cx">     JITWriteBarrier&lt;JSFunction&gt; m_callee;
</span><span class="cx">     WriteBarrier&lt;JSFunction&gt; m_lastSeenCallee;
</span><span class="cx">     RefPtr&lt;PolymorphicCallStubRoutine&gt; m_stub;
</span><del>-    bool m_isFTL : 1;
</del><ins>+    RefPtr&lt;JITStubRoutine&gt; m_slowStub;
+    unsigned m_registerPreservationMode : 1; // Real type is RegisterPreservationMode
</ins><span class="cx">     bool m_hasSeenShouldRepatch : 1;
</span><span class="cx">     bool m_hasSeenClosure : 1;
</span><span class="cx">     bool m_clearedByGC : 1;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGDrivercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGDriver.cpp (187504 => 187505)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGDriver.cpp        2015-07-28 20:10:03 UTC (rev 187504)
+++ trunk/Source/JavaScriptCore/dfg/DFGDriver.cpp        2015-07-28 20:12:33 UTC (rev 187505)
</span><span class="lines">@@ -81,19 +81,8 @@
</span><span class="cx">     // make sure that all JIT code generation does finalization on the main thread.
</span><span class="cx">     vm.getCTIStub(osrExitGenerationThunkGenerator);
</span><span class="cx">     vm.getCTIStub(throwExceptionFromCallSlowPathGenerator);
</span><del>-    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);
-    }
</del><ins>+    vm.getCTIStub(linkCallThunkGenerator);
+    vm.getCTIStub(linkPolymorphicCallThunkGenerator);
</ins><span class="cx">     
</span><span class="cx">     if (vm.typeProfiler())
</span><span class="cx">         vm.typeProfilerLog()-&gt;processLogEntries(ASCIILiteral(&quot;Preparing for DFG compilation.&quot;));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGJITCompilercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp (187504 => 187505)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp        2015-07-28 20:10:03 UTC (rev 187504)
+++ trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp        2015-07-28 20:12:33 UTC (rev 187505)
</span><span class="lines">@@ -244,10 +244,7 @@
</span><span class="cx">     for (unsigned i = 0; i &lt; m_jsCalls.size(); ++i) {
</span><span class="cx">         JSCallRecord&amp; record = m_jsCalls[i];
</span><span class="cx">         CallLinkInfo&amp; info = *record.m_info;
</span><del>-        ThunkGenerator generator = linkThunkGeneratorFor(
-            info.specializationKind(),
-            RegisterPreservationNotRequired);
-        linkBuffer.link(record.m_slowCall, FunctionPtr(m_vm-&gt;getCTIStub(generator).code().executableAddress()));
</del><ins>+        linkBuffer.link(record.m_slowCall, FunctionPtr(m_vm-&gt;getCTIStub(linkCallThunkGenerator).code().executableAddress()));
</ins><span class="cx">         info.setCallLocations(linkBuffer.locationOfNearCall(record.m_slowCall),
</span><span class="cx">             linkBuffer.locationOf(record.m_targetToCheck),
</span><span class="cx">             linkBuffer.locationOfNearCall(record.m_fastCall));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLJSCallBasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLJSCallBase.cpp (187504 => 187505)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLJSCallBase.cpp        2015-07-28 20:10:03 UTC (rev 187504)
+++ trunk/Source/JavaScriptCore/ftl/FTLJSCallBase.cpp        2015-07-28 20:12:33 UTC (rev 187505)
</span><span class="lines">@@ -69,11 +69,8 @@
</span><span class="cx"> 
</span><span class="cx"> void JSCallBase::link(VM&amp; vm, LinkBuffer&amp; linkBuffer)
</span><span class="cx"> {
</span><del>-    ThunkGenerator generator = linkThunkGeneratorFor(
-        CallLinkInfo::specializationKindFor(m_type), MustPreserveRegisters);
-    
</del><span class="cx">     linkBuffer.link(
</span><del>-        m_slowCall, FunctionPtr(vm.getCTIStub(generator).code().executableAddress()));
</del><ins>+        m_slowCall, FunctionPtr(vm.getCTIStub(linkCallThunkGenerator).code().executableAddress()));
</ins><span class="cx"> 
</span><span class="cx">     m_callLinkInfo-&gt;setUpCallFromFTL(m_type, m_origin, linkBuffer.locationOfNearCall(m_slowCall),
</span><span class="cx">         linkBuffer.locationOf(m_targetToCheck), linkBuffer.locationOfNearCall(m_fastCall),
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITCallcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITCall.cpp (187504 => 187505)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITCall.cpp        2015-07-28 20:10:03 UTC (rev 187504)
+++ trunk/Source/JavaScriptCore/jit/JITCall.cpp        2015-07-28 20:12:33 UTC (rev 187505)
</span><span class="lines">@@ -106,14 +106,19 @@
</span><span class="cx"> 
</span><span class="cx"> void JIT::compileCallEvalSlowCase(Instruction* instruction, Vector&lt;SlowCaseEntry&gt;::iterator&amp; iter)
</span><span class="cx"> {
</span><ins>+    CallLinkInfo* info = m_codeBlock-&gt;addCallLinkInfo();
+    info-&gt;setUpCall(CallLinkInfo::Call, CodeOrigin(m_bytecodeOffset), regT0);
+
</ins><span class="cx">     linkSlowCase(iter);
</span><span class="cx">     int registerOffset = -instruction[4].u.operand;
</span><span class="cx"> 
</span><span class="cx">     addPtr(TrustedImm32(registerOffset * sizeof(Register) + sizeof(CallerFrameAndPC)), callFrameRegister, stackPointerRegister);
</span><span class="cx"> 
</span><span class="cx">     load64(Address(stackPointerRegister, sizeof(Register) * JSStack::Callee - sizeof(CallerFrameAndPC)), regT0);
</span><del>-    move(TrustedImmPtr(&amp;CallLinkInfo::dummy()), regT2);
-    emitNakedCall(m_vm-&gt;getCTIStub(virtualCallThunkGenerator).code());
</del><ins>+    move(TrustedImmPtr(info), regT2);
+    MacroAssemblerCodeRef virtualThunk = virtualThunkFor(m_vm, *info);
+    info-&gt;setSlowStub(createJITStubRoutine(virtualThunk, *m_vm, nullptr, true));
+    emitNakedCall(virtualThunk.code());
</ins><span class="cx">     addPtr(TrustedImm32(stackPointerOffsetFor(m_codeBlock) * sizeof(Register)), callFrameRegister, stackPointerRegister);
</span><span class="cx">     checkStackPointerAlignment();
</span><span class="cx"> 
</span><span class="lines">@@ -124,8 +129,6 @@
</span><span class="cx"> 
</span><span class="cx"> void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned callLinkInfoIndex)
</span><span class="cx"> {
</span><del>-    CallLinkInfo* info = m_codeBlock-&gt;addCallLinkInfo();
-
</del><span class="cx">     int callee = instruction[2].u.operand;
</span><span class="cx"> 
</span><span class="cx">     /* Caller always:
</span><span class="lines">@@ -143,6 +146,9 @@
</span><span class="cx">     COMPILE_ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_construct), call_and_construct_opcodes_must_be_same_length);
</span><span class="cx">     COMPILE_ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_call_varargs), call_and_call_varargs_opcodes_must_be_same_length);
</span><span class="cx">     COMPILE_ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_construct_varargs), call_and_construct_varargs_opcodes_must_be_same_length);
</span><ins>+    CallLinkInfo* info;
+    if (opcodeID != op_call_eval)
+        info = m_codeBlock-&gt;addCallLinkInfo();
</ins><span class="cx">     if (opcodeID == op_call_varargs || opcodeID == op_construct_varargs)
</span><span class="cx">         compileSetupVarargsFrame(instruction, info);
</span><span class="cx">     else {
</span><span class="lines">@@ -202,12 +208,8 @@
</span><span class="cx"> 
</span><span class="cx">     linkSlowCase(iter);
</span><span class="cx"> 
</span><del>-    ThunkGenerator generator = linkThunkGeneratorFor(
-        (opcodeID == op_construct || opcodeID == op_construct_varargs) ? CodeForConstruct : CodeForCall,
-        RegisterPreservationNotRequired);
-    
</del><span class="cx">     move(TrustedImmPtr(m_callCompilationInfo[callLinkInfoIndex].callLinkInfo), regT2);
</span><del>-    m_callCompilationInfo[callLinkInfoIndex].callReturnLocation = emitNakedCall(m_vm-&gt;getCTIStub(generator).code());
</del><ins>+    m_callCompilationInfo[callLinkInfoIndex].callReturnLocation = emitNakedCall(m_vm-&gt;getCTIStub(linkCallThunkGenerator).code());
</ins><span class="cx"> 
</span><span class="cx">     addPtr(TrustedImm32(stackPointerOffsetFor(m_codeBlock) * sizeof(Register)), callFrameRegister, stackPointerRegister);
</span><span class="cx">     checkStackPointerAlignment();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITCall32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITCall32_64.cpp (187504 => 187505)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITCall32_64.cpp        2015-07-28 20:10:03 UTC (rev 187504)
+++ trunk/Source/JavaScriptCore/jit/JITCall32_64.cpp        2015-07-28 20:12:33 UTC (rev 187505)
</span><span class="lines">@@ -166,6 +166,9 @@
</span><span class="cx"> 
</span><span class="cx"> void JIT::compileCallEvalSlowCase(Instruction* instruction, Vector&lt;SlowCaseEntry&gt;::iterator&amp; iter)
</span><span class="cx"> {
</span><ins>+    CallLinkInfo* info = m_codeBlock-&gt;addCallLinkInfo();
+    info-&gt;setUpCall(CallLinkInfo::Call, CodeOrigin(m_bytecodeOffset), regT0);
+
</ins><span class="cx">     linkSlowCase(iter);
</span><span class="cx"> 
</span><span class="cx">     int registerOffset = -instruction[4].u.operand;
</span><span class="lines">@@ -174,10 +177,12 @@
</span><span class="cx"> 
</span><span class="cx">     loadPtr(Address(stackPointerRegister, sizeof(Register) * JSStack::Callee - sizeof(CallerFrameAndPC)), regT0);
</span><span class="cx">     loadPtr(Address(stackPointerRegister, sizeof(Register) * JSStack::Callee - sizeof(CallerFrameAndPC)), regT1);
</span><del>-    move(TrustedImmPtr(&amp;CallLinkInfo::dummy()), regT2);
</del><ins>+    move(TrustedImmPtr(info), regT2);
</ins><span class="cx"> 
</span><span class="cx">     emitLoad(JSStack::Callee, regT1, regT0);
</span><del>-    emitNakedCall(m_vm-&gt;getCTIStub(virtualCallThunkGenerator).code());
</del><ins>+    MacroAssemblerCodeRef virtualThunk = virtualThunkFor(m_vm, *info);
+    info-&gt;setSlowStub(createJITStubRoutine(virtualThunk, *m_vm, nullptr, true));
+    emitNakedCall(virtualThunk.code());
</ins><span class="cx">     addPtr(TrustedImm32(stackPointerOffsetFor(m_codeBlock) * sizeof(Register)), callFrameRegister, stackPointerRegister);
</span><span class="cx">     checkStackPointerAlignment();
</span><span class="cx"> 
</span><span class="lines">@@ -188,7 +193,6 @@
</span><span class="cx"> 
</span><span class="cx"> void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned callLinkInfoIndex)
</span><span class="cx"> {
</span><del>-    CallLinkInfo* info = m_codeBlock-&gt;addCallLinkInfo();
</del><span class="cx">     int callee = instruction[2].u.operand;
</span><span class="cx"> 
</span><span class="cx">     /* Caller always:
</span><span class="lines">@@ -203,7 +207,9 @@
</span><span class="cx">         - Caller initializes ReturnPC; CodeBlock.
</span><span class="cx">         - Caller restores callFrameRegister after return.
</span><span class="cx">     */
</span><del>-    
</del><ins>+    CallLinkInfo* info;
+    if (opcodeID != op_call_eval)
+        info = m_codeBlock-&gt;addCallLinkInfo();
</ins><span class="cx">     if (opcodeID == op_call_varargs || opcodeID == op_construct_varargs)
</span><span class="cx">         compileSetupVarargsFrame(instruction, info);
</span><span class="cx">     else {
</span><span class="lines">@@ -268,12 +274,8 @@
</span><span class="cx">     linkSlowCase(iter);
</span><span class="cx">     linkSlowCase(iter);
</span><span class="cx"> 
</span><del>-    ThunkGenerator generator = linkThunkGeneratorFor(
-        (opcodeID == op_construct || opcodeID == op_construct_varargs) ? CodeForConstruct : CodeForCall,
-        RegisterPreservationNotRequired);
-    
</del><span class="cx">     move(TrustedImmPtr(m_callCompilationInfo[callLinkInfoIndex].callLinkInfo), regT2);
</span><del>-    m_callCompilationInfo[callLinkInfoIndex].callReturnLocation = emitNakedCall(m_vm-&gt;getCTIStub(generator).code());
</del><ins>+    m_callCompilationInfo[callLinkInfoIndex].callReturnLocation = emitNakedCall(m_vm-&gt;getCTIStub(linkCallThunkGenerator).code());
</ins><span class="cx"> 
</span><span class="cx">     addPtr(TrustedImm32(stackPointerOffsetFor(m_codeBlock) * sizeof(Register)), callFrameRegister, stackPointerRegister);
</span><span class="cx">     checkStackPointerAlignment();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOperationscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOperations.cpp (187504 => 187505)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2015-07-28 20:10:03 UTC (rev 187504)
+++ trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2015-07-28 20:12:33 UTC (rev 187505)
</span><span class="lines">@@ -752,12 +752,11 @@
</span><span class="cx">     return vm-&gt;getCTIStub(throwExceptionFromCallSlowPathGenerator).code().executableAddress();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline char* linkFor(
-    ExecState* execCallee, CallLinkInfo* callLinkInfo, CodeSpecializationKind kind,
-    RegisterPreservationMode registers)
</del><ins>+char* JIT_OPERATION operationLinkCall(ExecState* execCallee, CallLinkInfo* callLinkInfo)
</ins><span class="cx"> {
</span><span class="cx">     ExecState* exec = execCallee-&gt;callerFrame();
</span><span class="cx">     VM* vm = &amp;exec-&gt;vm();
</span><ins>+    CodeSpecializationKind kind = callLinkInfo-&gt;specializationKind();
</ins><span class="cx">     NativeCallFrameTracer tracer(vm, exec);
</span><span class="cx">     
</span><span class="cx">     JSValue calleeAsValue = execCallee-&gt;calleeAsValue();
</span><span class="lines">@@ -776,7 +775,7 @@
</span><span class="cx">     MacroAssemblerCodePtr codePtr;
</span><span class="cx">     CodeBlock* codeBlock = 0;
</span><span class="cx">     if (executable-&gt;isHostFunction())
</span><del>-        codePtr = executable-&gt;entrypointFor(*vm, kind, MustCheckArity, registers);
</del><ins>+        codePtr = executable-&gt;entrypointFor(*vm, kind, MustCheckArity, callLinkInfo-&gt;registerPreservationMode());
</ins><span class="cx">     else {
</span><span class="cx">         FunctionExecutable* functionExecutable = static_cast&lt;FunctionExecutable*&gt;(executable);
</span><span class="cx"> 
</span><span class="lines">@@ -796,42 +795,22 @@
</span><span class="cx">             arity = MustCheckArity;
</span><span class="cx">         else
</span><span class="cx">             arity = ArityCheckNotRequired;
</span><del>-        codePtr = functionExecutable-&gt;entrypointFor(*vm, kind, arity, registers);
</del><ins>+        codePtr = functionExecutable-&gt;entrypointFor(*vm, kind, arity, callLinkInfo-&gt;registerPreservationMode());
</ins><span class="cx">     }
</span><span class="cx">     if (!callLinkInfo-&gt;seenOnce())
</span><span class="cx">         callLinkInfo-&gt;setSeen();
</span><span class="cx">     else
</span><del>-        linkFor(execCallee, *callLinkInfo, codeBlock, callee, codePtr, kind, registers);
</del><ins>+        linkFor(execCallee, *callLinkInfo, codeBlock, callee, codePtr);
</ins><span class="cx">     
</span><span class="cx">     return reinterpret_cast&lt;char*&gt;(codePtr.executableAddress());
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-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);
-}
-
</del><span class="cx"> inline char* virtualForWithFunction(
</span><del>-    ExecState* execCallee, CodeSpecializationKind kind, RegisterPreservationMode registers,
-    JSCell*&amp; calleeAsFunctionCell)
</del><ins>+    ExecState* execCallee, CallLinkInfo* callLinkInfo, JSCell*&amp; calleeAsFunctionCell)
</ins><span class="cx"> {
</span><span class="cx">     ExecState* exec = execCallee-&gt;callerFrame();
</span><span class="cx">     VM* vm = &amp;exec-&gt;vm();
</span><ins>+    CodeSpecializationKind kind = callLinkInfo-&gt;specializationKind();
</ins><span class="cx">     NativeCallFrameTracer tracer(vm, exec);
</span><span class="cx"> 
</span><span class="cx">     JSValue calleeAsValue = execCallee-&gt;calleeAsValue();
</span><span class="lines">@@ -857,56 +836,26 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx">     return reinterpret_cast&lt;char*&gt;(executable-&gt;entrypointFor(
</span><del>-        *vm, kind, MustCheckArity, registers).executableAddress());
</del><ins>+        *vm, kind, MustCheckArity, callLinkInfo-&gt;registerPreservationMode()).executableAddress());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline char* virtualFor(
-    ExecState* execCallee, CodeSpecializationKind kind, RegisterPreservationMode registers)
-{
-    JSCell* calleeAsFunctionCellIgnored;
-    return virtualForWithFunction(execCallee, kind, registers, calleeAsFunctionCellIgnored);
-}
-
</del><span class="cx"> char* JIT_OPERATION operationLinkPolymorphicCall(ExecState* execCallee, CallLinkInfo* callLinkInfo)
</span><span class="cx"> {
</span><ins>+    ASSERT(callLinkInfo-&gt;specializationKind() == CodeForCall);
</ins><span class="cx">     JSCell* calleeAsFunctionCell;
</span><del>-    char* result = virtualForWithFunction(execCallee, CodeForCall, RegisterPreservationNotRequired, calleeAsFunctionCell);
</del><ins>+    char* result = virtualForWithFunction(execCallee, callLinkInfo, calleeAsFunctionCell);
</ins><span class="cx"> 
</span><del>-    linkPolymorphicCall(execCallee, *callLinkInfo, CallVariant(calleeAsFunctionCell), RegisterPreservationNotRequired);
</del><ins>+    linkPolymorphicCall(execCallee, *callLinkInfo, CallVariant(calleeAsFunctionCell));
</ins><span class="cx">     
</span><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-char* JIT_OPERATION operationVirtualCall(ExecState* execCallee, CallLinkInfo*)
-{    
-    return virtualFor(execCallee, CodeForCall, RegisterPreservationNotRequired);
-}
-
-char* JIT_OPERATION operationVirtualConstruct(ExecState* execCallee, CallLinkInfo*)
</del><ins>+char* JIT_OPERATION operationVirtualCall(ExecState* execCallee, CallLinkInfo* callLinkInfo)
</ins><span class="cx"> {
</span><del>-    return virtualFor(execCallee, CodeForConstruct, RegisterPreservationNotRequired);
</del><ins>+    JSCell* calleeAsFunctionCellIgnored;
+    return virtualForWithFunction(execCallee, callLinkInfo, calleeAsFunctionCellIgnored);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-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);
-}
-
</del><span class="cx"> size_t JIT_OPERATION operationCompareLess(ExecState* exec, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2)
</span><span class="cx"> {
</span><span class="cx">     VM* vm = &amp;exec-&gt;vm();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOperationsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOperations.h (187504 => 187505)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOperations.h        2015-07-28 20:10:03 UTC (rev 187504)
+++ trunk/Source/JavaScriptCore/jit/JITOperations.h        2015-07-28 20:12:33 UTC (rev 187505)
</span><span class="lines">@@ -267,13 +267,6 @@
</span><span class="cx"> char* JIT_OPERATION operationLinkCall(ExecState*, CallLinkInfo*) WTF_INTERNAL;
</span><span class="cx"> char* JIT_OPERATION operationLinkPolymorphicCall(ExecState*, CallLinkInfo*) WTF_INTERNAL;
</span><span class="cx"> char* JIT_OPERATION operationVirtualCall(ExecState*, CallLinkInfo*) WTF_INTERNAL;
</span><del>-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;
</del><span class="cx"> 
</span><span class="cx"> size_t JIT_OPERATION operationCompareLess(ExecState*, EncodedJSValue, EncodedJSValue) WTF_INTERNAL;
</span><span class="cx"> size_t JIT_OPERATION operationCompareLessEq(ExecState*, EncodedJSValue, EncodedJSValue) WTF_INTERNAL;
</span><span class="lines">@@ -356,68 +349,6 @@
</span><span class="cx"> 
</span><span class="cx"> } // extern &quot;C&quot;
</span><span class="cx"> 
</span><del>-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;
-}
-
</del><span class="cx"> } // namespace JSC
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(JIT)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitRepatchcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/Repatch.cpp (187504 => 187505)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/Repatch.cpp        2015-07-28 20:10:03 UTC (rev 187504)
+++ trunk/Source/JavaScriptCore/jit/Repatch.cpp        2015-07-28 20:12:33 UTC (rev 187505)
</span><span class="lines">@@ -586,10 +586,8 @@
</span><span class="cx">             patchBuffer.locationOf(addressOfLinkFunctionCheck),
</span><span class="cx">             patchBuffer.locationOfNearCall(fastPathCall));
</span><span class="cx"> 
</span><del>-        ThunkGenerator generator = linkThunkGeneratorFor(
-            CodeForCall, RegisterPreservationNotRequired);
</del><span class="cx">         patchBuffer.link(
</span><del>-            slowPathCall, CodeLocationLabel(vm-&gt;getCTIStub(generator).code()));
</del><ins>+            slowPathCall, CodeLocationLabel(vm-&gt;getCTIStub(linkCallThunkGenerator).code()));
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     MacroAssemblerCodeRef code = FINALIZE_CODE_FOR(
</span><span class="lines">@@ -1601,23 +1599,29 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static void linkSlowFor(
</span><del>-    RepatchBuffer&amp; repatchBuffer, VM* vm, CallLinkInfo&amp; callLinkInfo, ThunkGenerator generator)
</del><ins>+    RepatchBuffer&amp; repatchBuffer, VM*, CallLinkInfo&amp; callLinkInfo, MacroAssemblerCodeRef codeRef)
</ins><span class="cx"> {
</span><span class="cx">     repatchBuffer.relink(
</span><del>-        callLinkInfo.callReturnLocation(), vm-&gt;getCTIStub(generator).code());
</del><ins>+        callLinkInfo.callReturnLocation(), codeRef.code());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static void linkSlowFor(
</span><del>-    RepatchBuffer&amp; repatchBuffer, VM* vm, CallLinkInfo&amp; callLinkInfo,
-    CodeSpecializationKind kind, RegisterPreservationMode registers)
</del><ins>+    RepatchBuffer&amp; repatchBuffer, VM* vm, CallLinkInfo&amp; callLinkInfo, ThunkGenerator generator)
</ins><span class="cx"> {
</span><del>-    linkSlowFor(repatchBuffer, vm, callLinkInfo, virtualThunkGeneratorFor(kind, registers));
</del><ins>+    linkSlowFor(repatchBuffer, vm, callLinkInfo, vm-&gt;getCTIStub(generator));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static void linkSlowFor(
+    RepatchBuffer&amp; repatchBuffer, VM* vm, CallLinkInfo&amp; callLinkInfo)
+{
+    MacroAssemblerCodeRef virtualThunk = virtualThunkFor(vm, callLinkInfo);
+    linkSlowFor(repatchBuffer, vm, callLinkInfo, virtualThunk);
+    callLinkInfo.setSlowStub(createJITStubRoutine(virtualThunk, *vm, nullptr, true));
+}
+
</ins><span class="cx"> void linkFor(
</span><span class="cx">     ExecState* exec, CallLinkInfo&amp; callLinkInfo, CodeBlock* calleeCodeBlock,
</span><del>-    JSFunction* callee, MacroAssemblerCodePtr codePtr, CodeSpecializationKind kind,
-    RegisterPreservationMode registers)
</del><ins>+    JSFunction* callee, MacroAssemblerCodePtr codePtr)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(!callLinkInfo.stub());
</span><span class="cx">     
</span><span class="lines">@@ -1637,61 +1641,55 @@
</span><span class="cx">     if (calleeCodeBlock)
</span><span class="cx">         calleeCodeBlock-&gt;linkIncomingCall(exec-&gt;callerFrame(), &amp;callLinkInfo);
</span><span class="cx">     
</span><del>-    if (kind == CodeForCall) {
</del><ins>+    if (callLinkInfo.specializationKind() == CodeForCall) {
</ins><span class="cx">         linkSlowFor(
</span><del>-            repatchBuffer, vm, callLinkInfo, linkPolymorphicCallThunkGeneratorFor(registers));
</del><ins>+            repatchBuffer, vm, callLinkInfo, linkPolymorphicCallThunkGenerator);
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    ASSERT(kind == CodeForConstruct);
-    linkSlowFor(repatchBuffer, vm, callLinkInfo, CodeForConstruct, registers);
</del><ins>+    ASSERT(callLinkInfo.specializationKind() == CodeForConstruct);
+    linkSlowFor(repatchBuffer, vm, callLinkInfo);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void linkSlowFor(
</span><del>-    ExecState* exec, CallLinkInfo&amp; callLinkInfo, CodeSpecializationKind kind,
-    RegisterPreservationMode registers)
</del><ins>+    ExecState* exec, CallLinkInfo&amp; callLinkInfo)
</ins><span class="cx"> {
</span><span class="cx">     CodeBlock* callerCodeBlock = exec-&gt;callerFrame()-&gt;codeBlock();
</span><span class="cx">     VM* vm = callerCodeBlock-&gt;vm();
</span><span class="cx">     
</span><span class="cx">     RepatchBuffer repatchBuffer(callerCodeBlock);
</span><span class="cx">     
</span><del>-    linkSlowFor(repatchBuffer, vm, callLinkInfo, kind, registers);
</del><ins>+    linkSlowFor(repatchBuffer, vm, callLinkInfo);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static void revertCall(
</span><del>-    RepatchBuffer&amp; repatchBuffer, VM* vm, CallLinkInfo&amp; callLinkInfo, ThunkGenerator generator)
</del><ins>+    RepatchBuffer&amp; repatchBuffer, VM* vm, CallLinkInfo&amp; callLinkInfo, MacroAssemblerCodeRef codeRef)
</ins><span class="cx"> {
</span><span class="cx">     repatchBuffer.revertJumpReplacementToBranchPtrWithPatch(
</span><span class="cx">         RepatchBuffer::startOfBranchPtrWithPatchOnRegister(callLinkInfo.hotPathBegin()),
</span><span class="cx">         static_cast&lt;MacroAssembler::RegisterID&gt;(callLinkInfo.calleeGPR()), 0);
</span><del>-    linkSlowFor(repatchBuffer, vm, callLinkInfo, generator);
</del><ins>+    linkSlowFor(repatchBuffer, vm, callLinkInfo, codeRef);
</ins><span class="cx">     callLinkInfo.clearSeen();
</span><span class="cx">     callLinkInfo.clearCallee();
</span><span class="cx">     callLinkInfo.clearStub();
</span><ins>+    callLinkInfo.clearSlowStub();
</ins><span class="cx">     if (callLinkInfo.isOnList())
</span><span class="cx">         callLinkInfo.remove();
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void unlinkFor(
</span><del>-    RepatchBuffer&amp; repatchBuffer, CallLinkInfo&amp; callLinkInfo,
-    CodeSpecializationKind kind, RegisterPreservationMode registers)
</del><ins>+    RepatchBuffer&amp; repatchBuffer, CallLinkInfo&amp; callLinkInfo)
</ins><span class="cx"> {
</span><span class="cx">     if (Options::showDisassembly())
</span><span class="cx">         dataLog(&quot;Unlinking call from &quot;, callLinkInfo.callReturnLocation(), &quot; in request from &quot;, pointerDump(repatchBuffer.codeBlock()), &quot;\n&quot;);
</span><span class="cx">     
</span><del>-    revertCall(
-        repatchBuffer, repatchBuffer.codeBlock()-&gt;vm(), callLinkInfo,
-        linkThunkGeneratorFor(kind, registers));
</del><ins>+    VM* vm = repatchBuffer.codeBlock()-&gt;vm();
+    revertCall(repatchBuffer, vm, callLinkInfo, vm-&gt;getCTIStub(linkCallThunkGenerator));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void linkVirtualFor(
</span><del>-    ExecState* exec, CallLinkInfo&amp; callLinkInfo,
-    CodeSpecializationKind kind, RegisterPreservationMode registers)
</del><ins>+    ExecState* exec, CallLinkInfo&amp; callLinkInfo)
</ins><span class="cx"> {
</span><del>-    // 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.
-    
</del><span class="cx">     CodeBlock* callerCodeBlock = exec-&gt;callerFrame()-&gt;codeBlock();
</span><span class="cx">     VM* vm = callerCodeBlock-&gt;vm();
</span><span class="cx">     
</span><span class="lines">@@ -1699,7 +1697,9 @@
</span><span class="cx">         dataLog(&quot;Linking virtual call at &quot;, *callerCodeBlock, &quot; &quot;, exec-&gt;callerFrame()-&gt;codeOrigin(), &quot;\n&quot;);
</span><span class="cx">     
</span><span class="cx">     RepatchBuffer repatchBuffer(callerCodeBlock);
</span><del>-    revertCall(repatchBuffer, vm, callLinkInfo, virtualThunkGeneratorFor(kind, registers));
</del><ins>+    MacroAssemblerCodeRef virtualThunk = virtualThunkFor(vm, callLinkInfo);
+    revertCall(repatchBuffer, vm, callLinkInfo, virtualThunk);
+    callLinkInfo.setSlowStub(createJITStubRoutine(virtualThunk, *vm, nullptr, true));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> namespace {
</span><span class="lines">@@ -1710,13 +1710,12 @@
</span><span class="cx"> } // annonymous namespace
</span><span class="cx"> 
</span><span class="cx"> void linkPolymorphicCall(
</span><del>-    ExecState* exec, CallLinkInfo&amp; callLinkInfo, CallVariant newVariant,
-    RegisterPreservationMode registers)
</del><ins>+    ExecState* exec, CallLinkInfo&amp; callLinkInfo, CallVariant newVariant)
</ins><span class="cx"> {
</span><span class="cx">     // Currently we can't do anything for non-function callees.
</span><span class="cx">     // https://bugs.webkit.org/show_bug.cgi?id=140685
</span><span class="cx">     if (!newVariant || !newVariant.executable()) {
</span><del>-        linkVirtualFor(exec, callLinkInfo, CodeForCall, registers);
</del><ins>+        linkVirtualFor(exec, callLinkInfo);
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="lines">@@ -1759,7 +1758,7 @@
</span><span class="cx">             // If we cannot handle a callee, assume that it's better for this whole thing to be a
</span><span class="cx">             // virtual call.
</span><span class="cx">             if (exec-&gt;argumentCountIncludingThis() &lt; static_cast&lt;size_t&gt;(codeBlock-&gt;numParameters()) || callLinkInfo.callType() == CallLinkInfo::CallVarargs || callLinkInfo.callType() == CallLinkInfo::ConstructVarargs) {
</span><del>-                linkVirtualFor(exec, callLinkInfo, CodeForCall, registers);
</del><ins>+                linkVirtualFor(exec, callLinkInfo);
</ins><span class="cx">                 return;
</span><span class="cx">             }
</span><span class="cx">         }
</span><span class="lines">@@ -1774,7 +1773,7 @@
</span><span class="cx">     else
</span><span class="cx">         maxPolymorphicCallVariantListSize = Options::maxPolymorphicCallVariantListSize();
</span><span class="cx">     if (list.size() &gt; maxPolymorphicCallVariantListSize) {
</span><del>-        linkVirtualFor(exec, callLinkInfo, CodeForCall, registers);
</del><ins>+        linkVirtualFor(exec, callLinkInfo);
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="lines">@@ -1874,7 +1873,7 @@
</span><span class="cx">         ASSERT(variant.executable()-&gt;hasJITCodeForCall());
</span><span class="cx">         MacroAssemblerCodePtr codePtr =
</span><span class="cx">             variant.executable()-&gt;generatedJITCodeForCall()-&gt;addressForCall(
</span><del>-                *vm, variant.executable(), ArityCheckNotRequired, registers);
</del><ins>+                *vm, variant.executable(), ArityCheckNotRequired, callLinkInfo.registerPreservationMode());
</ins><span class="cx">         
</span><span class="cx">         if (fastCounts) {
</span><span class="cx">             stubJit.add32(
</span><span class="lines">@@ -1900,7 +1899,7 @@
</span><span class="cx">         
</span><span class="cx">     LinkBuffer patchBuffer(*vm, stubJit, callerCodeBlock, JITCompilationCanFail);
</span><span class="cx">     if (patchBuffer.didFailToAllocate()) {
</span><del>-        linkVirtualFor(exec, callLinkInfo, CodeForCall, registers);
</del><ins>+        linkVirtualFor(exec, callLinkInfo);
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="lines">@@ -1913,7 +1912,7 @@
</span><span class="cx">         patchBuffer.link(done, callLinkInfo.callReturnLocation().labelAtOffset(0));
</span><span class="cx">     else
</span><span class="cx">         patchBuffer.link(done, callLinkInfo.hotPathOther().labelAtOffset(0));
</span><del>-    patchBuffer.link(slow, CodeLocationLabel(vm-&gt;getCTIStub(linkPolymorphicCallThunkGeneratorFor(registers)).code()));
</del><ins>+    patchBuffer.link(slow, CodeLocationLabel(vm-&gt;getCTIStub(linkPolymorphicCallThunkGenerator).code()));
</ins><span class="cx">     
</span><span class="cx">     RefPtr&lt;PolymorphicCallStubRoutine&gt; stubRoutine = adoptRef(new PolymorphicCallStubRoutine(
</span><span class="cx">         FINALIZE_CODE_FOR(
</span><span class="lines">@@ -1929,8 +1928,10 @@
</span><span class="cx">     repatchBuffer.replaceWithJump(
</span><span class="cx">         RepatchBuffer::startOfBranchPtrWithPatchOnRegister(callLinkInfo.hotPathBegin()),
</span><span class="cx">         CodeLocationLabel(stubRoutine-&gt;code().code()));
</span><del>-    // This is weird. The original slow path should no longer be reachable.
-    linkSlowFor(repatchBuffer, vm, callLinkInfo, CodeForCall, registers);
</del><ins>+    // 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);
</ins><span class="cx">     
</span><span class="cx">     // If there had been a previous stub routine, that one will die as soon as the GC runs and sees
</span><span class="cx">     // that it's no longer on stack.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitRepatchh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/Repatch.h (187504 => 187505)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/Repatch.h        2015-07-28 20:10:03 UTC (rev 187504)
+++ trunk/Source/JavaScriptCore/jit/Repatch.h        2015-07-28 20:12:33 UTC (rev 187505)
</span><span class="lines">@@ -40,11 +40,11 @@
</span><span class="cx"> void repatchPutByID(ExecState*, JSValue, Structure*, const Identifier&amp;, const PutPropertySlot&amp;, StructureStubInfo&amp;, PutKind);
</span><span class="cx"> void buildPutByIdList(ExecState*, JSValue, Structure*, const Identifier&amp;, const PutPropertySlot&amp;, StructureStubInfo&amp;, PutKind);
</span><span class="cx"> void repatchIn(ExecState*, JSCell*, const Identifier&amp;, bool wasFound, const PropertySlot&amp;, StructureStubInfo&amp;);
</span><del>-void linkFor(ExecState*, CallLinkInfo&amp;, CodeBlock*, JSFunction* callee, MacroAssemblerCodePtr, CodeSpecializationKind, RegisterPreservationMode);
-void linkSlowFor(ExecState*, CallLinkInfo&amp;, CodeSpecializationKind, RegisterPreservationMode);
-void unlinkFor(RepatchBuffer&amp;, CallLinkInfo&amp;, CodeSpecializationKind, RegisterPreservationMode);
-void linkVirtualFor(ExecState*, CallLinkInfo&amp;, CodeSpecializationKind, RegisterPreservationMode);
-void linkPolymorphicCall(ExecState*, CallLinkInfo&amp;, CallVariant, RegisterPreservationMode);
</del><ins>+void linkFor(ExecState*, CallLinkInfo&amp;, CodeBlock*, JSFunction* callee, MacroAssemblerCodePtr);
+void linkSlowFor(ExecState*, CallLinkInfo&amp;);
+void unlinkFor(RepatchBuffer&amp;, CallLinkInfo&amp;);
+void linkVirtualFor(ExecState*, CallLinkInfo&amp;);
+void linkPolymorphicCall(ExecState*, CallLinkInfo&amp;, CallVariant);
</ins><span class="cx"> void resetGetByID(RepatchBuffer&amp;, StructureStubInfo&amp;);
</span><span class="cx"> void resetPutByID(RepatchBuffer&amp;, StructureStubInfo&amp;);
</span><span class="cx"> void resetIn(RepatchBuffer&amp;, StructureStubInfo&amp;);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitThunkGeneratorscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/ThunkGenerators.cpp (187504 => 187505)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/ThunkGenerators.cpp        2015-07-28 20:10:03 UTC (rev 187504)
+++ trunk/Source/JavaScriptCore/jit/ThunkGenerators.cpp        2015-07-28 20:12:33 UTC (rev 187505)
</span><span class="lines">@@ -99,8 +99,7 @@
</span><span class="cx">     jit.jump(GPRInfo::returnValueGPR);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-static MacroAssemblerCodeRef linkForThunkGenerator(
-    VM* vm, CodeSpecializationKind kind, RegisterPreservationMode registers)
</del><ins>+MacroAssemblerCodeRef linkCallThunkGenerator(VM* vm)
</ins><span class="cx"> {
</span><span class="cx">     // The return address is on the stack or in the link register. We will hence
</span><span class="cx">     // save the return address to the call frame while we make a C++ function call
</span><span class="lines">@@ -110,60 +109,26 @@
</span><span class="cx">     
</span><span class="cx">     CCallHelpers jit(vm);
</span><span class="cx">     
</span><del>-    slowPathFor(jit, vm, operationLinkFor(kind, registers));
</del><ins>+    slowPathFor(jit, vm, operationLinkCall);
</ins><span class="cx">     
</span><span class="cx">     LinkBuffer patchBuffer(*vm, jit, GLOBAL_THUNK_ID);
</span><del>-    return FINALIZE_CODE(
-        patchBuffer,
-        (&quot;Link %s%s slow path thunk&quot;, kind == CodeForCall ? &quot;call&quot; : &quot;construct&quot;, registers == MustPreserveRegisters ? &quot; that preserves registers&quot; : &quot;&quot;));
</del><ins>+    return FINALIZE_CODE(patchBuffer, (&quot;Link call slow path thunk&quot;));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-MacroAssemblerCodeRef linkCallThunkGenerator(VM* vm)
</del><ins>+// 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)
</ins><span class="cx"> {
</span><del>-    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)
-{
</del><span class="cx">     CCallHelpers jit(vm);
</span><span class="cx">     
</span><del>-    slowPathFor(jit, vm, operationLinkPolymorphicCallFor(registers));
</del><ins>+    slowPathFor(jit, vm, operationLinkPolymorphicCall);
</ins><span class="cx">     
</span><span class="cx">     LinkBuffer patchBuffer(*vm, jit, GLOBAL_THUNK_ID);
</span><del>-    return FINALIZE_CODE(patchBuffer, (&quot;Link polymorphic call %s slow path thunk&quot;, registers == MustPreserveRegisters ? &quot; that preserves registers&quot; : &quot;&quot;));
</del><ins>+    return FINALIZE_CODE(patchBuffer, (&quot;Link polymorphic call slow path thunk&quot;));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-// 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)
</del><ins>+MacroAssemblerCodeRef virtualThunkFor(VM* vm, CallLinkInfo&amp; callLinkInfo)
</ins><span class="cx"> {
</span><del>-    return linkPolymorphicCallForThunkGenerator(vm, RegisterPreservationNotRequired);
-}
-
-MacroAssemblerCodeRef linkPolymorphicCallThatPreservesRegsThunkGenerator(VM* vm)
-{
-    return linkPolymorphicCallForThunkGenerator(vm, MustPreserveRegisters);
-}
-
-static MacroAssemblerCodeRef virtualForThunkGenerator(
-    VM* vm, CodeSpecializationKind kind, RegisterPreservationMode registers)
-{
</del><span class="cx">     // The callee is in regT0 (for JSVALUE32_64, the tag is in regT1).
</span><span class="cx">     // The return address is on the stack, or in the link register. We will hence
</span><span class="cx">     // jump to the callee, or save the return address to the call frame while we
</span><span class="lines">@@ -208,7 +173,8 @@
</span><span class="cx">         GPRInfo::regT4);
</span><span class="cx">     jit.loadPtr(
</span><span class="cx">         CCallHelpers::Address(
</span><del>-            GPRInfo::regT4, ExecutableBase::offsetOfJITCodeWithArityCheckFor(kind, registers)),
</del><ins>+            GPRInfo::regT4, ExecutableBase::offsetOfJITCodeWithArityCheckFor(
+                callLinkInfo.specializationKind(), callLinkInfo.registerPreservationMode())),
</ins><span class="cx">         GPRInfo::regT4);
</span><span class="cx">     slowCase.append(jit.branchTestPtr(CCallHelpers::Zero, GPRInfo::regT4));
</span><span class="cx">     
</span><span class="lines">@@ -223,34 +189,17 @@
</span><span class="cx">     
</span><span class="cx">     // Here we don't know anything, so revert to the full slow path.
</span><span class="cx">     
</span><del>-    slowPathFor(jit, vm, operationVirtualFor(kind, registers));
</del><ins>+    slowPathFor(jit, vm, operationVirtualCall);
</ins><span class="cx">     
</span><span class="cx">     LinkBuffer patchBuffer(*vm, jit, GLOBAL_THUNK_ID);
</span><span class="cx">     return FINALIZE_CODE(
</span><span class="cx">         patchBuffer,
</span><del>-        (&quot;Virtual %s%s slow path thunk&quot;, kind == CodeForCall ? &quot;call&quot; : &quot;construct&quot;, registers == MustPreserveRegisters ? &quot; that preserves registers&quot; : &quot;&quot;));
</del><ins>+        (&quot;Virtual %s%s slow path thunk at CodePtr(%p)&quot;,
+        callLinkInfo.specializationKind() == CodeForCall ? &quot;call&quot; : &quot;construct&quot;,
+        callLinkInfo.registerPreservationMode() == MustPreserveRegisters ? &quot; that preserves registers&quot; : &quot;&quot;,
+        callLinkInfo.callReturnLocation().dataLocation()));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-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);
-}
-
</del><span class="cx"> enum ThunkEntryType { EnterViaCall, EnterViaJump };
</span><span class="cx"> 
</span><span class="cx"> static MacroAssemblerCodeRef nativeForGenerator(VM* vm, CodeSpecializationKind kind, ThunkEntryType entryType = EnterViaCall)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitThunkGeneratorsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/ThunkGenerators.h (187504 => 187505)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/ThunkGenerators.h        2015-07-28 20:10:03 UTC (rev 187504)
+++ trunk/Source/JavaScriptCore/jit/ThunkGenerators.h        2015-07-28 20:12:33 UTC (rev 187505)
</span><span class="lines">@@ -33,83 +33,15 @@
</span><span class="cx"> #if ENABLE(JIT)
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><ins>+class CallLinkInfo;
+
</ins><span class="cx"> MacroAssemblerCodeRef throwExceptionFromCallSlowPathGenerator(VM*);
</span><span class="cx"> 
</span><span class="cx"> MacroAssemblerCodeRef linkCallThunkGenerator(VM*);
</span><del>-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;
-}
-
</del><span class="cx"> MacroAssemblerCodeRef linkPolymorphicCallThunkGenerator(VM*);
</span><del>-MacroAssemblerCodeRef linkPolymorphicCallThatPreservesRegsThunkGenerator(VM*);
</del><span class="cx"> 
</span><del>-inline ThunkGenerator linkPolymorphicCallThunkGeneratorFor(RegisterPreservationMode registers)
-{
-    switch (registers) {
-    case RegisterPreservationNotRequired:
-        return linkPolymorphicCallThunkGenerator;
-    case MustPreserveRegisters:
-        return linkPolymorphicCallThatPreservesRegsThunkGenerator;
-    }
-    RELEASE_ASSERT_NOT_REACHED();
-    return 0;
-}
</del><ins>+MacroAssemblerCodeRef virtualThunkFor(VM*, CallLinkInfo&amp;);
</ins><span class="cx"> 
</span><del>-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;
-}
-
</del><span class="cx"> MacroAssemblerCodeRef nativeCallGenerator(VM*);
</span><span class="cx"> MacroAssemblerCodeRef nativeConstructGenerator(VM*);
</span><span class="cx"> MacroAssemblerCodeRef nativeTailCallGenerator(VM*);
</span></span></pre>
</div>
</div>

</body>
</html>