<!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>[161126] 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/161126">161126</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2013-12-29 13:50:55 -0800 (Sun, 29 Dec 2013)</dd>
</dl>

<h3>Log Message</h3>
<pre>Get rid of DFG forward exiting
https://bugs.webkit.org/show_bug.cgi?id=125531

Reviewed by Oliver Hunt.
        
This finally gets rid of forward exiting. Forward exiting was always a fragile concept
since it involved the compiler trying to figure out how to &quot;roll forward&quot; the
execution from some DFG node to the next bytecode index. It was always easy to find
counterexamples where it broke, and it has always served as an obstacle to adding
compiler improvements - the latest being http://webkit.org/b/125523, which tried to
make DCE work for more things.
        
This change finishes the work of removing forward exiting. A lot of forward exiting
was already removed in some other bugs, but SetLocal still did forward exits. SetLocal
is in many ways the hardest to remove, since the forward exiting of SetLocal also
implied that any conversion nodes inserted before the SetLocal would then also be
marked as forward-exiting. Hence SetLocal's forward-exiting made a bunch of other
things also forward-exiting, and this was always a source of weirdo bugs.
        
SetLocal must be able to exit in case it performs a hoisted type speculation. Nodes
inserted just before SetLocal must also be able to exit - for example type check
hoisting may insert a CheckStructure, or fixup phase may insert something like
Int32ToDouble. But if any of those nodes tried to backward exit, then this could lead
to the reexecution of a side-effecting operation, for example:
        
    a: Call(...)
    b: SetLocal(@a, <a href="http://trac.webkit.org/projects/webkit/changeset/1">r1</a>)
        
