<!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>[165842] 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/165842">165842</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2014-03-18 13:53:07 -0700 (Tue, 18 Mar 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>Add CompareStrictEq(StringIdent:, NotStringVar:) and CompareStrictEq(String:, Untyped:)
https://bugs.webkit.org/show_bug.cgi?id=130300

Reviewed by Mark Hahnenberg.
        
We can quickly strictly compare StringIdent's to NotStringVar's and String's to Untyped's.
This makes the DFG aware of this.
        
Also adds StringIdent-to-StringIdent and StringIdent-to-NotStringVar strict comparisons to
the FTL. Also adds StringIdent-to-StringIdent non-strict comparisons to the FTL.
        
This also gives the DFG some abstractions for checking something is a cell or is other.
This made this patch easier to write and also simplified a bunch of other stuff.
        
1% speed-up on Octane.

* assembler/AbstractMacroAssembler.h:
(JSC::AbstractMacroAssembler::JumpList::JumpList):
* bytecode/SpeculatedType.h:
(JSC::isNotStringVarSpeculation):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* dfg/DFGNode.h:
(JSC::DFG::Node::childFor):
(JSC::DFG::Node::shouldSpeculateNotStringVar):
* dfg/DFGSafeToExecute.h:
(JSC::DFG::SafeToExecuteEdge::operator()):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileIn):
(JSC::DFG::SpeculativeJIT::compileValueToInt32):
(JSC::DFG::SpeculativeJIT::compileInstanceOfForObject):
(JSC::DFG::SpeculativeJIT::compileInstanceOf):
(JSC::DFG::SpeculativeJIT::compileStrictEq):
(JSC::DFG::SpeculativeJIT::compileBooleanCompare):
(JSC::DFG::SpeculativeJIT::compileStringEquality):
(JSC::DFG::SpeculativeJIT::compileStringToUntypedEquality):
(JSC::DFG::SpeculativeJIT::compileStringIdentEquality):
(JSC::DFG::SpeculativeJIT::compileStringIdentToNotStringVarEquality):
(JSC::DFG::SpeculativeJIT::compileStringZeroLength):
(JSC::DFG::SpeculativeJIT::speculateObjectOrOther):
(JSC::DFG::SpeculativeJIT::speculateString):
(JSC::DFG::SpeculativeJIT::speculateStringIdentAndLoadStorage):
(JSC::DFG::SpeculativeJIT::speculateNotStringVar):
(JSC::DFG::SpeculativeJIT::speculateNotCell):
(JSC::DFG::SpeculativeJIT::speculateOther):
(JSC::DFG::SpeculativeJIT::speculate):
(JSC::DFG::SpeculativeJIT::emitSwitchChar):
(JSC::DFG::SpeculativeJIT::emitSwitchString):
* dfg/DFGSpeculativeJIT.h:
(JSC::DFG::SpeculativeJIT::blessedBooleanResult):
(JSC::DFG::SpeculativeJIT::unblessedBooleanResult):
(JSC::DFG::SpeculativeJIT::booleanResult):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::nonSpeculativeNonPeepholeCompareNull):
(JSC::DFG::SpeculativeJIT::nonSpeculativePeepholeBranchNull):
(JSC::DFG::SpeculativeJIT::emitCall):
(JSC::DFG::SpeculativeJIT::fillSpeculateCell):
(JSC::DFG::SpeculativeJIT::compileObjectToObjectOrOtherEquality):
(JSC::DFG::SpeculativeJIT::compilePeepHoleObjectToObjectOrOtherEquality):
(JSC::DFG::SpeculativeJIT::compileObjectOrOtherLogicalNot):
(JSC::DFG::SpeculativeJIT::emitObjectOrOtherBranch):
(JSC::DFG::SpeculativeJIT::compile):
(JSC::DFG::branchIsCell):
(JSC::DFG::branchNotCell):
(JSC::DFG::SpeculativeJIT::branchIsOther):
(JSC::DFG::SpeculativeJIT::branchNotOther):
(JSC::DFG::SpeculativeJIT::moveTrueTo):
(JSC::DFG::SpeculativeJIT::moveFalseTo):
(JSC::DFG::SpeculativeJIT::blessBoolean):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::nonSpeculativeNonPeepholeCompareNull):
(JSC::DFG::SpeculativeJIT::nonSpeculativePeepholeBranchNull):
(JSC::DFG::SpeculativeJIT::fillSpeculateCell):
(JSC::DFG::SpeculativeJIT::compileObjectToObjectOrOtherEquality):
(JSC::DFG::SpeculativeJIT::compilePeepHoleObjectToObjectOrOtherEquality):
(JSC::DFG::SpeculativeJIT::compileObjectOrOtherLogicalNot):
(JSC::DFG::SpeculativeJIT::emitObjectOrOtherBranch):
(JSC::DFG::SpeculativeJIT::compile):
(JSC::DFG::SpeculativeJIT::writeBarrier):
(JSC::DFG::SpeculativeJIT::branchIsCell):
(JSC::DFG::SpeculativeJIT::branchNotCell):
(JSC::DFG::SpeculativeJIT::branchIsOther):
(JSC::DFG::SpeculativeJIT::branchNotOther):
(JSC::DFG::SpeculativeJIT::moveTrueTo):
(JSC::DFG::SpeculativeJIT::moveFalseTo):
(JSC::DFG::SpeculativeJIT::blessBoolean):
* dfg/DFGUseKind.cpp:
(WTF::printInternal):
* dfg/DFGUseKind.h:
(JSC::DFG::typeFilterFor):
* ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::LowerDFGToLLVM::compileCompareStrictEq):
(JSC::FTL::LowerDFGToLLVM::lowString):
(JSC::FTL::LowerDFGToLLVM::lowStringIdent):
(JSC::FTL::LowerDFGToLLVM::speculate):
(JSC::FTL::LowerDFGToLLVM::speculateString):
(JSC::FTL::LowerDFGToLLVM::speculateStringIdent):
(JSC::FTL::LowerDFGToLLVM::speculateNotStringVar):
* runtime/JSCJSValue.h:
* tests/stress/string-ident-to-not-string-var-equality.js: Added.
(foo):
(bar):
(test):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreassemblerAbstractMacroAssemblerh">trunk/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeSpeculatedTypeh">trunk/Source/JavaScriptCore/bytecode/SpeculatedType.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGFixupPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGNodeh">trunk/Source/JavaScriptCore/dfg/DFGNode.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSafeToExecuteh">trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h</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="#trunkSourceJavaScriptCoredfgDFGUseKindcpp">trunk/Source/JavaScriptCore/dfg/DFGUseKind.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGUseKindh">trunk/Source/JavaScriptCore/dfg/DFGUseKind.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLCapabilitiescpp">trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLLowerDFGToLLVMcpp">trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSCJSValueh">trunk/Source/JavaScriptCore/runtime/JSCJSValue.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoretestsstressstringidenttonotstringvarequalityjs">trunk/Source/JavaScriptCore/tests/stress/string-ident-to-not-string-var-equality.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (165841 => 165842)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2014-03-18 20:45:27 UTC (rev 165841)
+++ trunk/Source/JavaScriptCore/ChangeLog        2014-03-18 20:53:07 UTC (rev 165842)
</span><span class="lines">@@ -1,3 +1,111 @@
</span><ins>+2014-03-17  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        Add CompareStrictEq(StringIdent:, NotStringVar:) and CompareStrictEq(String:, Untyped:)
+        https://bugs.webkit.org/show_bug.cgi?id=130300
+
+        Reviewed by Mark Hahnenberg.
+        
+        We can quickly strictly compare StringIdent's to NotStringVar's and String's to Untyped's.
+        This makes the DFG aware of this.
+        
+        Also adds StringIdent-to-StringIdent and StringIdent-to-NotStringVar strict comparisons to
+        the FTL. Also adds StringIdent-to-StringIdent non-strict comparisons to the FTL.
+        
+        This also gives the DFG some abstractions for checking something is a cell or is other.
+        This made this patch easier to write and also simplified a bunch of other stuff.
+        
+        1% speed-up on Octane.
+
+        * assembler/AbstractMacroAssembler.h:
+        (JSC::AbstractMacroAssembler::JumpList::JumpList):
+        * bytecode/SpeculatedType.h:
+        (JSC::isNotStringVarSpeculation):
+        * dfg/DFGFixupPhase.cpp:
+        (JSC::DFG::FixupPhase::fixupNode):
+        * dfg/DFGNode.h:
+        (JSC::DFG::Node::childFor):
+        (JSC::DFG::Node::shouldSpeculateNotStringVar):
+        * dfg/DFGSafeToExecute.h:
+        (JSC::DFG::SafeToExecuteEdge::operator()):
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compileIn):
+        (JSC::DFG::SpeculativeJIT::compileValueToInt32):
+        (JSC::DFG::SpeculativeJIT::compileInstanceOfForObject):
+        (JSC::DFG::SpeculativeJIT::compileInstanceOf):
+        (JSC::DFG::SpeculativeJIT::compileStrictEq):
+        (JSC::DFG::SpeculativeJIT::compileBooleanCompare):
+        (JSC::DFG::SpeculativeJIT::compileStringEquality):
+        (JSC::DFG::SpeculativeJIT::compileStringToUntypedEquality):
+        (JSC::DFG::SpeculativeJIT::compileStringIdentEquality):
+        (JSC::DFG::SpeculativeJIT::compileStringIdentToNotStringVarEquality):
+        (JSC::DFG::SpeculativeJIT::compileStringZeroLength):
+        (JSC::DFG::SpeculativeJIT::speculateObjectOrOther):
+        (JSC::DFG::SpeculativeJIT::speculateString):
+        (JSC::DFG::SpeculativeJIT::speculateStringIdentAndLoadStorage):
+        (JSC::DFG::SpeculativeJIT::speculateNotStringVar):
+        (JSC::DFG::SpeculativeJIT::speculateNotCell):
+        (JSC::DFG::SpeculativeJIT::speculateOther):
+        (JSC::DFG::SpeculativeJIT::speculate):
+        (JSC::DFG::SpeculativeJIT::emitSwitchChar):
+        (JSC::DFG::SpeculativeJIT::emitSwitchString):
+        * dfg/DFGSpeculativeJIT.h:
+        (JSC::DFG::SpeculativeJIT::blessedBooleanResult):
+        (JSC::DFG::SpeculativeJIT::unblessedBooleanResult):
+        (JSC::DFG::SpeculativeJIT::booleanResult):
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::nonSpeculativeNonPeepholeCompareNull):
+        (JSC::DFG::SpeculativeJIT::nonSpeculativePeepholeBranchNull):
+        (JSC::DFG::SpeculativeJIT::emitCall):
+        (JSC::DFG::SpeculativeJIT::fillSpeculateCell):
+        (JSC::DFG::SpeculativeJIT::compileObjectToObjectOrOtherEquality):
+        (JSC::DFG::SpeculativeJIT::compilePeepHoleObjectToObjectOrOtherEquality):
+        (JSC::DFG::SpeculativeJIT::compileObjectOrOtherLogicalNot):
+        (JSC::DFG::SpeculativeJIT::emitObjectOrOtherBranch):
+        (JSC::DFG::SpeculativeJIT::compile):
+        (JSC::DFG::branchIsCell):
+        (JSC::DFG::branchNotCell):
+        (JSC::DFG::SpeculativeJIT::branchIsOther):
+        (JSC::DFG::SpeculativeJIT::branchNotOther):
+        (JSC::DFG::SpeculativeJIT::moveTrueTo):
+        (JSC::DFG::SpeculativeJIT::moveFalseTo):
+        (JSC::DFG::SpeculativeJIT::blessBoolean):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::nonSpeculativeNonPeepholeCompareNull):
+        (JSC::DFG::SpeculativeJIT::nonSpeculativePeepholeBranchNull):
+        (JSC::DFG::SpeculativeJIT::fillSpeculateCell):
+        (JSC::DFG::SpeculativeJIT::compileObjectToObjectOrOtherEquality):
+        (JSC::DFG::SpeculativeJIT::compilePeepHoleObjectToObjectOrOtherEquality):
+        (JSC::DFG::SpeculativeJIT::compileObjectOrOtherLogicalNot):
+        (JSC::DFG::SpeculativeJIT::emitObjectOrOtherBranch):
+        (JSC::DFG::SpeculativeJIT::compile):
+        (JSC::DFG::SpeculativeJIT::writeBarrier):
+        (JSC::DFG::SpeculativeJIT::branchIsCell):
+        (JSC::DFG::SpeculativeJIT::branchNotCell):
+        (JSC::DFG::SpeculativeJIT::branchIsOther):
+        (JSC::DFG::SpeculativeJIT::branchNotOther):
+        (JSC::DFG::SpeculativeJIT::moveTrueTo):
+        (JSC::DFG::SpeculativeJIT::moveFalseTo):
+        (JSC::DFG::SpeculativeJIT::blessBoolean):
+        * dfg/DFGUseKind.cpp:
+        (WTF::printInternal):
+        * dfg/DFGUseKind.h:
+        (JSC::DFG::typeFilterFor):
+        * ftl/FTLCapabilities.cpp:
+        (JSC::FTL::canCompile):
+        * ftl/FTLLowerDFGToLLVM.cpp:
+        (JSC::FTL::LowerDFGToLLVM::compileCompareStrictEq):
+        (JSC::FTL::LowerDFGToLLVM::lowString):
+        (JSC::FTL::LowerDFGToLLVM::lowStringIdent):
+        (JSC::FTL::LowerDFGToLLVM::speculate):
+        (JSC::FTL::LowerDFGToLLVM::speculateString):
+        (JSC::FTL::LowerDFGToLLVM::speculateStringIdent):
+        (JSC::FTL::LowerDFGToLLVM::speculateNotStringVar):
+        * runtime/JSCJSValue.h:
+        * tests/stress/string-ident-to-not-string-var-equality.js: Added.
+        (foo):
+        (bar):
+        (test):
+
</ins><span class="cx"> 2014-03-18  Joseph Pecoraro  &lt;pecoraro@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Add Copyright to framework.sb
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreassemblerAbstractMacroAssemblerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h (165841 => 165842)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h        2014-03-18 20:45:27 UTC (rev 165841)
+++ trunk/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h        2014-03-18 20:53:07 UTC (rev 165842)
</span><span class="lines">@@ -693,7 +693,8 @@
</span><span class="cx">         
</span><span class="cx">         JumpList(Jump jump)
</span><span class="cx">         {
</span><del>-            append(jump);
</del><ins>+            if (jump.isSet())
+                append(jump);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         void link(AbstractMacroAssembler&lt;AssemblerType&gt;* masm)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeSpeculatedTypeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/SpeculatedType.h (165841 => 165842)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/SpeculatedType.h        2014-03-18 20:45:27 UTC (rev 165841)
+++ trunk/Source/JavaScriptCore/bytecode/SpeculatedType.h        2014-03-18 20:53:07 UTC (rev 165842)
</span><span class="lines">@@ -120,6 +120,11 @@
</span><span class="cx">     return value == SpecStringIdent;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+inline bool isNotStringVarSpeculation(SpeculatedType value)
+{
+    return !(value &amp; SpecStringVar);
+}
+
</ins><span class="cx"> inline bool isStringSpeculation(SpeculatedType value)
</span><span class="cx"> {
</span><span class="cx">     return !!value &amp;&amp; (value &amp; SpecString) == value;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGFixupPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp (165841 => 165842)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2014-03-18 20:45:27 UTC (rev 165841)
+++ trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2014-03-18 20:53:07 UTC (rev 165842)
</span><span class="lines">@@ -436,6 +436,26 @@
</span><span class="cx">                 fixEdge&lt;MiscUse&gt;(node-&gt;child2());
</span><span class="cx">                 break;
</span><span class="cx">             }
</span><ins>+            if (node-&gt;child1()-&gt;shouldSpeculateStringIdent()
+                &amp;&amp; node-&gt;child2()-&gt;shouldSpeculateNotStringVar()) {
+                fixEdge&lt;StringIdentUse&gt;(node-&gt;child1());
+                fixEdge&lt;NotStringVarUse&gt;(node-&gt;child2());
+                break;
+            }
+            if (node-&gt;child2()-&gt;shouldSpeculateStringIdent()
+                &amp;&amp; node-&gt;child1()-&gt;shouldSpeculateNotStringVar()) {
+                fixEdge&lt;StringIdentUse&gt;(node-&gt;child2());
+                fixEdge&lt;NotStringVarUse&gt;(node-&gt;child1());
+                break;
+            }
+            if (node-&gt;child1()-&gt;shouldSpeculateString()) {
+                fixEdge&lt;StringUse&gt;(node-&gt;child1());
+                break;
+            }
+            if (node-&gt;child2()-&gt;shouldSpeculateString()) {
+                fixEdge&lt;StringUse&gt;(node-&gt;child2());
+                break;
+            }
</ins><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGNodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGNode.h (165841 => 165842)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNode.h        2014-03-18 20:45:27 UTC (rev 165841)
+++ trunk/Source/JavaScriptCore/dfg/DFGNode.h        2014-03-18 20:53:07 UTC (rev 165842)
</span><span class="lines">@@ -1340,6 +1340,17 @@
</span><span class="cx">         return isBinaryUseKind(useKind, useKind);
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+    Edge childFor(UseKind useKind)
+    {
+        if (child1().useKind() == useKind)
+            return child1();
+        if (child2().useKind() == useKind)
+            return child2();
+        if (child3().useKind() == useKind)
+            return child3();
+        return Edge();
+    }
+    
</ins><span class="cx">     SpeculatedType prediction()
</span><span class="cx">     {
</span><span class="cx">         return m_prediction;
</span><span class="lines">@@ -1419,6 +1430,11 @@
</span><span class="cx">     {
</span><span class="cx">         return isStringIdentSpeculation(prediction());
</span><span class="cx">     }
</span><ins>+    
+    bool shouldSpeculateNotStringVar()
+    {
+        return isNotStringVarSpeculation(prediction());
+    }
</ins><span class="cx">  
</span><span class="cx">     bool shouldSpeculateString()
</span><span class="cx">     {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSafeToExecuteh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h (165841 => 165842)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h        2014-03-18 20:45:27 UTC (rev 165841)
+++ trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h        2014-03-18 20:53:07 UTC (rev 165842)
</span><span class="lines">@@ -57,6 +57,7 @@
</span><span class="cx">         case StringUse:
</span><span class="cx">         case StringObjectUse:
</span><span class="cx">         case StringOrStringObjectUse:
</span><ins>+        case NotStringVarUse:
</ins><span class="cx">         case NotCellUse:
</span><span class="cx">         case OtherUse:
</span><span class="cx">         case MiscUse:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp (165841 => 165842)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2014-03-18 20:45:27 UTC (rev 165841)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2014-03-18 20:53:07 UTC (rev 165842)
</span><span class="lines">@@ -886,13 +886,8 @@
</span><span class="cx">             addSlowPathGenerator(slowPath.release());
</span><span class="cx">                 
</span><span class="cx">             base.use();
</span><del>-                
-#if USE(JSVALUE64)
-            jsValueResult(
-                resultGPR, node, DataFormatJSBoolean, UseChildrenCalledExplicitly);
-#else
-            booleanResult(resultGPR, node, UseChildrenCalledExplicitly);
-#endif
</del><ins>+            
+            blessedBooleanResult(resultGPR, node, UseChildrenCalledExplicitly);
</ins><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="lines">@@ -910,11 +905,7 @@
</span><span class="cx">     callOperation(
</span><span class="cx">         operationGenericIn, extractResult(JSValueRegs::payloadOnly(resultGPR)),
</span><span class="cx">         baseGPR, regs);
</span><del>-#if USE(JSVALUE64)
-    jsValueResult(resultGPR, node, DataFormatJSBoolean, UseChildrenCalledExplicitly);
-#else
-    booleanResult(resultGPR, node, UseChildrenCalledExplicitly);
-#endif
</del><ins>+    blessedBooleanResult(resultGPR, node, UseChildrenCalledExplicitly);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool SpeculativeJIT::nonSpeculativeCompare(Node* node, MacroAssembler::RelationalCondition cond, S_JITOperation_EJJ helperFunction)
</span><span class="lines">@@ -1939,9 +1930,7 @@
</span><span class="cx">                 JITCompiler::Jump isNumber = m_jit.branchTest64(MacroAssembler::NonZero, gpr, GPRInfo::tagTypeNumberRegister);
</span><span class="cx">                 
</span><span class="cx">                 DFG_TYPE_CHECK(
</span><del>-                    JSValueRegs(gpr), node-&gt;child1(), ~SpecCell,
-                    m_jit.branchTest64(
-                        JITCompiler::Zero, gpr, GPRInfo::tagMaskRegister));
</del><ins>+                    JSValueRegs(gpr), node-&gt;child1(), ~SpecCell, branchIsCell(JSValueRegs(gpr)));
</ins><span class="cx">                 
</span><span class="cx">                 // It's not a cell: so true turns into 1 and all else turns into 0.
</span><span class="cx">                 m_jit.compare64(JITCompiler::Equal, gpr, TrustedImm32(ValueTrue), resultGpr);
</span><span class="lines">@@ -1988,7 +1977,7 @@
</span><span class="cx"> 
</span><span class="cx">                 if (node-&gt;child1().useKind() == NumberUse) {
</span><span class="cx">                     DFG_TYPE_CHECK(
</span><del>-                        JSValueRegs(tagGPR, payloadGPR), node-&gt;child1(), SpecFullNumber,
</del><ins>+                        op1.jsValueRegs(), node-&gt;child1(), SpecFullNumber,
</ins><span class="cx">                         m_jit.branch32(
</span><span class="cx">                             MacroAssembler::AboveOrEqual, tagGPR,
</span><span class="cx">                             TrustedImm32(JSValue::LowestTag)));
</span><span class="lines">@@ -1996,9 +1985,8 @@
</span><span class="cx">                     JITCompiler::Jump isNumber = m_jit.branch32(MacroAssembler::Below, tagGPR, TrustedImm32(JSValue::LowestTag));
</span><span class="cx">                     
</span><span class="cx">                     DFG_TYPE_CHECK(
</span><del>-                        JSValueRegs(tagGPR, payloadGPR), node-&gt;child1(), ~SpecCell,
-                        m_jit.branch32(
-                            JITCompiler::Equal, tagGPR, TrustedImm32(JSValue::CellTag)));
</del><ins>+                        op1.jsValueRegs(), node-&gt;child1(), ~SpecCell,
+                        branchIsCell(op1.jsValueRegs()));
</ins><span class="cx">                     
</span><span class="cx">                     // It's not a cell: so true turns into 1 and all else turns into 0.
</span><span class="cx">                     JITCompiler::Jump isBoolean = m_jit.branch32(JITCompiler::Equal, tagGPR, TrustedImm32(JSValue::BooleanTag));
</span><span class="lines">@@ -2542,14 +2530,12 @@
</span><span class="cx">     // Walk up the prototype chain of the value (in scratchReg), comparing to prototypeReg.
</span><span class="cx">     MacroAssembler::Label loop(&amp;m_jit);
</span><span class="cx">     m_jit.emitLoadStructure(scratchReg, scratchReg, scratch2Reg);
</span><ins>+    m_jit.loadPtr(MacroAssembler::Address(scratchReg, Structure::prototypeOffset() + CellPayloadOffset), scratchReg);
+    MacroAssembler::Jump isInstance = m_jit.branchPtr(MacroAssembler::Equal, scratchReg, prototypeReg);
</ins><span class="cx"> #if USE(JSVALUE64)
</span><del>-    m_jit.load64(MacroAssembler::Address(scratchReg, Structure::prototypeOffset()), scratchReg);
-    MacroAssembler::Jump isInstance = m_jit.branch64(MacroAssembler::Equal, scratchReg, prototypeReg);
-    m_jit.branchTest64(MacroAssembler::Zero, scratchReg, GPRInfo::tagMaskRegister).linkTo(loop, &amp;m_jit);
</del><ins>+    branchIsCell(JSValueRegs(scratchReg)).linkTo(loop, &amp;m_jit);
</ins><span class="cx"> #else
</span><del>-    m_jit.load32(MacroAssembler::Address(scratchReg, Structure::prototypeOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), scratchReg);
-    MacroAssembler::Jump isInstance = m_jit.branchPtr(MacroAssembler::Equal, scratchReg, prototypeReg);
-    m_jit.branchTest32(MacroAssembler::NonZero, scratchReg).linkTo(loop, &amp;m_jit);
</del><ins>+    m_jit.branchTestPtr(MacroAssembler::NonZero, scratchReg).linkTo(loop, &amp;m_jit);
</ins><span class="cx"> #endif
</span><span class="cx">     
</span><span class="cx">     // No match - result is false.
</span><span class="lines">@@ -2586,16 +2572,9 @@
</span><span class="cx">         GPRReg scratchReg = scratch.gpr();
</span><span class="cx">         GPRReg scratch2Reg = scratch2.gpr();
</span><span class="cx">         
</span><del>-#if USE(JSVALUE64)
-        GPRReg valueReg = value.gpr();
-        MacroAssembler::Jump isCell = m_jit.branchTest64(MacroAssembler::Zero, valueReg, GPRInfo::tagMaskRegister);
-        m_jit.move(MacroAssembler::TrustedImm64(JSValue::encode(jsBoolean(false))), scratchReg);
-#else
-        GPRReg valueTagReg = value.tagGPR();
-        GPRReg valueReg = value.payloadGPR();
-        MacroAssembler::Jump isCell = m_jit.branch32(MacroAssembler::Equal, valueTagReg, TrustedImm32(JSValue::CellTag));
-        m_jit.move(MacroAssembler::TrustedImm32(0), scratchReg);
-#endif
</del><ins>+        MacroAssembler::Jump isCell = branchIsCell(value.jsValueRegs());
+        GPRReg valueReg = value.jsValueRegs().payloadGPR();
+        moveFalseTo(scratchReg);
</ins><span class="cx"> 
</span><span class="cx">         MacroAssembler::Jump done = m_jit.jump();
</span><span class="cx">         
</span><span class="lines">@@ -2605,11 +2584,7 @@
</span><span class="cx">         
</span><span class="cx">         done.link(&amp;m_jit);
</span><span class="cx"> 
</span><del>-#if USE(JSVALUE64)
-        jsValueResult(scratchReg, node, DataFormatJSBoolean);
-#else
-        booleanResult(scratchReg, node);
-#endif
</del><ins>+        blessedBooleanResult(scratchReg, node);
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="lines">@@ -2626,11 +2601,7 @@
</span><span class="cx">     
</span><span class="cx">     compileInstanceOfForObject(node, valueReg, prototypeReg, scratchReg, scratch2Reg);
</span><span class="cx"> 
</span><del>-#if USE(JSVALUE64)
-    jsValueResult(scratchReg, node, DataFormatJSBoolean);
-#else
-    booleanResult(scratchReg, node);
-#endif
</del><ins>+    blessedBooleanResult(scratchReg, node);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void SpeculativeJIT::compileAdd(Node* node)
</span><span class="lines">@@ -3731,6 +3702,26 @@
</span><span class="cx">         return false;
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+    if (node-&gt;isBinaryUseKind(StringIdentUse, NotStringVarUse)) {
+        compileStringIdentToNotStringVarEquality(node, node-&gt;child1(), node-&gt;child2());
+        return false;
+    }
+    
+    if (node-&gt;isBinaryUseKind(NotStringVarUse, StringIdentUse)) {
+        compileStringIdentToNotStringVarEquality(node, node-&gt;child2(), node-&gt;child1());
+        return false;
+    }
+    
+    if (node-&gt;isBinaryUseKind(StringUse, UntypedUse)) {
+        compileStringToUntypedEquality(node, node-&gt;child1(), node-&gt;child2());
+        return false;
+    }
+    
+    if (node-&gt;isBinaryUseKind(UntypedUse, StringUse)) {
+        compileStringToUntypedEquality(node, node-&gt;child2(), node-&gt;child1());
+        return false;
+    }
+    
</ins><span class="cx">     RELEASE_ASSERT(node-&gt;isBinaryUseKind(UntypedUse));
</span><span class="cx">     return nonSpeculativeStrictEq(node);
</span><span class="cx"> }
</span><span class="lines">@@ -3743,44 +3734,20 @@
</span><span class="cx">     
</span><span class="cx">     m_jit.compare32(condition, op1.gpr(), op2.gpr(), result.gpr());
</span><span class="cx">     
</span><del>-    // If we add a DataFormatBool, we should use it here.
-#if USE(JSVALUE32_64)
-    booleanResult(result.gpr(), node);
-#else
-    m_jit.or32(TrustedImm32(ValueFalse), result.gpr());
-    jsValueResult(result.gpr(), m_currentNode, DataFormatJSBoolean);
-#endif
</del><ins>+    unblessedBooleanResult(result.gpr(), node);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SpeculativeJIT::compileStringEquality(Node* node)
</del><ins>+void SpeculativeJIT::compileStringEquality(
+    Node* node, GPRReg leftGPR, GPRReg rightGPR, GPRReg lengthGPR, GPRReg leftTempGPR,
+    GPRReg rightTempGPR, GPRReg leftTemp2GPR, GPRReg rightTemp2GPR,
+    JITCompiler::JumpList fastTrue, JITCompiler::JumpList fastFalse)
</ins><span class="cx"> {
</span><del>-    SpeculateCellOperand left(this, node-&gt;child1());
-    SpeculateCellOperand right(this, node-&gt;child2());
-    GPRTemporary length(this);
-    GPRTemporary leftTemp(this);
-    GPRTemporary rightTemp(this);
-    GPRTemporary leftTemp2(this, Reuse, left);
-    GPRTemporary rightTemp2(this, Reuse, right);
-    
-    GPRReg leftGPR = left.gpr();
-    GPRReg rightGPR = right.gpr();
-    GPRReg lengthGPR = length.gpr();
-    GPRReg leftTempGPR = leftTemp.gpr();
-    GPRReg rightTempGPR = rightTemp.gpr();
-    GPRReg leftTemp2GPR = leftTemp2.gpr();
-    GPRReg rightTemp2GPR = rightTemp2.gpr();
-    
</del><span class="cx">     JITCompiler::JumpList trueCase;
</span><span class="cx">     JITCompiler::JumpList falseCase;
</span><span class="cx">     JITCompiler::JumpList slowCase;
</span><span class="cx">     
</span><del>-    speculateString(node-&gt;child1(), leftGPR);
-    
-    // It's safe to branch around the type check below, since proving that the values are
-    // equal does indeed prove that the right value is a string.
-    trueCase.append(m_jit.branchPtr(MacroAssembler::Equal, leftGPR, rightGPR));
-    
-    speculateString(node-&gt;child2(), rightGPR);
</del><ins>+    trueCase.append(fastTrue);
+    falseCase.append(fastFalse);
</ins><span class="cx"> 
</span><span class="cx">     m_jit.load32(MacroAssembler::Address(leftGPR, JSString::offsetOfLength()), lengthGPR);
</span><span class="cx">     
</span><span class="lines">@@ -3822,48 +3789,104 @@
</span><span class="cx">     m_jit.branchTest32(MacroAssembler::NonZero, lengthGPR).linkTo(loop, &amp;m_jit);
</span><span class="cx">     
</span><span class="cx">     trueCase.link(&amp;m_jit);
</span><del>-#if USE(JSVALUE64)
-    m_jit.move(TrustedImm64(ValueTrue), leftTempGPR);
-#else
-    m_jit.move(TrustedImm32(true), leftTempGPR);
-#endif
</del><ins>+    moveTrueTo(leftTempGPR);
</ins><span class="cx">     
</span><span class="cx">     JITCompiler::Jump done = m_jit.jump();
</span><span class="cx"> 
</span><span class="cx">     falseCase.link(&amp;m_jit);
</span><del>-#if USE(JSVALUE64)
-    m_jit.move(TrustedImm64(ValueFalse), leftTempGPR);
-#else
-    m_jit.move(TrustedImm32(false), leftTempGPR);
-#endif
</del><ins>+    moveFalseTo(leftTempGPR);
</ins><span class="cx">     
</span><span class="cx">     done.link(&amp;m_jit);
</span><span class="cx">     addSlowPathGenerator(
</span><span class="cx">         slowPathCall(
</span><span class="cx">             slowCase, this, operationCompareStringEq, leftTempGPR, leftGPR, rightGPR));
</span><span class="cx">     
</span><del>-#if USE(JSVALUE64)
-    jsValueResult(leftTempGPR, node, DataFormatJSBoolean);
-#else
-    booleanResult(leftTempGPR, node);
-#endif
</del><ins>+    blessedBooleanResult(leftTempGPR, node);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SpeculativeJIT::compileStringIdentEquality(Node* node)
</del><ins>+void SpeculativeJIT::compileStringEquality(Node* node)
</ins><span class="cx"> {
</span><span class="cx">     SpeculateCellOperand left(this, node-&gt;child1());
</span><span class="cx">     SpeculateCellOperand right(this, node-&gt;child2());
</span><ins>+    GPRTemporary length(this);
</ins><span class="cx">     GPRTemporary leftTemp(this);
</span><span class="cx">     GPRTemporary rightTemp(this);
</span><ins>+    GPRTemporary leftTemp2(this, Reuse, left);
+    GPRTemporary rightTemp2(this, Reuse, right);
</ins><span class="cx">     
</span><span class="cx">     GPRReg leftGPR = left.gpr();
</span><span class="cx">     GPRReg rightGPR = right.gpr();
</span><ins>+    GPRReg lengthGPR = length.gpr();
</ins><span class="cx">     GPRReg leftTempGPR = leftTemp.gpr();
</span><span class="cx">     GPRReg rightTempGPR = rightTemp.gpr();
</span><ins>+    GPRReg leftTemp2GPR = leftTemp2.gpr();
+    GPRReg rightTemp2GPR = rightTemp2.gpr();
+    
+    speculateString(node-&gt;child1(), leftGPR);
+    
+    // It's safe to branch around the type check below, since proving that the values are
+    // equal does indeed prove that the right value is a string.
+    JITCompiler::Jump fastTrue = m_jit.branchPtr(MacroAssembler::Equal, leftGPR, rightGPR);
+    
+    speculateString(node-&gt;child2(), rightGPR);
+    
+    compileStringEquality(
+        node, leftGPR, rightGPR, lengthGPR, leftTempGPR, rightTempGPR, leftTemp2GPR,
+        rightTemp2GPR, fastTrue, JITCompiler::Jump());
+}
</ins><span class="cx"> 
</span><del>-    JITCompiler::JumpList trueCase;
-    JITCompiler::JumpList falseCase;
</del><ins>+void SpeculativeJIT::compileStringToUntypedEquality(Node* node, Edge stringEdge, Edge untypedEdge)
+{
+    SpeculateCellOperand left(this, stringEdge);
+    JSValueOperand right(this, untypedEdge, ManualOperandSpeculation);
+    GPRTemporary length(this);
+    GPRTemporary leftTemp(this);
+    GPRTemporary rightTemp(this);
+    GPRTemporary leftTemp2(this, Reuse, left);
+    GPRTemporary rightTemp2(this);
</ins><span class="cx">     
</span><ins>+    GPRReg leftGPR = left.gpr();
+    JSValueRegs rightRegs = right.jsValueRegs();
+    GPRReg lengthGPR = length.gpr();
+    GPRReg leftTempGPR = leftTemp.gpr();
+    GPRReg rightTempGPR = rightTemp.gpr();
+    GPRReg leftTemp2GPR = leftTemp2.gpr();
+    GPRReg rightTemp2GPR = rightTemp2.gpr();
+    
+    speculateString(stringEdge, leftGPR);
+    
+    JITCompiler::JumpList fastTrue;
+    JITCompiler::JumpList fastFalse;
+    
+    fastFalse.append(branchNotCell(rightRegs));
+    
+    // It's safe to branch around the type check below, since proving that the values are
+    // equal does indeed prove that the right value is a string.
+    fastTrue.append(m_jit.branchPtr(
+        MacroAssembler::Equal, leftGPR, rightRegs.payloadGPR()));
+    
+    fastFalse.append(m_jit.branchStructurePtr(
+        MacroAssembler::NotEqual, 
+        MacroAssembler::Address(rightRegs.payloadGPR(), JSCell::structureIDOffset()), 
+        m_jit.vm()-&gt;stringStructure.get()));
+    
+    compileStringEquality(
+        node, leftGPR, rightRegs.payloadGPR(), lengthGPR, leftTempGPR, rightTempGPR, leftTemp2GPR,
+        rightTemp2GPR, fastTrue, fastFalse);
+}
+
+void SpeculativeJIT::compileStringIdentEquality(Node* node)
+{
+    SpeculateCellOperand left(this, node-&gt;child1());
+    SpeculateCellOperand right(this, node-&gt;child2());
+    GPRTemporary leftTemp(this);
+    GPRTemporary rightTemp(this);
+    
+    GPRReg leftGPR = left.gpr();
+    GPRReg rightGPR = right.gpr();
+    GPRReg leftTempGPR = leftTemp.gpr();
+    GPRReg rightTempGPR = rightTemp.gpr();
+
</ins><span class="cx">     speculateString(node-&gt;child1(), leftGPR);
</span><span class="cx">     speculateString(node-&gt;child2(), rightGPR);
</span><span class="cx">     
</span><span class="lines">@@ -3872,14 +3895,40 @@
</span><span class="cx">     
</span><span class="cx">     m_jit.comparePtr(MacroAssembler::Equal, leftTempGPR, rightTempGPR, leftTempGPR);
</span><span class="cx">     
</span><del>-#if USE(JSVALUE64)
-    m_jit.or32(TrustedImm32(ValueFalse), leftTempGPR);
-    jsValueResult(leftTempGPR, node, DataFormatJSBoolean);
-#else
-    booleanResult(leftTempGPR, node);
-#endif
</del><ins>+    unblessedBooleanResult(leftTempGPR, node);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void SpeculativeJIT::compileStringIdentToNotStringVarEquality(
+    Node* node, Edge stringEdge, Edge notStringVarEdge)
+{
+    SpeculateCellOperand left(this, stringEdge);
+    JSValueOperand right(this, notStringVarEdge, ManualOperandSpeculation);
+    GPRTemporary leftTemp(this);
+    GPRTemporary rightTemp(this);
+    GPRReg leftTempGPR = leftTemp.gpr();
+    GPRReg rightTempGPR = rightTemp.gpr();
+    GPRReg leftGPR = left.gpr();
+    JSValueRegs rightRegs = right.jsValueRegs();
+    
+    speculateString(stringEdge, leftGPR);
+    speculateStringIdentAndLoadStorage(stringEdge, leftGPR, leftTempGPR);
+
+    moveFalseTo(rightTempGPR);
+    JITCompiler::JumpList notString;
+    notString.append(branchNotCell(rightRegs));
+    notString.append(m_jit.branchStructurePtr(
+        MacroAssembler::NotEqual, 
+        MacroAssembler::Address(rightRegs.payloadGPR(), JSCell::structureIDOffset()), 
+        m_jit.vm()-&gt;stringStructure.get()));
+    
+    speculateStringIdentAndLoadStorage(notStringVarEdge, rightRegs.payloadGPR(), rightTempGPR);
+    
+    m_jit.comparePtr(MacroAssembler::Equal, leftTempGPR, rightTempGPR, rightTempGPR);
+    notString.link(&amp;m_jit);
+    
+    unblessedBooleanResult(rightTempGPR, node);
+}
+
</ins><span class="cx"> void SpeculativeJIT::compileStringZeroLength(Node* node)
</span><span class="cx"> {
</span><span class="cx">     SpeculateCellOperand str(this, node-&gt;child1());
</span><span class="lines">@@ -3894,12 +3943,7 @@
</span><span class="cx">     // Fetch the length field from the string object.
</span><span class="cx">     m_jit.test32(MacroAssembler::Zero, MacroAssembler::Address(strGPR, JSString::offsetOfLength()), MacroAssembler::TrustedImm32(-1), eqGPR);
</span><span class="cx"> 
</span><del>-#if USE(JSVALUE64)
-    m_jit.or32(TrustedImm32(ValueFalse), eqGPR);
-    jsValueResult(eqGPR, node, DataFormatJSBoolean);
-#else
-    booleanResult(eqGPR, node);
-#endif
</del><ins>+    unblessedBooleanResult(eqGPR, node);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void SpeculativeJIT::compileConstantStoragePointer(Node* node)
</span><span class="lines">@@ -4559,58 +4603,28 @@
</span><span class="cx">     JSValueOperand operand(this, edge, ManualOperandSpeculation);
</span><span class="cx">     GPRTemporary temp(this);
</span><span class="cx">     GPRReg tempGPR = temp.gpr();
</span><del>-#if USE(JSVALUE64)
-    GPRReg gpr = operand.gpr();
-    MacroAssembler::Jump notCell = m_jit.branchTest64(
-        MacroAssembler::NonZero, gpr, GPRInfo::tagMaskRegister);
</del><ins>+    MacroAssembler::Jump notCell = branchNotCell(operand.jsValueRegs());
+    GPRReg gpr = operand.jsValueRegs().payloadGPR();
</ins><span class="cx">     DFG_TYPE_CHECK(
</span><del>-        JSValueRegs(gpr), edge, (~SpecCell) | SpecObject, m_jit.branchStructurePtr(
</del><ins>+        operand.jsValueRegs(), edge, (~SpecCell) | SpecObject, m_jit.branchStructurePtr(
</ins><span class="cx">             MacroAssembler::Equal, 
</span><span class="cx">             MacroAssembler::Address(gpr, JSCell::structureIDOffset()), 
</span><span class="cx">             m_jit.vm()-&gt;stringStructure.get()));
</span><span class="cx">     MacroAssembler::Jump done = m_jit.jump();
</span><span class="cx">     notCell.link(&amp;m_jit);
</span><span class="cx">     if (needsTypeCheck(edge, SpecCell | SpecOther)) {
</span><del>-        m_jit.move(gpr, tempGPR);
-        m_jit.and64(MacroAssembler::TrustedImm32(~TagBitUndefined), tempGPR);
-        
</del><span class="cx">         typeCheck(
</span><del>-            JSValueRegs(gpr), edge, SpecCell | SpecOther,
-            m_jit.branch64(
-                MacroAssembler::NotEqual, tempGPR,
-                MacroAssembler::TrustedImm64(ValueNull)));
</del><ins>+            operand.jsValueRegs(), edge, SpecCell | SpecOther,
+            branchNotOther(operand.jsValueRegs(), tempGPR));
</ins><span class="cx">     }
</span><span class="cx">     done.link(&amp;m_jit);
</span><del>-#else
-    GPRReg tagGPR = operand.tagGPR();
-    GPRReg payloadGPR = operand.payloadGPR();
-    MacroAssembler::Jump notCell =
-        m_jit.branch32(MacroAssembler::NotEqual, tagGPR, TrustedImm32(JSValue::CellTag));
-    DFG_TYPE_CHECK(
-        JSValueRegs(tagGPR, payloadGPR), edge, (~SpecCell) | SpecObject, m_jit.branchStructurePtr(
-            MacroAssembler::Equal, 
-            MacroAssembler::Address(payloadGPR, JSCell::structureIDOffset()), 
-            m_jit.vm()-&gt;stringStructure.get()));
-    MacroAssembler::Jump done = m_jit.jump();
-    notCell.link(&amp;m_jit);
-    if (needsTypeCheck(edge, SpecCell | SpecOther)) {
-        m_jit.move(tagGPR, tempGPR);
-        m_jit.or32(TrustedImm32(1), tempGPR);
-        
-        typeCheck(
-            JSValueRegs(tagGPR, payloadGPR), edge, SpecCell | SpecOther,
-            m_jit.branch32(
-                MacroAssembler::NotEqual, tempGPR,
-                MacroAssembler::TrustedImm32(JSValue::NullTag)));
-    }
-    done.link(&amp;m_jit);
-#endif
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void SpeculativeJIT::speculateString(Edge edge, GPRReg cell)
</span><span class="cx"> {
</span><span class="cx">     DFG_TYPE_CHECK(
</span><del>-        JSValueSource::unboxedCell(cell), edge, SpecString, m_jit.branchStructurePtr(
</del><ins>+        JSValueSource::unboxedCell(cell), edge, SpecString | ~SpecCell,
+        m_jit.branchStructurePtr(
</ins><span class="cx">             MacroAssembler::NotEqual, 
</span><span class="cx">             MacroAssembler::Address(cell, JSCell::structureIDOffset()), 
</span><span class="cx">             m_jit.vm()-&gt;stringStructure.get()));
</span><span class="lines">@@ -4620,7 +4634,7 @@
</span><span class="cx"> {
</span><span class="cx">     m_jit.loadPtr(MacroAssembler::Address(string, JSString::offsetOfValue()), storage);
</span><span class="cx">     
</span><del>-    if (!needsTypeCheck(edge, SpecStringIdent))
</del><ins>+    if (!needsTypeCheck(edge, SpecStringIdent | ~SpecString))
</ins><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     speculationCheck(
</span><span class="lines">@@ -4632,7 +4646,7 @@
</span><span class="cx">             MacroAssembler::Address(storage, StringImpl::flagsOffset()),
</span><span class="cx">             MacroAssembler::TrustedImm32(StringImpl::flagIsIdentifier())));
</span><span class="cx">     
</span><del>-    m_interpreter.filter(edge, SpecStringIdent);
</del><ins>+    m_interpreter.filter(edge, SpecStringIdent | ~SpecString);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void SpeculativeJIT::speculateStringIdent(Edge edge, GPRReg string)
</span><span class="lines">@@ -4709,23 +4723,33 @@
</span><span class="cx">     m_interpreter.filter(edge, SpecString | SpecStringObject);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void SpeculativeJIT::speculateNotStringVar(Edge edge)
+{
+    JSValueOperand operand(this, edge, ManualOperandSpeculation);
+    GPRTemporary temp(this);
+    GPRReg tempGPR = temp.gpr();
+    
+    JITCompiler::Jump notCell = branchNotCell(operand.jsValueRegs());
+    GPRReg cell = operand.jsValueRegs().payloadGPR();
+    
+    JITCompiler::Jump notString = m_jit.branchStructurePtr(
+        MacroAssembler::NotEqual,
+        MacroAssembler::Address(cell, JSCell::structureIDOffset()),
+        m_jit.vm()-&gt;stringStructure.get());
+    
+    speculateStringIdentAndLoadStorage(edge, cell, tempGPR);
+    
+    notString.link(&amp;m_jit);
+    notCell.link(&amp;m_jit);
+}
+
</ins><span class="cx"> void SpeculativeJIT::speculateNotCell(Edge edge)
</span><span class="cx"> {
</span><span class="cx">     if (!needsTypeCheck(edge, ~SpecCell))
</span><span class="cx">         return;
</span><span class="cx">     
</span><del>-    JSValueOperand operand(this, edge, ManualOperandSpeculation);
-#if USE(JSVALUE64)
-    typeCheck(
-        JSValueRegs(operand.gpr()), edge, ~SpecCell,
-        m_jit.branchTest64(
-            JITCompiler::Zero, operand.gpr(), GPRInfo::tagMaskRegister));
-#else
-    typeCheck(
-        JSValueRegs(operand.tagGPR(), operand.payloadGPR()), edge, ~SpecCell,
-        m_jit.branch32(
-            JITCompiler::Equal, operand.tagGPR(), TrustedImm32(JSValue::CellTag)));
-#endif
</del><ins>+    JSValueOperand operand(this, edge, ManualOperandSpeculation); 
+    typeCheck(operand.jsValueRegs(), edge, ~SpecCell, branchIsCell(operand.jsValueRegs()));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void SpeculativeJIT::speculateOther(Edge edge)
</span><span class="lines">@@ -4736,21 +4760,9 @@
</span><span class="cx">     JSValueOperand operand(this, edge, ManualOperandSpeculation);
</span><span class="cx">     GPRTemporary temp(this);
</span><span class="cx">     GPRReg tempGPR = temp.gpr();
</span><del>-#if USE(JSVALUE64)
-    m_jit.move(operand.gpr(), tempGPR);
-    m_jit.and64(MacroAssembler::TrustedImm32(~TagBitUndefined), tempGPR);
</del><span class="cx">     typeCheck(
</span><del>-        JSValueRegs(operand.gpr()), edge, SpecOther,
-        m_jit.branch64(
-            MacroAssembler::NotEqual, tempGPR,
-            MacroAssembler::TrustedImm64(ValueNull)));
-#else
-    m_jit.move(operand.tagGPR(), tempGPR);
-    m_jit.or32(TrustedImm32(1), tempGPR);
-    typeCheck(
-        JSValueRegs(operand.tagGPR(), operand.payloadGPR()), edge, SpecOther,
-        m_jit.branch32(MacroAssembler::NotEqual, tempGPR, TrustedImm32(JSValue::NullTag)));
-#endif    
</del><ins>+        operand.jsValueRegs(), edge, SpecOther,
+        branchNotOther(operand.jsValueRegs(), tempGPR));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void SpeculativeJIT::speculateMisc(Edge edge, JSValueRegs regs)
</span><span class="lines">@@ -4834,6 +4846,9 @@
</span><span class="cx">     case StringOrStringObjectUse:
</span><span class="cx">         speculateStringOrStringObject(edge);
</span><span class="cx">         break;
</span><ins>+    case NotStringVarUse:
+        speculateNotStringVar(edge);
+        break;
</ins><span class="cx">     case NotCellUse:
</span><span class="cx">         speculateNotCell(edge);
</span><span class="cx">         break;
</span><span class="lines">@@ -4982,17 +4997,7 @@
</span><span class="cx">         
</span><span class="cx">         op1.use();
</span><span class="cx">         
</span><del>-#if USE(JSVALUE64)
-        addBranch(
-            m_jit.branchTest64(
-                MacroAssembler::NonZero, op1Regs.gpr(), GPRInfo::tagMaskRegister),
-            data-&gt;fallThrough.block);
-#else
-        addBranch(
-            m_jit.branch32(
-                MacroAssembler::NotEqual, op1Regs.tagGPR(), TrustedImm32(JSValue::CellTag)),
-            data-&gt;fallThrough.block);
-#endif
</del><ins>+        addBranch(branchNotCell(op1Regs), data-&gt;fallThrough.block);
</ins><span class="cx">         
</span><span class="cx">         addBranch(
</span><span class="cx">             m_jit.branchStructurePtr(
</span><span class="lines">@@ -5282,17 +5287,7 @@
</span><span class="cx">         
</span><span class="cx">         op1.use();
</span><span class="cx">         
</span><del>-#if USE(JSVALUE64)
-        addBranch(
-            m_jit.branchTest64(
-                MacroAssembler::NonZero, op1Regs.gpr(), GPRInfo::tagMaskRegister),
-            data-&gt;fallThrough.block);
-#else
-        addBranch(
-            m_jit.branch32(
-                MacroAssembler::NotEqual, op1Regs.tagGPR(), TrustedImm32(JSValue::CellTag)),
-            data-&gt;fallThrough.block);
-#endif
</del><ins>+        addBranch(branchNotCell(op1Regs), data-&gt;fallThrough.block);
</ins><span class="cx">         
</span><span class="cx">         addBranch(
</span><span class="cx">             m_jit.branchStructurePtr(
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h (165841 => 165842)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h        2014-03-18 20:45:27 UTC (rev 165841)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h        2014-03-18 20:53:07 UTC (rev 165842)
</span><span class="lines">@@ -861,8 +861,11 @@
</span><span class="cx">         GenerationInfo&amp; info = generationInfoFromVirtualRegister(virtualRegister);
</span><span class="cx">         info.initCell(node, node-&gt;refCount(), reg);
</span><span class="cx">     }
</span><del>-    void booleanResult(GPRReg reg, Node* node, UseChildrenMode mode = CallUseChildren)
</del><ins>+    void blessedBooleanResult(GPRReg reg, Node* node, UseChildrenMode mode = CallUseChildren)
</ins><span class="cx">     {
</span><ins>+#if USE(JSVALUE64)
+        jsValueResult(reg, node, DataFormatJSBoolean, mode);
+#else
</ins><span class="cx">         if (mode == CallUseChildren)
</span><span class="cx">             useChildren(node);
</span><span class="cx"> 
</span><span class="lines">@@ -870,8 +873,16 @@
</span><span class="cx">         m_gprs.retain(reg, virtualRegister, SpillOrderBoolean);
</span><span class="cx">         GenerationInfo&amp; info = generationInfoFromVirtualRegister(virtualRegister);
</span><span class="cx">         info.initBoolean(node, node-&gt;refCount(), reg);
</span><ins>+#endif
</ins><span class="cx">     }
</span><ins>+    void unblessedBooleanResult(GPRReg reg, Node* node, UseChildrenMode mode = CallUseChildren)
+    {
</ins><span class="cx"> #if USE(JSVALUE64)
</span><ins>+        blessBoolean(reg);
+#endif
+        blessedBooleanResult(reg, node, mode);
+    }
+#if USE(JSVALUE64)
</ins><span class="cx">     void jsValueResult(GPRReg reg, Node* node, DataFormat format = DataFormatJS, UseChildrenMode mode = CallUseChildren)
</span><span class="cx">     {
</span><span class="cx">         if (format == DataFormatJSInt32)
</span><span class="lines">@@ -890,6 +901,16 @@
</span><span class="cx">         jsValueResult(reg, node, DataFormatJS, mode);
</span><span class="cx">     }
</span><span class="cx"> #elif USE(JSVALUE32_64)
</span><ins>+    void booleanResult(GPRReg reg, Node* node, UseChildrenMode mode = CallUseChildren)
+    {
+        if (mode == CallUseChildren)
+            useChildren(node);
+
+        VirtualRegister virtualRegister = node-&gt;virtualRegister();
+        m_gprs.retain(reg, virtualRegister, SpillOrderBoolean);
+        GenerationInfo&amp; info = generationInfoFromVirtualRegister(virtualRegister);
+        info.initBoolean(node, node-&gt;refCount(), reg);
+    }
</ins><span class="cx">     void jsValueResult(GPRReg tag, GPRReg payload, Node* node, DataFormat format = DataFormatJS, UseChildrenMode mode = CallUseChildren)
</span><span class="cx">     {
</span><span class="cx">         if (mode == CallUseChildren)
</span><span class="lines">@@ -1980,8 +2001,15 @@
</span><span class="cx">     void compileObjectToObjectOrOtherEquality(Edge leftChild, Edge rightChild);
</span><span class="cx">     void compileObjectOrOtherLogicalNot(Edge value);
</span><span class="cx">     void compileLogicalNot(Node*);
</span><ins>+    void compileStringEquality(
+        Node*, GPRReg leftGPR, GPRReg rightGPR, GPRReg lengthGPR,
+        GPRReg leftTempGPR, GPRReg rightTempGPR, GPRReg leftTemp2GPR,
+        GPRReg rightTemp2GPR, JITCompiler::JumpList fastTrue,
+        JITCompiler::JumpList fastSlow);
</ins><span class="cx">     void compileStringEquality(Node*);
</span><span class="cx">     void compileStringIdentEquality(Node*);
</span><ins>+    void compileStringToUntypedEquality(Node*, Edge stringEdge, Edge untypedEdge);
+    void compileStringIdentToNotStringVarEquality(Node*, Edge stringEdge, Edge notStringVarEdge);
</ins><span class="cx">     void compileStringZeroLength(Node*);
</span><span class="cx">     void compileMiscStrictEq(Node*);
</span><span class="cx"> 
</span><span class="lines">@@ -2078,6 +2106,15 @@
</span><span class="cx">     void compileNewFunctionExpression(Node*);
</span><span class="cx">     bool compileRegExpExec(Node*);
</span><span class="cx">     
</span><ins>+    JITCompiler::Jump branchIsCell(JSValueRegs);
+    JITCompiler::Jump branchNotCell(JSValueRegs);
+    JITCompiler::Jump branchIsOther(JSValueRegs, GPRReg tempGPR);
+    JITCompiler::Jump branchNotOther(JSValueRegs, GPRReg tempGPR);
+    
+    void moveTrueTo(GPRReg);
+    void moveFalseTo(GPRReg);
+    void blessBoolean(GPRReg);
+    
</ins><span class="cx">     // size can be an immediate or a register, and must be in bytes. If size is a register,
</span><span class="cx">     // it must be a different register than resultGPR. Emits code that place a pointer to
</span><span class="cx">     // the end of the allocation. The returned jump is the jump to the slow path.
</span><span class="lines">@@ -2193,6 +2230,7 @@
</span><span class="cx">     void speculateStringIdent(Edge edge, GPRReg string);
</span><span class="cx">     void speculateStringIdent(Edge);
</span><span class="cx">     void speculateString(Edge);
</span><ins>+    void speculateNotStringVar(Edge);
</ins><span class="cx">     template&lt;typename StructureLocationType&gt;
</span><span class="cx">     void speculateStringObjectForStructure(Edge, StructureLocationType);
</span><span class="cx">     void speculateStringObject(Edge, GPRReg);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp (165841 => 165842)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2014-03-18 20:45:27 UTC (rev 165841)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2014-03-18 20:53:07 UTC (rev 165842)
</span><span class="lines">@@ -236,8 +236,8 @@
</span><span class="cx">     JITCompiler::Jump notMasqueradesAsUndefined;   
</span><span class="cx">     if (masqueradesAsUndefinedWatchpointIsStillValid()) {
</span><span class="cx">         if (!isKnownCell(operand.node()))
</span><del>-            notCell = m_jit.branch32(MacroAssembler::NotEqual, argTagGPR, TrustedImm32(JSValue::CellTag));
-
</del><ins>+            notCell = branchNotCell(arg.jsValueRegs());
+        
</ins><span class="cx">         m_jit.move(invert ? TrustedImm32(1) : TrustedImm32(0), resultPayloadGPR);
</span><span class="cx">         notMasqueradesAsUndefined = m_jit.jump();
</span><span class="cx">     } else {
</span><span class="lines">@@ -245,8 +245,8 @@
</span><span class="cx">         GPRTemporary remoteGlobalObject(this);
</span><span class="cx"> 
</span><span class="cx">         if (!isKnownCell(operand.node()))
</span><del>-            notCell = m_jit.branch32(MacroAssembler::NotEqual, argTagGPR, TrustedImm32(JSValue::CellTag));
-
</del><ins>+            notCell = branchNotCell(arg.jsValueRegs());
+        
</ins><span class="cx">         JITCompiler::Jump isMasqueradesAsUndefined = m_jit.branchTest8(
</span><span class="cx">             JITCompiler::NonZero, 
</span><span class="cx">             JITCompiler::Address(argPayloadGPR, JSCell::typeInfoFlagsOffset()), 
</span><span class="lines">@@ -305,16 +305,16 @@
</span><span class="cx"> 
</span><span class="cx">     if (masqueradesAsUndefinedWatchpointIsStillValid()) {
</span><span class="cx">         if (!isKnownCell(operand.node()))
</span><del>-            notCell = m_jit.branch32(MacroAssembler::NotEqual, argTagGPR, TrustedImm32(JSValue::CellTag));
-
</del><ins>+            notCell = branchNotCell(arg.jsValueRegs());
+        
</ins><span class="cx">         jump(invert ? taken : notTaken, ForceJump);
</span><span class="cx">     } else {
</span><span class="cx">         GPRTemporary localGlobalObject(this);
</span><span class="cx">         GPRTemporary remoteGlobalObject(this);
</span><span class="cx"> 
</span><span class="cx">         if (!isKnownCell(operand.node()))
</span><del>-            notCell = m_jit.branch32(MacroAssembler::NotEqual, argTagGPR, TrustedImm32(JSValue::CellTag));
-
</del><ins>+            notCell = branchNotCell(arg.jsValueRegs());
+        
</ins><span class="cx">         branchTest8(JITCompiler::Zero, 
</span><span class="cx">             JITCompiler::Address(argPayloadGPR, JSCell::typeInfoFlagsOffset()), 
</span><span class="cx">             JITCompiler::TrustedImm32(MasqueradesAsUndefined), 
</span><span class="lines">@@ -682,7 +682,7 @@
</span><span class="cx"> 
</span><span class="cx">     m_jit.emitStoreCodeOrigin(node-&gt;origin.semantic);
</span><span class="cx">     
</span><del>-    slowPath.append(m_jit.branch32(MacroAssembler::NotEqual, calleeTagGPR, TrustedImm32(JSValue::CellTag)));
</del><ins>+    slowPath.append(branchNotCell(callee.jsValueRegs()));
</ins><span class="cx">     slowPath.append(m_jit.branchPtrWithPatch(MacroAssembler::NotEqual, calleePayloadGPR, targetToCheck));
</span><span class="cx">     m_jit.loadPtr(MacroAssembler::Address(calleePayloadGPR, OBJECT_OFFSETOF(JSFunction, m_scope)), resultPayloadGPR);
</span><span class="cx">     m_jit.storePtr(resultPayloadGPR, calleeFramePayloadSlot(JSStack::ScopeChain));
</span><span class="lines">@@ -980,8 +980,16 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         ASSERT((info.spillFormat() &amp; DataFormatJS) || info.spillFormat() == DataFormatCell);
</span><del>-        if (type &amp; ~SpecCell)
-            speculationCheck(BadType, JSValueSource(JITCompiler::addressFor(virtualRegister)), edge, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::CellTag)));
</del><ins>+        if (type &amp; ~SpecCell) {
+            speculationCheck(
+                BadType,
+                JSValueSource(JITCompiler::addressFor(virtualRegister)),
+                edge,
+                m_jit.branch32(
+                    MacroAssembler::NotEqual,
+                    JITCompiler::tagFor(virtualRegister),
+                    TrustedImm32(JSValue::CellTag)));
+        }
</ins><span class="cx">         GPRReg gpr = allocate();
</span><span class="cx">         m_jit.load32(JITCompiler::payloadFor(virtualRegister), gpr);
</span><span class="cx">         m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
</span><span class="lines">@@ -1001,8 +1009,11 @@
</span><span class="cx">         GPRReg payloadGPR = info.payloadGPR();
</span><span class="cx">         m_gprs.lock(tagGPR);
</span><span class="cx">         m_gprs.lock(payloadGPR);
</span><del>-        if (type &amp; ~SpecCell)
-            speculationCheck(BadType, JSValueRegs(tagGPR, payloadGPR), edge, m_jit.branch32(MacroAssembler::NotEqual, tagGPR, TrustedImm32(JSValue::CellTag)));
</del><ins>+        if (type &amp; ~SpecCell) {
+            speculationCheck(
+                BadType, JSValueRegs(tagGPR, payloadGPR), edge,
+                branchNotCell(info.jsValueRegs()));
+        }
</ins><span class="cx">         m_gprs.unlock(tagGPR);
</span><span class="cx">         m_gprs.release(tagGPR);
</span><span class="cx">         m_gprs.release(payloadGPR);
</span><span class="lines">@@ -1240,8 +1251,7 @@
</span><span class="cx">     
</span><span class="cx">     // It seems that most of the time when programs do a == b where b may be either null/undefined
</span><span class="cx">     // or an object, b is usually an object. Balance the branches to make that case fast.
</span><del>-    MacroAssembler::Jump rightNotCell =
-        m_jit.branch32(MacroAssembler::NotEqual, op2TagGPR, TrustedImm32(JSValue::CellTag));
</del><ins>+    MacroAssembler::Jump rightNotCell = branchNotCell(op2.jsValueRegs());
</ins><span class="cx">     
</span><span class="cx">     // We know that within this branch, rightChild must be a cell.
</span><span class="cx">     if (masqueradesAsUndefinedWatchpointValid) {
</span><span class="lines">@@ -1334,8 +1344,7 @@
</span><span class="cx">     
</span><span class="cx">     // It seems that most of the time when programs do a == b where b may be either null/undefined
</span><span class="cx">     // or an object, b is usually an object. Balance the branches to make that case fast.
</span><del>-    MacroAssembler::Jump rightNotCell =
-        m_jit.branch32(MacroAssembler::NotEqual, op2TagGPR, TrustedImm32(JSValue::CellTag));
</del><ins>+    MacroAssembler::Jump rightNotCell = branchNotCell(op2.jsValueRegs());
</ins><span class="cx">     
</span><span class="cx">     // We know that within this branch, rightChild must be a cell.
</span><span class="cx">     if (masqueradesAsUndefinedWatchpointValid) {
</span><span class="lines">@@ -1432,7 +1441,7 @@
</span><span class="cx">         structureGPR = structure.gpr();
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    MacroAssembler::Jump notCell = m_jit.branch32(MacroAssembler::NotEqual, valueTagGPR, TrustedImm32(JSValue::CellTag));
</del><ins>+    MacroAssembler::Jump notCell = branchNotCell(value.jsValueRegs());
</ins><span class="cx">     if (masqueradesAsUndefinedWatchpointValid) {
</span><span class="cx">         DFG_TYPE_CHECK(
</span><span class="cx">             JSValueRegs(valueTagGPR, valuePayloadGPR), nodeUse, (~SpecCell) | SpecObject,
</span><span class="lines">@@ -1562,7 +1571,7 @@
</span><span class="cx">     GPRReg valuePayloadGPR = value.payloadGPR();
</span><span class="cx">     GPRReg scratchGPR = scratch.gpr();
</span><span class="cx">     
</span><del>-    MacroAssembler::Jump notCell = m_jit.branch32(MacroAssembler::NotEqual, valueTagGPR, TrustedImm32(JSValue::CellTag));
</del><ins>+    MacroAssembler::Jump notCell = branchNotCell(value.jsValueRegs());
</ins><span class="cx">     if (masqueradesAsUndefinedWatchpointIsStillValid()) {
</span><span class="cx">         DFG_TYPE_CHECK(
</span><span class="cx">             JSValueRegs(valueTagGPR, valuePayloadGPR), nodeUse, (~SpecCell) | SpecObject,
</span><span class="lines">@@ -3069,7 +3078,7 @@
</span><span class="cx">             m_jit.move(op1TagGPR, resultTagGPR);
</span><span class="cx">             m_jit.move(op1PayloadGPR, resultPayloadGPR);
</span><span class="cx">         } else {
</span><del>-            MacroAssembler::Jump alreadyPrimitive = m_jit.branch32(MacroAssembler::NotEqual, op1TagGPR, TrustedImm32(JSValue::CellTag));
</del><ins>+            MacroAssembler::Jump alreadyPrimitive = branchNotCell(op1.jsValueRegs());
</ins><span class="cx">             MacroAssembler::Jump notPrimitive = m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op1PayloadGPR, JSCell::structureIDOffset()), MacroAssembler::TrustedImmPtr(m_jit.vm()-&gt;stringStructure.get()));
</span><span class="cx">             
</span><span class="cx">             alreadyPrimitive.link(&amp;m_jit);
</span><span class="lines">@@ -3099,8 +3108,7 @@
</span><span class="cx">             
</span><span class="cx">             JITCompiler::Jump done;
</span><span class="cx">             if (node-&gt;child1()-&gt;prediction() &amp; SpecString) {
</span><del>-                JITCompiler::Jump slowPath1 = m_jit.branch32(
-                    JITCompiler::NotEqual, op1TagGPR, TrustedImm32(JSValue::CellTag));
</del><ins>+                JITCompiler::Jump slowPath1 = branchNotCell(op1.jsValueRegs());
</ins><span class="cx">                 JITCompiler::Jump slowPath2 = m_jit.branchPtr(
</span><span class="cx">                     JITCompiler::NotEqual,
</span><span class="cx">                     JITCompiler::Address(op1PayloadGPR, JSCell::structureIDOffset()),
</span><span class="lines">@@ -3467,8 +3475,7 @@
</span><span class="cx">         GPRReg tempTagGPR = tempTag.gpr();
</span><span class="cx">         
</span><span class="cx">         MacroAssembler::JumpList slowCases;
</span><del>-        slowCases.append(m_jit.branch32(
-            MacroAssembler::NotEqual, thisValueTagGPR, TrustedImm32(JSValue::CellTag)));
</del><ins>+        slowCases.append(branchNotCell(thisValue.jsValueRegs()));
</ins><span class="cx">         slowCases.append(m_jit.branch8(
</span><span class="cx">             MacroAssembler::NotEqual,
</span><span class="cx">             MacroAssembler::Address(thisValuePayloadGPR, JSCell::typeInfoTypeOffset()),
</span><span class="lines">@@ -3679,7 +3686,7 @@
</span><span class="cx">         
</span><span class="cx">             base.use();
</span><span class="cx">         
</span><del>-            JITCompiler::Jump notCell = m_jit.branch32(JITCompiler::NotEqual, baseTagGPR, TrustedImm32(JSValue::CellTag));
</del><ins>+            JITCompiler::Jump notCell = branchNotCell(base.jsValueRegs());
</ins><span class="cx">         
</span><span class="cx">             cachedGetById(node-&gt;origin.semantic, baseTagGPR, basePayloadGPR, resultTagGPR, resultPayloadGPR, node-&gt;identifierNumber(), notCell);
</span><span class="cx">         
</span><span class="lines">@@ -3735,7 +3742,7 @@
</span><span class="cx">         
</span><span class="cx">             flushRegisters();
</span><span class="cx">         
</span><del>-            JITCompiler::Jump notCell = m_jit.branch32(JITCompiler::NotEqual, baseTagGPR, TrustedImm32(JSValue::CellTag));
</del><ins>+            JITCompiler::Jump notCell = branchNotCell(base.jsValueRegs());
</ins><span class="cx">         
</span><span class="cx">             cachedGetById(node-&gt;origin.semantic, baseTagGPR, basePayloadGPR, resultTagGPR, resultPayloadGPR, node-&gt;identifierNumber(), notCell, DontSpill);
</span><span class="cx">         
</span><span class="lines">@@ -4079,7 +4086,7 @@
</span><span class="cx">         GPRTemporary localGlobalObject(this);
</span><span class="cx">         GPRTemporary remoteGlobalObject(this);
</span><span class="cx"> 
</span><del>-        JITCompiler::Jump isCell = m_jit.branch32(JITCompiler::Equal, value.tagGPR(), JITCompiler::TrustedImm32(JSValue::CellTag));
</del><ins>+        JITCompiler::Jump isCell = branchIsCell(value.jsValueRegs());
</ins><span class="cx">         
</span><span class="cx">         m_jit.compare32(JITCompiler::Equal, value.tagGPR(), TrustedImm32(JSValue::UndefinedTag), result.gpr());
</span><span class="cx">         JITCompiler::Jump done = m_jit.jump();
</span><span class="lines">@@ -4135,7 +4142,7 @@
</span><span class="cx">         JSValueOperand value(this, node-&gt;child1());
</span><span class="cx">         GPRTemporary result(this, Reuse, value, TagWord);
</span><span class="cx">         
</span><del>-        JITCompiler::Jump isNotCell = m_jit.branch32(JITCompiler::NotEqual, value.tagGPR(), JITCompiler::TrustedImm32(JSValue::CellTag));
</del><ins>+        JITCompiler::Jump isNotCell = branchNotCell(value.jsValueRegs());
</ins><span class="cx">         
</span><span class="cx">         m_jit.compare8(JITCompiler::Equal, 
</span><span class="cx">             JITCompiler::Address(value.payloadGPR(), JSCell::typeInfoTypeOffset()), 
</span><span class="lines">@@ -4188,7 +4195,7 @@
</span><span class="cx"> 
</span><span class="cx">         ASSERT(node-&gt;child1().useKind() == UntypedUse || node-&gt;child1().useKind() == CellUse || node-&gt;child1().useKind() == StringUse);
</span><span class="cx"> 
</span><del>-        JITCompiler::Jump isNotCell = m_jit.branch32(JITCompiler::NotEqual, tagGPR, JITCompiler::TrustedImm32(JSValue::CellTag));
</del><ins>+        JITCompiler::Jump isNotCell = branchNotCell(value.jsValueRegs());
</ins><span class="cx">         if (node-&gt;child1().useKind() != UntypedUse)
</span><span class="cx">             DFG_TYPE_CHECK(JSValueRegs(tagGPR, payloadGPR), node-&gt;child1(), SpecCell, isNotCell);
</span><span class="cx"> 
</span><span class="lines">@@ -4747,6 +4754,48 @@
</span><span class="cx"> }
</span><span class="cx"> #endif // ENABLE(GGC)
</span><span class="cx"> 
</span><ins>+JITCompiler::Jump SpeculativeJIT::branchIsCell(JSValueRegs regs)
+{
+    return m_jit.branch32(MacroAssembler::Equal, regs.tagGPR(), TrustedImm32(JSValue::CellTag));
+}
+
+JITCompiler::Jump SpeculativeJIT::branchNotCell(JSValueRegs regs)
+{
+    return m_jit.branch32(MacroAssembler::NotEqual, regs.tagGPR(), TrustedImm32(JSValue::CellTag));
+}
+
+JITCompiler::Jump SpeculativeJIT::branchIsOther(JSValueRegs regs, GPRReg tempGPR)
+{
+    m_jit.move(regs.tagGPR(), tempGPR);
+    m_jit.or32(TrustedImm32(1), tempGPR);
+    return m_jit.branch32(
+        MacroAssembler::Equal, tempGPR,
+        MacroAssembler::TrustedImm32(JSValue::NullTag));
+}
+
+JITCompiler::Jump SpeculativeJIT::branchNotOther(JSValueRegs regs, GPRReg tempGPR)
+{
+    m_jit.move(regs.tagGPR(), tempGPR);
+    m_jit.or32(TrustedImm32(1), tempGPR);
+    return m_jit.branch32(
+        MacroAssembler::NotEqual, tempGPR,
+        MacroAssembler::TrustedImm32(JSValue::NullTag));
+}
+
+void SpeculativeJIT::moveTrueTo(GPRReg gpr)
+{
+    m_jit.move(TrustedImm32(1), gpr);
+}
+
+void SpeculativeJIT::moveFalseTo(GPRReg gpr)
+{
+    m_jit.move(TrustedImm32(0), gpr);
+}
+
+void SpeculativeJIT::blessBoolean(GPRReg)
+{
+}
+
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> } } // namespace JSC::DFG
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (165841 => 165842)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2014-03-18 20:45:27 UTC (rev 165841)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2014-03-18 20:53:07 UTC (rev 165842)
</span><span class="lines">@@ -242,7 +242,7 @@
</span><span class="cx">     JITCompiler::Jump notMasqueradesAsUndefined;
</span><span class="cx">     if (masqueradesAsUndefinedWatchpointIsStillValid()) {
</span><span class="cx">         if (!isKnownCell(operand.node()))
</span><del>-            notCell = m_jit.branchTest64(MacroAssembler::NonZero, argGPR, GPRInfo::tagMaskRegister);
</del><ins>+            notCell = branchNotCell(JSValueRegs(argGPR));
</ins><span class="cx"> 
</span><span class="cx">         m_jit.move(invert ? TrustedImm32(1) : TrustedImm32(0), resultGPR);
</span><span class="cx">         notMasqueradesAsUndefined = m_jit.jump();
</span><span class="lines">@@ -252,8 +252,8 @@
</span><span class="cx">         GPRTemporary scratch(this);
</span><span class="cx"> 
</span><span class="cx">         if (!isKnownCell(operand.node()))
</span><del>-            notCell = m_jit.branchTest64(MacroAssembler::NonZero, argGPR, GPRInfo::tagMaskRegister);
-
</del><ins>+            notCell = branchNotCell(JSValueRegs(argGPR));
+        
</ins><span class="cx">         JITCompiler::Jump isMasqueradesAsUndefined = m_jit.branchTest8(
</span><span class="cx">             JITCompiler::NonZero, 
</span><span class="cx">             JITCompiler::Address(argGPR, JSCell::typeInfoFlagsOffset()), 
</span><span class="lines">@@ -311,8 +311,8 @@
</span><span class="cx">     
</span><span class="cx">     if (masqueradesAsUndefinedWatchpointIsStillValid()) {
</span><span class="cx">         if (!isKnownCell(operand.node()))
</span><del>-            notCell = m_jit.branchTest64(MacroAssembler::NonZero, argGPR, GPRInfo::tagMaskRegister);
-
</del><ins>+            notCell = branchNotCell(JSValueRegs(argGPR));
+        
</ins><span class="cx">         jump(invert ? taken : notTaken, ForceJump);
</span><span class="cx">     } else {
</span><span class="cx">         GPRTemporary localGlobalObject(this);
</span><span class="lines">@@ -320,8 +320,8 @@
</span><span class="cx">         GPRTemporary scratch(this);
</span><span class="cx"> 
</span><span class="cx">         if (!isKnownCell(operand.node()))
</span><del>-            notCell = m_jit.branchTest64(MacroAssembler::NonZero, argGPR, GPRInfo::tagMaskRegister);
-
</del><ins>+            notCell = branchNotCell(JSValueRegs(argGPR));
+        
</ins><span class="cx">         branchTest8(JITCompiler::Zero, 
</span><span class="cx">             JITCompiler::Address(argGPR, JSCell::typeInfoFlagsOffset()), 
</span><span class="cx">             JITCompiler::TrustedImm32(MasqueradesAsUndefined), 
</span><span class="lines">@@ -1367,7 +1367,7 @@
</span><span class="cx"> 
</span><span class="cx">         info.fillJSValue(*m_stream, gpr, DataFormatJS);
</span><span class="cx">         if (type &amp; ~SpecCell)
</span><del>-            speculationCheck(BadType, JSValueRegs(gpr), edge, m_jit.branchTest64(MacroAssembler::NonZero, gpr, GPRInfo::tagMaskRegister));
</del><ins>+            speculationCheck(BadType, JSValueRegs(gpr), edge, branchNotCell(JSValueRegs(gpr)));
</ins><span class="cx">         info.fillJSValue(*m_stream, gpr, DataFormatJSCell);
</span><span class="cx">         return gpr;
</span><span class="cx">     }
</span><span class="lines">@@ -1377,7 +1377,7 @@
</span><span class="cx">         GPRReg gpr = info.gpr();
</span><span class="cx">         m_gprs.lock(gpr);
</span><span class="cx">         if (!ASSERT_DISABLED) {
</span><del>-            MacroAssembler::Jump checkCell = m_jit.branchTest64(MacroAssembler::Zero, gpr, GPRInfo::tagMaskRegister);
</del><ins>+            MacroAssembler::Jump checkCell = branchIsCell(JSValueRegs(gpr));
</ins><span class="cx">             m_jit.breakpoint();
</span><span class="cx">             checkCell.link(&amp;m_jit);
</span><span class="cx">         }
</span><span class="lines">@@ -1388,7 +1388,7 @@
</span><span class="cx">         GPRReg gpr = info.gpr();
</span><span class="cx">         m_gprs.lock(gpr);
</span><span class="cx">         if (type &amp; ~SpecCell)
</span><del>-            speculationCheck(BadType, JSValueRegs(gpr), edge, m_jit.branchTest64(MacroAssembler::NonZero, gpr, GPRInfo::tagMaskRegister));
</del><ins>+            speculationCheck(BadType, JSValueRegs(gpr), edge, branchNotCell(JSValueRegs(gpr)));
</ins><span class="cx">         info.fillJSValue(*m_stream, gpr, DataFormatJSCell);
</span><span class="cx">         return gpr;
</span><span class="cx">     }
</span><span class="lines">@@ -1622,8 +1622,7 @@
</span><span class="cx">     
</span><span class="cx">     // It seems that most of the time when programs do a == b where b may be either null/undefined
</span><span class="cx">     // or an object, b is usually an object. Balance the branches to make that case fast.
</span><del>-    MacroAssembler::Jump rightNotCell =
-        m_jit.branchTest64(MacroAssembler::NonZero, op2GPR, GPRInfo::tagMaskRegister);
</del><ins>+    MacroAssembler::Jump rightNotCell = branchNotCell(JSValueRegs(op2GPR));
</ins><span class="cx">     
</span><span class="cx">     // We know that within this branch, rightChild must be a cell. 
</span><span class="cx">     if (masqueradesAsUndefinedWatchpointValid) {
</span><span class="lines">@@ -1713,8 +1712,7 @@
</span><span class="cx"> 
</span><span class="cx">     // It seems that most of the time when programs do a == b where b may be either null/undefined
</span><span class="cx">     // or an object, b is usually an object. Balance the branches to make that case fast.
</span><del>-    MacroAssembler::Jump rightNotCell =
-        m_jit.branchTest64(MacroAssembler::NonZero, op2GPR, GPRInfo::tagMaskRegister);
</del><ins>+    MacroAssembler::Jump rightNotCell = branchNotCell(JSValueRegs(op2GPR));
</ins><span class="cx">     
</span><span class="cx">     // We know that within this branch, rightChild must be a cell. 
</span><span class="cx">     if (masqueradesAsUndefinedWatchpointValid) {
</span><span class="lines">@@ -1847,7 +1845,7 @@
</span><span class="cx">         scratchGPR = scratch.gpr();
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    MacroAssembler::Jump notCell = m_jit.branchTest64(MacroAssembler::NonZero, valueGPR, GPRInfo::tagMaskRegister);
</del><ins>+    MacroAssembler::Jump notCell = branchNotCell(JSValueRegs(valueGPR));
</ins><span class="cx">     if (masqueradesAsUndefinedWatchpointValid) {
</span><span class="cx">         DFG_TYPE_CHECK(
</span><span class="cx">             JSValueRegs(valueGPR), nodeUse, (~SpecCell) | SpecObject, m_jit.branchStructurePtr(
</span><span class="lines">@@ -1997,7 +1995,7 @@
</span><span class="cx">         structureGPR = structure.gpr();
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    MacroAssembler::Jump notCell = m_jit.branchTest64(MacroAssembler::NonZero, valueGPR, GPRInfo::tagMaskRegister);
</del><ins>+    MacroAssembler::Jump notCell = branchNotCell(JSValueRegs(valueGPR));
</ins><span class="cx">     if (masqueradesAsUndefinedWatchpointIsStillValid()) {
</span><span class="cx">         DFG_TYPE_CHECK(
</span><span class="cx">             JSValueRegs(valueGPR), nodeUse, (~SpecCell) | SpecObject, m_jit.branchStructurePtr(
</span><span class="lines">@@ -3422,7 +3420,7 @@
</span><span class="cx">         
</span><span class="cx">         op1.use();
</span><span class="cx">         
</span><del>-        MacroAssembler::Jump alreadyPrimitive = m_jit.branchTest64(MacroAssembler::NonZero, op1GPR, GPRInfo::tagMaskRegister);
</del><ins>+        MacroAssembler::Jump alreadyPrimitive = branchNotCell(JSValueRegs(op1GPR));
</ins><span class="cx">         MacroAssembler::Jump notPrimitive = m_jit.branchStructurePtr(
</span><span class="cx">             MacroAssembler::NotEqual, 
</span><span class="cx">             MacroAssembler::Address(op1GPR, JSCell::structureIDOffset()), 
</span><span class="lines">@@ -3450,8 +3448,7 @@
</span><span class="cx">             
</span><span class="cx">             JITCompiler::Jump done;
</span><span class="cx">             if (node-&gt;child1()-&gt;prediction() &amp; SpecString) {
</span><del>-                JITCompiler::Jump slowPath1 = m_jit.branchTest64(
-                    JITCompiler::NonZero, op1GPR, GPRInfo::tagMaskRegister);
</del><ins>+                JITCompiler::Jump slowPath1 = branchNotCell(JSValueRegs(op1GPR));
</ins><span class="cx">                 JITCompiler::Jump slowPath2 = m_jit.branchStructurePtr(
</span><span class="cx">                     JITCompiler::NotEqual,
</span><span class="cx">                     JITCompiler::Address(op1GPR, JSCell::structureIDOffset()),
</span><span class="lines">@@ -3810,8 +3807,7 @@
</span><span class="cx">         GPRReg tempGPR = temp.gpr();
</span><span class="cx">         
</span><span class="cx">         MacroAssembler::JumpList slowCases;
</span><del>-        slowCases.append(m_jit.branchTest64(
-            MacroAssembler::NonZero, thisValueGPR, GPRInfo::tagMaskRegister));
</del><ins>+        slowCases.append(branchNotCell(JSValueRegs(thisValueGPR)));
</ins><span class="cx">         slowCases.append(m_jit.branch8(
</span><span class="cx">             MacroAssembler::NotEqual,
</span><span class="cx">             MacroAssembler::Address(thisValueGPR, JSCell::typeInfoTypeOffset()),
</span><span class="lines">@@ -4008,7 +4004,7 @@
</span><span class="cx">         
</span><span class="cx">             base.use();
</span><span class="cx">         
</span><del>-            JITCompiler::Jump notCell = m_jit.branchTest64(JITCompiler::NonZero, baseGPR, GPRInfo::tagMaskRegister);
</del><ins>+            JITCompiler::Jump notCell = branchNotCell(JSValueRegs(baseGPR));
</ins><span class="cx">         
</span><span class="cx">             cachedGetById(node-&gt;origin.semantic, baseGPR, resultGPR, node-&gt;identifierNumber(), notCell);
</span><span class="cx">         
</span><span class="lines">@@ -4058,7 +4054,7 @@
</span><span class="cx">             base.use();
</span><span class="cx">             flushRegisters();
</span><span class="cx">         
</span><del>-            JITCompiler::Jump notCell = m_jit.branchTest64(JITCompiler::NonZero, baseGPR, GPRInfo::tagMaskRegister);
</del><ins>+            JITCompiler::Jump notCell = branchNotCell(JSValueRegs(baseGPR));
</ins><span class="cx">         
</span><span class="cx">             cachedGetById(node-&gt;origin.semantic, baseGPR, resultGPR, node-&gt;identifierNumber(), notCell, DontSpill);
</span><span class="cx">         
</span><span class="lines">@@ -4389,7 +4385,7 @@
</span><span class="cx">         GPRTemporary remoteGlobalObject(this);
</span><span class="cx">         GPRTemporary scratch(this);
</span><span class="cx"> 
</span><del>-        JITCompiler::Jump isCell = m_jit.branchTest64(JITCompiler::Zero, value.gpr(), GPRInfo::tagMaskRegister);
</del><ins>+        JITCompiler::Jump isCell = branchIsCell(value.jsValueRegs());
</ins><span class="cx"> 
</span><span class="cx">         m_jit.compare64(JITCompiler::Equal, value.gpr(), TrustedImm32(ValueUndefined), result.gpr());
</span><span class="cx">         JITCompiler::Jump done = m_jit.jump();
</span><span class="lines">@@ -4449,7 +4445,7 @@
</span><span class="cx">         JSValueOperand value(this, node-&gt;child1());
</span><span class="cx">         GPRTemporary result(this, Reuse, value);
</span><span class="cx">         
</span><del>-        JITCompiler::Jump isNotCell = m_jit.branchTest64(JITCompiler::NonZero, value.gpr(), GPRInfo::tagMaskRegister);
</del><ins>+        JITCompiler::Jump isNotCell = branchNotCell(value.jsValueRegs());
</ins><span class="cx">         
</span><span class="cx">         m_jit.compare8(JITCompiler::Equal, 
</span><span class="cx">             JITCompiler::Address(value.gpr(), JSCell::typeInfoTypeOffset()), 
</span><span class="lines">@@ -4501,7 +4497,7 @@
</span><span class="cx">         
</span><span class="cx">         ASSERT(node-&gt;child1().useKind() == UntypedUse || node-&gt;child1().useKind() == CellUse || node-&gt;child1().useKind() == StringUse);
</span><span class="cx"> 
</span><del>-        JITCompiler::Jump isNotCell = m_jit.branchTest64(JITCompiler::NonZero, valueGPR, GPRInfo::tagMaskRegister);
</del><ins>+        JITCompiler::Jump isNotCell = branchNotCell(JSValueRegs(valueGPR));
</ins><span class="cx">         if (node-&gt;child1().useKind() != UntypedUse)
</span><span class="cx">             DFG_TYPE_CHECK(JSValueSource(valueGPR), node-&gt;child1(), SpecCell, isNotCell);
</span><span class="cx"> 
</span><span class="lines">@@ -5056,8 +5052,8 @@
</span><span class="cx"> {
</span><span class="cx">     JITCompiler::Jump isNotCell;
</span><span class="cx">     if (!isKnownCell(valueUse.node()))
</span><del>-        isNotCell = m_jit.branchTest64(JITCompiler::NonZero, valueGPR, GPRInfo::tagMaskRegister);
-
</del><ins>+        isNotCell = branchNotCell(JSValueRegs(valueGPR));
+    
</ins><span class="cx">     JITCompiler::Jump ownerNotMarkedOrAlreadyRemembered = m_jit.checkMarkByte(ownerGPR);
</span><span class="cx">     storeToWriteBarrierBuffer(ownerGPR, scratch1, scratch2);
</span><span class="cx">     ownerNotMarkedOrAlreadyRemembered.link(&amp;m_jit);
</span><span class="lines">@@ -5070,8 +5066,8 @@
</span><span class="cx"> {
</span><span class="cx">     JITCompiler::Jump isNotCell;
</span><span class="cx">     if (!isKnownCell(valueUse.node()))
</span><del>-        isNotCell = m_jit.branchTest64(JITCompiler::NonZero, valueGPR, GPRInfo::tagMaskRegister);
-
</del><ins>+        isNotCell = branchNotCell(JSValueRegs(valueGPR));
+    
</ins><span class="cx">     JITCompiler::Jump ownerNotMarkedOrAlreadyRemembered = m_jit.checkMarkByte(owner);
</span><span class="cx">     storeToWriteBarrierBuffer(owner, scratch1, scratch2);
</span><span class="cx">     ownerNotMarkedOrAlreadyRemembered.link(&amp;m_jit);
</span><span class="lines">@@ -5081,6 +5077,49 @@
</span><span class="cx"> }
</span><span class="cx"> #endif // ENABLE(GGC)
</span><span class="cx"> 
</span><ins>+JITCompiler::Jump SpeculativeJIT::branchIsCell(JSValueRegs regs)
+{
+    return m_jit.branchTest64(MacroAssembler::Zero, regs.gpr(), GPRInfo::tagMaskRegister);
+}
+
+JITCompiler::Jump SpeculativeJIT::branchNotCell(JSValueRegs regs)
+{
+    return m_jit.branchTest64(MacroAssembler::NonZero, regs.gpr(), GPRInfo::tagMaskRegister);
+}
+
+JITCompiler::Jump SpeculativeJIT::branchIsOther(JSValueRegs regs, GPRReg tempGPR)
+{
+    m_jit.move(regs.gpr(), tempGPR);
+    m_jit.and64(MacroAssembler::TrustedImm32(~TagBitUndefined), tempGPR);
+    return m_jit.branch64(
+        MacroAssembler::Equal, tempGPR,
+        MacroAssembler::TrustedImm64(ValueNull));
+}
+
+JITCompiler::Jump SpeculativeJIT::branchNotOther(JSValueRegs regs, GPRReg tempGPR)
+{
+    m_jit.move(regs.gpr(), tempGPR);
+    m_jit.and64(MacroAssembler::TrustedImm32(~TagBitUndefined), tempGPR);
+    return m_jit.branch64(
+        MacroAssembler::NotEqual, tempGPR,
+        MacroAssembler::TrustedImm64(ValueNull));
+}
+
+void SpeculativeJIT::moveTrueTo(GPRReg gpr)
+{
+    m_jit.move(TrustedImm32(ValueTrue), gpr);
+}
+
+void SpeculativeJIT::moveFalseTo(GPRReg gpr)
+{
+    m_jit.move(TrustedImm32(ValueFalse), gpr);
+}
+
+void SpeculativeJIT::blessBoolean(GPRReg gpr)
+{
+    m_jit.or32(TrustedImm32(ValueFalse), gpr);
+}
+
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> } } // namespace JSC::DFG
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGUseKindcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGUseKind.cpp (165841 => 165842)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGUseKind.cpp        2014-03-18 20:45:27 UTC (rev 165841)
+++ trunk/Source/JavaScriptCore/dfg/DFGUseKind.cpp        2014-03-18 20:53:07 UTC (rev 165842)
</span><span class="lines">@@ -91,6 +91,9 @@
</span><span class="cx">     case StringOrStringObjectUse:
</span><span class="cx">         out.print(&quot;StringOrStringObject&quot;);
</span><span class="cx">         break;
</span><ins>+    case NotStringVarUse:
+        out.print(&quot;NotStringVar&quot;);
+        break;
</ins><span class="cx">     case NotCellUse:
</span><span class="cx">         out.print(&quot;NotCell&quot;);
</span><span class="cx">         break;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGUseKindh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGUseKind.h (165841 => 165842)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGUseKind.h        2014-03-18 20:45:27 UTC (rev 165841)
+++ trunk/Source/JavaScriptCore/dfg/DFGUseKind.h        2014-03-18 20:53:07 UTC (rev 165842)
</span><span class="lines">@@ -52,6 +52,7 @@
</span><span class="cx">     KnownStringUse,
</span><span class="cx">     StringObjectUse,
</span><span class="cx">     StringOrStringObjectUse,
</span><ins>+    NotStringVarUse,
</ins><span class="cx">     NotCellUse,
</span><span class="cx">     OtherUse,
</span><span class="cx">     MiscUse,
</span><span class="lines">@@ -93,6 +94,8 @@
</span><span class="cx">         return SpecStringObject;
</span><span class="cx">     case StringOrStringObjectUse:
</span><span class="cx">         return SpecString | SpecStringObject;
</span><ins>+    case NotStringVarUse:
+        return ~SpecStringVar;
</ins><span class="cx">     case NotCellUse:
</span><span class="cx">         return ~SpecCell;
</span><span class="cx">     case OtherUse:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLCapabilitiescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp (165841 => 165842)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp        2014-03-18 20:45:27 UTC (rev 165841)
+++ trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp        2014-03-18 20:53:07 UTC (rev 165842)
</span><span class="lines">@@ -238,6 +238,8 @@
</span><span class="cx">             break;
</span><span class="cx">         if (node-&gt;isBinaryUseKind(NumberUse))
</span><span class="cx">             break;
</span><ins>+        if (node-&gt;isBinaryUseKind(StringIdentUse))
+            break;
</ins><span class="cx">         if (node-&gt;isBinaryUseKind(ObjectUse))
</span><span class="cx">             break;
</span><span class="cx">         if (node-&gt;isBinaryUseKind(UntypedUse))
</span><span class="lines">@@ -256,6 +258,8 @@
</span><span class="cx">             break;
</span><span class="cx">         if (node-&gt;isBinaryUseKind(NumberUse))
</span><span class="cx">             break;
</span><ins>+        if (node-&gt;isBinaryUseKind(StringIdentUse))
+            break;
</ins><span class="cx">         if (node-&gt;isBinaryUseKind(ObjectUse))
</span><span class="cx">             break;
</span><span class="cx">         if (node-&gt;isBinaryUseKind(BooleanUse))
</span><span class="lines">@@ -264,6 +268,10 @@
</span><span class="cx">             break;
</span><span class="cx">         if (node-&gt;isBinaryUseKind(UntypedUse, MiscUse))
</span><span class="cx">             break;
</span><ins>+        if (node-&gt;isBinaryUseKind(StringIdentUse, NotStringVarUse))
+            break;
+        if (node-&gt;isBinaryUseKind(NotStringVarUse, StringIdentUse))
+            break;
</ins><span class="cx">         return CannotCompile;
</span><span class="cx">     case CompareLess:
</span><span class="cx">     case CompareLessEq:
</span><span class="lines">@@ -358,6 +366,8 @@
</span><span class="cx">                 case NotCellUse:
</span><span class="cx">                 case OtherUse:
</span><span class="cx">                 case MiscUse:
</span><ins>+                case StringIdentUse:
+                case NotStringVarUse:
</ins><span class="cx">                     // These are OK.
</span><span class="cx">                     break;
</span><span class="cx">                 default:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLLowerDFGToLLVMcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp (165841 => 165842)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2014-03-18 20:45:27 UTC (rev 165841)
+++ trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2014-03-18 20:53:07 UTC (rev 165842)
</span><span class="lines">@@ -3364,7 +3364,8 @@
</span><span class="cx">             || m_node-&gt;isBinaryUseKind(MachineIntUse)
</span><span class="cx">             || m_node-&gt;isBinaryUseKind(NumberUse)
</span><span class="cx">             || m_node-&gt;isBinaryUseKind(ObjectUse)
</span><del>-            || m_node-&gt;isBinaryUseKind(BooleanUse)) {
</del><ins>+            || m_node-&gt;isBinaryUseKind(BooleanUse)
+            || m_node-&gt;isBinaryUseKind(StringIdentUse)) {
</ins><span class="cx">             compileCompareStrictEq();
</span><span class="cx">             return;
</span><span class="cx">         }
</span><span class="lines">@@ -3417,6 +3418,12 @@
</span><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx">         
</span><ins>+        if (m_node-&gt;isBinaryUseKind(StringIdentUse)) {
+            setBoolean(
+                m_out.equal(lowStringIdent(m_node-&gt;child1()), lowStringIdent(m_node-&gt;child2())));
+            return;
+        }
+        
</ins><span class="cx">         if (m_node-&gt;isBinaryUseKind(ObjectUse)) {
</span><span class="cx">             setBoolean(
</span><span class="cx">                 m_out.equal(
</span><span class="lines">@@ -3441,6 +3448,36 @@
</span><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx">         
</span><ins>+        if (m_node-&gt;isBinaryUseKind(StringIdentUse, NotStringVarUse)
+            || m_node-&gt;isBinaryUseKind(NotStringVarUse, StringIdentUse)) {
+            Edge leftEdge = m_node-&gt;childFor(StringIdentUse);
+            Edge rightEdge = m_node-&gt;childFor(NotStringVarUse);
+            
+            LValue left = lowStringIdent(leftEdge);
+            LValue rightValue = lowJSValue(rightEdge, ManualOperandSpeculation);
+            
+            LBasicBlock isCellCase = FTL_NEW_BLOCK(m_out, (&quot;CompareStrictEq StringIdent to NotStringVar is cell case&quot;));
+            LBasicBlock isStringCase = FTL_NEW_BLOCK(m_out, (&quot;CompareStrictEq StringIdent to NotStringVar is string case&quot;));
+            LBasicBlock continuation = FTL_NEW_BLOCK(m_out, (&quot;CompareStrictEq StringIdent to NotStringVar continuation&quot;));
+            
+            ValueFromBlock notCellResult = m_out.anchor(m_out.booleanFalse);
+            m_out.branch(isCell(rightValue), unsure(isCellCase), unsure(continuation));
+            
+            LBasicBlock lastNext = m_out.appendTo(isCellCase, isStringCase);
+            ValueFromBlock notStringResult = m_out.anchor(m_out.booleanFalse);
+            m_out.branch(isString(rightValue), unsure(isStringCase), unsure(continuation));
+            
+            m_out.appendTo(isStringCase, continuation);
+            LValue right = m_out.loadPtr(rightValue, m_heaps.JSString_value);
+            speculateStringIdent(rightEdge, rightValue, right);
+            ValueFromBlock isStringResult = m_out.anchor(m_out.equal(left, right));
+            m_out.jump(continuation);
+            
+            m_out.appendTo(continuation, lastNext);
+            setBoolean(m_out.phi(m_out.boolean, notCellResult, notStringResult, isStringResult));
+            return;
+        }
+        
</ins><span class="cx">         RELEASE_ASSERT_NOT_REACHED();
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="lines">@@ -4821,13 +4858,23 @@
</span><span class="cx">     
</span><span class="cx">     LValue lowString(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
</span><span class="cx">     {
</span><del>-        ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == StringUse || edge.useKind() == KnownStringUse);
</del><ins>+        ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == StringUse || edge.useKind() == KnownStringUse || edge.useKind() == StringIdentUse);
</ins><span class="cx">         
</span><span class="cx">         LValue result = lowCell(edge, mode);
</span><span class="cx">         speculateString(edge, result);
</span><span class="cx">         return result;
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+    LValue lowStringIdent(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
+    {
+        ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == StringIdentUse);
+        
+        LValue string = lowString(edge, mode);
+        LValue stringImpl = m_out.loadPtr(string, m_heaps.JSString_value);
+        speculateStringIdent(edge, string, stringImpl);
+        return stringImpl;
+    }
+    
</ins><span class="cx">     LValue lowNonNullObject(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
</span><span class="cx">     {
</span><span class="cx">         ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == ObjectUse);
</span><span class="lines">@@ -5189,6 +5236,9 @@
</span><span class="cx">         case StringUse:
</span><span class="cx">             speculateString(edge);
</span><span class="cx">             break;
</span><ins>+        case StringIdentUse:
+            speculateStringIdent(edge);
+            break;
</ins><span class="cx">         case StringObjectUse:
</span><span class="cx">             speculateStringObject(edge);
</span><span class="cx">             break;
</span><span class="lines">@@ -5207,6 +5257,9 @@
</span><span class="cx">         case BooleanUse:
</span><span class="cx">             speculateBoolean(edge);
</span><span class="cx">             break;
</span><ins>+        case NotStringVarUse:
+            speculateNotStringVar(edge);
+            break;
</ins><span class="cx">         case NotCellUse:
</span><span class="cx">             speculateNotCell(edge);
</span><span class="cx">             break;
</span><span class="lines">@@ -5366,7 +5419,7 @@
</span><span class="cx">     
</span><span class="cx">     void speculateString(Edge edge, LValue cell)
</span><span class="cx">     {
</span><del>-        FTL_TYPE_CHECK(jsValueValue(cell), edge, SpecString, isNotString(cell));
</del><ins>+        FTL_TYPE_CHECK(jsValueValue(cell), edge, SpecString | ~SpecCell, isNotString(cell));
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     void speculateString(Edge edge)
</span><span class="lines">@@ -5374,6 +5427,25 @@
</span><span class="cx">         speculateString(edge, lowCell(edge));
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+    void speculateStringIdent(Edge edge, LValue string, LValue stringImpl)
+    {
+        if (!m_interpreter.needsTypeCheck(edge, SpecStringIdent | ~SpecString))
+            return;
+        
+        speculate(BadType, jsValueValue(string), edge.node(), m_out.isNull(stringImpl));
+        speculate(
+            BadType, jsValueValue(string), edge.node(),
+            m_out.testIsZero32(
+                m_out.load32(stringImpl, m_heaps.StringImpl_hashAndFlags),
+                m_out.constInt32(StringImpl::flagIsIdentifier())));
+        m_interpreter.filter(edge, SpecStringIdent | ~SpecString);
+    }
+    
+    void speculateStringIdent(Edge edge)
+    {
+        lowStringIdent(edge);
+    }
+    
</ins><span class="cx">     void speculateStringObject(Edge edge)
</span><span class="cx">     {
</span><span class="cx">         if (!m_interpreter.needsTypeCheck(edge, SpecStringObject))
</span><span class="lines">@@ -5475,6 +5547,29 @@
</span><span class="cx">         lowBoolean(edge);
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+    void speculateNotStringVar(Edge edge)
+    {
+        if (!m_interpreter.needsTypeCheck(edge, ~SpecStringVar))
+            return;
+        
+        LValue value = lowJSValue(edge, ManualOperandSpeculation);
+        
+        LBasicBlock isCellCase = FTL_NEW_BLOCK(m_out, (&quot;Speculate NotStringVar is cell case&quot;));
+        LBasicBlock isStringCase = FTL_NEW_BLOCK(m_out, (&quot;Speculate NotStringVar is string case&quot;));
+        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, (&quot;Speculate NotStringVar continuation&quot;));
+        
+        m_out.branch(isCell(value), unsure(isCellCase), unsure(continuation));
+        
+        LBasicBlock lastNext = m_out.appendTo(isCellCase, isStringCase);
+        m_out.branch(isString(value), unsure(isStringCase), unsure(continuation));
+        
+        m_out.appendTo(isStringCase, continuation);
+        speculateStringIdent(edge, value, m_out.loadPtr(value, m_heaps.JSString_value));
+        m_out.jump(continuation);
+        
+        m_out.appendTo(continuation, lastNext);
+    }
+    
</ins><span class="cx">     void speculateNotCell(Edge edge)
</span><span class="cx">     {
</span><span class="cx">         if (!m_interpreter.needsTypeCheck(edge))
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSCJSValueh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSCJSValue.h (165841 => 165842)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSCJSValue.h        2014-03-18 20:45:27 UTC (rev 165841)
+++ trunk/Source/JavaScriptCore/runtime/JSCJSValue.h        2014-03-18 20:53:07 UTC (rev 165842)
</span><span class="lines">@@ -100,6 +100,12 @@
</span><span class="cx"> #define TagOffset (OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag))
</span><span class="cx"> #define PayloadOffset (OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload))
</span><span class="cx"> 
</span><ins>+#if USE(JSVALUE64)
+#define CellPayloadOffset 0
+#else
+#define CellPayloadOffset PayloadOffset
+#endif
+
</ins><span class="cx"> enum WhichValueWord {
</span><span class="cx">     TagWord,
</span><span class="cx">     PayloadWord
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressstringidenttonotstringvarequalityjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/string-ident-to-not-string-var-equality.js (0 => 165842)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/string-ident-to-not-string-var-equality.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/string-ident-to-not-string-var-equality.js        2014-03-18 20:53:07 UTC (rev 165842)
</span><span class="lines">@@ -0,0 +1,32 @@
</span><ins>+function foo(a, b) {
+    return a === b;
+}
+
+function bar(a, b) {
+    return b === a;
+}
+
+function test(a, b, expected) {
+    var fooActual = foo(a, b);
+    var barActual = bar(a, b);
+    
+    if (fooActual != expected)
+        throw new Error(&quot;Bad result: &quot; + fooActual);
+    if (barActual != expected)
+        throw new Error(&quot;Bad result: &quot; + barActual);
+}
+
+for (var i = 0; i &lt; 10000; ++i) {
+    test(&quot;foo&quot;, &quot;foo&quot;, true);
+    test(&quot;foo&quot;, &quot;bar&quot;, false);
+    test(&quot;fuz&quot;, 42, false);
+    test(&quot;buz&quot;, {}, false);
+    test(&quot;bla&quot;, null, false);
+}
+
+var fooString = &quot;&quot;;
+fooString += &quot;f&quot;;
+for (var i = 0; i &lt; 2; ++i)
+    fooString += &quot;o&quot;;
+
+test(fooString, &quot;foo&quot;, true);
</ins></span></pre>
</div>
</div>

</body>
</html>