<!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>[160587] 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/160587">160587</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2013-12-13 22:33:42 -0800 (Fri, 13 Dec 2013)</dd>
</dl>

<h3>Log Message</h3>
<pre>Get rid of forward exit on UInt32ToNumber by adding an op_unsigned bytecode instruction
https://bugs.webkit.org/show_bug.cgi?id=125553

Reviewed by Oliver Hunt.
        
UInt32ToNumber was a super complicated node because it had to do a speculation, but it
would do it after we already had computed the urshift. It couldn't just back to the
beginning of the urshift because the inputs to the urshift weren't necessarily live
anymore. We couldn't jump forward to the beginning of the next instruction because the
result of the urshift was not yet unsigned-converted.
        
For a while we solved this by forward-exiting in UInt32ToNumber. But that's really
gross and I want to get rid of all forward exits. They cause a lot of bugs.
        
We could also have turned UInt32ToNumber to a backwards exit by forcing the inputs to
the urshift to be live. I figure that this might be a bit too extreme.
        
So, I just created a new place that we can exit to: I split op_urshift into op_urshift
followed by op_unsigned. op_unsigned is an &quot;unsigned cast&quot; along the lines of what
UInt32ToNumber does. This allows me to get rid of all of the nastyness in the DFG for
forward exiting in UInt32ToNumber.
        
This patch enables massive code carnage in the DFG and FTL, and brings us closer to
eliminating one of the DFG's most confusing concepts. On the flipside, it does make the
bytecode slightly more complex (one new instruction). This is a profitable trade. We
want the DFG and FTL to trend towards simplicity, since they are both currently too
complicated.