For a long time it seemed like SetLocal *had* to exit forward because of this. But
this change side-steps the problem by changing the ByteCodeParser to always emit a
kind of &quot;two-phase commit&quot; for stores to local variables. Now when the ByteCodeParser
wishes to store to a local, it first emits a MovHint and then enqueues a SetLocal.
The SetLocal isn't actually emitted until the beginning of the next bytecode
instruction (which the exception of op_enter and op_ret, which emit theirs immediately
since it's always safe to reexecute those bytecode instructions and since deferring
SetLocals would be weird there - op_enter has many SetLocals and op_ret is a set
followed by a jump in case of inlining, so we'd have to emit the SetLocal &quot;after&quot; the
jump and that would be awkward). This means that the above IR snippet would look
something like:
        
    a: Call(..., bc#42)
    b: MovHint(@a, <a href="http://trac.webkit.org/projects/webkit/changeset/1">r1</a>, bc#42)
    c: SetLocal(@a, <a href="http://trac.webkit.org/projects/webkit/changeset/1">r1</a>, bc#47)
        
Where the SetLocal exits &quot;backwards&quot; but appears at the beginning of the next bytecode
instruction. This means that by the time we get to that SetLocal, the OSR exit
analysis already knows that <a href="http://trac.webkit.org/projects/webkit/changeset/1">r1</a> is associated with @a, and it means that the SetLocal
or anything hoisted above it can exit backwards as normal.
        
This change also means that the &quot;forward rewiring&quot; can be killed. Previously, we might
have inserted a conversion node on SetLocal and then the SetLocal died (i.e. turned
into a MovHint) and the conversion node either died completely or had its lifetime
truncated to be less than the actual value's bytecode lifetime. This no longer happens
since conversion nodes are only inserted at SetLocals.
        
More precisely, this change introduces two laws that we were basically already
following anyway:
        
1) A MovHint's child should never be changed except if all other uses of that child
   are also replaced. Specifically, this prohibits insertion of conversion nodes at
   MovHints.
        
2) Anytime any child is replaced with something else, and all other uses aren't also
   replaced, we must insert a Phantom use of the original child.

This is a slight compile-time regression but has no effect on code-gen. It unlocks a
bunch of optimization opportunities so I think it's worth it.

* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::dumpAssumingJITType):
* bytecode/CodeBlock.h:
(JSC::CodeBlock::instructionCount):
* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter&lt;AbstractStateType&gt;::executeEffects):
* dfg/DFGArgumentsSimplificationPhase.cpp:
(JSC::DFG::ArgumentsSimplificationPhase::run):
* dfg/DFGArrayifySlowPathGenerator.h:
(JSC::DFG::ArrayifySlowPathGenerator::ArrayifySlowPathGenerator):
* dfg/DFGBackwardsPropagationPhase.cpp:
(JSC::DFG::BackwardsPropagationPhase::propagate):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::setDirect):
(JSC::DFG::ByteCodeParser::DelayedSetLocal::DelayedSetLocal):
(JSC::DFG::ByteCodeParser::DelayedSetLocal::execute):
(JSC::DFG::ByteCodeParser::handleInlining):
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGCSEPhase.cpp:
(JSC::DFG::CSEPhase::eliminate):
* dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
* dfg/DFGCommon.h:
* dfg/DFGConstantFoldingPhase.cpp:
(JSC::DFG::ConstantFoldingPhase::foldConstants):
* dfg/DFGDCEPhase.cpp:
(JSC::DFG::DCEPhase::run):
(JSC::DFG::DCEPhase::fixupBlock):
(JSC::DFG::DCEPhase::cleanVariables):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
(JSC::DFG::FixupPhase::fixEdge):
(JSC::DFG::FixupPhase::injectInt32ToDoubleNode):
* dfg/DFGLICMPhase.cpp:
(JSC::DFG::LICMPhase::run):
(JSC::DFG::LICMPhase::attemptHoist):
* dfg/DFGMinifiedNode.cpp:
(JSC::DFG::MinifiedNode::fromNode):
* dfg/DFGMinifiedNode.h:
(JSC::DFG::belongsInMinifiedGraph):
(JSC::DFG::MinifiedNode::constantNumber):
(JSC::DFG::MinifiedNode::weakConstant):
* dfg/DFGNode.cpp:
(JSC::DFG::Node::hasVariableAccessData):
* dfg/DFGNode.h:
(JSC::DFG::Node::convertToPhantom):
(JSC::DFG::Node::convertToPhantomUnchecked):
(JSC::DFG::Node::convertToIdentity):
(JSC::DFG::Node::containsMovHint):
(JSC::DFG::Node::hasUnlinkedLocal):
(JSC::DFG::Node::willHaveCodeGenOrOSR):
* dfg/DFGNodeFlags.cpp:
(JSC::DFG::dumpNodeFlags):
* dfg/DFGNodeFlags.h:
* dfg/DFGNodeType.h:
* dfg/DFGOSRAvailabilityAnalysisPhase.cpp:
(JSC::DFG::OSRAvailabilityAnalysisPhase::run):
* dfg/DFGOSREntrypointCreationPhase.cpp:
(JSC::DFG::OSREntrypointCreationPhase::run):
* dfg/DFGOSRExit.cpp:
* dfg/DFGOSRExit.h:
* dfg/DFGOSRExitBase.cpp:
* dfg/DFGOSRExitBase.h:
(JSC::DFG::OSRExitBase::considerAddingAsFrequentExitSite):
* dfg/DFGPredictionPropagationPhase.cpp:
(JSC::DFG::PredictionPropagationPhase::propagate):
(JSC::DFG::PredictionPropagationPhase::doDoubleVoting):
* dfg/DFGSSAConversionPhase.cpp:
(JSC::DFG::SSAConversionPhase::run):
* dfg/DFGSafeToExecute.h:
(JSC::DFG::safeToExecute):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::speculationCheck):
(JSC::DFG::SpeculativeJIT::emitInvalidationPoint):
(JSC::DFG::SpeculativeJIT::typeCheck):
(JSC::DFG::SpeculativeJIT::compileMovHint):
(JSC::DFG::SpeculativeJIT::compileCurrentBlock):
(JSC::DFG::SpeculativeJIT::checkArgumentTypes):
(JSC::DFG::SpeculativeJIT::compileInt32ToDouble):
* dfg/DFGSpeculativeJIT.h:
(JSC::DFG::SpeculativeJIT::detectPeepHoleBranch):
(JSC::DFG::SpeculativeJIT::needsTypeCheck):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGTypeCheckHoistingPhase.cpp:
(JSC::DFG::TypeCheckHoistingPhase::run):
(JSC::DFG::TypeCheckHoistingPhase::identifyRedundantStructureChecks):
(JSC::DFG::TypeCheckHoistingPhase::identifyRedundantArrayChecks):
* dfg/DFGValidate.cpp:
(JSC::DFG::Validate::validateCPS):
* dfg/DFGVariableAccessData.h:
(JSC::DFG::VariableAccessData::VariableAccessData):
* dfg/DFGVariableEventStream.cpp:
(JSC::DFG::VariableEventStream::reconstruct):
* ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::LowerDFGToLLVM::compileNode):
(JSC::FTL::LowerDFGToLLVM::compileGetArgument):
(JSC::FTL::LowerDFGToLLVM::compileSetLocal):
(JSC::FTL::LowerDFGToLLVM::compileMovHint):
(JSC::FTL::LowerDFGToLLVM::compileZombieHint):
(JSC::FTL::LowerDFGToLLVM::compileInt32ToDouble):
(JSC::FTL::LowerDFGToLLVM::speculate):
(JSC::FTL::LowerDFGToLLVM::typeCheck):
(JSC::FTL::LowerDFGToLLVM::appendTypeCheck):
(JSC::FTL::LowerDFGToLLVM::appendOSRExit):
(JSC::FTL::LowerDFGToLLVM::emitOSRExitCall):
* ftl/FTLOSRExit.cpp:
* ftl/FTLOSRExit.h:
* tests/stress/dead-int32-to-double.js: Added.
(foo):
* tests/stress/dead-uint32-to-number.js: Added.
(foo):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCodeBlockcpp">trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCodeBlockh">trunk/Source/JavaScriptCore/bytecode/CodeBlock.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh">trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGArgumentsSimplificationPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGArgumentsSimplificationPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGArrayifySlowPathGeneratorh">trunk/Source/JavaScriptCore/dfg/DFGArrayifySlowPathGenerator.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGBackwardsPropagationPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGBackwardsPropagationPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp">trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGCSEPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGClobberizeh">trunk/Source/JavaScriptCore/dfg/DFGClobberize.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGCommonh">trunk/Source/JavaScriptCore/dfg/DFGCommon.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGConstantFoldingPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGDCEPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGDCEPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGFixupPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGLICMPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGLICMPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGMinifiedNodecpp">trunk/Source/JavaScriptCore/dfg/DFGMinifiedNode.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGMinifiedNodeh">trunk/Source/JavaScriptCore/dfg/DFGMinifiedNode.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGNodecpp">trunk/Source/JavaScriptCore/dfg/DFGNode.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGNodeh">trunk/Source/JavaScriptCore/dfg/DFGNode.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGNodeFlagscpp">trunk/Source/JavaScriptCore/dfg/DFGNodeFlags.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGNodeFlagsh">trunk/Source/JavaScriptCore/dfg/DFGNodeFlags.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGNodeTypeh">trunk/Source/JavaScriptCore/dfg/DFGNodeType.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGOSRAvailabilityAnalysisPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGOSRAvailabilityAnalysisPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGOSREntrypointCreationPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGOSREntrypointCreationPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGOSRExitcpp">trunk/Source/JavaScriptCore/dfg/DFGOSRExit.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGOSRExith">trunk/Source/JavaScriptCore/dfg/DFGOSRExit.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGOSRExitBasecpp">trunk/Source/JavaScriptCore/dfg/DFGOSRExitBase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGOSRExitBaseh">trunk/Source/JavaScriptCore/dfg/DFGOSRExitBase.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGPredictionPropagationPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSSAConversionPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGSSAConversionPhase.cpp</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="#trunkSourceJavaScriptCoredfgDFGTypeCheckHoistingPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGTypeCheckHoistingPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGValidatecpp">trunk/Source/JavaScriptCore/dfg/DFGValidate.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGVariableAccessDatah">trunk/Source/JavaScriptCore/dfg/DFGVariableAccessData.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGVariableEventStreamcpp">trunk/Source/JavaScriptCore/dfg/DFGVariableEventStream.cpp</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="#trunkSourceJavaScriptCoreftlFTLOSRExitcpp">trunk/Source/JavaScriptCore/ftl/FTLOSRExit.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLOSRExith">trunk/Source/JavaScriptCore/ftl/FTLOSRExit.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoretestsstressdeadint32todoublejs">trunk/Source/JavaScriptCore/tests/stress/dead-int32-to-double.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressdeaduint32tonumberjs">trunk/Source/JavaScriptCore/tests/stress/dead-uint32-to-number.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (161125 => 161126)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2013-12-29 21:49:03 UTC (rev 161125)
+++ trunk/Source/JavaScriptCore/ChangeLog        2013-12-29 21:50:55 UTC (rev 161126)
</span><span class="lines">@@ -1,3 +1,190 @@
</span><ins>+2013-12-28  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        Get rid of DFG forward exiting
+        https://bugs.webkit.org/show_bug.cgi?id=125531
+
+        Reviewed by Oliver Hunt.
+        
+        This finally gets rid of forward exiting. Forward exiting was always a fragile concept
+        since it involved the compiler trying to figure out how to &quot;roll forward&quot; the
+        execution from some DFG node to the next bytecode index. It was always easy to find
+        counterexamples where it broke, and it has always served as an obstacle to adding
+        compiler improvements - the latest being http://webkit.org/b/125523, which tried to
+        make DCE work for more things.
+        
+        This change finishes the work of removing forward exiting. A lot of forward exiting
+        was already removed in some other bugs, but SetLocal still did forward exits. SetLocal
+        is in many ways the hardest to remove, since the forward exiting of SetLocal also
+        implied that any conversion nodes inserted before the SetLocal would then also be
+        marked as forward-exiting. Hence SetLocal's forward-exiting made a bunch of other
+        things also forward-exiting, and this was always a source of weirdo bugs.
+        
+        SetLocal must be able to exit in case it performs a hoisted type speculation. Nodes
+        inserted just before SetLocal must also be able to exit - for example type check
+        hoisting may insert a CheckStructure, or fixup phase may insert something like
+        Int32ToDouble. But if any of those nodes tried to backward exit, then this could lead
+        to the reexecution of a side-effecting operation, for example:
+        
+            a: Call(...)
+            b: SetLocal(@a, r1)
+        
+        For a long time it seemed like SetLocal *had* to exit forward because of this. But
+        this change side-steps the problem by changing the ByteCodeParser to always emit a
+        kind of &quot;two-phase commit&quot; for stores to local variables. Now when the ByteCodeParser
+        wishes to store to a local, it first emits a MovHint and then enqueues a SetLocal.
+        The SetLocal isn't actually emitted until the beginning of the next bytecode
+        instruction (which the exception of op_enter and op_ret, which emit theirs immediately
+        since it's always safe to reexecute those bytecode instructions and since deferring
+        SetLocals would be weird there - op_enter has many SetLocals and op_ret is a set
+        followed by a jump in case of inlining, so we'd have to emit the SetLocal &quot;after&quot; the
+        jump and that would be awkward). This means that the above IR snippet would look
+        something like:
+        
+            a: Call(..., bc#42)
+            b: MovHint(@a, r1, bc#42)
+            c: SetLocal(@a, r1, bc#47)
+        
+        Where the SetLocal exits &quot;backwards&quot; but appears at the beginning of the next bytecode
+        instruction. This means that by the time we get to that SetLocal, the OSR exit
+        analysis already knows that r1 is associated with @a, and it means that the SetLocal
+        or anything hoisted above it can exit backwards as normal.
+        
+        This change also means that the &quot;forward rewiring&quot; can be killed. Previously, we might
+        have inserted a conversion node on SetLocal and then the SetLocal died (i.e. turned
+        into a MovHint) and the conversion node either died completely or had its lifetime
+        truncated to be less than the actual value's bytecode lifetime. This no longer happens
+        since conversion nodes are only inserted at SetLocals.
+        
+        More precisely, this change introduces two laws that we were basically already
+        following anyway:
+        
+        1) A MovHint's child should never be changed except if all other uses of that child
+           are also replaced. Specifically, this prohibits insertion of conversion nodes at
+           MovHints.
+        
+        2) Anytime any child is replaced with something else, and all other uses aren't also
+           replaced, we must insert a Phantom use of the original child.
+
+        This is a slight compile-time regression but has no effect on code-gen. It unlocks a
+        bunch of optimization opportunities so I think it's worth it.
+
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::dumpAssumingJITType):
+        * bytecode/CodeBlock.h:
+        (JSC::CodeBlock::instructionCount):
+        * dfg/DFGAbstractInterpreterInlines.h:
+        (JSC::DFG::AbstractInterpreter&lt;AbstractStateType&gt;::executeEffects):
+        * dfg/DFGArgumentsSimplificationPhase.cpp:
+        (JSC::DFG::ArgumentsSimplificationPhase::run):
+        * dfg/DFGArrayifySlowPathGenerator.h:
+        (JSC::DFG::ArrayifySlowPathGenerator::ArrayifySlowPathGenerator):
+        * dfg/DFGBackwardsPropagationPhase.cpp:
+        (JSC::DFG::BackwardsPropagationPhase::propagate):
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::setDirect):
+        (JSC::DFG::ByteCodeParser::DelayedSetLocal::DelayedSetLocal):
+        (JSC::DFG::ByteCodeParser::DelayedSetLocal::execute):
+        (JSC::DFG::ByteCodeParser::handleInlining):
+        (JSC::DFG::ByteCodeParser::parseBlock):
+        * dfg/DFGCSEPhase.cpp:
+        (JSC::DFG::CSEPhase::eliminate):
+        * dfg/DFGClobberize.h:
+        (JSC::DFG::clobberize):
+        * dfg/DFGCommon.h:
+        * dfg/DFGConstantFoldingPhase.cpp:
+        (JSC::DFG::ConstantFoldingPhase::foldConstants):
+        * dfg/DFGDCEPhase.cpp:
+        (JSC::DFG::DCEPhase::run):
+        (JSC::DFG::DCEPhase::fixupBlock):
+        (JSC::DFG::DCEPhase::cleanVariables):
+        * dfg/DFGFixupPhase.cpp:
+        (JSC::DFG::FixupPhase::fixupNode):
+        (JSC::DFG::FixupPhase::fixEdge):
+        (JSC::DFG::FixupPhase::injectInt32ToDoubleNode):
+        * dfg/DFGLICMPhase.cpp:
+        (JSC::DFG::LICMPhase::run):
+        (JSC::DFG::LICMPhase::attemptHoist):
+        * dfg/DFGMinifiedNode.cpp:
+        (JSC::DFG::MinifiedNode::fromNode):
+        * dfg/DFGMinifiedNode.h:
+        (JSC::DFG::belongsInMinifiedGraph):
+        (JSC::DFG::MinifiedNode::constantNumber):
+        (JSC::DFG::MinifiedNode::weakConstant):
+        * dfg/DFGNode.cpp:
+        (JSC::DFG::Node::hasVariableAccessData):
+        * dfg/DFGNode.h:
+        (JSC::DFG::Node::convertToPhantom):
+        (JSC::DFG::Node::convertToPhantomUnchecked):
+        (JSC::DFG::Node::convertToIdentity):
+        (JSC::DFG::Node::containsMovHint):
+        (JSC::DFG::Node::hasUnlinkedLocal):
+        (JSC::DFG::Node::willHaveCodeGenOrOSR):
+        * dfg/DFGNodeFlags.cpp:
+        (JSC::DFG::dumpNodeFlags):
+        * dfg/DFGNodeFlags.h:
+        * dfg/DFGNodeType.h:
+        * dfg/DFGOSRAvailabilityAnalysisPhase.cpp:
+        (JSC::DFG::OSRAvailabilityAnalysisPhase::run):
+        * dfg/DFGOSREntrypointCreationPhase.cpp:
+        (JSC::DFG::OSREntrypointCreationPhase::run):
+        * dfg/DFGOSRExit.cpp:
+        * dfg/DFGOSRExit.h:
+        * dfg/DFGOSRExitBase.cpp:
+        * dfg/DFGOSRExitBase.h:
+        (JSC::DFG::OSRExitBase::considerAddingAsFrequentExitSite):
+        * dfg/DFGPredictionPropagationPhase.cpp:
+        (JSC::DFG::PredictionPropagationPhase::propagate):
+        (JSC::DFG::PredictionPropagationPhase::doDoubleVoting):
+        * dfg/DFGSSAConversionPhase.cpp:
+        (JSC::DFG::SSAConversionPhase::run):
+        * dfg/DFGSafeToExecute.h:
+        (JSC::DFG::safeToExecute):
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::speculationCheck):
+        (JSC::DFG::SpeculativeJIT::emitInvalidationPoint):
+        (JSC::DFG::SpeculativeJIT::typeCheck):
+        (JSC::DFG::SpeculativeJIT::compileMovHint):
+        (JSC::DFG::SpeculativeJIT::compileCurrentBlock):
+        (JSC::DFG::SpeculativeJIT::checkArgumentTypes):
+        (JSC::DFG::SpeculativeJIT::compileInt32ToDouble):
+        * dfg/DFGSpeculativeJIT.h:
+        (JSC::DFG::SpeculativeJIT::detectPeepHoleBranch):
+        (JSC::DFG::SpeculativeJIT::needsTypeCheck):
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGTypeCheckHoistingPhase.cpp:
+        (JSC::DFG::TypeCheckHoistingPhase::run):
+        (JSC::DFG::TypeCheckHoistingPhase::identifyRedundantStructureChecks):
+        (JSC::DFG::TypeCheckHoistingPhase::identifyRedundantArrayChecks):
+        * dfg/DFGValidate.cpp:
+        (JSC::DFG::Validate::validateCPS):
+        * dfg/DFGVariableAccessData.h:
+        (JSC::DFG::VariableAccessData::VariableAccessData):
+        * dfg/DFGVariableEventStream.cpp:
+        (JSC::DFG::VariableEventStream::reconstruct):
+        * ftl/FTLCapabilities.cpp:
+        (JSC::FTL::canCompile):
+        * ftl/FTLLowerDFGToLLVM.cpp:
+        (JSC::FTL::LowerDFGToLLVM::compileNode):
+        (JSC::FTL::LowerDFGToLLVM::compileGetArgument):
+        (JSC::FTL::LowerDFGToLLVM::compileSetLocal):
+        (JSC::FTL::LowerDFGToLLVM::compileMovHint):
+        (JSC::FTL::LowerDFGToLLVM::compileZombieHint):
+        (JSC::FTL::LowerDFGToLLVM::compileInt32ToDouble):
+        (JSC::FTL::LowerDFGToLLVM::speculate):
+        (JSC::FTL::LowerDFGToLLVM::typeCheck):
+        (JSC::FTL::LowerDFGToLLVM::appendTypeCheck):
+        (JSC::FTL::LowerDFGToLLVM::appendOSRExit):
+        (JSC::FTL::LowerDFGToLLVM::emitOSRExitCall):
+        * ftl/FTLOSRExit.cpp:
+        * ftl/FTLOSRExit.h:
+        * tests/stress/dead-int32-to-double.js: Added.
+        (foo):
+        * tests/stress/dead-uint32-to-number.js: Added.
+        (foo):
+
</ins><span class="cx"> 2013-12-25  Commit Queue  &lt;commit-queue@webkit.org&gt;
</span><span class="cx"> 
</span><span class="cx">         Unreviewed, rolling out r161033 and r161074.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCodeBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp (161125 => 161126)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2013-12-29 21:49:03 UTC (rev 161125)
+++ trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2013-12-29 21:50:55 UTC (rev 161126)
</span><span class="lines">@@ -135,6 +135,7 @@
</span><span class="cx"> 
</span><span class="cx">     if (codeType() == FunctionCode)
</span><span class="cx">         out.print(specializationKind());
</span><ins>+    out.print(&quot;, &quot;, instructionCount());
</ins><span class="cx">     if (this-&gt;jitType() == JITCode::BaselineJIT &amp;&amp; m_shouldAlwaysBeInlined)
</span><span class="cx">         out.print(&quot; (SABI)&quot;);
</span><span class="cx">     if (ownerExecutable()-&gt;neverInline())
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCodeBlockh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeBlock.h (161125 => 161126)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeBlock.h        2013-12-29 21:49:03 UTC (rev 161125)
+++ trunk/Source/JavaScriptCore/bytecode/CodeBlock.h        2013-12-29 21:50:55 UTC (rev 161126)
</span><span class="lines">@@ -244,7 +244,7 @@
</span><span class="cx"> 
</span><span class="cx">     bool usesOpcode(OpcodeID);
</span><span class="cx"> 
</span><del>-    unsigned instructionCount() { return m_instructions.size(); }
</del><ins>+    unsigned instructionCount() const { return m_instructions.size(); }
</ins><span class="cx"> 
</span><span class="cx">     int argumentIndexAfterCapture(size_t argument);
</span><span class="cx">     
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h (161125 => 161126)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2013-12-29 21:49:03 UTC (rev 161125)
+++ trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2013-12-29 21:50:55 UTC (rev 161126)
</span><span class="lines">@@ -195,10 +195,10 @@
</span><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx">         
</span><del>-    case MovHint:
-    case MovHintAndCheck: {
-        // Don't need to do anything. A MovHint is effectively a promise that the SetLocal
-        // was dead.
</del><ins>+    case MovHint: {
+        // Don't need to do anything. A MovHint only informs us about what would have happened
+        // in bytecode, but this code is just concerned with what is actually happening during
+        // DFG execution.
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx">         
</span><span class="lines">@@ -1583,6 +1583,7 @@
</span><span class="cx">         break;
</span><span class="cx">             
</span><span class="cx">     case Phantom:
</span><ins>+    case Check:
</ins><span class="cx">     case CountExecution:
</span><span class="cx">     case CheckTierUpInLoop:
</span><span class="cx">     case CheckTierUpAtReturn:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGArgumentsSimplificationPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGArgumentsSimplificationPhase.cpp (161125 => 161126)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGArgumentsSimplificationPhase.cpp        2013-12-29 21:49:03 UTC (rev 161125)
+++ trunk/Source/JavaScriptCore/dfg/DFGArgumentsSimplificationPhase.cpp        2013-12-29 21:50:55 UTC (rev 161126)
</span><span class="lines">@@ -333,6 +333,11 @@
</span><span class="cx">                     // structures of another variable.
</span><span class="cx">                     break;
</span><span class="cx">                     
</span><ins>+                case MovHint:
+                    // We don't care about MovHints at all, since they represent what happens
+                    // in bytecode. We rematerialize arguments objects on OSR exit anyway.
+                    break;
+                    
</ins><span class="cx">                 default:
</span><span class="cx">                     observeBadArgumentsUses(node);
</span><span class="cx">                     break;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGArrayifySlowPathGeneratorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGArrayifySlowPathGenerator.h (161125 => 161126)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGArrayifySlowPathGenerator.h        2013-12-29 21:49:03 UTC (rev 161125)
+++ trunk/Source/JavaScriptCore/dfg/DFGArrayifySlowPathGenerator.h        2013-12-29 21:50:55 UTC (rev 161126)
</span><span class="lines">@@ -63,13 +63,13 @@
</span><span class="cx">             case Array::Int32:
</span><span class="cx">             case Array::Double:
</span><span class="cx">             case Array::Contiguous:
</span><del>-                m_badPropertyJump = jit-&gt;backwardSpeculationCheck(Uncountable, JSValueRegs(), 0);
</del><ins>+                m_badPropertyJump = jit-&gt;speculationCheck(Uncountable, JSValueRegs(), 0);
</ins><span class="cx">                 break;
</span><span class="cx">             default:
</span><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx">         }
</span><del>-        m_badIndexingTypeJump = jit-&gt;backwardSpeculationCheck(BadIndexingType, JSValueSource::unboxedCell(m_baseGPR), 0);
</del><ins>+        m_badIndexingTypeJump = jit-&gt;speculationCheck(BadIndexingType, JSValueSource::unboxedCell(m_baseGPR), 0);
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx"> protected:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGBackwardsPropagationPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGBackwardsPropagationPhase.cpp (161125 => 161126)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGBackwardsPropagationPhase.cpp        2013-12-29 21:49:03 UTC (rev 161125)
+++ trunk/Source/JavaScriptCore/dfg/DFGBackwardsPropagationPhase.cpp        2013-12-29 21:50:55 UTC (rev 161126)
</span><span class="lines">@@ -187,6 +187,10 @@
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">             
</span><ins>+        case MovHint:
+        case Check:
+            break;
+            
</ins><span class="cx">         case BitAnd:
</span><span class="cx">         case BitOr:
</span><span class="cx">         case BitXor:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp (161125 => 161126)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2013-12-29 21:49:03 UTC (rev 161125)
+++ trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2013-12-29 21:50:55 UTC (rev 161126)
</span><span class="lines">@@ -232,15 +232,19 @@
</span><span class="cx">         return getDirect(m_inlineStackTop-&gt;remapOperand(operand));
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    enum SetMode { NormalSet, SetOnEntry };
</del><ins>+    enum SetMode { NormalSet, ImmediateSet };
</ins><span class="cx">     Node* setDirect(VirtualRegister operand, Node* value, SetMode setMode = NormalSet)
</span><span class="cx">     {
</span><del>-        // Is this an argument?
-        if (operand.isArgument())
-            return setArgument(operand, value, setMode);
-
-        // Must be a local.
-        return setLocal(operand, value, setMode);
</del><ins>+        addToGraph(MovHint, OpInfo(operand.offset()), value);
+        
+        DelayedSetLocal delayed = DelayedSetLocal(operand, value);
+        
+        if (setMode == NormalSet) {
+            m_setLocalQueue.append(delayed);
+            return 0;
+        }
+        
+        return delayed.execute(this, setMode);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     Node* set(VirtualRegister operand, Node* value, SetMode setMode = NormalSet)
</span><span class="lines">@@ -1121,6 +1125,27 @@
</span><span class="cx">     };
</span><span class="cx">     
</span><span class="cx">     InlineStackEntry* m_inlineStackTop;
</span><ins>+    
+    struct DelayedSetLocal {
+        VirtualRegister m_operand;
+        Node* m_value;
+        
+        DelayedSetLocal() { }
+        DelayedSetLocal(VirtualRegister operand, Node* value)
+            : m_operand(operand)
+            , m_value(value)
+        {
+        }
+        
+        Node* execute(ByteCodeParser* parser, SetMode setMode = NormalSet)
+        {
+            if (m_operand.isArgument())
+                return parser-&gt;setArgument(m_operand, m_value, setMode);
+            return parser-&gt;setLocal(m_operand, m_value, setMode);
+        }
+    };
+    
+    Vector&lt;DelayedSetLocal, 2&gt; m_setLocalQueue;
</ins><span class="cx"> 
</span><span class="cx">     // Have we built operand maps? We initialize them lazily, and only when doing
</span><span class="cx">     // inlining.
</span><span class="lines">@@ -1325,9 +1350,9 @@
</span><span class="cx">         == callLinkStatus.isClosureCall());
</span><span class="cx">     if (callLinkStatus.isClosureCall()) {
</span><span class="cx">         VariableAccessData* calleeVariable =
</span><del>-            set(VirtualRegister(JSStack::Callee), callTargetNode)-&gt;variableAccessData();
</del><ins>+            set(VirtualRegister(JSStack::Callee), callTargetNode, ImmediateSet)-&gt;variableAccessData();
</ins><span class="cx">         VariableAccessData* scopeVariable =
</span><del>-            set(VirtualRegister(JSStack::ScopeChain), addToGraph(GetScope, callTargetNode))-&gt;variableAccessData();
</del><ins>+            set(VirtualRegister(JSStack::ScopeChain), addToGraph(GetScope, callTargetNode), ImmediateSet)-&gt;variableAccessData();
</ins><span class="cx">         
</span><span class="cx">         calleeVariable-&gt;mergeShouldNeverUnbox(true);
</span><span class="cx">         scopeVariable-&gt;mergeShouldNeverUnbox(true);
</span><span class="lines">@@ -1872,6 +1897,10 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     while (true) {
</span><ins>+        for (unsigned i = 0; i &lt; m_setLocalQueue.size(); ++i)
+            m_setLocalQueue[i].execute(this);
+        m_setLocalQueue.resize(0);
+        
</ins><span class="cx">         // Don't extend over jump destinations.
</span><span class="cx">         if (m_currentIndex == limit) {
</span><span class="cx">             // Ordinarily we want to plant a jump. But refuse to do this if the block is
</span><span class="lines">@@ -1903,7 +1932,7 @@
</span><span class="cx">         case op_enter:
</span><span class="cx">             // Initialize all locals to undefined.
</span><span class="cx">             for (int i = 0; i &lt; m_inlineStackTop-&gt;m_codeBlock-&gt;m_numVars; ++i)
</span><del>-                set(virtualRegisterForLocal(i), constantUndefined(), SetOnEntry);
</del><ins>+                set(virtualRegisterForLocal(i), constantUndefined(), ImmediateSet);
</ins><span class="cx">             NEXT_OPCODE(op_enter);
</span><span class="cx">             
</span><span class="cx">         case op_touch_entry:
</span><span class="lines">@@ -2908,7 +2937,7 @@
</span><span class="cx">             flushArgumentsAndCapturedVariables();
</span><span class="cx">             if (inlineCallFrame()) {
</span><span class="cx">                 ASSERT(m_inlineStackTop-&gt;m_returnValue.isValid());
</span><del>-                setDirect(m_inlineStackTop-&gt;m_returnValue, get(VirtualRegister(currentInstruction[1].u.operand)));
</del><ins>+                setDirect(m_inlineStackTop-&gt;m_returnValue, get(VirtualRegister(currentInstruction[1].u.operand)), ImmediateSet);
</ins><span class="cx">                 m_inlineStackTop-&gt;m_didReturn = true;
</span><span class="cx">                 if (m_inlineStackTop-&gt;m_unlinkedBlocks.isEmpty()) {
</span><span class="cx">                     // If we're returning from the first block, then we're done parsing.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGCSEPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp (161125 => 161126)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp        2013-12-29 21:49:03 UTC (rev 161125)
+++ trunk/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp        2013-12-29 21:50:55 UTC (rev 161126)
</span><span class="lines">@@ -1051,7 +1051,7 @@
</span><span class="cx">         if (!node)
</span><span class="cx">             return;
</span><span class="cx">         ASSERT(node-&gt;mustGenerate());
</span><del>-        node-&gt;setOpAndDefaultNonExitFlags(phantomType);
</del><ins>+        node-&gt;setOpAndDefaultFlags(phantomType);
</ins><span class="cx">         if (phantomType == Phantom)
</span><span class="cx">             eliminateIrrelevantPhantomChildren(node);
</span><span class="cx">         
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGClobberizeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGClobberize.h (161125 => 161126)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGClobberize.h        2013-12-29 21:49:03 UTC (rev 161125)
+++ trunk/Source/JavaScriptCore/dfg/DFGClobberize.h        2013-12-29 21:50:55 UTC (rev 161126)
</span><span class="lines">@@ -129,9 +129,9 @@
</span><span class="cx">     case ConstantStoragePointer:
</span><span class="cx">     case UInt32ToNumber:
</span><span class="cx">     case DoubleAsInt32:
</span><ins>+    case Check:
</ins><span class="cx">         return;
</span><span class="cx">         
</span><del>-    case MovHintAndCheck:
</del><span class="cx">     case MovHint:
</span><span class="cx">     case ZombieHint:
</span><span class="cx">     case Upsilon:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGCommonh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGCommon.h (161125 => 161126)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGCommon.h        2013-12-29 21:49:03 UTC (rev 161125)
+++ trunk/Source/JavaScriptCore/dfg/DFGCommon.h        2013-12-29 21:50:55 UTC (rev 161126)
</span><span class="lines">@@ -182,8 +182,6 @@
</span><span class="cx"> 
</span><span class="cx"> enum OperandSpeculationMode { AutomaticOperandSpeculation, ManualOperandSpeculation };
</span><span class="cx"> 
</span><del>-enum SpeculationDirection { ForwardSpeculation, BackwardSpeculation };
-
</del><span class="cx"> enum ProofStatus { NeedsCheck, IsProved };
</span><span class="cx"> 
</span><span class="cx"> inline bool isProved(ProofStatus proofStatus)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGConstantFoldingPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp (161125 => 161126)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp        2013-12-29 21:49:03 UTC (rev 161125)
+++ trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp        2013-12-29 21:50:55 UTC (rev 161126)
</span><span class="lines">@@ -110,12 +110,8 @@
</span><span class="cx">                     m_interpreter.execute(indexInBlock); // Catch the fact that we may filter on cell.
</span><span class="cx">                     AdjacencyList children = node-&gt;children;
</span><span class="cx">                     children.removeEdge(0);
</span><del>-                    if (!!children.child1()) {
-                        Node phantom(Phantom, node-&gt;codeOrigin, children);
-                        if (node-&gt;flags() &amp; NodeExitsForward)
-                            phantom.mergeFlags(NodeExitsForward);
-                        m_insertionSet.insertNode(indexInBlock, SpecNone, phantom);
-                    }
</del><ins>+                    if (!!children.child1())
+                        m_insertionSet.insertNode(indexInBlock, SpecNone, Phantom, node-&gt;codeOrigin, children);
</ins><span class="cx">                     node-&gt;children.setChild2(Edge());
</span><span class="cx">                     node-&gt;children.setChild3(Edge());
</span><span class="cx">                     node-&gt;convertToStructureTransitionWatchpoint(structure);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGDCEPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGDCEPhase.cpp (161125 => 161126)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGDCEPhase.cpp        2013-12-29 21:49:03 UTC (rev 161125)
+++ trunk/Source/JavaScriptCore/dfg/DFGDCEPhase.cpp        2013-12-29 21:50:55 UTC (rev 161126)
</span><span class="lines">@@ -113,8 +113,12 @@
</span><span class="cx">             for (unsigned i = depthFirst.size(); i--;)
</span><span class="cx">                 fixupBlock(depthFirst[i]);
</span><span class="cx">         } else {
</span><ins>+            RELEASE_ASSERT(m_graph.m_form == ThreadedCPS);
+            
</ins><span class="cx">             for (BlockIndex blockIndex = 0; blockIndex &lt; m_graph.numBlocks(); ++blockIndex)
</span><span class="cx">                 fixupBlock(m_graph.block(blockIndex));
</span><ins>+            
+            cleanVariables(m_graph.m_arguments);
</ins><span class="cx">         }
</span><span class="cx">         
</span><span class="cx">         m_graph.m_refCountState = ExactRefCount;
</span><span class="lines">@@ -152,6 +156,36 @@
</span><span class="cx">     {
</span><span class="cx">         if (!block)
</span><span class="cx">             return;
</span><ins>+        
+        switch (m_graph.m_form) {
+        case SSA:
+            break;
+            
+        case ThreadedCPS: {
+            // Clean up variable links for the block. We need to do this before the actual DCE
+            // because we need to see GetLocals, so we can bypass them in situations where the
+            // vars-at-tail point to a GetLocal, the GetLocal is dead, but the Phi it points
+            // to is alive.
+            
+            for (unsigned phiIndex = 0; phiIndex &lt; block-&gt;phis.size(); ++phiIndex) {
+                if (!block-&gt;phis[phiIndex]-&gt;shouldGenerate()) {
+                    // FIXME: We could actually free nodes here. Except that it probably
+                    // doesn't matter, since we don't add any nodes after this phase.
+                    // https://bugs.webkit.org/show_bug.cgi?id=126239
+                    block-&gt;phis[phiIndex--] = block-&gt;phis.last();
+                    block-&gt;phis.removeLast();
+                }
+            }
+            
+            cleanVariables(block-&gt;variablesAtHead);
+            cleanVariables(block-&gt;variablesAtTail);
+            break;
+        }
+            
+        default:
+            RELEASE_ASSERT_NOT_REACHED();
+            return;
+        }
</ins><span class="cx"> 
</span><span class="cx">         for (unsigned indexInBlock = block-&gt;size(); indexInBlock--;) {
</span><span class="cx">             Node* node = block-&gt;at(indexInBlock);
</span><span class="lines">@@ -159,37 +193,23 @@
</span><span class="cx">                 continue;
</span><span class="cx">                 
</span><span class="cx">             switch (node-&gt;op()) {
</span><del>-            case SetLocal:
</del><span class="cx">             case MovHint: {
</span><del>-                ASSERT((node-&gt;op() == SetLocal) == (m_graph.m_form == ThreadedCPS));
-                if (node-&gt;child1().willNotHaveCheck()) {
-                    // Consider the possibility that UInt32ToNumber is dead but its
-                    // child isn't; if so then we should MovHint the child.
-                    if (!node-&gt;child1()-&gt;shouldGenerate()
-                        &amp;&amp; permitsOSRBackwardRewiring(node-&gt;child1()-&gt;op()))
-                        node-&gt;child1() = node-&gt;child1()-&gt;child1();
-
-                    if (!node-&gt;child1()-&gt;shouldGenerate()) {
-                        node-&gt;setOpAndDefaultFlags(ZombieHint);
-                        node-&gt;child1() = Edge();
-                        break;
-                    }
-                    node-&gt;setOpAndDefaultFlags(MovHint);
</del><ins>+                ASSERT(node-&gt;child1().useKind() == UntypedUse);
+                if (!node-&gt;child1()-&gt;shouldGenerate()) {
+                    node-&gt;setOpAndDefaultFlags(ZombieHint);
+                    node-&gt;child1() = Edge();
</ins><span class="cx">                     break;
</span><span class="cx">                 }
</span><del>-                node-&gt;setOpAndDefaultFlags(MovHintAndCheck);
-                node-&gt;setRefCount(1);
</del><ins>+                node-&gt;setOpAndDefaultFlags(MovHint);
</ins><span class="cx">                 break;
</span><span class="cx">             }
</span><del>-                    
-            case GetLocal:
-            case SetArgument: {
-                if (m_graph.m_form == ThreadedCPS) {
-                    // Leave them as not shouldGenerate.
-                    break;
-                }
</del><ins>+                
+            case ZombieHint: {
+                // Currently we assume that DCE runs only once.
+                RELEASE_ASSERT_NOT_REACHED();
+                break;
</ins><span class="cx">             }
</span><del>-
</del><ins>+            
</ins><span class="cx">             default: {
</span><span class="cx">                 if (node-&gt;flags() &amp; NodeHasVarArgs) {
</span><span class="cx">                     for (unsigned childIdx = node-&gt;firstChild(); childIdx &lt; node-&gt;firstChild() + node-&gt;numChildren(); childIdx++) {
</span><span class="lines">@@ -228,6 +248,27 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+    template&lt;typename VariablesVectorType&gt;
+    void cleanVariables(VariablesVectorType&amp; variables)
+    {
+        for (unsigned i = variables.size(); i--;) {
+            Node* node = variables[i];
+            if (!node)
+                continue;
+            if (node-&gt;op() != Phantom &amp;&amp; node-&gt;shouldGenerate())
+                continue;
+            if (node-&gt;op() == GetLocal) {
+                node = node-&gt;child1().node();
+                ASSERT(node-&gt;op() == Phi);
+                if (node-&gt;shouldGenerate()) {
+                    variables[i] = node;
+                    continue;
+                }
+            }
+            variables[i] = 0;
+        }
+    }
+    
</ins><span class="cx">     Vector&lt;Node*, 128&gt; m_worklist;
</span><span class="cx">     InsertionSet m_insertionSet;
</span><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGFixupPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp (161125 => 161126)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2013-12-29 21:49:03 UTC (rev 161125)
+++ trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2013-12-29 21:50:55 UTC (rev 161126)
</span><span class="lines">@@ -886,7 +886,8 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         case Phantom:
</span><del>-        case Identity: {
</del><ins>+        case Identity:
+        case Check: {
</ins><span class="cx">             switch (node-&gt;child1().useKind()) {
</span><span class="cx">             case NumberUse:
</span><span class="cx">                 if (node-&gt;child1()-&gt;shouldSpeculateInt32ForArithmetic())
</span><span class="lines">@@ -907,9 +908,6 @@
</span><span class="cx">         case GetIndexedPropertyStorage:
</span><span class="cx">         case GetTypedArrayByteOffset:
</span><span class="cx">         case LastNodeType:
</span><del>-        case MovHint:
-        case MovHintAndCheck:
-        case ZombieHint:
</del><span class="cx">         case CheckTierUpInLoop:
</span><span class="cx">         case CheckTierUpAtReturn:
</span><span class="cx">         case CheckTierUpAndOSREnter:
</span><span class="lines">@@ -951,7 +949,7 @@
</span><span class="cx">                 observeUseKindOnNode&lt;StringUse&gt;(node);
</span><span class="cx">             }
</span><span class="cx">             break;
</span><del>-
</del><ins>+            
</ins><span class="cx"> #if !ASSERT_DISABLED
</span><span class="cx">         // Have these no-op cases here to ensure that nobody forgets to add handlers for new opcodes.
</span><span class="cx">         case SetArgument:
</span><span class="lines">@@ -1005,6 +1003,8 @@
</span><span class="cx">         case StoreBarrierWithNullCheck:
</span><span class="cx">         case FunctionReentryWatchpoint:
</span><span class="cx">         case TypedArrayWatchpoint:
</span><ins>+        case MovHint:
+        case ZombieHint:
</ins><span class="cx">             break;
</span><span class="cx"> #else
</span><span class="cx">         default:
</span><span class="lines">@@ -1012,7 +1012,8 @@
</span><span class="cx"> #endif
</span><span class="cx">         }
</span><span class="cx">         
</span><del>-        DFG_NODE_DO_TO_CHILDREN(m_graph, node, observeUntypedEdge);
</del><ins>+        if (!node-&gt;containsMovHint())
+            DFG_NODE_DO_TO_CHILDREN(m_graph, node, observeUntypedEdge);
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     void observeUntypedEdge(Node*, Edge&amp; edge)
</span><span class="lines">@@ -1478,7 +1479,7 @@
</span><span class="cx">     {
</span><span class="cx">         if (isDouble(useKind)) {
</span><span class="cx">             if (edge-&gt;shouldSpeculateInt32ForArithmetic()) {
</span><del>-                injectInt32ToDoubleNode(edge, useKind, m_currentNode-&gt;speculationDirection());
</del><ins>+                injectInt32ToDoubleNode(edge, useKind);
</ins><span class="cx">                 return;
</span><span class="cx">             }
</span><span class="cx">             
</span><span class="lines">@@ -1491,7 +1492,6 @@
</span><span class="cx">                 Node* result = m_insertionSet.insertNode(
</span><span class="cx">                     m_indexInBlock, SpecInt52AsDouble, Int52ToDouble,
</span><span class="cx">                     m_currentNode-&gt;codeOrigin, Edge(edge.node(), NumberUse));
</span><del>-                result-&gt;setSpeculationDirection(m_currentNode-&gt;speculationDirection());
</del><span class="cx">                 edge = Edge(result, useKind);
</span><span class="cx">                 return;
</span><span class="cx">             }
</span><span class="lines">@@ -1545,7 +1545,6 @@
</span><span class="cx">             Node* result = m_insertionSet.insertNode(
</span><span class="cx">                 m_indexInBlock, SpecInt52, Int52ToValue,
</span><span class="cx">                 m_currentNode-&gt;codeOrigin, Edge(edge.node(), UntypedUse));
</span><del>-            result-&gt;setSpeculationDirection(m_currentNode-&gt;speculationDirection());
</del><span class="cx">             edge = Edge(result, useKind);
</span><span class="cx">             return;
</span><span class="cx">         }
</span><span class="lines">@@ -1587,13 +1586,11 @@
</span><span class="cx">         edge = newEdge;
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    void injectInt32ToDoubleNode(Edge&amp; edge, UseKind useKind = NumberUse, SpeculationDirection direction = BackwardSpeculation)
</del><ins>+    void injectInt32ToDoubleNode(Edge&amp; edge, UseKind useKind = NumberUse)
</ins><span class="cx">     {
</span><span class="cx">         Node* result = m_insertionSet.insertNode(
</span><span class="cx">             m_indexInBlock, SpecInt52AsDouble, Int32ToDouble,
</span><span class="cx">             m_currentNode-&gt;codeOrigin, Edge(edge.node(), NumberUse));
</span><del>-        if (direction == ForwardSpeculation)
-            result-&gt;mergeFlags(NodeExitsForward);
</del><span class="cx">         
</span><span class="cx">         edge = Edge(result, useKind);
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGLICMPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGLICMPhase.cpp (161125 => 161126)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGLICMPhase.cpp        2013-12-29 21:49:03 UTC (rev 161125)
+++ trunk/Source/JavaScriptCore/dfg/DFGLICMPhase.cpp        2013-12-29 21:50:55 UTC (rev 161126)
</span><span class="lines">@@ -128,7 +128,6 @@
</span><span class="cx">         //   time and preserve some kind of sanity, if we hoist something that must exit.
</span><span class="cx">         //
</span><span class="cx">         // Also, we need to remember to:
</span><del>-        // - Clear NodeExitsForward for any nodes we hoisted.
</del><span class="cx">         // - Update the state-at-tail with the node we hoisted, so future hoist candidates
</span><span class="cx">         //   know about any type checks we hoisted.
</span><span class="cx">         //
</span><span class="lines">@@ -230,8 +229,6 @@
</span><span class="cx">         
</span><span class="cx">         data.preHeader-&gt;insertBeforeLast(node);
</span><span class="cx">         node-&gt;misc.owner = data.preHeader;
</span><del>-        NodeFlags didExitForward = node-&gt;flags() &amp; NodeExitsForward;
-        node-&gt;clearFlags(NodeExitsForward);
</del><span class="cx">         node-&gt;codeOriginForExitTarget = data.preHeader-&gt;last()-&gt;codeOriginForExitTarget;
</span><span class="cx">         
</span><span class="cx">         // Modify the states at the end of the preHeader of the loop we hoisted to,
</span><span class="lines">@@ -256,7 +253,6 @@
</span><span class="cx">         RELEASE_ASSERT(!(node-&gt;flags() &amp; NodeHasVarArgs));
</span><span class="cx">         
</span><span class="cx">         nodeRef = m_graph.addNode(SpecNone, Phantom, node-&gt;codeOrigin, node-&gt;children);
</span><del>-        nodeRef-&gt;mergeFlags(didExitForward);
</del><span class="cx">         
</span><span class="cx">         return true;
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGMinifiedNodecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGMinifiedNode.cpp (161125 => 161126)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGMinifiedNode.cpp        2013-12-29 21:49:03 UTC (rev 161125)
+++ trunk/Source/JavaScriptCore/dfg/DFGMinifiedNode.cpp        2013-12-29 21:50:55 UTC (rev 161126)
</span><span class="lines">@@ -38,15 +38,13 @@
</span><span class="cx">     MinifiedNode result;
</span><span class="cx">     result.m_id = MinifiedID(node);
</span><span class="cx">     result.m_op = node-&gt;op();
</span><del>-    if (hasChild(node-&gt;op()))
-        result.m_childOrInfo = MinifiedID(node-&gt;child1().node()).m_id;
-    else if (hasConstantNumber(node-&gt;op()))
-        result.m_childOrInfo = node-&gt;constantNumber();
</del><ins>+    if (hasConstantNumber(node-&gt;op()))
+        result.m_info = node-&gt;constantNumber();
</ins><span class="cx">     else if (hasWeakConstant(node-&gt;op()))
</span><del>-        result.m_childOrInfo = bitwise_cast&lt;uintptr_t&gt;(node-&gt;weakConstant());
</del><ins>+        result.m_info = bitwise_cast&lt;uintptr_t&gt;(node-&gt;weakConstant());
</ins><span class="cx">     else {
</span><span class="cx">         ASSERT(node-&gt;op() == PhantomArguments);
</span><del>-        result.m_childOrInfo = 0;
</del><ins>+        result.m_info = 0;
</ins><span class="cx">     }
</span><span class="cx">     return result;
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGMinifiedNodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGMinifiedNode.h (161125 => 161126)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGMinifiedNode.h        2013-12-29 21:49:03 UTC (rev 161125)
+++ trunk/Source/JavaScriptCore/dfg/DFGMinifiedNode.h        2013-12-29 21:50:55 UTC (rev 161126)
</span><span class="lines">@@ -43,16 +43,9 @@
</span><span class="cx">     switch (type) {
</span><span class="cx">     case JSConstant:
</span><span class="cx">     case WeakJSConstant:
</span><del>-    case ValueToInt32:
-    case Int32ToDouble:
-    case UInt32ToNumber:
-    case DoubleAsInt32:
</del><span class="cx">     case PhantomArguments:
</span><del>-    case Int52ToValue:
-    case Int52ToDouble:
</del><span class="cx">         return true;
</span><span class="cx">     default:
</span><del>-        ASSERT(!permitsOSRBackwardRewiring(type) &amp;&amp; !permitsOSRForwardRewiring(type));
</del><span class="cx">         return false;
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="lines">@@ -66,14 +59,6 @@
</span><span class="cx">     MinifiedID id() const { return m_id; }
</span><span class="cx">     NodeType op() const { return m_op; }
</span><span class="cx">     
</span><del>-    bool hasChild1() const { return hasChild(m_op); }
-    
-    MinifiedID child1() const
-    {
-        ASSERT(hasChild(m_op));
-        return MinifiedID::fromBits(m_childOrInfo);
-    }
-    
</del><span class="cx">     bool hasConstant() const { return hasConstantNumber() || hasWeakConstant(); }
</span><span class="cx">     
</span><span class="cx">     bool hasConstantNumber() const { return hasConstantNumber(m_op); }
</span><span class="lines">@@ -81,7 +66,7 @@
</span><span class="cx">     unsigned constantNumber() const
</span><span class="cx">     {
</span><span class="cx">         ASSERT(hasConstantNumber(m_op));
</span><del>-        return m_childOrInfo;
</del><ins>+        return m_info;
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     bool hasWeakConstant() const { return hasWeakConstant(m_op); }
</span><span class="lines">@@ -89,7 +74,7 @@
</span><span class="cx">     JSCell* weakConstant() const
</span><span class="cx">     {
</span><span class="cx">         ASSERT(hasWeakConstant(m_op));
</span><del>-        return bitwise_cast&lt;JSCell*&gt;(m_childOrInfo);
</del><ins>+        return bitwise_cast&lt;JSCell*&gt;(m_info);
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     static MinifiedID getID(MinifiedNode* node) { return node-&gt;id(); }
</span><span class="lines">@@ -99,20 +84,6 @@
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx"> private:
</span><del>-    static bool hasChild(NodeType type)
-    {
-        switch (type) {
-        case ValueToInt32:
-        case Int32ToDouble:
-        case UInt32ToNumber:
-        case DoubleAsInt32:
-        case Int52ToDouble:
-        case Int52ToValue:
-            return true;
-        default:
-            return false;
-        }
-    }
</del><span class="cx">     static bool hasConstantNumber(NodeType type)
</span><span class="cx">     {
</span><span class="cx">         return type == JSConstant;
</span><span class="lines">@@ -123,7 +94,7 @@
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     MinifiedID m_id;
</span><del>-    uintptr_t m_childOrInfo; // Nodes in the minified graph have only one child each.
</del><ins>+    uintptr_t m_info;
</ins><span class="cx">     NodeType m_op;
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGNodecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGNode.cpp (161125 => 161126)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNode.cpp        2013-12-29 21:49:03 UTC (rev 161125)
+++ trunk/Source/JavaScriptCore/dfg/DFGNode.cpp        2013-12-29 21:50:55 UTC (rev 161126)
</span><span class="lines">@@ -46,9 +46,6 @@
</span><span class="cx">     case GetLocal:
</span><span class="cx">     case GetArgument:
</span><span class="cx">     case SetLocal:
</span><del>-    case MovHint:
-    case MovHintAndCheck:
-    case ZombieHint:
</del><span class="cx">     case SetArgument:
</span><span class="cx">     case Flush:
</span><span class="cx">     case PhantomLocal:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGNodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGNode.h (161125 => 161126)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNode.h        2013-12-29 21:49:03 UTC (rev 161125)
+++ trunk/Source/JavaScriptCore/dfg/DFGNode.h        2013-12-29 21:50:55 UTC (rev 161126)
</span><span class="lines">@@ -274,59 +274,27 @@
</span><span class="cx">         return filterFlags(~flags);
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    SpeculationDirection speculationDirection()
-    {
-        if (flags() &amp; NodeExitsForward)
-            return ForwardSpeculation;
-        return BackwardSpeculation;
-    }
-    
-    void setSpeculationDirection(SpeculationDirection direction)
-    {
-        switch (direction) {
-        case ForwardSpeculation:
-            mergeFlags(NodeExitsForward);
-            return;
-        case BackwardSpeculation:
-            clearFlags(NodeExitsForward);
-            return;
-        }
-        RELEASE_ASSERT_NOT_REACHED();
-    }
-    
</del><span class="cx">     void setOpAndDefaultFlags(NodeType op)
</span><span class="cx">     {
</span><span class="cx">         m_op = op;
</span><span class="cx">         m_flags = defaultFlags(op);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    void setOpAndDefaultNonExitFlags(NodeType op)
-    {
-        ASSERT(!(m_flags &amp; NodeHasVarArgs));
-        setOpAndDefaultNonExitFlagsUnchecked(op);
-    }
-
-    void setOpAndDefaultNonExitFlagsUnchecked(NodeType op)
-    {
-        m_op = op;
-        m_flags = (defaultFlags(op) &amp; ~NodeExitsForward) | (m_flags &amp; NodeExitsForward);
-    }
-
</del><span class="cx">     void convertToPhantom()
</span><span class="cx">     {
</span><del>-        setOpAndDefaultNonExitFlags(Phantom);
</del><ins>+        setOpAndDefaultFlags(Phantom);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     void convertToPhantomUnchecked()
</span><span class="cx">     {
</span><del>-        setOpAndDefaultNonExitFlagsUnchecked(Phantom);
</del><ins>+        setOpAndDefaultFlags(Phantom);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     void convertToIdentity()
</span><span class="cx">     {
</span><span class="cx">         RELEASE_ASSERT(child1());
</span><span class="cx">         RELEASE_ASSERT(!child2());
</span><del>-        setOpAndDefaultNonExitFlags(Identity);
</del><ins>+        setOpAndDefaultFlags(Identity);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     bool mustGenerate()
</span><span class="lines">@@ -531,9 +499,7 @@
</span><span class="cx">     bool containsMovHint()
</span><span class="cx">     {
</span><span class="cx">         switch (op()) {
</span><del>-        case SetLocal:
</del><span class="cx">         case MovHint:
</span><del>-        case MovHintAndCheck:
</del><span class="cx">         case ZombieHint:
</span><span class="cx">             return true;
</span><span class="cx">         default:
</span><span class="lines">@@ -567,6 +533,8 @@
</span><span class="cx">         switch (op()) {
</span><span class="cx">         case GetLocalUnlinked:
</span><span class="cx">         case ExtractOSREntryLocal:
</span><ins>+        case MovHint:
+        case ZombieHint:
</ins><span class="cx">             return true;
</span><span class="cx">         default:
</span><span class="cx">             return false;
</span><span class="lines">@@ -1190,11 +1158,6 @@
</span><span class="cx">         case SetLocal:
</span><span class="cx">         case MovHint:
</span><span class="cx">         case ZombieHint:
</span><del>-        case MovHintAndCheck:
-        case Int32ToDouble:
-        case ValueToInt32:
-        case UInt32ToNumber:
-        case DoubleAsInt32:
</del><span class="cx">         case PhantomArguments:
</span><span class="cx">             return true;
</span><span class="cx">         case Phantom:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGNodeFlagscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGNodeFlags.cpp (161125 => 161126)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNodeFlags.cpp        2013-12-29 21:49:03 UTC (rev 161125)
+++ trunk/Source/JavaScriptCore/dfg/DFGNodeFlags.cpp        2013-12-29 21:50:55 UTC (rev 161126)
</span><span class="lines">@@ -96,9 +96,6 @@
</span><span class="cx">     if (!(flags &amp; NodeDoesNotExit))
</span><span class="cx">         out.print(comma, &quot;CanExit&quot;);
</span><span class="cx">     
</span><del>-    if (flags &amp; NodeExitsForward)
-        out.print(comma, &quot;NodeExitsForward&quot;);
-    
</del><span class="cx">     CString string = out.toCString();
</span><span class="cx">     if (!string.length())
</span><span class="cx">         actualOut.print(&quot;&lt;empty&gt;&quot;);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGNodeFlagsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGNodeFlags.h (161125 => 161126)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNodeFlags.h        2013-12-29 21:49:03 UTC (rev 161125)
+++ trunk/Source/JavaScriptCore/dfg/DFGNodeFlags.h        2013-12-29 21:50:55 UTC (rev 161126)
</span><span class="lines">@@ -68,10 +68,8 @@
</span><span class="cx"> 
</span><span class="cx"> #define NodeRelevantToOSR                0x4000
</span><span class="cx"> 
</span><del>-#define NodeExitsForward                 0x8000
</del><ins>+#define NodeIsStaticConstant             0x8000 // Used only by the parser, to determine if a constant arose statically and hence could be folded at parse-time.
</ins><span class="cx"> 
</span><del>-#define NodeIsStaticConstant            0x10000 // Used only by the parser, to determine if a constant arose statically and hence could be folded at parse-time.
-
</del><span class="cx"> typedef uint32_t NodeFlags;
</span><span class="cx"> 
</span><span class="cx"> static inline bool bytecodeUsesAsNumber(NodeFlags flags)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGNodeTypeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGNodeType.h (161125 => 161126)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNodeType.h        2013-12-29 21:49:03 UTC (rev 161125)
+++ trunk/Source/JavaScriptCore/dfg/DFGNodeType.h        2013-12-29 21:50:55 UTC (rev 161126)
</span><span class="lines">@@ -57,12 +57,12 @@
</span><span class="cx">     /* Any two nodes that are part of the same Phi graph will share the same */\
</span><span class="cx">     /* VariableAccessData, and thus will share predictions. */\
</span><span class="cx">     macro(GetLocal, NodeResultJS) \
</span><del>-    macro(SetLocal, NodeExitsForward) \
-    macro(MovHintAndCheck, NodeMustGenerate | NodeExitsForward) \
</del><ins>+    macro(SetLocal, 0) \
</ins><span class="cx">     macro(MovHint, NodeDoesNotExit) \
</span><span class="cx">     macro(ZombieHint, NodeDoesNotExit) \
</span><span class="cx">     macro(GetArgument, NodeResultJS | NodeMustGenerate) \
</span><span class="cx">     macro(Phantom, NodeMustGenerate) \
</span><ins>+    macro(Check, 0) /* Used if we want just a type check but not liveness. DCE eithers kills this or converts it to Phantom. */\
</ins><span class="cx">     macro(Upsilon, NodeDoesNotExit | NodeRelevantToOSR) \
</span><span class="cx">     macro(Phi, NodeDoesNotExit | NodeRelevantToOSR) \
</span><span class="cx">     macro(Flush, NodeMustGenerate | NodeDoesNotExit) \
</span><span class="lines">@@ -318,80 +318,6 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline bool permitsOSRBackwardRewiring(NodeType op)
-{
-    switch (op) {
-    case Identity:
-        RELEASE_ASSERT_NOT_REACHED();
-        return true;
-    case UInt32ToNumber:
-    case Int52ToValue:
-    case Int52ToDouble:
-        // These are the only node where we do:
-        //
-        //     b: UInt32ToNumber(@a)
-        //     c: SetLocal(@b)
-        //
-        // and then also have some uses of @a without Phantom'ing @b.
-        return true;
-    default:
-        return false;
-    }
-}
-
-// Returns the priority with which we should select the given node for forward
-// rewiring. Higher is better. Zero means that the node is not useful for rewiring.
-// By convention, we use 100 to mean that the node is totally equivalent to its
-// input with no information loss.
-inline unsigned forwardRewiringSelectionScore(NodeType op)
-{
-    switch (op) {
-    case Identity:
-        // We shouldn't see these by the time we get to OSR even though it clearly
-        // is a perfect identity function.
-        RELEASE_ASSERT_NOT_REACHED();
-        return 100;
-        
-    case DoubleAsInt32:
-        // This speculates that the incoming double is convertible to an int32. So
-        // its result is totally equivalent.
-        return 100;
-        
-    case Int32ToDouble:
-        // This converts an int32 to a double, but that loses a bit of information.
-        // OTOH it's still an equivalent number.
-        return 75;
-        
-    case UInt32ToNumber:
-        // It's completely fine to use this for OSR exit, since the uint32 isn't
-        // actually representable in bytecode.
-        return 100;
-
-    case ValueToInt32:
-        // This loses information. Only use it if there are no better alternatives.
-        return 25;
-        
-    case Int52ToValue:
-        // Loses no information. It just boxes the value, which is what OSR wants
-        // to do anyway.
-        return 100;
-        
-    case Int52ToDouble:
-        // This is like Int32ToDouble; we can use it because it gives a semantically
-        // equivalent value but that value may be an int32 in a double, so we'd
-        // rather not if we can avoid it.
-        return 75;
-        
-    default:
-        return 0;
-    }
-}
-
-inline bool permitsOSRForwardRewiring(NodeType op)
-{
-    return forwardRewiringSelectionScore(op) &gt; 0;
-}
-
</del><span class="cx"> } } // namespace JSC::DFG
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(DFG_JIT)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGOSRAvailabilityAnalysisPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGOSRAvailabilityAnalysisPhase.cpp (161125 => 161126)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGOSRAvailabilityAnalysisPhase.cpp        2013-12-29 21:49:03 UTC (rev 161125)
+++ trunk/Source/JavaScriptCore/dfg/DFGOSRAvailabilityAnalysisPhase.cpp        2013-12-29 21:50:55 UTC (rev 161126)
</span><span class="lines">@@ -103,17 +103,15 @@
</span><span class="cx">                         break;
</span><span class="cx">                     }
</span><span class="cx">                         
</span><del>-                    case MovHint:
-                    case MovHintAndCheck: {
-                        VariableAccessData* variable = node-&gt;variableAccessData();
-                        availability.operand(variable-&gt;local()) =
</del><ins>+                    case MovHint: {
+                        availability.operand(node-&gt;unlinkedLocal()) =
</ins><span class="cx">                             Availability(node-&gt;child1().node());
</span><span class="cx">                         break;
</span><span class="cx">                     }
</span><span class="cx">                         
</span><span class="cx">                     case ZombieHint: {
</span><del>-                        VariableAccessData* variable = node-&gt;variableAccessData();
-                        availability.operand(variable-&gt;local()) = Availability::unavailable();
</del><ins>+                        availability.operand(node-&gt;unlinkedLocal()) =
+                            Availability::unavailable();
</ins><span class="cx">                         break;
</span><span class="cx">                     }
</span><span class="cx">                         
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGOSREntrypointCreationPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGOSREntrypointCreationPhase.cpp (161125 => 161126)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGOSREntrypointCreationPhase.cpp        2013-12-29 21:49:03 UTC (rev 161125)
+++ trunk/Source/JavaScriptCore/dfg/DFGOSREntrypointCreationPhase.cpp        2013-12-29 21:50:55 UTC (rev 161126)
</span><span class="lines">@@ -104,17 +104,9 @@
</span><span class="cx">                 m_graph, variable-&gt;prediction(), ExtractOSREntryLocal, codeOrigin,
</span><span class="cx">                 OpInfo(variable-&gt;local().offset()));
</span><span class="cx">             
</span><del>-            // Create a MovHint. We can't use MovHint's directly at this stage of
-            // compilation, so we cook one up by creating a new VariableAccessData
-            // that isn't unified with any of the others. This ensures that this
-            // SetLocal will turn into a MovHint and will not have any type checks.
-            m_graph.m_variableAccessData.append(
-                VariableAccessData(variable-&gt;local(), variable-&gt;isCaptured()));
-            VariableAccessData* newVariable = &amp;m_graph.m_variableAccessData.last();
-            Node* setLocal = newRoot-&gt;appendNode(
-                m_graph, SpecNone, SetLocal, codeOrigin, OpInfo(newVariable),
</del><ins>+            newRoot-&gt;appendNode(
+                m_graph, SpecNone, MovHint, codeOrigin, OpInfo(variable-&gt;local().offset()),
</ins><span class="cx">                 Edge(locals[local]));
</span><del>-            setLocal-&gt;setSpeculationDirection(BackwardSpeculation);
</del><span class="cx">         }
</span><span class="cx">         for (int local = 0; local &lt; baseline-&gt;m_numCalleeRegisters; ++local) {
</span><span class="cx">             Node* previousHead = target-&gt;variablesAtHead.local(local);
</span><span class="lines">@@ -122,9 +114,8 @@
</span><span class="cx">                 continue;
</span><span class="cx">             VariableAccessData* variable = previousHead-&gt;variableAccessData();
</span><span class="cx">             Node* node = locals[local];
</span><del>-            Node* setLocal = newRoot-&gt;appendNode(
</del><ins>+            newRoot-&gt;appendNode(
</ins><span class="cx">                 m_graph, SpecNone, SetLocal, codeOrigin, OpInfo(variable), Edge(node));
</span><del>-            setLocal-&gt;setSpeculationDirection(BackwardSpeculation);
</del><span class="cx">         }
</span><span class="cx">         
</span><span class="cx">         newRoot-&gt;appendNode(
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGOSRExitcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGOSRExit.cpp (161125 => 161126)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGOSRExit.cpp        2013-12-29 21:49:03 UTC (rev 161125)
+++ trunk/Source/JavaScriptCore/dfg/DFGOSRExit.cpp        2013-12-29 21:50:55 UTC (rev 161126)
</span><span class="lines">@@ -68,26 +68,6 @@
</span><span class="cx">     m_patchableCodeOffset = linkBuffer.offsetOf(label);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void OSRExit::convertToForward(BasicBlock* block, Node* currentNode, unsigned nodeIndex, const ValueRecovery&amp; valueRecovery)
-{
-    Node* node;
-    Node* lastMovHint;
-    if (!doSearchForForwardConversion(block, currentNode, nodeIndex, !!valueRecovery, node, lastMovHint))
-        return;
-
-    ASSERT(node-&gt;codeOrigin != currentNode-&gt;codeOrigin);
-    
-    m_codeOrigin = node-&gt;codeOrigin;
-    
-    if (!valueRecovery)
-        return;
-    
-    ASSERT(lastMovHint);
-    ASSERT(lastMovHint-&gt;child1() == currentNode);
-    m_valueRecoveryOverride = adoptRef(
-        new ValueRecoveryOverride(lastMovHint-&gt;local(), valueRecovery));
-}
-
</del><span class="cx"> } } // namespace JSC::DFG
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(DFG_JIT)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGOSRExith"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGOSRExit.h (161125 => 161126)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGOSRExit.h        2013-12-29 21:49:03 UTC (rev 161125)
+++ trunk/Source/JavaScriptCore/dfg/DFGOSRExit.h        2013-12-29 21:50:55 UTC (rev 161126)
</span><span class="lines">@@ -101,8 +101,6 @@
</span><span class="cx">     MacroAssembler::Jump getPatchableCodeOffsetAsJump() const;
</span><span class="cx">     CodeLocationJump codeLocationForRepatch(CodeBlock*) const;
</span><span class="cx">     void correctJump(LinkBuffer&amp;);
</span><del>-    
-    void convertToForward(BasicBlock*, Node*, unsigned nodeIndex, const ValueRecovery&amp;);
</del><span class="cx"> 
</span><span class="cx">     unsigned m_streamIndex;
</span><span class="cx">     
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGOSRExitBasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGOSRExitBase.cpp (161125 => 161126)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGOSRExitBase.cpp        2013-12-29 21:49:03 UTC (rev 161125)
+++ trunk/Source/JavaScriptCore/dfg/DFGOSRExitBase.cpp        2013-12-29 21:50:55 UTC (rev 161126)
</span><span class="lines">@@ -46,45 +46,6 @@
</span><span class="cx">             FrequentExitSite(m_codeOriginForExitProfile.bytecodeIndex, m_kind));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool OSRExitBase::doSearchForForwardConversion(
-    BasicBlock* block, Node* currentNode, unsigned nodeIndex, bool hasValueRecovery,
-    Node*&amp; node, Node*&amp; lastMovHint)
-{
-    // Check that either the current node is a SetLocal, or the preceding node was a
-    // SetLocal with the same code origin, or that we've provided a valueRecovery.
-    if (!ASSERT_DISABLED
-        &amp;&amp; !hasValueRecovery
-        &amp;&amp; !currentNode-&gt;containsMovHint()) {
-        Node* setLocal = block-&gt;at(nodeIndex - 1);
-        ASSERT_UNUSED(setLocal, setLocal-&gt;containsMovHint());
-        ASSERT_UNUSED(setLocal, setLocal-&gt;codeOriginForExitTarget == currentNode-&gt;codeOriginForExitTarget);
-    }
-    
-    // Find the first node for the next bytecode instruction. Also track the last mov hint
-    // on this node.
-    unsigned indexInBlock = nodeIndex + 1;
-    node = 0;
-    lastMovHint = 0;
-    for (;;) {
-        if (indexInBlock == block-&gt;size()) {
-            // This is an inline return. Give up and do a backwards speculation. This is safe
-            // because an inline return has its own bytecode index and it's always safe to
-            // reexecute that bytecode.
-            ASSERT(node-&gt;op() == Jump);
-            return false;
-        }
-        node = block-&gt;at(indexInBlock);
-        if (node-&gt;containsMovHint() &amp;&amp; node-&gt;child1() == currentNode)
-            lastMovHint = node;
-        if (node-&gt;codeOriginForExitTarget != currentNode-&gt;codeOriginForExitTarget)
-            break;
-        indexInBlock++;
-    }
-    
-    ASSERT(node-&gt;codeOriginForExitTarget != currentNode-&gt;codeOriginForExitTarget);
-    return true;
-}
-
</del><span class="cx"> } } // namespace JSC::DFG
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(DFG_JIT)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGOSRExitBaseh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGOSRExitBase.h (161125 => 161126)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGOSRExitBase.h        2013-12-29 21:49:03 UTC (rev 161125)
+++ trunk/Source/JavaScriptCore/dfg/DFGOSRExitBase.h        2013-12-29 21:50:55 UTC (rev 161126)
</span><span class="lines">@@ -64,11 +64,6 @@
</span><span class="cx">             return false;
</span><span class="cx">         return considerAddingAsFrequentExitSiteSlow(profiledCodeBlock);
</span><span class="cx">     }
</span><del>-    
-    // Returns true if the forward conversion is really needed.
-    bool doSearchForForwardConversion(
-        BasicBlock*, Node* currentNode, unsigned nodeIndex, bool hasValueRecovery,
-        Node*&amp; nextBCNode, Node*&amp; lastMovHint);
</del><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     bool considerAddingAsFrequentExitSiteSlow(CodeBlock* profiledCodeBlock);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGPredictionPropagationPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp (161125 => 161126)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp        2013-12-29 21:49:03 UTC (rev 161125)
+++ trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp        2013-12-29 21:50:55 UTC (rev 161126)
</span><span class="lines">@@ -504,9 +504,6 @@
</span><span class="cx">         case CheckArray:
</span><span class="cx">         case Arrayify:
</span><span class="cx">         case ArrayifyToStructure:
</span><del>-        case MovHint:
-        case MovHintAndCheck:
-        case ZombieHint:
</del><span class="cx">         case CheckTierUpInLoop:
</span><span class="cx">         case CheckTierUpAtReturn:
</span><span class="cx">         case CheckTierUpAndOSREnter:
</span><span class="lines">@@ -577,6 +574,7 @@
</span><span class="cx">         case VarInjectionWatchpoint:
</span><span class="cx">         case AllocationProfileWatchpoint:
</span><span class="cx">         case Phantom:
</span><ins>+        case Check:
</ins><span class="cx">         case PutGlobalVar:
</span><span class="cx">         case CheckWatchdogTimer:
</span><span class="cx">         case Unreachable:
</span><span class="lines">@@ -585,6 +583,8 @@
</span><span class="cx">         case FunctionReentryWatchpoint:
</span><span class="cx">         case TypedArrayWatchpoint:
</span><span class="cx">         case ConstantStoragePointer:
</span><ins>+        case MovHint:
+        case ZombieHint:
</ins><span class="cx">             break;
</span><span class="cx">             
</span><span class="cx">         // This gets ignored because it already has a prediction.
</span><span class="lines">@@ -744,6 +744,10 @@
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">             
</span><ins>+        case MovHint:
+            // Ignore these since they have no effect on in-DFG execution.
+            break;
+            
</ins><span class="cx">         default:
</span><span class="cx">             m_graph.voteChildren(node, VoteValue);
</span><span class="cx">             break;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSSAConversionPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSSAConversionPhase.cpp (161125 => 161126)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSSAConversionPhase.cpp        2013-12-29 21:49:03 UTC (rev 161125)
+++ trunk/Source/JavaScriptCore/dfg/DFGSSAConversionPhase.cpp        2013-12-29 21:50:55 UTC (rev 161126)
</span><span class="lines">@@ -186,8 +186,8 @@
</span><span class="cx">                             // the value was already on the stack.
</span><span class="cx">                         } else {
</span><span class="cx">                             m_insertionSet.insertNode(
</span><del>-                                0, SpecNone, MovHint, CodeOrigin(), OpInfo(variable),
-                                Edge(node));
</del><ins>+                                0, SpecNone, MovHint, CodeOrigin(),
+                                OpInfo(variable-&gt;local().offset()), Edge(node));
</ins><span class="cx">                         }
</span><span class="cx">                     }
</span><span class="cx">                 }
</span><span class="lines">@@ -269,7 +269,7 @@
</span><span class="cx">         // - GetLocal over uncaptured variables die and get replaced with references
</span><span class="cx">         //   to the node specified by variablesAtHead.
</span><span class="cx">         // - SetLocal gets NodeMustGenerate if it's flushed, or turns into a
</span><del>-        //   MovHint otherwise.
</del><ins>+        //   Check otherwise.
</ins><span class="cx">         // - Flush loses its children but remains, because we want to know when a
</span><span class="cx">         //   flushed SetLocal's value is no longer needed. This also makes it simpler
</span><span class="cx">         //   to reason about the format of a local, since we can just do a backwards
</span><span class="lines">@@ -308,7 +308,7 @@
</span><span class="cx">                     if (variable-&gt;isCaptured() || m_flushedLocalOps.contains(node))
</span><span class="cx">                         node-&gt;mergeFlags(NodeMustGenerate);
</span><span class="cx">                     else
</span><del>-                        node-&gt;setOpAndDefaultFlags(MovHint);
</del><ins>+                        node-&gt;setOpAndDefaultFlags(Check);
</ins><span class="cx">                     node-&gt;misc.replacement = node-&gt;child1().node(); // Only for Upsilons.
</span><span class="cx">                     break;
</span><span class="cx">                 }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSafeToExecuteh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h (161125 => 161126)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h        2013-12-29 21:49:03 UTC (rev 161125)
+++ trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h        2013-12-29 21:50:55 UTC (rev 161126)
</span><span class="lines">@@ -118,7 +118,6 @@
</span><span class="cx">     case GetCallee:
</span><span class="cx">     case GetLocal:
</span><span class="cx">     case SetLocal:
</span><del>-    case MovHintAndCheck:
</del><span class="cx">     case MovHint:
</span><span class="cx">     case ZombieHint:
</span><span class="cx">     case GetArgument:
</span><span class="lines">@@ -250,6 +249,7 @@
</span><span class="cx">     case TypedArrayWatchpoint:
</span><span class="cx">     case CheckInBounds:
</span><span class="cx">     case ConstantStoragePointer:
</span><ins>+    case Check:
</ins><span class="cx">         return true;
</span><span class="cx">         
</span><span class="cx">     case GetByVal:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp (161125 => 161126)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2013-12-29 21:49:03 UTC (rev 161125)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2013-12-29 21:50:55 UTC (rev 161126)
</span><span class="lines">@@ -106,7 +106,7 @@
</span><span class="cx">             structure, numElements)));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SpeculativeJIT::backwardSpeculationCheck(ExitKind kind, JSValueSource jsValueSource, Node* node, MacroAssembler::Jump jumpToFail)
</del><ins>+void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Node* node, MacroAssembler::Jump jumpToFail)
</ins><span class="cx"> {
</span><span class="cx">     if (!m_compileOkay)
</span><span class="cx">         return;
</span><span class="lines">@@ -115,7 +115,7 @@
</span><span class="cx">     m_jit.jitCode()-&gt;appendOSRExit(OSRExit(kind, jsValueSource, m_jit.graph().methodOfGettingAValueProfileFor(node), this, m_stream-&gt;size()));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SpeculativeJIT::backwardSpeculationCheck(ExitKind kind, JSValueSource jsValueSource, Node* node, const MacroAssembler::JumpList&amp; jumpsToFail)
</del><ins>+void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Node* node, const MacroAssembler::JumpList&amp; jumpsToFail)
</ins><span class="cx"> {
</span><span class="cx">     if (!m_compileOkay)
</span><span class="cx">         return;
</span><span class="lines">@@ -124,24 +124,9 @@
</span><span class="cx">     m_jit.jitCode()-&gt;appendOSRExit(OSRExit(kind, jsValueSource, m_jit.graph().methodOfGettingAValueProfileFor(node), this, m_stream-&gt;size()));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Node* node, MacroAssembler::Jump jumpToFail)
</del><ins>+OSRExitJumpPlaceholder SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Node* node)
</ins><span class="cx"> {
</span><span class="cx">     if (!m_compileOkay)
</span><del>-        return;
-    backwardSpeculationCheck(kind, jsValueSource, node, jumpToFail);
-    if (m_speculationDirection == ForwardSpeculation)
-        convertLastOSRExitToForward();
-}
-
-void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse, MacroAssembler::Jump jumpToFail)
-{
-    ASSERT(m_isCheckingArgumentTypes || m_canExit);
-    speculationCheck(kind, jsValueSource, nodeUse.node(), jumpToFail);
-}
-
-OSRExitJumpPlaceholder SpeculativeJIT::backwardSpeculationCheck(ExitKind kind, JSValueSource jsValueSource, Node* node)
-{
-    if (!m_compileOkay)
</del><span class="cx">         return OSRExitJumpPlaceholder();
</span><span class="cx">     ASSERT(m_isCheckingArgumentTypes || m_canExit);
</span><span class="cx">     unsigned index = m_jit.jitCode()-&gt;osrExit.size();
</span><span class="lines">@@ -150,19 +135,16 @@
</span><span class="cx">     return OSRExitJumpPlaceholder(index);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-OSRExitJumpPlaceholder SpeculativeJIT::backwardSpeculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse)
</del><ins>+OSRExitJumpPlaceholder SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(m_isCheckingArgumentTypes || m_canExit);
</span><del>-    return backwardSpeculationCheck(kind, jsValueSource, nodeUse.node());
</del><ins>+    return speculationCheck(kind, jsValueSource, nodeUse.node());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Node* node, const MacroAssembler::JumpList&amp; jumpsToFail)
</del><ins>+void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse, MacroAssembler::Jump jumpToFail)
</ins><span class="cx"> {
</span><del>-    if (!m_compileOkay)
-        return;
-    backwardSpeculationCheck(kind, jsValueSource, node, jumpsToFail);
-    if (m_speculationDirection == ForwardSpeculation)
-        convertLastOSRExitToForward();
</del><ins>+    ASSERT(m_isCheckingArgumentTypes || m_canExit);
+    speculationCheck(kind, jsValueSource, nodeUse.node(), jumpToFail);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse, const MacroAssembler::JumpList&amp; jumpsToFail)
</span><span class="lines">@@ -171,7 +153,7 @@
</span><span class="cx">     speculationCheck(kind, jsValueSource, nodeUse.node(), jumpsToFail);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SpeculativeJIT::backwardSpeculationCheck(ExitKind kind, JSValueSource jsValueSource, Node* node, MacroAssembler::Jump jumpToFail, const SpeculationRecovery&amp; recovery)
</del><ins>+void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Node* node, MacroAssembler::Jump jumpToFail, const SpeculationRecovery&amp; recovery)
</ins><span class="cx"> {
</span><span class="cx">     if (!m_compileOkay)
</span><span class="cx">         return;
</span><span class="lines">@@ -181,32 +163,17 @@
</span><span class="cx">     m_jit.jitCode()-&gt;appendOSRExit(OSRExit(kind, jsValueSource, m_jit.graph().methodOfGettingAValueProfileFor(node), this, m_stream-&gt;size(), recoveryIndex));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SpeculativeJIT::backwardSpeculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse, MacroAssembler::Jump jumpToFail, const SpeculationRecovery&amp; recovery)
</del><ins>+void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse, MacroAssembler::Jump jumpToFail, const SpeculationRecovery&amp; recovery)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(m_isCheckingArgumentTypes || m_canExit);
</span><del>-    backwardSpeculationCheck(kind, jsValueSource, nodeUse.node(), jumpToFail, recovery);
</del><ins>+    speculationCheck(kind, jsValueSource, nodeUse.node(), jumpToFail, recovery);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Node* node, MacroAssembler::Jump jumpToFail, const SpeculationRecovery&amp; recovery)
-{
-    if (!m_compileOkay)
-        return;
-    backwardSpeculationCheck(kind, jsValueSource, node, jumpToFail, recovery);
-    if (m_speculationDirection == ForwardSpeculation)
-        convertLastOSRExitToForward();
-}
-
-void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge edge, MacroAssembler::Jump jumpToFail, const SpeculationRecovery&amp; recovery)
-{
-    speculationCheck(kind, jsValueSource, edge.node(), jumpToFail, recovery);
-}
-
</del><span class="cx"> void SpeculativeJIT::emitInvalidationPoint(Node* node)
</span><span class="cx"> {
</span><span class="cx">     if (!m_compileOkay)
</span><span class="cx">         return;
</span><span class="cx">     ASSERT(m_canExit);
</span><del>-    ASSERT(m_speculationDirection == BackwardSpeculation);
</del><span class="cx">     OSRExitCompilationInfo&amp; info = m_jit.appendExitInfo(JITCompiler::JumpList());
</span><span class="cx">     m_jit.jitCode()-&gt;appendOSRExit(OSRExit(
</span><span class="cx">         UncountableInvalidation, JSValueSource(),
</span><span class="lines">@@ -217,26 +184,6 @@
</span><span class="cx">     noResult(node);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SpeculativeJIT::convertLastOSRExitToForward(const ValueRecovery&amp; valueRecovery)
-{
-    m_jit.jitCode()-&gt;lastOSRExit().convertToForward(
-        m_block, m_currentNode, m_indexInBlock, valueRecovery);
-}
-
-void SpeculativeJIT::forwardSpeculationCheck(ExitKind kind, JSValueSource jsValueSource, Node* node, MacroAssembler::Jump jumpToFail, const ValueRecovery&amp; valueRecovery)
-{
-    ASSERT(m_isCheckingArgumentTypes || m_canExit);
-    backwardSpeculationCheck(kind, jsValueSource, node, jumpToFail);
-    convertLastOSRExitToForward(valueRecovery);
-}
-
-void SpeculativeJIT::forwardSpeculationCheck(ExitKind kind, JSValueSource jsValueSource, Node* node, const MacroAssembler::JumpList&amp; jumpsToFail, const ValueRecovery&amp; valueRecovery)
-{
-    ASSERT(m_isCheckingArgumentTypes || m_canExit);
-    backwardSpeculationCheck(kind, jsValueSource, node, jumpsToFail);
-    convertLastOSRExitToForward(valueRecovery);
-}
-
</del><span class="cx"> void SpeculativeJIT::terminateSpeculativeExecution(ExitKind kind, JSValueRegs jsValueRegs, Node* node)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(m_isCheckingArgumentTypes || m_canExit);
</span><span class="lines">@@ -252,26 +199,13 @@
</span><span class="cx">     terminateSpeculativeExecution(kind, jsValueRegs, nodeUse.node());
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SpeculativeJIT::backwardTypeCheck(JSValueSource source, Edge edge, SpeculatedType typesPassedThrough, MacroAssembler::Jump jumpToFail)
</del><ins>+void SpeculativeJIT::typeCheck(JSValueSource source, Edge edge, SpeculatedType typesPassedThrough, MacroAssembler::Jump jumpToFail)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(needsTypeCheck(edge, typesPassedThrough));
</span><span class="cx">     m_interpreter.filter(edge, typesPassedThrough);
</span><del>-    backwardSpeculationCheck(BadType, source, edge.node(), jumpToFail);
</del><ins>+    speculationCheck(BadType, source, edge.node(), jumpToFail);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SpeculativeJIT::typeCheck(JSValueSource source, Edge edge, SpeculatedType typesPassedThrough, MacroAssembler::Jump jumpToFail)
-{
-    backwardTypeCheck(source, edge, typesPassedThrough, jumpToFail);
-    if (m_speculationDirection == ForwardSpeculation)
-        convertLastOSRExitToForward();
-}
-
-void SpeculativeJIT::forwardTypeCheck(JSValueSource source, Edge edge, SpeculatedType typesPassedThrough, MacroAssembler::Jump jumpToFail, const ValueRecovery&amp; valueRecovery)
-{
-    backwardTypeCheck(source, edge, typesPassedThrough, jumpToFail);
-    convertLastOSRExitToForward(valueRecovery);
-}
-
</del><span class="cx"> RegisterSet SpeculativeJIT::usedRegisters()
</span><span class="cx"> {
</span><span class="cx">     RegisterSet result;
</span><span class="lines">@@ -1380,16 +1314,9 @@
</span><span class="cx">     Node* child = node-&gt;child1().node();
</span><span class="cx">     noticeOSRBirth(child);
</span><span class="cx">     
</span><del>-    m_stream-&gt;appendAndLog(VariableEvent::movHint(MinifiedID(child), node-&gt;local()));
</del><ins>+    m_stream-&gt;appendAndLog(VariableEvent::movHint(MinifiedID(child), node-&gt;unlinkedLocal()));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SpeculativeJIT::compileMovHintAndCheck(Node* node)
-{
-    compileMovHint(node);
-    speculate(node, node-&gt;child1());
-    noResult(node);
-}
-
</del><span class="cx"> void SpeculativeJIT::bail()
</span><span class="cx"> {
</span><span class="cx">     m_compileOkay = true;
</span><span class="lines">@@ -1482,7 +1409,7 @@
</span><span class="cx">                 break;
</span><span class="cx">                 
</span><span class="cx">             case ZombieHint: {
</span><del>-                recordSetLocal(DataFormatDead);
</del><ins>+                recordSetLocal(m_currentNode-&gt;unlinkedLocal(), VirtualRegister(), DataFormatDead);
</ins><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx"> 
</span><span class="lines">@@ -1501,8 +1428,6 @@
</span><span class="cx">                 dataLog(&quot;\n&quot;);
</span><span class="cx">             }
</span><span class="cx">             
</span><del>-            m_speculationDirection = (m_currentNode-&gt;flags() &amp; NodeExitsForward) ? ForwardSpeculation : BackwardSpeculation;
-            
</del><span class="cx">             compile(m_currentNode);
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(DFG_REGISTER_ALLOCATION_VALIDATION)
</span><span class="lines">@@ -1540,18 +1465,19 @@
</span><span class="cx"> {
</span><span class="cx">     ASSERT(!m_currentNode);
</span><span class="cx">     m_isCheckingArgumentTypes = true;
</span><del>-    m_speculationDirection = BackwardSpeculation;
</del><span class="cx">     m_codeOriginForExitTarget = CodeOrigin(0);
</span><span class="cx">     m_codeOriginForExitProfile = CodeOrigin(0);
</span><span class="cx"> 
</span><span class="cx">     for (int i = 0; i &lt; m_jit.codeBlock()-&gt;numParameters(); ++i) {
</span><span class="cx">         Node* node = m_jit.graph().m_arguments[i];
</span><del>-        ASSERT(node-&gt;op() == SetArgument);
-        if (!node-&gt;shouldGenerate()) {
</del><ins>+        if (!node) {
</ins><span class="cx">             // The argument is dead. We don't do any checks for such arguments.
</span><span class="cx">             continue;
</span><span class="cx">         }
</span><span class="cx">         
</span><ins>+        ASSERT(node-&gt;op() == SetArgument);
+        ASSERT(node-&gt;shouldGenerate());
+
</ins><span class="cx">         VariableAccessData* variableAccessData = node-&gt;variableAccessData();
</span><span class="cx">         FlushFormat format = variableAccessData-&gt;flushFormat();
</span><span class="cx">         
</span><span class="lines">@@ -2167,16 +2093,9 @@
</span><span class="cx">         MacroAssembler::AboveOrEqual, op1GPR, GPRInfo::tagTypeNumberRegister);
</span><span class="cx">     
</span><span class="cx">     if (needsTypeCheck(node-&gt;child1(), SpecFullNumber)) {
</span><del>-        if (node-&gt;flags() &amp; NodeExitsForward) {
-            forwardTypeCheck(
-                JSValueRegs(op1GPR), node-&gt;child1(), SpecFullNumber,
-                m_jit.branchTest64(MacroAssembler::Zero, op1GPR, GPRInfo::tagTypeNumberRegister),
-                ValueRecovery::inGPR(op1GPR, DataFormatJS));
-        } else {
-            backwardTypeCheck(
-                JSValueRegs(op1GPR), node-&gt;child1(), SpecFullNumber,
-                m_jit.branchTest64(MacroAssembler::Zero, op1GPR, GPRInfo::tagTypeNumberRegister));
-        }
</del><ins>+        typeCheck(
+            JSValueRegs(op1GPR), node-&gt;child1(), SpecFullNumber,
+            m_jit.branchTest64(MacroAssembler::Zero, op1GPR, GPRInfo::tagTypeNumberRegister));
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     m_jit.move(op1GPR, tempGPR);
</span><span class="lines">@@ -2198,16 +2117,9 @@
</span><span class="cx">         MacroAssembler::Equal, op1TagGPR, TrustedImm32(JSValue::Int32Tag));
</span><span class="cx">     
</span><span class="cx">     if (needsTypeCheck(node-&gt;child1(), SpecFullNumber)) {
</span><del>-        if (node-&gt;flags() &amp; NodeExitsForward) {
-            forwardTypeCheck(
-                JSValueRegs(op1TagGPR, op1PayloadGPR), node-&gt;child1(), SpecFullNumber,
-                m_jit.branch32(MacroAssembler::AboveOrEqual, op1TagGPR, TrustedImm32(JSValue::LowestTag)),
-                ValueRecovery::inPair(op1TagGPR, op1PayloadGPR));
-        } else {
-            backwardTypeCheck(
-                JSValueRegs(op1TagGPR, op1PayloadGPR), node-&gt;child1(), SpecFullNumber,
-                m_jit.branch32(MacroAssembler::AboveOrEqual, op1TagGPR, TrustedImm32(JSValue::LowestTag)));
-        }
</del><ins>+        typeCheck(
+            JSValueRegs(op1TagGPR, op1PayloadGPR), node-&gt;child1(), SpecFullNumber,
+            m_jit.branch32(MacroAssembler::AboveOrEqual, op1TagGPR, TrustedImm32(JSValue::LowestTag)));
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     unboxDouble(op1TagGPR, op1PayloadGPR, resultFPR, tempFPR);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h (161125 => 161126)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h        2013-12-29 21:49:03 UTC (rev 161125)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h        2013-12-29 21:50:55 UTC (rev 161126)
</span><span class="lines">@@ -697,8 +697,12 @@
</span><span class="cx">         // Check that no intervening nodes will be generated.
</span><span class="cx">         for (unsigned index = m_indexInBlock + 1; index &lt; m_block-&gt;size() - 1; ++index) {
</span><span class="cx">             Node* node = m_block-&gt;at(index);
</span><del>-            if (node-&gt;shouldGenerate())
-                return UINT_MAX;
</del><ins>+            if (!node-&gt;shouldGenerate())
+                continue;
+            // Check if it's a Phantom that can be safely ignored.
+            if (node-&gt;op() == Phantom &amp;&amp; !node-&gt;child1())
+                continue;
+            return UINT_MAX;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         // Check if the lastNode is a branch on this node.
</span><span class="lines">@@ -2143,43 +2147,28 @@
</span><span class="cx">     JITCompiler::Jump convertToDouble(JSValueOperand&amp;, FPRReg result);
</span><span class="cx"> #endif
</span><span class="cx">     
</span><del>-    // Add a backward speculation check.
-    void backwardSpeculationCheck(ExitKind, JSValueSource, Node*, MacroAssembler::Jump jumpToFail);
-    void backwardSpeculationCheck(ExitKind, JSValueSource, Node*, const MacroAssembler::JumpList&amp; jumpsToFail);
-
-    // Add a speculation check without additional recovery.
</del><ins>+    // Add a speculation check.
</ins><span class="cx">     void speculationCheck(ExitKind, JSValueSource, Node*, MacroAssembler::Jump jumpToFail);
</span><del>-    void speculationCheck(ExitKind, JSValueSource, Edge, MacroAssembler::Jump jumpToFail);
-    // Add a speculation check without additional recovery, and with a promise to supply a jump later.
-    OSRExitJumpPlaceholder backwardSpeculationCheck(ExitKind, JSValueSource, Node*);
-    OSRExitJumpPlaceholder backwardSpeculationCheck(ExitKind, JSValueSource, Edge);
-    // Add a set of speculation checks without additional recovery.
</del><span class="cx">     void speculationCheck(ExitKind, JSValueSource, Node*, const MacroAssembler::JumpList&amp; jumpsToFail);
</span><ins>+
+    // Add a speculation check without additional recovery, and with a promise to supply a jump later.
+    OSRExitJumpPlaceholder speculationCheck(ExitKind, JSValueSource, Node*);
+    OSRExitJumpPlaceholder speculationCheck(ExitKind, JSValueSource, Edge);
+    void speculationCheck(ExitKind, JSValueSource, Edge, MacroAssembler::Jump jumpToFail);
</ins><span class="cx">     void speculationCheck(ExitKind, JSValueSource, Edge, const MacroAssembler::JumpList&amp; jumpsToFail);
</span><span class="cx">     // Add a speculation check with additional recovery.
</span><del>-    void backwardSpeculationCheck(ExitKind, JSValueSource, Node*, MacroAssembler::Jump jumpToFail, const SpeculationRecovery&amp;);
-    void backwardSpeculationCheck(ExitKind, JSValueSource, Edge, MacroAssembler::Jump jumpToFail, const SpeculationRecovery&amp;);
</del><ins>+    void speculationCheck(ExitKind, JSValueSource, Node*, MacroAssembler::Jump jumpToFail, const SpeculationRecovery&amp;);
+    void speculationCheck(ExitKind, JSValueSource, Edge, MacroAssembler::Jump jumpToFail, const SpeculationRecovery&amp;);
</ins><span class="cx">     
</span><span class="cx">     void emitInvalidationPoint(Node*);
</span><span class="cx">     
</span><del>-    // It is generally a good idea to not use this directly.
-    void convertLastOSRExitToForward(const ValueRecovery&amp; = ValueRecovery());
-    
-    // Note: not specifying the valueRecovery argument (leaving it as ValueRecovery()) implies
-    // that you've ensured that there exists a MovHint prior to your use of forwardSpeculationCheck().
-    void forwardSpeculationCheck(ExitKind, JSValueSource, Node*, MacroAssembler::Jump jumpToFail, const ValueRecovery&amp; = ValueRecovery());
-    void forwardSpeculationCheck(ExitKind, JSValueSource, Node*, const MacroAssembler::JumpList&amp; jumpsToFail, const ValueRecovery&amp; = ValueRecovery());
-    void speculationCheck(ExitKind, JSValueSource, Node*, MacroAssembler::Jump jumpToFail, const SpeculationRecovery&amp;);
-    void speculationCheck(ExitKind, JSValueSource, Edge, MacroAssembler::Jump jumpToFail, const SpeculationRecovery&amp;);
</del><span class="cx">     // Called when we statically determine that a speculation will fail.
</span><span class="cx">     void terminateSpeculativeExecution(ExitKind, JSValueRegs, Node*);
</span><span class="cx">     void terminateSpeculativeExecution(ExitKind, JSValueRegs, Edge);
</span><span class="cx">     
</span><span class="cx">     // Helpers for performing type checks on an edge stored in the given registers.
</span><span class="cx">     bool needsTypeCheck(Edge edge, SpeculatedType typesPassedThrough) { return m_interpreter.needsTypeCheck(edge, typesPassedThrough); }
</span><del>-    void backwardTypeCheck(JSValueSource, Edge, SpeculatedType typesPassedThrough, MacroAssembler::Jump jumpToFail);
</del><span class="cx">     void typeCheck(JSValueSource, Edge, SpeculatedType typesPassedThrough, MacroAssembler::Jump jumpToFail);
</span><del>-    void forwardTypeCheck(JSValueSource, Edge, SpeculatedType typesPassedThrough, MacroAssembler::Jump jumpToFail, const ValueRecovery&amp;);
</del><span class="cx"> 
</span><span class="cx">     void speculateInt32(Edge);
</span><span class="cx">     void speculateMachineInt(Edge);
</span><span class="lines">@@ -2252,7 +2241,6 @@
</span><span class="cx">     // The current node being generated.
</span><span class="cx">     BasicBlock* m_block;
</span><span class="cx">     Node* m_currentNode;
</span><del>-    SpeculationDirection m_speculationDirection;
</del><span class="cx">     bool m_canExit;
</span><span class="cx">     unsigned m_indexInBlock;
</span><span class="cx">     // Virtual and physical register maps.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp (161125 => 161126)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2013-12-29 21:49:03 UTC (rev 161125)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2013-12-29 21:50:55 UTC (rev 161126)
</span><span class="lines">@@ -1921,24 +1921,14 @@
</span><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    case MovHintAndCheck: {
-        compileMovHintAndCheck(node);
-        break;
-    }
-        
</del><span class="cx">     case MovHint:
</span><del>-    case ZombieHint: {
</del><ins>+    case ZombieHint:
+    case Check: {
</ins><span class="cx">         RELEASE_ASSERT_NOT_REACHED();
</span><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     case SetLocal: {
</span><del>-        // SetLocal doubles as a hint as to where a node will be stored and
-        // as a speculation point. So before we speculate make sure that we
-        // know where the child of this node needs to go in the virtual
-        // stack.
-        compileMovHint(node);
-        
</del><span class="cx">         switch (node-&gt;variableAccessData()-&gt;flushFormat()) {
</span><span class="cx">         case FlushedDouble: {
</span><span class="cx">             SpeculateDoubleOperand value(this, node-&gt;child1());
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (161125 => 161126)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2013-12-29 21:49:03 UTC (rev 161125)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2013-12-29 21:50:55 UTC (rev 161126)
</span><span class="lines">@@ -2236,24 +2236,14 @@
</span><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx">         
</span><del>-    case MovHintAndCheck: {
-        compileMovHintAndCheck(node);
-        break;
-    }
-        
</del><span class="cx">     case MovHint:
</span><del>-    case ZombieHint: {
</del><ins>+    case ZombieHint:
+    case Check: {
</ins><span class="cx">         RELEASE_ASSERT_NOT_REACHED();
</span><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     case SetLocal: {
</span><del>-        // SetLocal doubles as a hint as to where a node will be stored and
-        // as a speculation point. So before we speculate make sure that we
-        // know where the child of this node needs to go in the virtual
-        // stack.
-        compileMovHint(node);
-        
</del><span class="cx">         switch (node-&gt;variableAccessData()-&gt;flushFormat()) {
</span><span class="cx">         case FlushedDouble: {
</span><span class="cx">             SpeculateDoubleOperand value(this, node-&gt;child1());
</span><span class="lines">@@ -2304,7 +2294,6 @@
</span><span class="cx">             JSValueOperand value(this, node-&gt;child1());
</span><span class="cx">             m_jit.store64(value.gpr(), JITCompiler::addressFor(node-&gt;machineLocal()));
</span><span class="cx">             noResult(node);
</span><del>-            
</del><span class="cx">             recordSetLocal(DataFormatJS);
</span><span class="cx">             break;
</span><span class="cx">         }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGTypeCheckHoistingPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGTypeCheckHoistingPhase.cpp (161125 => 161126)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGTypeCheckHoistingPhase.cpp        2013-12-29 21:49:03 UTC (rev 161125)
+++ trunk/Source/JavaScriptCore/dfg/DFGTypeCheckHoistingPhase.cpp        2013-12-29 21:50:55 UTC (rev 161126)
</span><span class="lines">@@ -163,33 +163,22 @@
</span><span class="cx">                     if (!iter-&gt;value.m_structure &amp;&amp; !iter-&gt;value.m_arrayModeIsValid)
</span><span class="cx">                         break;
</span><span class="cx"> 
</span><del>-                    // First insert a dead SetLocal to tell OSR that the child's value should
-                    // be dropped into this bytecode variable if the CheckStructure decides
-                    // to exit.
-                    
</del><span class="cx">                     CodeOrigin codeOrigin = node-&gt;codeOrigin;
</span><span class="cx">                     Edge child1 = node-&gt;child1();
</span><span class="cx">                     
</span><del>-                    insertionSet.insertNode(
-                        indexInBlock, SpecNone, SetLocal, codeOrigin, OpInfo(variable), child1);
-
-                    // Use NodeExitsForward to indicate that we should exit to the next
-                    // bytecode instruction rather than reexecuting the current one.
-                    Node* newNode = 0;
</del><span class="cx">                     if (iter-&gt;value.m_structure) {
</span><del>-                        newNode = insertionSet.insertNode(
</del><ins>+                        insertionSet.insertNode(
</ins><span class="cx">                             indexInBlock, SpecNone, CheckStructure, codeOrigin,
</span><span class="cx">                             OpInfo(m_graph.addStructureSet(iter-&gt;value.m_structure)),
</span><span class="cx">                             Edge(child1.node(), CellUse));
</span><span class="cx">                     } else if (iter-&gt;value.m_arrayModeIsValid) {
</span><span class="cx">                         ASSERT(iter-&gt;value.m_arrayModeHoistingOkay);
</span><del>-                        newNode = insertionSet.insertNode(
</del><ins>+                        insertionSet.insertNode(
</ins><span class="cx">                             indexInBlock, SpecNone, CheckArray, codeOrigin,
</span><span class="cx">                             OpInfo(iter-&gt;value.m_arrayMode.asWord()),
</span><span class="cx">                             Edge(child1.node(), CellUse));
</span><span class="cx">                     } else
</span><span class="cx">                         RELEASE_ASSERT_NOT_REACHED();
</span><del>-                    newNode-&gt;mergeFlags(NodeExitsForward);
</del><span class="cx">                     changed = true;
</span><span class="cx">                     break;
</span><span class="cx">                 }
</span><span class="lines">@@ -228,9 +217,6 @@
</span><span class="cx">                 switch (node-&gt;op()) {
</span><span class="cx">                 case CheckStructure:
</span><span class="cx">                 case StructureTransitionWatchpoint: {
</span><del>-                    // We currently rely on the fact that we're the only ones who would
-                    // insert these nodes with NodeExitsForward.
-                    RELEASE_ASSERT(!(node-&gt;flags() &amp; NodeExitsForward));
</del><span class="cx">                     Node* child = node-&gt;child1().node();
</span><span class="cx">                     if (child-&gt;op() != GetLocal)
</span><span class="cx">                         break;
</span><span class="lines">@@ -257,6 +243,7 @@
</span><span class="cx">                 case GetIndexedPropertyStorage:
</span><span class="cx">                 case GetTypedArrayByteOffset:
</span><span class="cx">                 case Phantom:
</span><ins>+                case MovHint:
</ins><span class="cx">                     // Don't count these uses.
</span><span class="cx">                     break;
</span><span class="cx">                     
</span><span class="lines">@@ -329,9 +316,6 @@
</span><span class="cx">                 Node* node = block-&gt;at(indexInBlock);
</span><span class="cx">                 switch (node-&gt;op()) {
</span><span class="cx">                 case CheckArray: {
</span><del>-                    // We currently rely on the fact that we're the only ones who would
-                    // insert these nodes with NodeExitsForward.
-                    RELEASE_ASSERT(!(node-&gt;flags() &amp; NodeExitsForward));
</del><span class="cx">                     Node* child = node-&gt;child1().node();
</span><span class="cx">                     if (child-&gt;op() != GetLocal)
</span><span class="cx">                         break;
</span><span class="lines">@@ -357,6 +341,7 @@
</span><span class="cx">                 case GetArrayLength:
</span><span class="cx">                 case GetIndexedPropertyStorage:
</span><span class="cx">                 case Phantom:
</span><ins>+                case MovHint:
</ins><span class="cx">                     // Don't count these uses.
</span><span class="cx">                     break;
</span><span class="cx">                     
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGValidatecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGValidate.cpp (161125 => 161126)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGValidate.cpp        2013-12-29 21:49:03 UTC (rev 161125)
+++ trunk/Source/JavaScriptCore/dfg/DFGValidate.cpp        2013-12-29 21:50:55 UTC (rev 161126)
</span><span class="lines">@@ -245,10 +245,7 @@
</span><span class="cx">                         edge-&gt;op() == SetLocal
</span><span class="cx">                         || edge-&gt;op() == SetArgument
</span><span class="cx">                         || edge-&gt;op() == Flush
</span><del>-                        || edge-&gt;op() == Phi
-                        || edge-&gt;op() == ZombieHint
-                        || edge-&gt;op() == MovHint
-                        || edge-&gt;op() == MovHintAndCheck);
</del><ins>+                        || edge-&gt;op() == Phi);
</ins><span class="cx">                     
</span><span class="cx">                     if (phisInThisBlock.contains(edge.node()))
</span><span class="cx">                         continue;
</span><span class="lines">@@ -257,9 +254,6 @@
</span><span class="cx">                         VALIDATE(
</span><span class="cx">                             (node, edge),
</span><span class="cx">                             edge-&gt;op() == SetLocal
</span><del>-                            || edge-&gt;op() == ZombieHint
-                            || edge-&gt;op() == MovHint
-                            || edge-&gt;op() == MovHintAndCheck
</del><span class="cx">                             || edge-&gt;op() == SetArgument
</span><span class="cx">                             || edge-&gt;op() == Flush);
</span><span class="cx">                         
</span><span class="lines">@@ -292,9 +286,6 @@
</span><span class="cx">                         VALIDATE(
</span><span class="cx">                             (local, block-&gt;predecessors[k], prevNode),
</span><span class="cx">                             prevNode-&gt;op() == SetLocal
</span><del>-                            || prevNode-&gt;op() == MovHint
-                            || prevNode-&gt;op() == MovHintAndCheck
-                            || prevNode-&gt;op() == ZombieHint
</del><span class="cx">                             || prevNode-&gt;op() == SetArgument
</span><span class="cx">                             || prevNode-&gt;op() == Phi);
</span><span class="cx">                         if (prevNode == edge.node()) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGVariableAccessDatah"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGVariableAccessData.h (161125 => 161126)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGVariableAccessData.h        2013-12-29 21:49:03 UTC (rev 161125)
+++ trunk/Source/JavaScriptCore/dfg/DFGVariableAccessData.h        2013-12-29 21:50:55 UTC (rev 161126)
</span><span class="lines">@@ -74,6 +74,7 @@
</span><span class="cx">         , m_structureCheckHoistingFailed(false)
</span><span class="cx">         , m_checkArrayHoistingFailed(false)
</span><span class="cx">         , m_isProfitableToUnbox(false)
</span><ins>+        , m_isLoadedFrom(false)
</ins><span class="cx">         , m_doubleFormatState(EmptyDoubleFormatState)
</span><span class="cx">     {
</span><span class="cx">         clearVotes();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGVariableEventStreamcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGVariableEventStream.cpp (161125 => 161126)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGVariableEventStream.cpp        2013-12-29 21:49:03 UTC (rev 161125)
+++ trunk/Source/JavaScriptCore/dfg/DFGVariableEventStream.cpp        2013-12-29 21:50:55 UTC (rev 161126)
</span><span class="lines">@@ -192,70 +192,8 @@
</span><span class="cx">         
</span><span class="cx">         MinifiedGenerationInfo info = generationInfos.get(source.id());
</span><span class="cx">         if (info.format == DataFormatNone) {
</span><del>-            // Try to see if there is an alternate node that would contain the value we want.
-            //
-            // Backward rewiring refers to:
-            //
-            //     a: Something(...)
-            //     b: Id(@a) // some identity function
-            //     c: SetLocal(@b)
-            //
-            // Where we find @b being dead, but @a is still alive.
-            //
-            // Forward rewiring refers to:
-            //
-            //     a: Something(...)
-            //     b: SetLocal(@a)
-            //     c: Id(@a) // some identity function
-            //
-            // Where we find @a being dead, but @b is still alive.
-            
-            bool found = false;
-            
-            if (node &amp;&amp; permitsOSRBackwardRewiring(node-&gt;op())) {
-                MinifiedID id = node-&gt;child1();
-                if (tryToSetConstantRecovery(valueRecoveries[i], codeBlock, graph.at(id)))
-                    continue;
-                info = generationInfos.get(id);
-                if (info.format != DataFormatNone)
-                    found = true;
-            }
-            
-            if (!found) {
-                MinifiedID bestID;
-                unsigned bestScore = 0;
-                
-                HashMap&lt;MinifiedID, MinifiedGenerationInfo&gt;::iterator iter = generationInfos.begin();
-                HashMap&lt;MinifiedID, MinifiedGenerationInfo&gt;::iterator end = generationInfos.end();
-                for (; iter != end; ++iter) {
-                    MinifiedID id = iter-&gt;key;
-                    node = graph.at(id);
-                    if (!node)
-                        continue;
-                    if (!node-&gt;hasChild1())
-                        continue;
-                    if (node-&gt;child1() != source.id())
-                        continue;
-                    if (iter-&gt;value.format == DataFormatNone)
-                        continue;
-                    unsigned myScore = forwardRewiringSelectionScore(node-&gt;op());
-                    if (myScore &lt;= bestScore)
-                        continue;
-                    bestID = id;
-                    bestScore = myScore;
-                }
-                
-                if (!!bestID) {
-                    info = generationInfos.get(bestID);
-                    ASSERT(info.format != DataFormatNone);
-                    found = true;
-                }
-            }
-            
-            if (!found) {
-                valueRecoveries[i] = ValueRecovery::constant(jsUndefined());
-                continue;
-            }
</del><ins>+            valueRecoveries[i] = ValueRecovery::constant(jsUndefined());
+            continue;
</ins><span class="cx">         }
</span><span class="cx">         
</span><span class="cx">         ASSERT(info.format != DataFormatNone);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLCapabilitiescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp (161125 => 161126)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp        2013-12-29 21:49:03 UTC (rev 161125)
+++ trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp        2013-12-29 21:50:55 UTC (rev 161126)
</span><span class="lines">@@ -42,7 +42,6 @@
</span><span class="cx">     case WeakJSConstant:
</span><span class="cx">     case GetLocal:
</span><span class="cx">     case SetLocal:
</span><del>-    case MovHintAndCheck:
</del><span class="cx">     case MovHint:
</span><span class="cx">     case ZombieHint:
</span><span class="cx">     case Phantom:
</span><span class="lines">@@ -111,6 +110,7 @@
</span><span class="cx">     case LogicalNot:
</span><span class="cx">     case CheckInBounds:
</span><span class="cx">     case ConstantStoragePointer:
</span><ins>+    case Check:
</ins><span class="cx">         // These are OK.
</span><span class="cx">         break;
</span><span class="cx">     case GetById:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLLowerDFGToLLVMcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp (161125 => 161126)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2013-12-29 21:49:03 UTC (rev 161125)
+++ trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2013-12-29 21:50:55 UTC (rev 161126)
</span><span class="lines">@@ -228,8 +228,6 @@
</span><span class="cx">         
</span><span class="cx">         bool shouldExecuteEffects = m_interpreter.startExecuting(m_node);
</span><span class="cx">         
</span><del>-        m_direction = (m_node-&gt;flags() &amp; NodeExitsForward) ? ForwardSpeculation : BackwardSpeculation;
-        
</del><span class="cx">         switch (m_node-&gt;op()) {
</span><span class="cx">         case Upsilon:
</span><span class="cx">             compileUpsilon();
</span><span class="lines">@@ -260,9 +258,6 @@
</span><span class="cx">         case ZombieHint:
</span><span class="cx">             compileZombieHint();
</span><span class="cx">             break;
</span><del>-        case MovHintAndCheck:
-            compileMovHintAndCheck();
-            break;
</del><span class="cx">         case Phantom:
</span><span class="cx">             compilePhantom();
</span><span class="cx">             break;
</span><span class="lines">@@ -657,15 +652,15 @@
</span><span class="cx"> 
</span><span class="cx">         switch (useKindFor(variable-&gt;flushFormat())) {
</span><span class="cx">         case Int32Use:
</span><del>-            speculateBackward(BadType, jsValueValue(jsValue), m_node, isNotInt32(jsValue));
</del><ins>+            speculate(BadType, jsValueValue(jsValue), m_node, isNotInt32(jsValue));
</ins><span class="cx">             setInt32(unboxInt32(jsValue));
</span><span class="cx">             break;
</span><span class="cx">         case CellUse:
</span><del>-            speculateBackward(BadType, jsValueValue(jsValue), m_node, isNotCell(jsValue));
</del><ins>+            speculate(BadType, jsValueValue(jsValue), m_node, isNotCell(jsValue));
</ins><span class="cx">             setJSValue(jsValue);
</span><span class="cx">             break;
</span><span class="cx">         case BooleanUse:
</span><del>-            speculateBackward(BadType, jsValueValue(jsValue), m_node, isNotBoolean(jsValue));
</del><ins>+            speculate(BadType, jsValueValue(jsValue), m_node, isNotBoolean(jsValue));
</ins><span class="cx">             setBoolean(unboxBoolean(jsValue));
</span><span class="cx">             break;
</span><span class="cx">         case UntypedUse:
</span><span class="lines">@@ -701,8 +696,6 @@
</span><span class="cx">     
</span><span class="cx">     void compileSetLocal()
</span><span class="cx">     {
</span><del>-        observeMovHint(m_node);
-        
</del><span class="cx">         VariableAccessData* variable = m_node-&gt;variableAccessData();
</span><span class="cx">         switch (variable-&gt;flushFormat()) {
</span><span class="cx">         case FlushedJSValue: {
</span><span class="lines">@@ -753,21 +746,18 @@
</span><span class="cx">     
</span><span class="cx">     void compileMovHint()
</span><span class="cx">     {
</span><del>-        observeMovHint(m_node);
</del><ins>+        ASSERT(m_node-&gt;containsMovHint());
+        ASSERT(m_node-&gt;op() != ZombieHint);
+        
+        VirtualRegister operand = m_node-&gt;unlinkedLocal();
+        m_availability.operand(operand) = Availability(m_node-&gt;child1().node());
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     void compileZombieHint()
</span><span class="cx">     {
</span><del>-        VariableAccessData* data = m_node-&gt;variableAccessData();
-        m_availability.operand(data-&gt;local()) = Availability::unavailable();
</del><ins>+        m_availability.operand(m_node-&gt;unlinkedLocal()) = Availability::unavailable();
</ins><span class="cx">     }
</span><span class="cx">     
</span><del>-    void compileMovHintAndCheck()
-    {
-        observeMovHint(m_node);
-        speculate(m_node-&gt;child1());
-    }
-    
</del><span class="cx">     void compilePhantom()
</span><span class="cx">     {
</span><span class="cx">         DFG_NODE_DO_TO_CHILDREN(m_graph, m_node, speculate);
</span><span class="lines">@@ -1177,40 +1167,7 @@
</span><span class="cx">     
</span><span class="cx">     void compileInt32ToDouble()
</span><span class="cx">     {
</span><del>-        if (!m_interpreter.needsTypeCheck(m_node-&gt;child1(), SpecFullNumber)
-            || m_node-&gt;speculationDirection() == BackwardSpeculation) {
-            setDouble(lowDouble(m_node-&gt;child1()));
-            return;
-        }
-        
-        LValue boxedValue = lowJSValue(m_node-&gt;child1(), ManualOperandSpeculation);
-        
-        LBasicBlock intCase = FTL_NEW_BLOCK(m_out, (&quot;Double unboxing int case&quot;));
-        LBasicBlock doubleCase = FTL_NEW_BLOCK(m_out, (&quot;Double unboxing double case&quot;));
-        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, (&quot;Double unboxing continuation&quot;));
-        
-        m_out.branch(isNotInt32(boxedValue), doubleCase, intCase);
-        
-        LBasicBlock lastNext = m_out.appendTo(intCase, doubleCase);
-        
-        ValueFromBlock intToDouble = m_out.anchor(
-            m_out.intToDouble(unboxInt32(boxedValue)));
-        m_out.jump(continuation);
-        
-        m_out.appendTo(doubleCase, continuation);
-
-        forwardTypeCheck(
-            jsValueValue(boxedValue), m_node-&gt;child1(), SpecFullNumber,
-            isCellOrMisc(boxedValue), jsValueValue(boxedValue));
-        
-        ValueFromBlock unboxedDouble = m_out.anchor(unboxDouble(boxedValue));
-        m_out.jump(continuation);
-        
-        m_out.appendTo(continuation, lastNext);
-        
-        LValue result = m_out.phi(m_out.doubleType, intToDouble, unboxedDouble);
-        
-        setDouble(result);
</del><ins>+        setDouble(lowDouble(m_node-&gt;child1()));
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     void compileCheckStructure()
</span><span class="lines">@@ -3196,26 +3153,10 @@
</span><span class="cx">         return m_out.phi(m_out.int32, fastResult, slowResult);
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    void speculateBackward(
-        ExitKind kind, FormattedValue lowValue, Node* highValue, LValue failCondition)
-    {
-        appendOSRExit(
-            kind, lowValue, highValue, failCondition, BackwardSpeculation, FormattedValue());
-    }
-    
-    void speculateForward(
-        ExitKind kind, FormattedValue lowValue, Node* highValue, LValue failCondition,
-        const FormattedValue&amp; recovery)
-    {
-        appendOSRExit(
-            kind, lowValue, highValue, failCondition, ForwardSpeculation, recovery);
-    }
-    
</del><span class="cx">     void speculate(
</span><span class="cx">         ExitKind kind, FormattedValue lowValue, Node* highValue, LValue failCondition)
</span><span class="cx">     {
</span><del>-        appendOSRExit(
-            kind, lowValue, highValue, failCondition, m_direction, FormattedValue());
</del><ins>+        appendOSRExit(kind, lowValue, highValue, failCondition);
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     void terminate(ExitKind kind)
</span><span class="lines">@@ -3223,41 +3164,21 @@
</span><span class="cx">         speculate(kind, noValue(), 0, m_out.booleanTrue);
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    void backwardTypeCheck(
-        FormattedValue lowValue, Edge highValue, SpeculatedType typesPassedThrough,
-        LValue failCondition)
-    {
-        appendTypeCheck(
-            lowValue, highValue, typesPassedThrough, failCondition, BackwardSpeculation,
-            FormattedValue());
-    }
-    
-    void forwardTypeCheck(
-        FormattedValue lowValue, Edge highValue, SpeculatedType typesPassedThrough,
-        LValue failCondition, const FormattedValue&amp; recovery)
-    {
-        appendTypeCheck(
-            lowValue, highValue, typesPassedThrough, failCondition, ForwardSpeculation,
-            recovery);
-    }
-    
</del><span class="cx">     void typeCheck(
</span><span class="cx">         FormattedValue lowValue, Edge highValue, SpeculatedType typesPassedThrough,
</span><span class="cx">         LValue failCondition)
</span><span class="cx">     {
</span><del>-        appendTypeCheck(
-            lowValue, highValue, typesPassedThrough, failCondition, m_direction,
-            FormattedValue());
</del><ins>+        appendTypeCheck(lowValue, highValue, typesPassedThrough, failCondition);
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     void appendTypeCheck(
</span><span class="cx">         FormattedValue lowValue, Edge highValue, SpeculatedType typesPassedThrough,
</span><del>-        LValue failCondition, SpeculationDirection direction, FormattedValue recovery)
</del><ins>+        LValue failCondition)
</ins><span class="cx">     {
</span><span class="cx">         if (!m_interpreter.needsTypeCheck(highValue, typesPassedThrough))
</span><span class="cx">             return;
</span><span class="cx">         ASSERT(mayHaveTypeCheck(highValue.useKind()));
</span><del>-        appendOSRExit(BadType, lowValue, highValue.node(), failCondition, direction, recovery);
</del><ins>+        appendOSRExit(BadType, lowValue, highValue.node(), failCondition);
</ins><span class="cx">         m_interpreter.filter(highValue, typesPassedThrough);
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="lines">@@ -4092,8 +4013,7 @@
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     void appendOSRExit(
</span><del>-        ExitKind kind, FormattedValue lowValue, Node* highValue, LValue failCondition,
-        SpeculationDirection direction, FormattedValue recovery)
</del><ins>+        ExitKind kind, FormattedValue lowValue, Node* highValue, LValue failCondition)
</ins><span class="cx">     {
</span><span class="cx">         if (verboseCompilationEnabled())
</span><span class="cx">             dataLog(&quot;    OSR exit #&quot;, m_ftlState.jitCode-&gt;osrExit.size(), &quot; with availability: &quot;, m_availability, &quot;\n&quot;);
</span><span class="lines">@@ -4118,38 +4038,20 @@
</span><span class="cx">         
</span><span class="cx">         lastNext = m_out.appendTo(failCase, continuation);
</span><span class="cx">         
</span><del>-        emitOSRExitCall(exit, lowValue, direction, recovery);
</del><ins>+        emitOSRExitCall(exit, lowValue);
</ins><span class="cx">         
</span><span class="cx">         m_out.unreachable();
</span><span class="cx">         
</span><span class="cx">         m_out.appendTo(continuation, lastNext);
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    void emitOSRExitCall(
-        OSRExit&amp; exit, FormattedValue lowValue, SpeculationDirection direction,
-        FormattedValue recovery)
</del><ins>+    void emitOSRExitCall(OSRExit&amp; exit, FormattedValue lowValue)
</ins><span class="cx">     {
</span><span class="cx">         ExitArgumentList arguments;
</span><span class="cx">         
</span><span class="cx">         CodeOrigin codeOrigin = exit.m_codeOrigin;
</span><span class="cx">         
</span><del>-        if (direction == BackwardSpeculation)
-            buildExitArguments(exit, arguments, lowValue, codeOrigin);
-        else {
-            ASSERT(direction == ForwardSpeculation);
-            if (!recovery) {
-                for (unsigned nodeIndex = m_nodeIndex; nodeIndex &lt; m_highBlock-&gt;size(); ++nodeIndex) {
-                    Node* node = m_highBlock-&gt;at(nodeIndex);
-                    if (node-&gt;codeOriginForExitTarget == codeOrigin)
-                        continue;
-                    codeOrigin = node-&gt;codeOriginForExitTarget;
-                    break;
-                }
-            }
-            
-            buildExitArguments(exit, arguments, lowValue, codeOrigin);
-            exit.convertToForward(m_highBlock, m_node, m_nodeIndex, recovery, arguments);
-        }
</del><ins>+        buildExitArguments(exit, arguments, lowValue, codeOrigin);
</ins><span class="cx">         
</span><span class="cx">         callStackmap(exit, arguments);
</span><span class="cx">     }
</span><span class="lines">@@ -4309,16 +4211,6 @@
</span><span class="cx">         arguments.append(value);
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    void observeMovHint(Node* node)
-    {
-        ASSERT(node-&gt;containsMovHint());
-        ASSERT(node-&gt;op() != ZombieHint);
-        
-        VirtualRegister operand = node-&gt;local();
-        
-        m_availability.operand(operand) = Availability(node-&gt;child1().node());
-    }
-    
</del><span class="cx">     void setInt32(Node* node, LValue value)
</span><span class="cx">     {
</span><span class="cx">         m_int32Values.set(node, LoweredNodeValue(value, m_highBlock));
</span><span class="lines">@@ -4489,7 +4381,6 @@
</span><span class="cx">     CodeOrigin m_codeOriginForExitProfile;
</span><span class="cx">     unsigned m_nodeIndex;
</span><span class="cx">     Node* m_node;
</span><del>-    SpeculationDirection m_direction;
</del><span class="cx">     
</span><span class="cx">     uint32_t m_stackmapIDs;
</span><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLOSRExitcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLOSRExit.cpp (161125 => 161126)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLOSRExit.cpp        2013-12-29 21:49:03 UTC (rev 161125)
+++ trunk/Source/JavaScriptCore/ftl/FTLOSRExit.cpp        2013-12-29 21:50:55 UTC (rev 161126)
</span><span class="lines">@@ -61,41 +61,6 @@
</span><span class="cx">         m_patchableCodeOffset);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void OSRExit::convertToForward(
-    BasicBlock* block, Node* currentNode, unsigned nodeIndex,
-    const FormattedValue &amp;value, ExitArgumentList&amp; arguments)
-{
-    Node* node;
-    Node* lastMovHint;
-    if (!doSearchForForwardConversion(block, currentNode, nodeIndex, !!value, node, lastMovHint))
-        return;
-
-    ASSERT(node-&gt;codeOrigin != currentNode-&gt;codeOrigin);
-    
-    m_codeOrigin = node-&gt;codeOrigin;
-    
-    if (!value)
-        return;
-    
-    VirtualRegister overriddenOperand = lastMovHint-&gt;local();
-    
-    // Is the value for this operand being passed as an argument to the exit, or is
-    // it something else? If it's an argument already, then replace that argument;
-    // otherwise add another argument.
-    if (m_values.operand(overriddenOperand).isArgument()) {
-        ExitArgument exitArgument = m_values.operand(overriddenOperand).exitArgument();
-        arguments[exitArgument.argument()] = value.value();
-        m_values.operand(overriddenOperand) = ExitValue::exitArgument(
-            exitArgument.withFormat(value.format()));
-        return;
-    }
-    
-    unsigned argument = arguments.size();
-    arguments.append(value.value());
-    m_values.operand(overriddenOperand) = ExitValue::exitArgument(
-        ExitArgument(value.format(), argument));
-}
-
</del><span class="cx"> } } // namespace JSC::FTL
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(FTL_JIT)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLOSRExith"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLOSRExit.h (161125 => 161126)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLOSRExit.h        2013-12-29 21:49:03 UTC (rev 161125)
+++ trunk/Source/JavaScriptCore/ftl/FTLOSRExit.h        2013-12-29 21:50:55 UTC (rev 161126)
</span><span class="lines">@@ -166,10 +166,6 @@
</span><span class="cx">     uint32_t m_stackmapID;
</span><span class="cx">     
</span><span class="cx">     CodeLocationJump codeLocationForRepatch(CodeBlock* ftlCodeBlock) const;
</span><del>-    
-    void convertToForward(
-        DFG::BasicBlock*, DFG::Node* currentNode, unsigned nodeIndex,
-        const FormattedValue&amp;, ExitArgumentList&amp; arguments);
</del><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } } // namespace JSC::FTL
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressdeadint32todoublejs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/dead-int32-to-double.js (0 => 161126)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/dead-int32-to-double.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/dead-int32-to-double.js        2013-12-29 21:50:55 UTC (rev 161126)
</span><span class="lines">@@ -0,0 +1,16 @@
</span><ins>+function foo(int, o) {
+    var x = int;
+    o.f = x;
+    for (var i = 0; i &lt; 100; ++i)
+        x += 0.5;
+}
+
+noInline(foo);
+
+for (var i = 0; i &lt; 100; ++i)
+    foo(42, {});
+
+var o = {g: 43};
+foo(47, o);
+if (o.f != 47)
+    throw &quot;Error: o.f is &quot; + o.f;
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressdeaduint32tonumberjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/dead-uint32-to-number.js (0 => 161126)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/dead-uint32-to-number.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/dead-uint32-to-number.js        2013-12-29 21:50:55 UTC (rev 161126)
</span><span class="lines">@@ -0,0 +1,16 @@
</span><ins>+function foo(a, o) {
+    var x = a &gt;&gt;&gt; 0;
+    o.f = x | 0;
+    for (var i = 0; i &lt; 100; ++i)
+        x++;
+}
+
+noInline(foo);
+
+for (var i = 0; i &lt; 100; ++i)
+    foo(42, {});
+
+var o = {g: 43};
+foo(47, o);
+if (o.f != 47)
+    throw &quot;Error: o.f is &quot; + o.f;
</ins></span></pre>
</div>
</div>

</body>
</html>