<!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>[190649] 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/190649">190649</a></dd>
<dt>Author</dt> <dd>mark.lam@apple.com</dd>
<dt>Date</dt> <dd>2015-10-06 15:29:27 -0700 (Tue, 06 Oct 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>Factoring out op_sub baseline code generation into JITSubGenerator.
https://bugs.webkit.org/show_bug.cgi?id=149600

Reviewed by Geoffrey Garen.

We're going to factor out baseline code generation into snippet generators so
that we can later use them in the DFG and FTL to emit code for to perform the
JS operations where the operand types are predicted to be polymorphic.
We are starting in this patch with the implementation of op_sub.

What was done in this patch:
1. Created JITSubGenerator based on the baseline implementation of op_sub as
   expressed in compileBinaryArithOp() and compileBinaryArithOpSlowCase().
   I did not attempt to do write a more optimal version of op_sub.  I'll
   leave that to a later patch.

2. Convert the 32-bit op_sub baseline implementation to use the same
   JITSubGenerator which was based on the 64-bit implementation.  The
   pre-existing 32-bit baseline op_sub had handling for more optimization cases.
   However, a benchmark run shows that simply going with the 64-bit version
   (foregoing those extra optimizations) did not change the performance.

   Also, previously, the 32-bit version was able to move double results directly
   into the result location on the stack directly.  By using JITSubGenerator,
   we now always move that result into a pair of GPRs before storing it into
   the stack location.

3. Add some needed emitters to AssemblyHelpers that play nice with JSValueRegs.

* JavaScriptCore.xcodeproj/project.pbxproj:
* jit/AssemblyHelpers.h:
(JSC::AssemblyHelpers::boxDouble):
(JSC::AssemblyHelpers::unboxDouble):
(JSC::AssemblyHelpers::boxBooleanPayload):
* jit/JIT.h:
(JSC::JIT::linkDummySlowCase):
* jit/JITArithmetic.cpp:
(JSC::JIT::compileBinaryArithOp):
(JSC::JIT::compileBinaryArithOpSlowCase):
(JSC::JIT::emitSlow_op_div):
(JSC::JIT::emit_op_sub):
(JSC::JIT::emitSlow_op_sub):
* jit/JITArithmetic32_64.cpp:
(JSC::JIT::emitBinaryDoubleOp):
(JSC::JIT::emit_op_sub): Deleted.
(JSC::JIT::emitSub32Constant): Deleted.
(JSC::JIT::emitSlow_op_sub): Deleted.
* jit/JITInlines.h:
(JSC::JIT::linkSlowCaseIfNotJSCell):
(JSC::JIT::linkAllSlowCasesForBytecodeOffset):
(JSC::JIT::addSlowCase):
(JSC::JIT::emitLoad):
(JSC::JIT::emitGetVirtualRegister):
(JSC::JIT::emitPutVirtualRegister):
* jit/JITSubGenerator.h: Added.
(JSC::JITSubGenerator::JITSubGenerator):
(JSC::JITSubGenerator::generateFastPath):
(JSC::JITSubGenerator::slowPathJumpList):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj">trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceJavaScriptCorejitAssemblyHelpersh">trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITh">trunk/Source/JavaScriptCore/jit/JIT.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITArithmeticcpp">trunk/Source/JavaScriptCore/jit/JITArithmetic.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITArithmetic32_64cpp">trunk/Source/JavaScriptCore/jit/JITArithmetic32_64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITInlinesh">trunk/Source/JavaScriptCore/jit/JITInlines.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCorejitJITSubGeneratorh">trunk/Source/JavaScriptCore/jit/JITSubGenerator.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (190648 => 190649)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-10-06 21:46:08 UTC (rev 190648)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-10-06 22:29:27 UTC (rev 190649)
</span><span class="lines">@@ -1,3 +1,64 @@
</span><ins>+2015-10-06  Mark Lam  &lt;mark.lam@apple.com&gt;
+
+        Factoring out op_sub baseline code generation into JITSubGenerator.
+        https://bugs.webkit.org/show_bug.cgi?id=149600
+
+        Reviewed by Geoffrey Garen.
+
+        We're going to factor out baseline code generation into snippet generators so
+        that we can later use them in the DFG and FTL to emit code for to perform the
+        JS operations where the operand types are predicted to be polymorphic.
+        We are starting in this patch with the implementation of op_sub.
+
+        What was done in this patch:
+        1. Created JITSubGenerator based on the baseline implementation of op_sub as
+           expressed in compileBinaryArithOp() and compileBinaryArithOpSlowCase().
+           I did not attempt to do write a more optimal version of op_sub.  I'll
+           leave that to a later patch.
+
+        2. Convert the 32-bit op_sub baseline implementation to use the same
+           JITSubGenerator which was based on the 64-bit implementation.  The
+           pre-existing 32-bit baseline op_sub had handling for more optimization cases.
+           However, a benchmark run shows that simply going with the 64-bit version
+           (foregoing those extra optimizations) did not change the performance.
+
+           Also, previously, the 32-bit version was able to move double results directly
+           into the result location on the stack directly.  By using JITSubGenerator,
+           we now always move that result into a pair of GPRs before storing it into
+           the stack location.
+
+        3. Add some needed emitters to AssemblyHelpers that play nice with JSValueRegs.
+
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * jit/AssemblyHelpers.h:
+        (JSC::AssemblyHelpers::boxDouble):
+        (JSC::AssemblyHelpers::unboxDouble):
+        (JSC::AssemblyHelpers::boxBooleanPayload):
+        * jit/JIT.h:
+        (JSC::JIT::linkDummySlowCase):
+        * jit/JITArithmetic.cpp:
+        (JSC::JIT::compileBinaryArithOp):
+        (JSC::JIT::compileBinaryArithOpSlowCase):
+        (JSC::JIT::emitSlow_op_div):
+        (JSC::JIT::emit_op_sub):
+        (JSC::JIT::emitSlow_op_sub):
+        * jit/JITArithmetic32_64.cpp:
+        (JSC::JIT::emitBinaryDoubleOp):
+        (JSC::JIT::emit_op_sub): Deleted.
+        (JSC::JIT::emitSub32Constant): Deleted.
+        (JSC::JIT::emitSlow_op_sub): Deleted.
+        * jit/JITInlines.h:
+        (JSC::JIT::linkSlowCaseIfNotJSCell):
+        (JSC::JIT::linkAllSlowCasesForBytecodeOffset):
+        (JSC::JIT::addSlowCase):
+        (JSC::JIT::emitLoad):
+        (JSC::JIT::emitGetVirtualRegister):
+        (JSC::JIT::emitPutVirtualRegister):
+        * jit/JITSubGenerator.h: Added.
+        (JSC::JITSubGenerator::JITSubGenerator):
+        (JSC::JITSubGenerator::generateFastPath):
+        (JSC::JITSubGenerator::slowPathJumpList):
+
</ins><span class="cx"> 2015-10-06  Daniel Bates  &lt;dbates@webkit.org&gt;
</span><span class="cx"> 
</span><span class="cx">         Enable XSLT when building WebKit for iOS using the public iOS SDK
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (190648 => 190649)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2015-10-06 21:46:08 UTC (rev 190648)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2015-10-06 22:29:27 UTC (rev 190649)
</span><span class="lines">@@ -3707,6 +3707,7 @@
</span><span class="cx">                 FE7BA60D1A1A7CEC00F1F7B4 /* HeapVerifier.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HeapVerifier.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 FE7BA60E1A1A7CEC00F1F7B4 /* HeapVerifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HeapVerifier.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 FE90BB3A1B7CF64E006B3F03 /* VMInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VMInlines.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                FE98B5B61BB9AE110073E7A6 /* JITSubGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITSubGenerator.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 FEA0861E182B7A0400F6D851 /* Breakpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Breakpoint.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 FEA0861F182B7A0400F6D851 /* DebuggerPrimitives.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DebuggerPrimitives.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 FEB51F6A1A97B688001F921C /* Regress141809.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Regress141809.h; path = API/tests/Regress141809.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -4189,6 +4190,7 @@
</span><span class="cx">                                 FEF6835D174343CC00A32E25 /* JITStubsX86.h */,
</span><span class="cx">                                 FEF6835C174343CC00A32E25 /* JITStubsX86_64.h */,
</span><span class="cx">                                 A7A4AE0C17973B4D005612B1 /* JITStubsX86Common.h */,
</span><ins>+                                FE98B5B61BB9AE110073E7A6 /* JITSubGenerator.h */,
</ins><span class="cx">                                 0F5EF91B16878F78003E5C25 /* JITThunks.cpp */,
</span><span class="cx">                                 0F5EF91C16878F78003E5C25 /* JITThunks.h */,
</span><span class="cx">                                 0FC712E017CD878F008CC93C /* JITToDFGDeferredCompilationCallback.cpp */,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitAssemblyHelpersh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h (190648 => 190649)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h        2015-10-06 21:46:08 UTC (rev 190648)
+++ trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h        2015-10-06 22:29:27 UTC (rev 190649)
</span><span class="lines">@@ -964,7 +964,11 @@
</span><span class="cx">     {
</span><span class="cx">         boxDouble(fpr, regs.gpr());
</span><span class="cx">     }
</span><del>-    
</del><ins>+    void unboxDouble(JSValueRegs regs, FPRReg destFPR, FPRReg)
+    {
+        unboxDouble(regs.payloadGPR(), destFPR);
+    }
+
</ins><span class="cx">     // Here are possible arrangements of source, target, scratch:
</span><span class="cx">     // - source, target, scratch can all be separate registers.
</span><span class="cx">     // - source and target can be the same but scratch is separate.
</span><span class="lines">@@ -1002,6 +1006,10 @@
</span><span class="cx">     {
</span><span class="cx">         boxDouble(fpr, regs.tagGPR(), regs.payloadGPR());
</span><span class="cx">     }
</span><ins>+    void unboxDouble(JSValueRegs regs, FPRReg fpr, FPRReg scratchFPR)
+    {
+        unboxDouble(regs.tagGPR(), regs.payloadGPR(), fpr, scratchFPR);
+    }
</ins><span class="cx"> #endif
</span><span class="cx">     
</span><span class="cx">     void boxBooleanPayload(GPRReg boolGPR, GPRReg payloadGPR)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JIT.h (190648 => 190649)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JIT.h        2015-10-06 21:46:08 UTC (rev 190648)
+++ trunk/Source/JavaScriptCore/jit/JIT.h        2015-10-06 22:29:27 UTC (rev 190649)
</span><span class="lines">@@ -400,6 +400,9 @@
</span><span class="cx"> 
</span><span class="cx">         enum FinalObjectMode { MayBeFinal, KnownNotFinal };
</span><span class="cx"> 
</span><ins>+        void emitGetVirtualRegister(int src, JSValueRegs dst);
+        void emitPutVirtualRegister(int dst, JSValueRegs src);
+
</ins><span class="cx"> #if USE(JSVALUE32_64)
</span><span class="cx">         bool getOperandConstantInt(int op1, int op2, int&amp; op, int32_t&amp; constant);
</span><span class="cx"> 
</span><span class="lines">@@ -708,6 +711,8 @@
</span><span class="cx">             ++iter;
</span><span class="cx">         }
</span><span class="cx">         void linkSlowCaseIfNotJSCell(Vector&lt;SlowCaseEntry&gt;::iterator&amp;, int virtualRegisterIndex);
</span><ins>+        void linkAllSlowCasesForBytecodeOffset(Vector&lt;SlowCaseEntry&gt;&amp; slowCases,
+            Vector&lt;SlowCaseEntry&gt;::iterator&amp;, unsigned bytecodeOffset);
</ins><span class="cx"> 
</span><span class="cx">         MacroAssembler::Call appendCallWithExceptionCheck(const FunctionPtr&amp;);
</span><span class="cx"> #if OS(WINDOWS) &amp;&amp; CPU(X86_64)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITArithmeticcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITArithmetic.cpp (190648 => 190649)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITArithmetic.cpp        2015-10-06 21:46:08 UTC (rev 190648)
+++ trunk/Source/JavaScriptCore/jit/JITArithmetic.cpp        2015-10-06 22:29:27 UTC (rev 190649)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2008 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2008, 2015 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -32,6 +32,7 @@
</span><span class="cx"> #include &quot;JITInlines.h&quot;
</span><span class="cx"> #include &quot;JITOperations.h&quot;
</span><span class="cx"> #include &quot;JITStubs.h&quot;
</span><ins>+#include &quot;JITSubGenerator.h&quot;
</ins><span class="cx"> #include &quot;JSArray.h&quot;
</span><span class="cx"> #include &quot;JSFunction.h&quot;
</span><span class="cx"> #include &quot;Interpreter.h&quot;
</span><span class="lines">@@ -668,8 +669,6 @@
</span><span class="cx">     emitJumpSlowCaseIfNotInt(regT1);
</span><span class="cx">     if (opcodeID == op_add)
</span><span class="cx">         addSlowCase(branchAdd32(Overflow, regT1, regT0));
</span><del>-    else if (opcodeID == op_sub)
-        addSlowCase(branchSub32(Overflow, regT1, regT0));
</del><span class="cx">     else {
</span><span class="cx">         ASSERT(opcodeID == op_mul);
</span><span class="cx">         if (shouldEmitProfiling()) {
</span><span class="lines">@@ -721,7 +720,7 @@
</span><span class="cx"> 
</span><span class="cx">     Label stubFunctionCall(this);
</span><span class="cx"> 
</span><del>-    JITSlowPathCall slowPathCall(this, currentInstruction, opcodeID == op_add ? slow_path_add : opcodeID == op_sub ? slow_path_sub : slow_path_mul);
</del><ins>+    JITSlowPathCall slowPathCall(this, currentInstruction, opcodeID == op_add ? slow_path_add : slow_path_mul);
</ins><span class="cx">     slowPathCall.call();
</span><span class="cx">     Jump end = jump();
</span><span class="cx"> 
</span><span class="lines">@@ -767,8 +766,6 @@
</span><span class="cx"> 
</span><span class="cx">     if (opcodeID == op_add)
</span><span class="cx">         addDouble(fpRegT2, fpRegT1);
</span><del>-    else if (opcodeID == op_sub)
-        subDouble(fpRegT2, fpRegT1);
</del><span class="cx">     else if (opcodeID == op_mul)
</span><span class="cx">         mulDouble(fpRegT2, fpRegT1);
</span><span class="cx">     else {
</span><span class="lines">@@ -961,6 +958,8 @@
</span><span class="cx">     slowPathCall.call();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+#endif // USE(JSVALUE64)
+
</ins><span class="cx"> void JIT::emit_op_sub(Instruction* currentInstruction)
</span><span class="cx"> {
</span><span class="cx">     int result = currentInstruction[1].u.operand;
</span><span class="lines">@@ -968,24 +967,42 @@
</span><span class="cx">     int op2 = currentInstruction[3].u.operand;
</span><span class="cx">     OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
</span><span class="cx"> 
</span><del>-    compileBinaryArithOp(op_sub, result, op1, op2, types);
-    emitPutVirtualRegister(result);
</del><ins>+#if USE(JSVALUE64)
+    JSValueRegs leftRegs = JSValueRegs(regT0);
+    JSValueRegs rightRegs = JSValueRegs(regT1);
+    JSValueRegs resultRegs = leftRegs;
+    GPRReg scratchGPR = InvalidGPRReg;
+    FPRReg scratchFPR = InvalidFPRReg;
+#else
+    JSValueRegs leftRegs = JSValueRegs(regT1, regT0);
+    JSValueRegs rightRegs = JSValueRegs(regT3, regT2);
+    JSValueRegs resultRegs = leftRegs;
+    GPRReg scratchGPR = regT4;
+    FPRReg scratchFPR = fpRegT2;
+#endif
+
+    emitGetVirtualRegister(op1, leftRegs);
+    emitGetVirtualRegister(op2, rightRegs);
+
+    JITSubGenerator gen(resultRegs, leftRegs, rightRegs, types.first(), types.second(),
+        fpRegT0, fpRegT1, scratchGPR, scratchFPR);
+
+    gen.generateFastPath(*this);
+    emitPutVirtualRegister(result, resultRegs);
+
+    addSlowCase(gen.slowPathJumpList());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void JIT::emitSlow_op_sub(Instruction* currentInstruction, Vector&lt;SlowCaseEntry&gt;::iterator&amp; iter)
</span><span class="cx"> {
</span><del>-    int result = currentInstruction[1].u.operand;
-    int op1 = currentInstruction[2].u.operand;
-    int op2 = currentInstruction[3].u.operand;
-    OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
</del><ins>+    linkAllSlowCasesForBytecodeOffset(m_slowCases, iter, m_bytecodeOffset);
</ins><span class="cx"> 
</span><del>-    compileBinaryArithOpSlowCase(currentInstruction, op_sub, iter, result, op1, op2, types, false, false);
</del><ins>+    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_sub);
+    slowPathCall.call();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /* ------------------------------ END: OP_ADD, OP_SUB, OP_MUL ------------------------------ */
</span><span class="cx"> 
</span><del>-#endif // USE(JSVALUE64)
-
</del><span class="cx"> } // namespace JSC
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(JIT)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITArithmetic32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITArithmetic32_64.cpp (190648 => 190649)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITArithmetic32_64.cpp        2015-10-06 21:46:08 UTC (rev 190648)
+++ trunk/Source/JavaScriptCore/jit/JITArithmetic32_64.cpp        2015-10-06 22:29:27 UTC (rev 190649)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>-* Copyright (C) 2008 Apple Inc. All rights reserved.
</del><ins>+* Copyright (C) 2008, 2015 Apple Inc. All rights reserved.
</ins><span class="cx"> *
</span><span class="cx"> * Redistribution and use in source and binary forms, with or without
</span><span class="cx"> * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -594,99 +594,6 @@
</span><span class="cx"> 
</span><span class="cx"> // Subtraction (-)
</span><span class="cx"> 
</span><del>-void JIT::emit_op_sub(Instruction* currentInstruction)
-{
-    int dst = currentInstruction[1].u.operand;
-    int op1 = currentInstruction[2].u.operand;
-    int op2 = currentInstruction[3].u.operand;
-    OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
-
-    JumpList notInt32Op1;
-    JumpList notInt32Op2;
-
-    if (isOperandConstantInt(op2)) {
-        emitSub32Constant(dst, op1, getConstantOperand(op2).asInt32(), types.first());
-        return;
-    }
-
-    emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
-    notInt32Op1.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
-    notInt32Op2.append(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
-
-    // Int32 case.
-    addSlowCase(branchSub32(Overflow, regT2, regT0));
-    emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst));
-
-    if (!supportsFloatingPoint()) {
-        addSlowCase(notInt32Op1);
-        addSlowCase(notInt32Op2);
-        return;
-    }
-    Jump end = jump();
-
-    // Double case.
-    emitBinaryDoubleOp(op_sub, dst, op1, op2, types, notInt32Op1, notInt32Op2);
-    end.link(this);
-}
-
-void JIT::emitSub32Constant(int dst, int op, int32_t constant, ResultType opType)
-{
-    // Int32 case.
-    emitLoad(op, regT1, regT0);
-    Jump notInt32 = branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag));
-    addSlowCase(branchSub32(Overflow, regT0, Imm32(constant), regT2, regT3));   
-    emitStoreInt32(dst, regT2, (op == dst));
-
-    // Double case.
-    if (!supportsFloatingPoint()) {
-        addSlowCase(notInt32);
-        return;
-    }
-    Jump end = jump();
-
-    notInt32.link(this);
-    if (!opType.definitelyIsNumber())
-        addSlowCase(branch32(Above, regT1, TrustedImm32(JSValue::LowestTag)));
-    move(Imm32(constant), regT2);
-    convertInt32ToDouble(regT2, fpRegT0);
-    emitLoadDouble(op, fpRegT1);
-    subDouble(fpRegT0, fpRegT1);
-    emitStoreDouble(dst, fpRegT1);
-
-    end.link(this);
-}
-
-void JIT::emitSlow_op_sub(Instruction* currentInstruction, Vector&lt;SlowCaseEntry&gt;::iterator&amp; iter)
-{
-    int op2 = currentInstruction[3].u.operand;
-    OperandTypes types = OperandTypes::fromInt(currentInstruction[4].u.operand);
-
-    if (isOperandConstantInt(op2)) {
-        linkSlowCase(iter); // overflow check
-
-        if (!supportsFloatingPoint() || !types.first().definitelyIsNumber())
-            linkSlowCase(iter); // int32 or double check
-    } else {
-        linkSlowCase(iter); // overflow check
-
-        if (!supportsFloatingPoint()) {
-            linkSlowCase(iter); // int32 check
-            linkSlowCase(iter); // int32 check
-        } else {
-            if (!types.first().definitelyIsNumber())
-                linkSlowCase(iter); // double check
-
-            if (!types.second().definitelyIsNumber()) {
-                linkSlowCase(iter); // int32 check
-                linkSlowCase(iter); // double check
-            }
-        }
-    }
-
-    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_sub);
-    slowPathCall.call();
-}
-
</del><span class="cx"> void JIT::emitBinaryDoubleOp(OpcodeID opcodeID, int dst, int op1, int op2, OperandTypes types, JumpList&amp; notInt32Op1, JumpList&amp; notInt32Op2, bool op1IsInRegisters, bool op2IsInRegisters)
</span><span class="cx"> {
</span><span class="cx">     JumpList end;
</span><span class="lines">@@ -729,11 +636,6 @@
</span><span class="cx">                 addDouble(fpRegT2, fpRegT0);
</span><span class="cx">                 emitStoreDouble(dst, fpRegT0);
</span><span class="cx">                 break;
</span><del>-            case op_sub:
-                emitLoadDouble(op1, fpRegT1);
-                subDouble(fpRegT0, fpRegT1);
-                emitStoreDouble(dst, fpRegT1);
-                break;
</del><span class="cx">             case op_div: {
</span><span class="cx">                 emitLoadDouble(op1, fpRegT1);
</span><span class="cx">                 divDouble(fpRegT0, fpRegT1);
</span><span class="lines">@@ -830,11 +732,6 @@
</span><span class="cx">                 addDouble(fpRegT2, fpRegT0);
</span><span class="cx">                 emitStoreDouble(dst, fpRegT0);
</span><span class="cx">                 break;
</span><del>-            case op_sub:
-                emitLoadDouble(op2, fpRegT2);
-                subDouble(fpRegT2, fpRegT0);
-                emitStoreDouble(dst, fpRegT0);
-                break;
</del><span class="cx">             case op_div: {
</span><span class="cx">                 emitLoadDouble(op2, fpRegT2);
</span><span class="cx">                 divDouble(fpRegT2, fpRegT0);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITInlines.h (190648 => 190649)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITInlines.h        2015-10-06 21:46:08 UTC (rev 190648)
+++ trunk/Source/JavaScriptCore/jit/JITInlines.h        2015-10-06 22:29:27 UTC (rev 190649)
</span><span class="lines">@@ -769,6 +769,14 @@
</span><span class="cx">         linkSlowCase(iter);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+ALWAYS_INLINE void JIT::linkAllSlowCasesForBytecodeOffset(Vector&lt;SlowCaseEntry&gt;&amp; slowCases, Vector&lt;SlowCaseEntry&gt;::iterator&amp; iter, unsigned bytecodeOffset)
+{
+    while (iter != slowCases.end() &amp;&amp; iter-&gt;to == bytecodeOffset) {
+        iter-&gt;from.link(this);
+        ++iter;
+    }
+}
+
</ins><span class="cx"> ALWAYS_INLINE void JIT::addSlowCase(Jump jump)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(m_bytecodeOffset != std::numeric_limits&lt;unsigned&gt;::max()); // This method should only be called during hot/cold path generation, so that m_bytecodeOffset is set.
</span><span class="lines">@@ -998,6 +1006,16 @@
</span><span class="cx">     move(Imm32(v.tag()), tag);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+ALWAYS_INLINE void JIT::emitGetVirtualRegister(int src, JSValueRegs dst)
+{
+    emitLoad(src, dst.tagGPR(), dst.payloadGPR());
+}
+
+ALWAYS_INLINE void JIT::emitPutVirtualRegister(int dst, JSValueRegs from)
+{
+    emitStore(dst, from.tagGPR(), from.payloadGPR());
+}
+
</ins><span class="cx"> inline void JIT::emitLoad(int index, RegisterID tag, RegisterID payload, RegisterID base)
</span><span class="cx"> {
</span><span class="cx">     RELEASE_ASSERT(tag != payload);
</span><span class="lines">@@ -1156,6 +1174,11 @@
</span><span class="cx">     load64(Address(callFrameRegister, src * sizeof(Register)), dst);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+ALWAYS_INLINE void JIT::emitGetVirtualRegister(int src, JSValueRegs dst)
+{
+    emitGetVirtualRegister(src, dst.payloadGPR());
+}
+
</ins><span class="cx"> ALWAYS_INLINE void JIT::emitGetVirtualRegister(VirtualRegister src, RegisterID dst)
</span><span class="cx"> {
</span><span class="cx">     emitGetVirtualRegister(src.offset(), dst);
</span><span class="lines">@@ -1187,6 +1210,11 @@
</span><span class="cx">     store64(from, Address(callFrameRegister, dst * sizeof(Register)));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+ALWAYS_INLINE void JIT::emitPutVirtualRegister(int dst, JSValueRegs from)
+{
+    emitPutVirtualRegister(dst, from.payloadGPR());
+}
+
</ins><span class="cx"> ALWAYS_INLINE void JIT::emitPutVirtualRegister(VirtualRegister dst, RegisterID from)
</span><span class="cx"> {
</span><span class="cx">     emitPutVirtualRegister(dst.offset(), from);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITSubGeneratorh"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/jit/JITSubGenerator.h (0 => 190649)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITSubGenerator.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/jit/JITSubGenerator.h        2015-10-06 22:29:27 UTC (rev 190649)
</span><span class="lines">@@ -0,0 +1,117 @@
</span><ins>+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef JITSubGenerator_h
+#define JITSubGenerator_h
+
+#include &quot;CCallHelpers.h&quot;
+
+namespace JSC {
+    
+class JITSubGenerator {
+public:
+
+    JITSubGenerator(JSValueRegs result, JSValueRegs left, JSValueRegs right,
+        ResultType leftType, ResultType rightType, FPRReg leftFPR, FPRReg rightFPR,
+        GPRReg scratchGPR, FPRReg scratchFPR)
+        : m_result(result)
+        , m_left(left)
+        , m_right(right)
+        , m_leftType(leftType)
+        , m_rightType(rightType)
+        , m_leftFPR(leftFPR)
+        , m_rightFPR(rightFPR)
+        , m_scratchGPR(scratchGPR)
+        , m_scratchFPR(scratchFPR)
+    { }
+
+    void generateFastPath(CCallHelpers&amp; jit)
+    {
+        CCallHelpers::JumpList slowPath;
+
+        CCallHelpers::Jump leftNotInt = jit.branchIfNotInt32(m_left);
+        CCallHelpers::Jump rightNotInt = jit.branchIfNotInt32(m_right);
+
+        m_slowPathJumpList.append(
+            jit.branchSub32(CCallHelpers::Overflow, m_right.payloadGPR(), m_left.payloadGPR()));
+
+        jit.boxInt32(m_left.payloadGPR(), m_result);
+
+        if (!jit.supportsFloatingPoint()) {
+            m_slowPathJumpList.append(leftNotInt);
+            m_slowPathJumpList.append(rightNotInt);
+            return;
+        }
+        
+        CCallHelpers::Jump end = jit.jump();
+
+        leftNotInt.link(&amp;jit);
+        if (!m_leftType.definitelyIsNumber())
+            m_slowPathJumpList.append(jit.branchIfNotNumber(m_left, m_scratchGPR));
+        if (!m_rightType.definitelyIsNumber())
+            m_slowPathJumpList.append(jit.branchIfNotNumber(m_right, m_scratchGPR));
+
+        jit.unboxDouble(m_left, m_leftFPR, m_scratchFPR);
+        CCallHelpers::Jump rightIsDouble = jit.branchIfNotInt32(m_right);
+
+        jit.convertInt32ToDouble(m_right.payloadGPR(), m_rightFPR);
+        CCallHelpers::Jump rightWasInteger = jit.jump();
+
+        rightNotInt.link(&amp;jit);
+        if (!m_rightType.definitelyIsNumber())
+            m_slowPathJumpList.append(jit.branchIfNotNumber(m_right, m_scratchGPR));
+
+        jit.convertInt32ToDouble(m_left.payloadGPR(), m_leftFPR);
+
+        rightIsDouble.link(&amp;jit);
+        jit.unboxDouble(m_right, m_rightFPR, m_scratchFPR);
+
+        rightWasInteger.link(&amp;jit);
+
+        jit.subDouble(m_rightFPR, m_leftFPR);
+        jit.boxDouble(m_leftFPR, m_result);
+
+        end.link(&amp;jit);
+    }
+
+    CCallHelpers::JumpList slowPathJumpList() { return m_slowPathJumpList; }
+
+private:
+    JSValueRegs m_result;
+    JSValueRegs m_left;
+    JSValueRegs m_right;
+    ResultType m_leftType;
+    ResultType m_rightType;
+    FPRReg m_leftFPR;
+    FPRReg m_rightFPR;
+    GPRReg m_scratchGPR;
+    FPRReg m_scratchFPR;
+
+    CCallHelpers::JumpList m_slowPathJumpList;
+};
+
+} // namespace JSC
+
+#endif // JITSubGenerator_h
</ins></span></pre>
</div>
</div>

</body>
</html>