* bytecode/BytecodeUseDef.h:
(JSC::computeUsesForBytecodeOffset):
(JSC::computeDefsForBytecodeOffset):
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::dumpBytecode):
* bytecode/Opcode.h:
(JSC::padOpcodeName):
* bytecode/ValueRecovery.cpp:
(JSC::ValueRecovery::dumpInContext):
* bytecode/ValueRecovery.h:
(JSC::ValueRecovery::gpr):
* bytecompiler/NodesCodegen.cpp:
(JSC::BinaryOpNode::emitBytecode):
(JSC::emitReadModifyAssignment):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::toInt32):
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
* dfg/DFGNodeType.h:
* dfg/DFGOSRExitCompiler32_64.cpp:
(JSC::DFG::OSRExitCompiler::compileExit):
* dfg/DFGOSRExitCompiler64.cpp:
(JSC::DFG::OSRExitCompiler::compileExit):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileMovHint):
(JSC::DFG::SpeculativeJIT::compileUInt32ToNumber):
* dfg/DFGSpeculativeJIT.h:
* dfg/DFGSpeculativeJIT32_64.cpp:
* dfg/DFGSpeculativeJIT64.cpp:
* dfg/DFGStrengthReductionPhase.cpp:
(JSC::DFG::StrengthReductionPhase::handleNode):
(JSC::DFG::StrengthReductionPhase::convertToIdentityOverChild):
(JSC::DFG::StrengthReductionPhase::convertToIdentityOverChild1):
(JSC::DFG::StrengthReductionPhase::convertToIdentityOverChild2):
* ftl/FTLFormattedValue.h:
(JSC::FTL::int32Value):
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::LowerDFGToLLVM::compileUInt32ToNumber):
* ftl/FTLValueFormat.cpp:
(JSC::FTL::reboxAccordingToFormat):
(WTF::printInternal):
* ftl/FTLValueFormat.h:
* jit/JIT.cpp:
(JSC::JIT::privateCompileMainPass):
(JSC::JIT::privateCompileSlowCases):
* jit/JIT.h:
* jit/JITArithmetic.cpp:
(JSC::JIT::emit_op_urshift):
(JSC::JIT::emitSlow_op_urshift):
(JSC::JIT::emit_op_unsigned):
(JSC::JIT::emitSlow_op_unsigned):
* jit/JITArithmetic32_64.cpp:
(JSC::JIT::emitRightShift):
(JSC::JIT::emitRightShiftSlowCase):
(JSC::JIT::emit_op_unsigned):
(JSC::JIT::emitSlow_op_unsigned):
* llint/LowLevelInterpreter32_64.asm:
* llint/LowLevelInterpreter64.asm:
* runtime/CommonSlowPaths.cpp:
(JSC::SLOW_PATH_DECL):
* runtime/CommonSlowPaths.h:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeBytecodeUseDefh">trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCodeBlockcpp">trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeOpcodeh">trunk/Source/JavaScriptCore/bytecode/Opcode.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeValueRecoverycpp">trunk/Source/JavaScriptCore/bytecode/ValueRecovery.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeValueRecoveryh">trunk/Source/JavaScriptCore/bytecode/ValueRecovery.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecompilerNodesCodegencpp">trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp">trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGCapabilitiescpp">trunk/Source/JavaScriptCore/dfg/DFGCapabilities.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGClobberizeh">trunk/Source/JavaScriptCore/dfg/DFGClobberize.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGFixupPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGNodeTypeh">trunk/Source/JavaScriptCore/dfg/DFGNodeType.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGOSRExitCompiler32_64cpp">trunk/Source/JavaScriptCore/dfg/DFGOSRExitCompiler32_64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGOSRExitCompiler64cpp">trunk/Source/JavaScriptCore/dfg/DFGOSRExitCompiler64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGPredictionPropagationPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJITh">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGStrengthReductionPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLFormattedValueh">trunk/Source/JavaScriptCore/ftl/FTLFormattedValue.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLLowerDFGToLLVMcpp">trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLValueFormatcpp">trunk/Source/JavaScriptCore/ftl/FTLValueFormat.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLValueFormath">trunk/Source/JavaScriptCore/ftl/FTLValueFormat.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITcpp">trunk/Source/JavaScriptCore/jit/JIT.cpp</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="#trunkSourceJavaScriptCorellintLowLevelInterpreter32_64asm">trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLowLevelInterpreter64asm">trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeCommonSlowPathscpp">trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeCommonSlowPathsh">trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (160586 => 160587)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2013-12-14 06:25:17 UTC (rev 160586)
+++ trunk/Source/JavaScriptCore/ChangeLog        2013-12-14 06:33:42 UTC (rev 160587)
</span><span class="lines">@@ -1,3 +1,96 @@
</span><ins>+2013-12-11  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        Get rid of forward exit on UInt32ToNumber by adding an op_unsigned bytecode instruction
+        https://bugs.webkit.org/show_bug.cgi?id=125553
+
+        Reviewed by Oliver Hunt.
+        
+        UInt32ToNumber was a super complicated node because it had to do a speculation, but it
+        would do it after we already had computed the urshift. It couldn't just back to the
+        beginning of the urshift because the inputs to the urshift weren't necessarily live
+        anymore. We couldn't jump forward to the beginning of the next instruction because the
+        result of the urshift was not yet unsigned-converted.
+        
+        For a while we solved this by forward-exiting in UInt32ToNumber. But that's really
+        gross and I want to get rid of all forward exits. They cause a lot of bugs.
+        
+        We could also have turned UInt32ToNumber to a backwards exit by forcing the inputs to
+        the urshift to be live. I figure that this might be a bit too extreme.
+        
+        So, I just created a new place that we can exit to: I split op_urshift into op_urshift
+        followed by op_unsigned. op_unsigned is an &quot;unsigned cast&quot; along the lines of what
+        UInt32ToNumber does. This allows me to get rid of all of the nastyness in the DFG for
+        forward exiting in UInt32ToNumber.
+        
+        This patch enables massive code carnage in the DFG and FTL, and brings us closer to
+        eliminating one of the DFG's most confusing concepts. On the flipside, it does make the
+        bytecode slightly more complex (one new instruction). This is a profitable trade. We
+        want the DFG and FTL to trend towards simplicity, since they are both currently too
+        complicated.
+
+        * bytecode/BytecodeUseDef.h:
+        (JSC::computeUsesForBytecodeOffset):
+        (JSC::computeDefsForBytecodeOffset):
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::dumpBytecode):
+        * bytecode/Opcode.h:
+        (JSC::padOpcodeName):
+        * bytecode/ValueRecovery.cpp:
+        (JSC::ValueRecovery::dumpInContext):
+        * bytecode/ValueRecovery.h:
+        (JSC::ValueRecovery::gpr):
+        * bytecompiler/NodesCodegen.cpp:
+        (JSC::BinaryOpNode::emitBytecode):
+        (JSC::emitReadModifyAssignment):
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::toInt32):
+        (JSC::DFG::ByteCodeParser::parseBlock):
+        * dfg/DFGClobberize.h:
+        (JSC::DFG::clobberize):
+        * dfg/DFGNodeType.h:
+        * dfg/DFGOSRExitCompiler32_64.cpp:
+        (JSC::DFG::OSRExitCompiler::compileExit):
+        * dfg/DFGOSRExitCompiler64.cpp:
+        (JSC::DFG::OSRExitCompiler::compileExit):
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compileMovHint):
+        (JSC::DFG::SpeculativeJIT::compileUInt32ToNumber):
+        * dfg/DFGSpeculativeJIT.h:
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        * dfg/DFGSpeculativeJIT64.cpp:
+        * dfg/DFGStrengthReductionPhase.cpp:
+        (JSC::DFG::StrengthReductionPhase::handleNode):
+        (JSC::DFG::StrengthReductionPhase::convertToIdentityOverChild):
+        (JSC::DFG::StrengthReductionPhase::convertToIdentityOverChild1):
+        (JSC::DFG::StrengthReductionPhase::convertToIdentityOverChild2):
+        * ftl/FTLFormattedValue.h:
+        (JSC::FTL::int32Value):
+        * ftl/FTLLowerDFGToLLVM.cpp:
+        (JSC::FTL::LowerDFGToLLVM::compileUInt32ToNumber):
+        * ftl/FTLValueFormat.cpp:
+        (JSC::FTL::reboxAccordingToFormat):
+        (WTF::printInternal):
+        * ftl/FTLValueFormat.h:
+        * jit/JIT.cpp:
+        (JSC::JIT::privateCompileMainPass):
+        (JSC::JIT::privateCompileSlowCases):
+        * jit/JIT.h:
+        * jit/JITArithmetic.cpp:
+        (JSC::JIT::emit_op_urshift):
+        (JSC::JIT::emitSlow_op_urshift):
+        (JSC::JIT::emit_op_unsigned):
+        (JSC::JIT::emitSlow_op_unsigned):
+        * jit/JITArithmetic32_64.cpp:
+        (JSC::JIT::emitRightShift):
+        (JSC::JIT::emitRightShiftSlowCase):
+        (JSC::JIT::emit_op_unsigned):
+        (JSC::JIT::emitSlow_op_unsigned):
+        * llint/LowLevelInterpreter32_64.asm:
+        * llint/LowLevelInterpreter64.asm:
+        * runtime/CommonSlowPaths.cpp:
+        (JSC::SLOW_PATH_DECL):
+        * runtime/CommonSlowPaths.h:
+
</ins><span class="cx"> 2013-12-13  Mark Hahnenberg  &lt;mhahnenberg@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         LLInt should not conditionally branch to to labels outside of its function
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeBytecodeUseDefh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h (160586 => 160587)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h        2013-12-14 06:25:17 UTC (rev 160586)
+++ trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h        2013-12-14 06:33:42 UTC (rev 160587)
</span><span class="lines">@@ -156,7 +156,8 @@
</span><span class="cx">     case op_new_array_with_size:
</span><span class="cx">     case op_create_this:
</span><span class="cx">     case op_get_pnames:
</span><del>-    case op_del_by_id: {
</del><ins>+    case op_del_by_id:
+    case op_unsigned: {
</ins><span class="cx">         functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="lines">@@ -390,7 +391,8 @@
</span><span class="cx">     case op_create_activation:
</span><span class="cx">     case op_create_arguments:
</span><span class="cx">     case op_del_by_id:
</span><del>-    case op_del_by_val: {
</del><ins>+    case op_del_by_val:
+    case op_unsigned: {
</ins><span class="cx">         functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
</span><span class="cx">         return;
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCodeBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp (160586 => 160587)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2013-12-14 06:25:17 UTC (rev 160586)
+++ trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2013-12-14 06:33:42 UTC (rev 160587)
</span><span class="lines">@@ -901,6 +901,10 @@
</span><span class="cx">             out.printf(&quot;%s, %s, %s&quot;, registerName(r0).data(), registerName(r1).data(), registerName(r2).data());
</span><span class="cx">             break;
</span><span class="cx">         }
</span><ins>+        case op_unsigned: {
+            printUnaryOp(out, exec, location, it, &quot;unsigned&quot;);
+            break;
+        }
</ins><span class="cx">         case op_typeof: {
</span><span class="cx">             printUnaryOp(out, exec, location, it, &quot;typeof&quot;);
</span><span class="cx">             break;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeOpcodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/Opcode.h (160586 => 160587)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/Opcode.h        2013-12-14 06:25:17 UTC (rev 160586)
+++ trunk/Source/JavaScriptCore/bytecode/Opcode.h        2013-12-14 06:33:42 UTC (rev 160587)
</span><span class="lines">@@ -82,6 +82,7 @@
</span><span class="cx">     macro(op_lshift, 4) \
</span><span class="cx">     macro(op_rshift, 4) \
</span><span class="cx">     macro(op_urshift, 4) \
</span><ins>+    macro(op_unsigned, 3) \
</ins><span class="cx">     macro(op_bitand, 5) \
</span><span class="cx">     macro(op_bitxor, 5) \
</span><span class="cx">     macro(op_bitor, 5) \
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeValueRecoverycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/ValueRecovery.cpp (160586 => 160587)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/ValueRecovery.cpp        2013-12-14 06:25:17 UTC (rev 160586)
+++ trunk/Source/JavaScriptCore/bytecode/ValueRecovery.cpp        2013-12-14 06:33:42 UTC (rev 160587)
</span><span class="lines">@@ -83,9 +83,6 @@
</span><span class="cx">     case UnboxedCellInGPR:
</span><span class="cx">         out.print(&quot;cell(&quot;, gpr(), &quot;)&quot;);
</span><span class="cx">         return;
</span><del>-    case UInt32InGPR:
-        out.print(&quot;uint32(&quot;, gpr(), &quot;)&quot;);
-        return;
</del><span class="cx">     case InFPR:
</span><span class="cx">         out.print(fpr());
</span><span class="cx">         return;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeValueRecoveryh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/ValueRecovery.h (160586 => 160587)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/ValueRecovery.h        2013-12-14 06:25:17 UTC (rev 160586)
+++ trunk/Source/JavaScriptCore/bytecode/ValueRecovery.h        2013-12-14 06:33:42 UTC (rev 160587)
</span><span class="lines">@@ -54,7 +54,6 @@
</span><span class="cx">     InPair,
</span><span class="cx"> #endif
</span><span class="cx">     InFPR,
</span><del>-    UInt32InGPR,
</del><span class="cx">     // It's in the stack, but at a different location.
</span><span class="cx">     DisplacedInJSStack,
</span><span class="cx">     // It's in the stack, at a different location, and it's unboxed.
</span><span class="lines">@@ -105,14 +104,6 @@
</span><span class="cx">         return result;
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    static ValueRecovery uint32InGPR(MacroAssembler::RegisterID gpr)
-    {
-        ValueRecovery result;
-        result.m_technique = UInt32InGPR;
-        result.m_source.gpr = gpr;
-        return result;
-    }
-    
</del><span class="cx"> #if USE(JSVALUE32_64)
</span><span class="cx">     static ValueRecovery inPair(MacroAssembler::RegisterID tagGPR, MacroAssembler::RegisterID payloadGPR)
</span><span class="cx">     {
</span><span class="lines">@@ -209,7 +200,7 @@
</span><span class="cx">     
</span><span class="cx">     MacroAssembler::RegisterID gpr() const
</span><span class="cx">     {
</span><del>-        ASSERT(m_technique == InGPR || m_technique == UnboxedInt32InGPR || m_technique == UnboxedBooleanInGPR || m_technique == UInt32InGPR || m_technique == UnboxedInt52InGPR || m_technique == UnboxedStrictInt52InGPR || m_technique == UnboxedCellInGPR);
</del><ins>+        ASSERT(m_technique == InGPR || m_technique == UnboxedInt32InGPR || m_technique == UnboxedBooleanInGPR || m_technique == UnboxedInt52InGPR || m_technique == UnboxedStrictInt52InGPR || m_technique == UnboxedCellInGPR);
</ins><span class="cx">         return m_source.gpr;
</span><span class="cx">     }
</span><span class="cx">     
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerNodesCodegencpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp (160586 => 160587)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp        2013-12-14 06:25:17 UTC (rev 160586)
+++ trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp        2013-12-14 06:33:42 UTC (rev 160587)
</span><span class="lines">@@ -1168,7 +1168,10 @@
</span><span class="cx">             RELEASE_ASSERT_NOT_REACHED();
</span><span class="cx">         return generator.emitUnaryOp(op_not, generator.finalDestination(dst, tmp.get()), tmp.get());
</span><span class="cx">     }
</span><del>-    return generator.emitBinaryOp(opcodeID, generator.finalDestination(dst, src1.get()), src1.get(), src2, OperandTypes(left-&gt;resultDescriptor(), right-&gt;resultDescriptor()));
</del><ins>+    RegisterID* result = generator.emitBinaryOp(opcodeID, generator.finalDestination(dst, src1.get()), src1.get(), src2, OperandTypes(left-&gt;resultDescriptor(), right-&gt;resultDescriptor()));
+    if (opcodeID == op_urshift &amp;&amp; dst != generator.ignoredResult())
+        return generator.emitUnaryOp(op_unsigned, result, result);
+    return result;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> RegisterID* EqualNode::emitBytecode(BytecodeGenerator&amp; generator, RegisterID* dst)
</span><span class="lines">@@ -1335,7 +1338,10 @@
</span><span class="cx">     // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now.
</span><span class="cx">     if (emitExpressionInfoForMe)
</span><span class="cx">         generator.emitExpressionInfo(emitExpressionInfoForMe-&gt;divot(), emitExpressionInfoForMe-&gt;divotStart(), emitExpressionInfoForMe-&gt;divotEnd());
</span><del>-    return generator.emitBinaryOp(opcodeID, dst, src1, src2, types);
</del><ins>+    RegisterID* result = generator.emitBinaryOp(opcodeID, dst, src1, src2, types);
+    if (oper == OpURShift)
+        return generator.emitUnaryOp(op_unsigned, result, result);
+    return result;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> RegisterID* ReadModifyResolveNode::emitBytecode(BytecodeGenerator&amp; generator, RegisterID* dst)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp (160586 => 160587)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2013-12-14 06:25:17 UTC (rev 160586)
+++ trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2013-12-14 06:33:42 UTC (rev 160587)
</span><span class="lines">@@ -513,9 +513,6 @@
</span><span class="cx">         if (node-&gt;hasInt32Result())
</span><span class="cx">             return node;
</span><span class="cx"> 
</span><del>-        if (node-&gt;op() == UInt32ToNumber)
-            return node-&gt;child1().node();
-
</del><span class="cx">         // Check for numeric constants boxed as JSValues.
</span><span class="cx">         if (canFold(node)) {
</span><span class="cx">             JSValue v = valueOfJSConstant(node);
</span><span class="lines">@@ -2050,55 +2047,32 @@
</span><span class="cx">         case op_rshift: {
</span><span class="cx">             Node* op1 = getToInt32(currentInstruction[2].u.operand);
</span><span class="cx">             Node* op2 = getToInt32(currentInstruction[3].u.operand);
</span><del>-            Node* result;
-            // Optimize out shifts by zero.
-            if (isInt32Constant(op2) &amp;&amp; !(valueOfInt32Constant(op2) &amp; 0x1f))
-                result = op1;
-            else
-                result = addToGraph(BitRShift, op1, op2);
-            set(VirtualRegister(currentInstruction[1].u.operand), result);
</del><ins>+            set(VirtualRegister(currentInstruction[1].u.operand),
+                addToGraph(BitRShift, op1, op2));
</ins><span class="cx">             NEXT_OPCODE(op_rshift);
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         case op_lshift: {
</span><span class="cx">             Node* op1 = getToInt32(currentInstruction[2].u.operand);
</span><span class="cx">             Node* op2 = getToInt32(currentInstruction[3].u.operand);
</span><del>-            Node* result;
-            // Optimize out shifts by zero.
-            if (isInt32Constant(op2) &amp;&amp; !(valueOfInt32Constant(op2) &amp; 0x1f))
-                result = op1;
-            else
-                result = addToGraph(BitLShift, op1, op2);
-            set(VirtualRegister(currentInstruction[1].u.operand), result);
</del><ins>+            set(VirtualRegister(currentInstruction[1].u.operand),
+                addToGraph(BitLShift, op1, op2));
</ins><span class="cx">             NEXT_OPCODE(op_lshift);
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         case op_urshift: {
</span><span class="cx">             Node* op1 = getToInt32(currentInstruction[2].u.operand);
</span><span class="cx">             Node* op2 = getToInt32(currentInstruction[3].u.operand);
</span><del>-            Node* result;
-            // The result of a zero-extending right shift is treated as an unsigned value.
-            // This means that if the top bit is set, the result is not in the int32 range,
-            // and as such must be stored as a double. If the shift amount is a constant,
-            // we may be able to optimize.
-            if (isInt32Constant(op2)) {
-                // If we know we are shifting by a non-zero amount, then since the operation
-                // zero fills we know the top bit of the result must be zero, and as such the
-                // result must be within the int32 range. Conversely, if this is a shift by
-                // zero, then the result may be changed by the conversion to unsigned, but it
-                // is not necessary to perform the shift!
-                if (valueOfInt32Constant(op2) &amp; 0x1f)
-                    result = addToGraph(BitURShift, op1, op2);
-                else
-                    result = makeSafe(addToGraph(UInt32ToNumber, op1));
-            }  else {
-                // Cannot optimize at this stage; shift &amp; potentially rebox as a double.
-                result = addToGraph(BitURShift, op1, op2);
-                result = makeSafe(addToGraph(UInt32ToNumber, result));
-            }
-            set(VirtualRegister(currentInstruction[1].u.operand), result);
</del><ins>+            set(VirtualRegister(currentInstruction[1].u.operand),
+                addToGraph(BitURShift, op1, op2));
</ins><span class="cx">             NEXT_OPCODE(op_urshift);
</span><span class="cx">         }
</span><ins>+            
+        case op_unsigned: {
+            set(VirtualRegister(currentInstruction[1].u.operand),
+                makeSafe(addToGraph(UInt32ToNumber, getToInt32(currentInstruction[2].u.operand))));
+            NEXT_OPCODE(op_unsigned);
+        }
</ins><span class="cx"> 
</span><span class="cx">         // === Increment/Decrement opcodes ===
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGCapabilitiescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGCapabilities.cpp (160586 => 160587)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGCapabilities.cpp        2013-12-14 06:25:17 UTC (rev 160586)
+++ trunk/Source/JavaScriptCore/dfg/DFGCapabilities.cpp        2013-12-14 06:33:42 UTC (rev 160587)
</span><span class="lines">@@ -91,6 +91,7 @@
</span><span class="cx">     case op_rshift:
</span><span class="cx">     case op_lshift:
</span><span class="cx">     case op_urshift:
</span><ins>+    case op_unsigned:
</ins><span class="cx">     case op_inc:
</span><span class="cx">     case op_dec:
</span><span class="cx">     case op_add:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGClobberizeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGClobberize.h (160586 => 160587)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGClobberize.h        2013-12-14 06:25:17 UTC (rev 160586)
+++ trunk/Source/JavaScriptCore/dfg/DFGClobberize.h        2013-12-14 06:33:42 UTC (rev 160587)
</span><span class="lines">@@ -118,6 +118,8 @@
</span><span class="cx">     case Int52ToValue:
</span><span class="cx">     case CheckInBounds:
</span><span class="cx">     case ConstantStoragePointer:
</span><ins>+    case UInt32ToNumber:
+    case DoubleAsInt32:
</ins><span class="cx">         return;
</span><span class="cx">         
</span><span class="cx">     case MovHintAndCheck:
</span><span class="lines">@@ -168,15 +170,6 @@
</span><span class="cx">         read(Watchpoint_fire);
</span><span class="cx">         return;
</span><span class="cx"> 
</span><del>-    // These are forward-exiting nodes that assume that the subsequent instruction
-    // is a MovHint, and they try to roll forward over this MovHint in their
-    // execution. This makes hoisting them impossible without additional magic. We
-    // may add such magic eventually, but just not yet.
-    case UInt32ToNumber:
-    case DoubleAsInt32:
-        write(SideState);
-        return;
-        
</del><span class="cx">     case ToThis:
</span><span class="cx">     case CreateThis:
</span><span class="cx">         read(MiscFields);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGFixupPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp (160586 => 160587)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2013-12-14 06:25:17 UTC (rev 160586)
+++ trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2013-12-14 06:33:42 UTC (rev 160587)
</span><span class="lines">@@ -112,6 +112,8 @@
</span><span class="cx">             
</span><span class="cx">         case UInt32ToNumber: {
</span><span class="cx">             fixEdge&lt;KnownInt32Use&gt;(node-&gt;child1());
</span><ins>+            if (bytecodeCanTruncateInteger(node-&gt;arithNodeFlags()))
+                node-&gt;convertToIdentity();
</ins><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">             
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGNodeTypeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGNodeType.h (160586 => 160587)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNodeType.h        2013-12-14 06:25:17 UTC (rev 160586)
+++ trunk/Source/JavaScriptCore/dfg/DFGNodeType.h        2013-12-14 06:33:42 UTC (rev 160587)
</span><span class="lines">@@ -105,7 +105,7 @@
</span><span class="cx">     /* Bitwise operators call ToInt32 on their operands. */\
</span><span class="cx">     macro(ValueToInt32, NodeResultInt32) \
</span><span class="cx">     /* Used to box the result of URShift nodes (result has range 0..2^32-1). */\
</span><del>-    macro(UInt32ToNumber, NodeResultNumber | NodeExitsForward) \
</del><ins>+    macro(UInt32ToNumber, NodeResultNumber) \
</ins><span class="cx">     \
</span><span class="cx">     /* Used to cast known integers to doubles, so as to separate the double form */\
</span><span class="cx">     /* of the value from the integer form. */\
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGOSRExitCompiler32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGOSRExitCompiler32_64.cpp (160586 => 160587)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGOSRExitCompiler32_64.cpp        2013-12-14 06:25:17 UTC (rev 160586)
+++ trunk/Source/JavaScriptCore/dfg/DFGOSRExitCompiler32_64.cpp        2013-12-14 06:33:42 UTC (rev 160587)
</span><span class="lines">@@ -177,7 +177,6 @@
</span><span class="cx">         
</span><span class="cx">         switch (recovery.technique()) {
</span><span class="cx">         case UnboxedInt32InGPR:
</span><del>-        case UInt32InGPR:
</del><span class="cx">         case UnboxedBooleanInGPR:
</span><span class="cx">         case UnboxedCellInGPR:
</span><span class="cx">             m_jit.store32(
</span><span class="lines">@@ -317,28 +316,6 @@
</span><span class="cx">                 AssemblyHelpers::payloadFor(operand));
</span><span class="cx">             break;
</span><span class="cx">             
</span><del>-        case UInt32InGPR: {
-            m_jit.load32(
-                &amp;bitwise_cast&lt;EncodedValueDescriptor*&gt;(scratch + index)-&gt;asBits.payload,
-                GPRInfo::regT0);
-            AssemblyHelpers::Jump positive = m_jit.branch32(
-                AssemblyHelpers::GreaterThanOrEqual,
-                GPRInfo::regT0, AssemblyHelpers::TrustedImm32(0));
-            m_jit.convertInt32ToDouble(GPRInfo::regT0, FPRInfo::fpRegT0);
-            m_jit.addDouble(
-                AssemblyHelpers::AbsoluteAddress(&amp;AssemblyHelpers::twoToThe32),
-                FPRInfo::fpRegT0);
-            m_jit.storeDouble(FPRInfo::fpRegT0, AssemblyHelpers::addressFor(operand));
-            AssemblyHelpers::Jump done = m_jit.jump();
-            positive.link(&amp;m_jit);
-            m_jit.store32(GPRInfo::regT0, AssemblyHelpers::payloadFor(operand));
-            m_jit.store32(
-                AssemblyHelpers::TrustedImm32(JSValue::Int32Tag),
-                AssemblyHelpers::tagFor(operand));
-            done.link(&amp;m_jit);
-            break;
-        }
-            
</del><span class="cx">         case Constant:
</span><span class="cx">             m_jit.store32(
</span><span class="cx">                 AssemblyHelpers::TrustedImm32(recovery.constant().tag()),
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGOSRExitCompiler64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGOSRExitCompiler64.cpp (160586 => 160587)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGOSRExitCompiler64.cpp        2013-12-14 06:25:17 UTC (rev 160586)
+++ trunk/Source/JavaScriptCore/dfg/DFGOSRExitCompiler64.cpp        2013-12-14 06:33:42 UTC (rev 160587)
</span><span class="lines">@@ -185,7 +185,6 @@
</span><span class="cx">         switch (recovery.technique()) {
</span><span class="cx">         case InGPR:
</span><span class="cx">         case UnboxedInt32InGPR:
</span><del>-        case UInt32InGPR:
</del><span class="cx">         case UnboxedInt52InGPR:
</span><span class="cx">         case UnboxedStrictInt52InGPR:
</span><span class="cx">         case UnboxedCellInGPR:
</span><span class="lines">@@ -283,13 +282,6 @@
</span><span class="cx">             m_jit.store64(GPRInfo::regT0, AssemblyHelpers::addressFor(operand));
</span><span class="cx">             break;
</span><span class="cx">             
</span><del>-        case UInt32InGPR:
-            m_jit.load64(scratch + index, GPRInfo::regT0);
-            m_jit.zeroExtend32ToPtr(GPRInfo::regT0, GPRInfo::regT0);
-            m_jit.boxInt52(GPRInfo::regT0, GPRInfo::regT0, GPRInfo::regT1, FPRInfo::fpRegT0);
-            m_jit.store64(GPRInfo::regT0, AssemblyHelpers::addressFor(operand));
-            break;
-            
</del><span class="cx">         case InFPR:
</span><span class="cx">         case DoubleDisplacedInJSStack:
</span><span class="cx">             m_jit.move(AssemblyHelpers::TrustedImmPtr(scratch + index), GPRInfo::regT0);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGPredictionPropagationPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp (160586 => 160587)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp        2013-12-14 06:25:17 UTC (rev 160586)
+++ trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp        2013-12-14 06:33:42 UTC (rev 160587)
</span><span class="lines">@@ -195,6 +195,8 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         case UInt32ToNumber: {
</span><ins>+            // FIXME: Support Int52.
+            // https://bugs.webkit.org/show_bug.cgi?id=125704
</ins><span class="cx">             if (nodeCanSpeculateInt32(node-&gt;arithNodeFlags()))
</span><span class="cx">                 changed |= mergePrediction(SpecInt32);
</span><span class="cx">             else
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp (160586 => 160587)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2013-12-14 06:25:17 UTC (rev 160586)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2013-12-14 06:33:42 UTC (rev 160587)
</span><span class="lines">@@ -1425,9 +1425,6 @@
</span><span class="cx">     Node* child = node-&gt;child1().node();
</span><span class="cx">     noticeOSRBirth(child);
</span><span class="cx">     
</span><del>-    if (child-&gt;op() == UInt32ToNumber)
-        noticeOSRBirth(child-&gt;child1().node());
-    
</del><span class="cx">     m_stream-&gt;appendAndLog(VariableEvent::movHint(MinifiedID(child), node-&gt;local()));
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -2160,18 +2157,15 @@
</span><span class="cx">         doubleResult(outputFPR, node);
</span><span class="cx">         return;
</span><span class="cx">     }
</span><ins>+    
+    RELEASE_ASSERT(!bytecodeCanTruncateInteger(node-&gt;arithNodeFlags()));
</ins><span class="cx"> 
</span><span class="cx">     SpeculateInt32Operand op1(this, node-&gt;child1());
</span><del>-    GPRTemporary result(this); // For the benefit of OSR exit, force these to be in different registers. In reality the OSR exit compiler could find cases where you have uint32(%r1) followed by int32(%r1) and then use different registers, but that seems like too much effort.
</del><ins>+    GPRTemporary result(this);
</ins><span class="cx"> 
</span><span class="cx">     m_jit.move(op1.gpr(), result.gpr());
</span><span class="cx"> 
</span><del>-    // Test the operand is positive. This is a very special speculation check - we actually
-    // use roll-forward speculation here, where if this fails, we jump to the baseline
-    // instruction that follows us, rather than the one we're executing right now. We have
-    // to do this because by this point, the original values necessary to compile whatever
-    // operation the UInt32ToNumber originated from might be dead.
-    forwardSpeculationCheck(Overflow, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::LessThan, result.gpr(), TrustedImm32(0)), ValueRecovery::uint32InGPR(result.gpr()));
</del><ins>+    speculationCheck(Overflow, JSValueRegs(), 0, m_jit.branch32(MacroAssembler::LessThan, result.gpr(), TrustedImm32(0)));
</ins><span class="cx"> 
</span><span class="cx">     int32Result(result.gpr(), node, op1.format());
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h (160586 => 160587)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h        2013-12-14 06:25:17 UTC (rev 160586)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h        2013-12-14 06:33:42 UTC (rev 160587)
</span><span class="lines">@@ -698,8 +698,6 @@
</span><span class="cx">     void compileMovHint(Node*);
</span><span class="cx">     void compileMovHintAndCheck(Node*);
</span><span class="cx"> 
</span><del>-    void nonSpeculativeUInt32ToNumber(Node*);
-
</del><span class="cx"> #if USE(JSVALUE64)
</span><span class="cx">     void cachedGetById(CodeOrigin, GPRReg baseGPR, GPRReg resultGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget = JITCompiler::Jump(), SpillRegistersMode = NeedToSpill);
</span><span class="cx">     void cachedPutById(CodeOrigin, GPRReg base, GPRReg value, Edge valueUse, GPRReg scratchGPR, unsigned identifierNumber, PutKind, JITCompiler::Jump slowPathTarget = JITCompiler::Jump());
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp (160586 => 160587)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2013-12-14 06:25:17 UTC (rev 160586)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2013-12-14 06:33:42 UTC (rev 160587)
</span><span class="lines">@@ -168,33 +168,6 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SpeculativeJIT::nonSpeculativeUInt32ToNumber(Node* node)
-{
-    SpeculateInt32Operand op1(this, node-&gt;child1());
-    FPRTemporary boxer(this);
-    GPRTemporary resultTag(this, Reuse, op1);
-    GPRTemporary resultPayload(this);
-        
-    JITCompiler::Jump positive = m_jit.branch32(MacroAssembler::GreaterThanOrEqual, op1.gpr(), TrustedImm32(0));
-        
-    m_jit.convertInt32ToDouble(op1.gpr(), boxer.fpr());
-    m_jit.move(JITCompiler::TrustedImmPtr(&amp;AssemblyHelpers::twoToThe32), resultPayload.gpr()); // reuse resultPayload register here.
-    m_jit.addDouble(JITCompiler::Address(resultPayload.gpr(), 0), boxer.fpr());
-        
-    boxDouble(boxer.fpr(), resultTag.gpr(), resultPayload.gpr());
-        
-    JITCompiler::Jump done = m_jit.jump();
-        
-    positive.link(&amp;m_jit);
-        
-    m_jit.move(TrustedImm32(JSValue::Int32Tag), resultTag.gpr());
-    m_jit.move(op1.gpr(), resultPayload.gpr());
-        
-    done.link(&amp;m_jit);
-
-    jsValueResult(resultTag.gpr(), resultPayload.gpr(), node);
-}
-
</del><span class="cx"> void SpeculativeJIT::cachedGetById(CodeOrigin codeOrigin, GPRReg baseTagGPROrNone, GPRReg basePayloadGPR, GPRReg resultTagGPR, GPRReg resultPayloadGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget, SpillRegistersMode spillMode)
</span><span class="cx"> {
</span><span class="cx">     JITGetByIdGenerator gen(
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (160586 => 160587)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2013-12-14 06:25:17 UTC (rev 160586)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2013-12-14 06:33:42 UTC (rev 160587)
</span><span class="lines">@@ -186,30 +186,6 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SpeculativeJIT::nonSpeculativeUInt32ToNumber(Node* node)
-{
-    SpeculateInt32Operand op1(this, node-&gt;child1());
-    FPRTemporary boxer(this);
-    GPRTemporary result(this, Reuse, op1);
-    
-    JITCompiler::Jump positive = m_jit.branch32(MacroAssembler::GreaterThanOrEqual, op1.gpr(), TrustedImm32(0));
-    
-    m_jit.convertInt32ToDouble(op1.gpr(), boxer.fpr());
-    m_jit.addDouble(JITCompiler::AbsoluteAddress(&amp;AssemblyHelpers::twoToThe32), boxer.fpr());
-    
-    boxDouble(boxer.fpr(), result.gpr());
-    
-    JITCompiler::Jump done = m_jit.jump();
-    
-    positive.link(&amp;m_jit);
-    
-    m_jit.or64(GPRInfo::tagTypeNumberRegister, op1.gpr(), result.gpr());
-    
-    done.link(&amp;m_jit);
-    
-    jsValueResult(result.gpr(), m_currentNode);
-}
-
</del><span class="cx"> void SpeculativeJIT::cachedGetById(CodeOrigin codeOrigin, GPRReg baseGPR, GPRReg resultGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget, SpillRegistersMode spillMode)
</span><span class="cx"> {
</span><span class="cx">     JITGetByIdGenerator gen(
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGStrengthReductionPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp (160586 => 160587)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp        2013-12-14 06:25:17 UTC (rev 160586)
+++ trunk/Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp        2013-12-14 06:33:42 UTC (rev 160587)
</span><span class="lines">@@ -70,14 +70,40 @@
</span><span class="cx">     {
</span><span class="cx">         switch (m_node-&gt;op()) {
</span><span class="cx">         case BitOr:
</span><del>-            // Optimize X|0 -&gt; X.
</del><ins>+            if (m_node-&gt;child1()-&gt;isConstant()) {
+                JSValue op1 = m_graph.valueOfJSConstant(m_node-&gt;child1().node());
+                if (op1.isInt32() &amp;&amp; !op1.asInt32()) {
+                    convertToIdentityOverChild2();
+                    break;
+                }
+            }
</ins><span class="cx">             if (m_node-&gt;child2()-&gt;isConstant()) {
</span><del>-                JSValue C2 = m_graph.valueOfJSConstant(m_node-&gt;child2().node());
-                if (C2.isInt32() &amp;&amp; !C2.asInt32()) {
-                    m_insertionSet.insertNode(
-                        m_nodeIndex, SpecNone, Phantom, m_node-&gt;codeOrigin,
-                        m_node-&gt;child2());
-                    m_node-&gt;children.removeEdge(1);
</del><ins>+                JSValue op2 = m_graph.valueOfJSConstant(m_node-&gt;child2().node());
+                if (op2.isInt32() &amp;&amp; !op2.asInt32()) {
+                    convertToIdentityOverChild1();
+                    break;
+                }
+            }
+            break;
+            
+        case BitLShift:
+        case BitRShift:
+        case BitURShift:
+            if (m_node-&gt;child2()-&gt;isConstant()) {
+                JSValue op2 = m_graph.valueOfJSConstant(m_node-&gt;child2().node());
+                if (op2.isInt32() &amp;&amp; !(op2.asInt32() &amp; 0x1f)) {
+                    convertToIdentityOverChild1();
+                    break;
+                }
+            }
+            break;
+            
+        case UInt32ToNumber:
+            if (m_node-&gt;child1()-&gt;op() == BitURShift
+                &amp;&amp; m_node-&gt;child1()-&gt;child2()-&gt;isConstant()) {
+                JSValue shiftAmount = m_graph.valueOfJSConstant(
+                    m_node-&gt;child1()-&gt;child2().node());
+                if (shiftAmount.isInt32() &amp;&amp; (shiftAmount.asInt32() &amp; 0x1f)) {
</ins><span class="cx">                     m_node-&gt;convertToIdentity();
</span><span class="cx">                     m_changed = true;
</span><span class="cx">                     break;
</span><span class="lines">@@ -116,7 +142,26 @@
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">     }
</span><ins>+            
+    void convertToIdentityOverChild(unsigned childIndex)
+    {
+        m_insertionSet.insertNode(
+            m_nodeIndex, SpecNone, Phantom, m_node-&gt;codeOrigin, m_node-&gt;children);
+        m_node-&gt;children.removeEdge(childIndex ^ 1);
+        m_node-&gt;convertToIdentity();
+        m_changed = true;
+    }
</ins><span class="cx">     
</span><ins>+    void convertToIdentityOverChild1()
+    {
+        convertToIdentityOverChild(0);
+    }
+    
+    void convertToIdentityOverChild2()
+    {
+        convertToIdentityOverChild(1);
+    }
+    
</ins><span class="cx">     void foldTypedArrayPropertyToConstant(JSArrayBufferView* view, JSValue constant)
</span><span class="cx">     {
</span><span class="cx">         prepareToFoldTypedArray(view);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLFormattedValueh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLFormattedValue.h (160586 => 160587)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLFormattedValue.h        2013-12-14 06:25:17 UTC (rev 160586)
+++ trunk/Source/JavaScriptCore/ftl/FTLFormattedValue.h        2013-12-14 06:33:42 UTC (rev 160587)
</span><span class="lines">@@ -72,7 +72,6 @@
</span><span class="cx"> 
</span><span class="cx"> static inline FormattedValue noValue() { return FormattedValue(); }
</span><span class="cx"> static inline FormattedValue int32Value(LValue value) { return FormattedValue(ValueFormatInt32, value); }
</span><del>-static inline FormattedValue uInt32Value(LValue value) { return FormattedValue(ValueFormatUInt32, value); }
</del><span class="cx"> static inline FormattedValue booleanValue(LValue value) { return FormattedValue(ValueFormatBoolean, value); }
</span><span class="cx"> static inline FormattedValue jsValueValue(LValue value) { return FormattedValue(ValueFormatJSValue, value); }
</span><span class="cx"> static inline FormattedValue doubleValue(LValue value) { return FormattedValue(ValueFormatDouble, value); }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLLowerDFGToLLVMcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp (160586 => 160587)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2013-12-14 06:25:17 UTC (rev 160586)
+++ trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2013-12-14 06:33:42 UTC (rev 160587)
</span><span class="lines">@@ -1171,9 +1171,7 @@
</span><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx">         
</span><del>-        speculateForward(
-            Overflow, noValue(), 0, m_out.lessThan(value, m_out.int32Zero),
-            FormattedValue(ValueFormatUInt32, value));
</del><ins>+        speculate(Overflow, noValue(), 0, m_out.lessThan(value, m_out.int32Zero));
</ins><span class="cx">         setInt32(value);
</span><span class="cx">     }
</span><span class="cx">     
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLValueFormatcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLValueFormat.cpp (160586 => 160587)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLValueFormat.cpp        2013-12-14 06:25:17 UTC (rev 160586)
+++ trunk/Source/JavaScriptCore/ftl/FTLValueFormat.cpp        2013-12-14 06:33:42 UTC (rev 160587)
</span><span class="lines">@@ -42,14 +42,6 @@
</span><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    case ValueFormatUInt32: {
-        jit.zeroExtend32ToPtr(value, value);
-        jit.moveDoubleTo64(FPRInfo::fpRegT0, scratch2);
-        jit.boxInt52(value, value, scratch1, FPRInfo::fpRegT0);
-        jit.move64ToDouble(scratch2, FPRInfo::fpRegT0);
-        break;
-    }
-    
</del><span class="cx">     case ValueFormatInt52: {
</span><span class="cx">         jit.rshift64(AssemblyHelpers::TrustedImm32(JSValue::int52ShiftAmount), value);
</span><span class="cx">         jit.moveDoubleTo64(FPRInfo::fpRegT0, scratch2);
</span><span class="lines">@@ -105,9 +97,6 @@
</span><span class="cx">     case ValueFormatInt32:
</span><span class="cx">         out.print(&quot;Int32&quot;);
</span><span class="cx">         return;
</span><del>-    case ValueFormatUInt32:
-        out.print(&quot;UInt32&quot;);
-        return;
</del><span class="cx">     case ValueFormatInt52:
</span><span class="cx">         out.print(&quot;Int52&quot;);
</span><span class="cx">         return;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLValueFormath"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLValueFormat.h (160586 => 160587)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLValueFormat.h        2013-12-14 06:25:17 UTC (rev 160586)
+++ trunk/Source/JavaScriptCore/ftl/FTLValueFormat.h        2013-12-14 06:33:42 UTC (rev 160587)
</span><span class="lines">@@ -45,7 +45,6 @@
</span><span class="cx"> enum ValueFormat {
</span><span class="cx">     InvalidValueFormat,
</span><span class="cx">     ValueFormatInt32,
</span><del>-    ValueFormatUInt32,
</del><span class="cx">     ValueFormatInt52,
</span><span class="cx">     ValueFormatStrictInt52,
</span><span class="cx">     ValueFormatBoolean,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JIT.cpp (160586 => 160587)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JIT.cpp        2013-12-14 06:25:17 UTC (rev 160586)
+++ trunk/Source/JavaScriptCore/jit/JIT.cpp        2013-12-14 06:33:42 UTC (rev 160587)
</span><span class="lines">@@ -267,6 +267,7 @@
</span><span class="cx">         DEFINE_OP(op_ret)
</span><span class="cx">         DEFINE_OP(op_ret_object_or_this)
</span><span class="cx">         DEFINE_OP(op_rshift)
</span><ins>+        DEFINE_OP(op_unsigned)
</ins><span class="cx">         DEFINE_OP(op_urshift)
</span><span class="cx">         DEFINE_OP(op_strcat)
</span><span class="cx">         DEFINE_OP(op_stricteq)
</span><span class="lines">@@ -412,6 +413,7 @@
</span><span class="cx">         case op_put_by_val_direct:
</span><span class="cx">         DEFINE_SLOWCASE_OP(op_put_by_val)
</span><span class="cx">         DEFINE_SLOWCASE_OP(op_rshift)
</span><ins>+        DEFINE_SLOWCASE_OP(op_unsigned)
</ins><span class="cx">         DEFINE_SLOWCASE_OP(op_urshift)
</span><span class="cx">         DEFINE_SLOWCASE_OP(op_stricteq)
</span><span class="cx">         DEFINE_SLOWCASE_OP(op_sub)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JIT.h (160586 => 160587)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JIT.h        2013-12-14 06:25:17 UTC (rev 160586)
+++ trunk/Source/JavaScriptCore/jit/JIT.h        2013-12-14 06:33:42 UTC (rev 160587)
</span><span class="lines">@@ -552,6 +552,7 @@
</span><span class="cx">         void emit_op_to_number(Instruction*);
</span><span class="cx">         void emit_op_to_primitive(Instruction*);
</span><span class="cx">         void emit_op_unexpected_load(Instruction*);
</span><ins>+        void emit_op_unsigned(Instruction*);
</ins><span class="cx">         void emit_op_urshift(Instruction*);
</span><span class="cx"> 
</span><span class="cx">         void emitSlow_op_add(Instruction*, Vector&lt;SlowCaseEntry&gt;::iterator&amp;);
</span><span class="lines">@@ -603,6 +604,7 @@
</span><span class="cx">         void emitSlow_op_sub(Instruction*, Vector&lt;SlowCaseEntry&gt;::iterator&amp;);
</span><span class="cx">         void emitSlow_op_to_number(Instruction*, Vector&lt;SlowCaseEntry&gt;::iterator&amp;);
</span><span class="cx">         void emitSlow_op_to_primitive(Instruction*, Vector&lt;SlowCaseEntry&gt;::iterator&amp;);
</span><ins>+        void emitSlow_op_unsigned(Instruction*, Vector&lt;SlowCaseEntry&gt;::iterator&amp;);
</ins><span class="cx">         void emitSlow_op_urshift(Instruction*, Vector&lt;SlowCaseEntry&gt;::iterator&amp;);
</span><span class="cx"> 
</span><span class="cx">         void emit_op_resolve_scope(Instruction*);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITArithmeticcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITArithmetic.cpp (160586 => 160587)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITArithmetic.cpp        2013-12-14 06:25:17 UTC (rev 160586)
+++ trunk/Source/JavaScriptCore/jit/JITArithmetic.cpp        2013-12-14 06:33:42 UTC (rev 160587)
</span><span class="lines">@@ -306,96 +306,82 @@
</span><span class="cx"> 
</span><span class="cx"> void JIT::emit_op_urshift(Instruction* currentInstruction)
</span><span class="cx"> {
</span><del>-    int dst = currentInstruction[1].u.operand;
</del><ins>+    int result = currentInstruction[1].u.operand;
</ins><span class="cx">     int op1 = currentInstruction[2].u.operand;
</span><span class="cx">     int op2 = currentInstruction[3].u.operand;
</span><span class="cx"> 
</span><del>-    // Slow case of urshift makes assumptions about what registers hold the
-    // shift arguments, so any changes must be updated there as well.
</del><span class="cx">     if (isOperandConstantImmediateInt(op2)) {
</span><ins>+        // isOperandConstantImmediateInt(op2) =&gt; 1 SlowCase
</ins><span class="cx">         emitGetVirtualRegister(op1, regT0);
</span><span class="cx">         emitJumpSlowCaseIfNotImmediateInteger(regT0);
</span><del>-        emitFastArithImmToInt(regT0);
-        int shift = getConstantOperand(op2).asInt32();
-        if (shift)
-            urshift32(Imm32(shift &amp; 0x1f), regT0);
-        // unsigned shift &lt; 0 or shift = k*2^32 may result in (essentially)
-        // a toUint conversion, which can result in a value we can represent
-        // as an immediate int.
-        if (shift &lt; 0 || !(shift &amp; 31))
-            addSlowCase(branch32(LessThan, regT0, TrustedImm32(0)));
-        emitFastArithReTagImmediate(regT0, regT0);
-        emitPutVirtualRegister(dst, regT0);
-        return;
</del><ins>+        // Mask with 0x1f as per ecma-262 11.7.2 step 7.
+        urshift32(Imm32(getConstantOperandImmediateInt(op2) &amp; 0x1f), regT0);
+    } else {
+        emitGetVirtualRegisters(op1, regT0, op2, regT2);
+        if (supportsFloatingPointTruncate()) {
+            Jump lhsIsInt = emitJumpIfImmediateInteger(regT0);
+            // supportsFloatingPoint() &amp;&amp; USE(JSVALUE64) =&gt; 3 SlowCases
+            addSlowCase(emitJumpIfNotImmediateNumber(regT0));
+            add64(tagTypeNumberRegister, regT0);
+            move64ToDouble(regT0, fpRegT0);
+            addSlowCase(branchTruncateDoubleToInt32(fpRegT0, regT0));
+            lhsIsInt.link(this);
+            emitJumpSlowCaseIfNotImmediateInteger(regT2);
+        } else {
+            // !supportsFloatingPoint() =&gt; 2 SlowCases
+            emitJumpSlowCaseIfNotImmediateInteger(regT0);
+            emitJumpSlowCaseIfNotImmediateInteger(regT2);
+        }
+        emitFastArithImmToInt(regT2);
+        urshift32(regT2, regT0);
</ins><span class="cx">     }
</span><del>-    emitGetVirtualRegisters(op1, regT0, op2, regT1);
-    if (!isOperandConstantImmediateInt(op1))
-        emitJumpSlowCaseIfNotImmediateInteger(regT0);
-    emitJumpSlowCaseIfNotImmediateInteger(regT1);
-    emitFastArithImmToInt(regT0);
-    emitFastArithImmToInt(regT1);
-    urshift32(regT1, regT0);
-    addSlowCase(branch32(LessThan, regT0, TrustedImm32(0)));
-    emitFastArithReTagImmediate(regT0, regT0);
-    emitPutVirtualRegister(dst, regT0);
</del><ins>+    emitFastArithIntToImmNoCheck(regT0, regT0);
+    emitPutVirtualRegister(result);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void JIT::emitSlow_op_urshift(Instruction* currentInstruction, Vector&lt;SlowCaseEntry&gt;::iterator&amp; iter)
</span><span class="cx"> {
</span><del>-    int dst = currentInstruction[1].u.operand;
-    int op1 = currentInstruction[2].u.operand;
</del><span class="cx">     int op2 = currentInstruction[3].u.operand;
</span><del>-    if (isOperandConstantImmediateInt(op2)) {
-        int shift = getConstantOperand(op2).asInt32();
-        // op1 = regT0
-        linkSlowCase(iter); // int32 check
</del><ins>+
+    if (isOperandConstantImmediateInt(op2))
+        linkSlowCase(iter);
+
+    else {
</ins><span class="cx">         if (supportsFloatingPointTruncate()) {
</span><del>-            JumpList failures;
-            failures.append(emitJumpIfNotImmediateNumber(regT0)); // op1 is not a double
-            add64(tagTypeNumberRegister, regT0);
-            move64ToDouble(regT0, fpRegT0);
-            failures.append(branchTruncateDoubleToInt32(fpRegT0, regT0));
-            if (shift)
-                urshift32(Imm32(shift &amp; 0x1f), regT0);
-            if (shift &lt; 0 || !(shift &amp; 31))
-                failures.append(branch32(LessThan, regT0, TrustedImm32(0)));
-            emitFastArithReTagImmediate(regT0, regT0);
-            emitPutVirtualRegister(dst, regT0);
-            emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_rshift));
-            failures.link(this);
</del><ins>+            linkSlowCase(iter);
+            linkSlowCase(iter);
+            linkSlowCase(iter);
+        } else {
+            linkSlowCase(iter);
+            linkSlowCase(iter);
</ins><span class="cx">         }
</span><del>-        if (shift &lt; 0 || !(shift &amp; 31))
-            linkSlowCase(iter); // failed to box in hot path
-    } else {
-        // op1 = regT0
-        // op2 = regT1
-        if (!isOperandConstantImmediateInt(op1)) {
-            linkSlowCase(iter); // int32 check -- op1 is not an int
-            if (supportsFloatingPointTruncate()) {
-                JumpList failures;
-                failures.append(emitJumpIfNotImmediateNumber(regT0)); // op1 is not a double
-                add64(tagTypeNumberRegister, regT0);
-                move64ToDouble(regT0, fpRegT0);
-                failures.append(branchTruncateDoubleToInt32(fpRegT0, regT0));
-                failures.append(emitJumpIfNotImmediateInteger(regT1)); // op2 is not an int
-                emitFastArithImmToInt(regT1);
-                urshift32(regT1, regT0);
-                failures.append(branch32(LessThan, regT0, TrustedImm32(0)));
-                emitFastArithReTagImmediate(regT0, regT0);
-                emitPutVirtualRegister(dst, regT0);
-                emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_rshift));
-                failures.link(this);
-            }
-        }
-        
-        linkSlowCase(iter); // int32 check - op2 is not an int
-        linkSlowCase(iter); // Can't represent unsigned result as an immediate
</del><span class="cx">     }
</span><del>-    
</del><ins>+
</ins><span class="cx">     JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_urshift);
</span><span class="cx">     slowPathCall.call();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void JIT::emit_op_unsigned(Instruction* currentInstruction)
+{
+    int result = currentInstruction[1].u.operand;
+    int op1 = currentInstruction[2].u.operand;
+    
+    emitGetVirtualRegister(op1, regT0);
+    emitJumpSlowCaseIfNotImmediateInteger(regT0);
+    addSlowCase(branch32(LessThan, regT0, TrustedImm32(0)));
+    emitFastArithReTagImmediate(regT0, regT0);
+    emitPutVirtualRegister(result, regT0);
+}
+
+void JIT::emitSlow_op_unsigned(Instruction* currentInstruction, Vector&lt;SlowCaseEntry&gt;::iterator&amp; iter)
+{
+    linkSlowCase(iter);
+    linkSlowCase(iter);
+    
+    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_unsigned);
+    slowPathCall.call();
+}
+
</ins><span class="cx"> void JIT::emit_compareAndJump(OpcodeID, int op1, int op2, unsigned target, RelationalCondition condition)
</span><span class="cx"> {
</span><span class="cx">     // We generate inline code for the following cases in the fast path:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITArithmetic32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITArithmetic32_64.cpp (160586 => 160587)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITArithmetic32_64.cpp        2013-12-14 06:25:17 UTC (rev 160586)
+++ trunk/Source/JavaScriptCore/jit/JITArithmetic32_64.cpp        2013-12-14 06:33:42 UTC (rev 160587)
</span><span class="lines">@@ -211,18 +211,16 @@
</span><span class="cx">                 urshift32(Imm32(shift), regT0);
</span><span class="cx">             else
</span><span class="cx">                 rshift32(Imm32(shift), regT0);
</span><del>-        } else if (isUnsigned) // signed right shift by zero is simply toInt conversion
-            addSlowCase(branch32(LessThan, regT0, TrustedImm32(0)));
</del><ins>+        }
</ins><span class="cx">         emitStoreInt32(dst, regT0, dst == op1);
</span><span class="cx">     } else {
</span><span class="cx">         emitLoad2(op1, regT1, regT0, op2, regT3, regT2);
</span><span class="cx">         if (!isOperandConstantImmediateInt(op1))
</span><span class="cx">             addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
</span><span class="cx">         addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag)));
</span><del>-        if (isUnsigned) {
</del><ins>+        if (isUnsigned)
</ins><span class="cx">             urshift32(regT2, regT0);
</span><del>-            addSlowCase(branch32(LessThan, regT0, TrustedImm32(0)));
-        } else
</del><ins>+        else
</ins><span class="cx">             rshift32(regT2, regT0);
</span><span class="cx">         emitStoreInt32(dst, regT0, dst == op1);
</span><span class="cx">     }
</span><span class="lines">@@ -247,15 +245,12 @@
</span><span class="cx">                     urshift32(Imm32(shift), regT0);
</span><span class="cx">                 else
</span><span class="cx">                     rshift32(Imm32(shift), regT0);
</span><del>-            } else if (isUnsigned) // signed right shift by zero is simply toInt conversion
-                failures.append(branch32(LessThan, regT0, TrustedImm32(0)));
</del><ins>+            }
</ins><span class="cx">             move(TrustedImm32(JSValue::Int32Tag), regT1);
</span><span class="cx">             emitStoreInt32(dst, regT0, false);
</span><span class="cx">             emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_rshift));
</span><span class="cx">             failures.link(this);
</span><span class="cx">         }
</span><del>-        if (isUnsigned &amp;&amp; !shift)
-            linkSlowCase(iter); // failed to box in hot path
</del><span class="cx">     } else {
</span><span class="cx">         // op1 = regT1:regT0
</span><span class="cx">         // op2 = regT3:regT2
</span><span class="lines">@@ -267,10 +262,9 @@
</span><span class="cx">                 emitLoadDouble(op1, fpRegT0);
</span><span class="cx">                 failures.append(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag))); // op2 is not an int
</span><span class="cx">                 failures.append(branchTruncateDoubleToInt32(fpRegT0, regT0));
</span><del>-                if (isUnsigned) {
</del><ins>+                if (isUnsigned)
</ins><span class="cx">                     urshift32(regT2, regT0);
</span><del>-                    failures.append(branch32(LessThan, regT0, TrustedImm32(0)));
-                } else
</del><ins>+                else
</ins><span class="cx">                     rshift32(regT2, regT0);
</span><span class="cx">                 move(TrustedImm32(JSValue::Int32Tag), regT1);
</span><span class="cx">                 emitStoreInt32(dst, regT0, false);
</span><span class="lines">@@ -280,8 +274,6 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         linkSlowCase(iter); // int32 check - op2 is not an int
</span><del>-        if (isUnsigned)
-            linkSlowCase(iter); // Can't represent unsigned result as an immediate
</del><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     JITSlowPathCall slowPathCall(this, currentInstruction, isUnsigned ? slow_path_urshift : slow_path_rshift);
</span><span class="lines">@@ -312,6 +304,27 @@
</span><span class="cx">     emitRightShiftSlowCase(currentInstruction, iter, true);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void JIT::emit_op_unsigned(Instruction* currentInstruction)
+{
+    int result = currentInstruction[1].u.operand;
+    int op1 = currentInstruction[2].u.operand;
+    
+    emitLoad(op1, regT1, regT0);
+    
+    addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
+    addSlowCase(branch32(LessThan, regT0, TrustedImm32(0)));
+    emitStoreInt32(result, regT0, result == op1);
+}
+
+void JIT::emitSlow_op_unsigned(Instruction* currentInstruction, Vector&lt;SlowCaseEntry&gt;::iterator&amp; iter)
+{
+    linkSlowCase(iter);
+    linkSlowCase(iter);
+    
+    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_unsigned);
+    slowPathCall.call();
+}
+
</ins><span class="cx"> // BitAnd (&amp;)
</span><span class="cx"> 
</span><span class="cx"> void JIT::emit_op_bitand(Instruction* currentInstruction)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLowLevelInterpreter32_64asm"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm (160586 => 160587)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm        2013-12-14 06:25:17 UTC (rev 160586)
+++ trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm        2013-12-14 06:33:42 UTC (rev 160587)
</span><span class="lines">@@ -1044,7 +1044,7 @@
</span><span class="cx">     bineq t3, Int32Tag, .slow
</span><span class="cx">     bineq t2, Int32Tag, .slow
</span><span class="cx">     loadi 4[PC], t2
</span><del>-    operation(t1, t0, .slow)
</del><ins>+    operation(t1, t0)
</ins><span class="cx">     storei t3, TagOffset[cfr, t2, 8]
</span><span class="cx">     storei t0, PayloadOffset[cfr, t2, 8]
</span><span class="cx">     dispatch(advance)
</span><span class="lines">@@ -1057,7 +1057,7 @@
</span><span class="cx"> _llint_op_lshift:
</span><span class="cx">     traceExecution()
</span><span class="cx">     bitOp(
</span><del>-        macro (left, right, slow) lshifti left, right end,
</del><ins>+        macro (left, right) lshifti left, right end,
</ins><span class="cx">         _slow_path_lshift,
</span><span class="cx">         4)
</span><span class="cx"> 
</span><span class="lines">@@ -1065,7 +1065,7 @@
</span><span class="cx"> _llint_op_rshift:
</span><span class="cx">     traceExecution()
</span><span class="cx">     bitOp(
</span><del>-        macro (left, right, slow) rshifti left, right end,
</del><ins>+        macro (left, right) rshifti left, right end,
</ins><span class="cx">         _slow_path_rshift,
</span><span class="cx">         4)
</span><span class="cx"> 
</span><span class="lines">@@ -1073,18 +1073,29 @@
</span><span class="cx"> _llint_op_urshift:
</span><span class="cx">     traceExecution()
</span><span class="cx">     bitOp(
</span><del>-        macro (left, right, slow)
-            urshifti left, right
-            bilt right, 0, slow
-        end,
</del><ins>+        macro (left, right) urshifti left, right end,
</ins><span class="cx">         _slow_path_urshift,
</span><span class="cx">         4)
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+_llint_op_unsigned:
+    traceExecution()
+    loadi 4[PC], t0
+    loadi 8[PC], t1
+    loadConstantOrVariablePayload(t1, Int32Tag, t2, .opUnsignedSlow)
+    bilt t2, 0, .opUnsignedSlow
+    storei t2, PayloadOffset[cfr, t0, 8]
+    storei Int32Tag, TagOffset[cfr, t0, 8]
+    dispatch(3)
+.opUnsignedSlow:
+    callSlowPath(_slow_path_unsigned)
+    dispatch(3)
+
+
</ins><span class="cx"> _llint_op_bitand:
</span><span class="cx">     traceExecution()
</span><span class="cx">     bitOp(
</span><del>-        macro (left, right, slow) andi left, right end,
</del><ins>+        macro (left, right) andi left, right end,
</ins><span class="cx">         _slow_path_bitand,
</span><span class="cx">         5)
</span><span class="cx"> 
</span><span class="lines">@@ -1092,7 +1103,7 @@
</span><span class="cx"> _llint_op_bitxor:
</span><span class="cx">     traceExecution()
</span><span class="cx">     bitOp(
</span><del>-        macro (left, right, slow) xori left, right end,
</del><ins>+        macro (left, right) xori left, right end,
</ins><span class="cx">         _slow_path_bitxor,
</span><span class="cx">         5)
</span><span class="cx"> 
</span><span class="lines">@@ -1100,7 +1111,7 @@
</span><span class="cx"> _llint_op_bitor:
</span><span class="cx">     traceExecution()
</span><span class="cx">     bitOp(
</span><del>-        macro (left, right, slow) ori left, right end,
</del><ins>+        macro (left, right) ori left, right end,
</ins><span class="cx">         _slow_path_bitor,
</span><span class="cx">         5)
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLowLevelInterpreter64asm"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm (160586 => 160587)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm        2013-12-14 06:25:17 UTC (rev 160586)
+++ trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm        2013-12-14 06:33:42 UTC (rev 160587)
</span><span class="lines">@@ -861,7 +861,7 @@
</span><span class="cx">     loadConstantOrVariable(t2, t0)
</span><span class="cx">     bqb t0, tagTypeNumber, .slow
</span><span class="cx">     bqb t1, tagTypeNumber, .slow
</span><del>-    operation(t1, t0, .slow)
</del><ins>+    operation(t1, t0)
</ins><span class="cx">     orq tagTypeNumber, t0
</span><span class="cx">     storeq t0, [cfr, t3, 8]
</span><span class="cx">     dispatch(advance)
</span><span class="lines">@@ -874,7 +874,7 @@
</span><span class="cx"> _llint_op_lshift:
</span><span class="cx">     traceExecution()
</span><span class="cx">     bitOp(
</span><del>-        macro (left, right, slow) lshifti left, right end,
</del><ins>+        macro (left, right) lshifti left, right end,
</ins><span class="cx">         _slow_path_lshift,
</span><span class="cx">         4)
</span><span class="cx"> 
</span><span class="lines">@@ -882,7 +882,7 @@
</span><span class="cx"> _llint_op_rshift:
</span><span class="cx">     traceExecution()
</span><span class="cx">     bitOp(
</span><del>-        macro (left, right, slow) rshifti left, right end,
</del><ins>+        macro (left, right) rshifti left, right end,
</ins><span class="cx">         _slow_path_rshift,
</span><span class="cx">         4)
</span><span class="cx"> 
</span><span class="lines">@@ -890,18 +890,28 @@
</span><span class="cx"> _llint_op_urshift:
</span><span class="cx">     traceExecution()
</span><span class="cx">     bitOp(
</span><del>-        macro (left, right, slow)
-            urshifti left, right
-            bilt right, 0, slow
-        end,
</del><ins>+        macro (left, right) urshifti left, right end,
</ins><span class="cx">         _slow_path_urshift,
</span><span class="cx">         4)
</span><span class="cx"> 
</span><span class="cx"> 
</span><ins>+_llint_op_unsigned:
+    traceExecution()
+    loadisFromInstruction(1, t0)
+    loadisFromInstruction(2, t1)
+    loadConstantOrVariable(t1, t2)
+    bilt t2, 0, .opUnsignedSlow
+    storeq t2, [cfr, t0, 8]
+    dispatch(3)
+.opUnsignedSlow:
+    callSlowPath(_slow_path_unsigned)
+    dispatch(3)
+
+
</ins><span class="cx"> _llint_op_bitand:
</span><span class="cx">     traceExecution()
</span><span class="cx">     bitOp(
</span><del>-        macro (left, right, slow) andi left, right end,
</del><ins>+        macro (left, right) andi left, right end,
</ins><span class="cx">         _slow_path_bitand,
</span><span class="cx">         5)
</span><span class="cx"> 
</span><span class="lines">@@ -909,7 +919,7 @@
</span><span class="cx"> _llint_op_bitxor:
</span><span class="cx">     traceExecution()
</span><span class="cx">     bitOp(
</span><del>-        macro (left, right, slow) xori left, right end,
</del><ins>+        macro (left, right) xori left, right end,
</ins><span class="cx">         _slow_path_bitxor,
</span><span class="cx">         5)
</span><span class="cx"> 
</span><span class="lines">@@ -917,7 +927,7 @@
</span><span class="cx"> _llint_op_bitor:
</span><span class="cx">     traceExecution()
</span><span class="cx">     bitOp(
</span><del>-        macro (left, right, slow) ori left, right end,
</del><ins>+        macro (left, right) ori left, right end,
</ins><span class="cx">         _slow_path_bitor,
</span><span class="cx">         5)
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeCommonSlowPathscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp (160586 => 160587)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp        2013-12-14 06:25:17 UTC (rev 160586)
+++ trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp        2013-12-14 06:33:42 UTC (rev 160587)
</span><span class="lines">@@ -417,9 +417,16 @@
</span><span class="cx">     BEGIN();
</span><span class="cx">     uint32_t a = OP_C(2).jsValue().toUInt32(exec);
</span><span class="cx">     uint32_t b = OP_C(3).jsValue().toUInt32(exec);
</span><del>-    RETURN(jsNumber(a &gt;&gt; (b &amp; 31)));
</del><ins>+    RETURN(jsNumber(static_cast&lt;int32_t&gt;(a &gt;&gt; (b &amp; 31))));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+SLOW_PATH_DECL(slow_path_unsigned)
+{
+    BEGIN();
+    uint32_t a = OP_C(2).jsValue().toUInt32(exec);
+    RETURN(jsNumber(a));
+}
+
</ins><span class="cx"> SLOW_PATH_DECL(slow_path_bitand)
</span><span class="cx"> {
</span><span class="cx">     BEGIN();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeCommonSlowPathsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.h (160586 => 160587)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.h        2013-12-14 06:25:17 UTC (rev 160586)
+++ trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.h        2013-12-14 06:33:42 UTC (rev 160587)
</span><span class="lines">@@ -188,6 +188,7 @@
</span><span class="cx"> SLOW_PATH_HIDDEN_DECL(slow_path_lshift);
</span><span class="cx"> SLOW_PATH_HIDDEN_DECL(slow_path_rshift);
</span><span class="cx"> SLOW_PATH_HIDDEN_DECL(slow_path_urshift);
</span><ins>+SLOW_PATH_HIDDEN_DECL(slow_path_unsigned);
</ins><span class="cx"> SLOW_PATH_HIDDEN_DECL(slow_path_bitand);
</span><span class="cx"> SLOW_PATH_HIDDEN_DECL(slow_path_bitor);
</span><span class="cx"> SLOW_PATH_HIDDEN_DECL(slow_path_bitxor);
</span></span></pre>
</div>
</div>

</body>
</html>