<!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>[169354] trunk</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/169354">169354</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2014-05-26 10:43:41 -0700 (Mon, 26 May 2014)</dd>
</dl>
<h3>Log Message</h3>
<pre>Latest emscripten life benchmark is 4x slower because the DFG doesn't realize that arithmetic on booleans is a thing
https://bugs.webkit.org/show_bug.cgi?id=133136
Reviewed by Oliver Hunt.
Source/JavaScriptCore:
Some key concepts:
- Except for the prediction propagation and type fixup phases, which are super early in
the pipeline, nobody has to know about the fact that booleans may flow into numerical
operations because there will just be a BooleanToNumber node that will take a value
and, if that value is a boolean, will convert it to the equivalent numerical value. It
will have a BooleanUse mode where it will also speculate that the input is a boolean
but it can also do UntypedUse in which case it will pass through any non-booleans.
This operation is very easy to model in all of the compiler tiers.
- No changes to the baseline JIT. The Baseline JIT will still believe that boolean
inputs require taking the slow path and it will still report that it took slow path
for any such operations. The DFG will now be smart enough to ignore baseline JIT slow
path profiling on operations that were known to have had boolean inputs. That's a
little quirky, but it's probably easier than modifying the baseline JIT to track
booleans correctly.
4.1x speed-up on the emscripten "life" benchmark. Up to 10x speed-up on microbenchmarks.
* bytecode/SpeculatedType.h:
(JSC::isInt32OrBooleanSpeculation):
(JSC::isInt32SpeculationForArithmetic):
(JSC::isInt32OrBooleanSpeculationForArithmetic):
(JSC::isInt32OrBooleanSpeculationExpectingDefined):
(JSC::isInt52Speculation):
(JSC::isMachineIntSpeculation):
(JSC::isFullNumberOrBooleanSpeculation):
(JSC::isFullNumberOrBooleanSpeculationExpectingDefined):
(JSC::isInt32SpeculationExpectingDefined): Deleted.
(JSC::isMachineIntSpeculationExpectingDefined): Deleted.
(JSC::isMachineIntSpeculationForArithmetic): Deleted.
(JSC::isBytecodeNumberSpeculationExpectingDefined): Deleted.
(JSC::isFullNumberSpeculationExpectingDefined): Deleted.
* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
* dfg/DFGAllocator.h:
(JSC::DFG::Allocator<T>::indexOf):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::makeSafe):
(JSC::DFG::ByteCodeParser::makeDivSafe):
(JSC::DFG::ByteCodeParser::handleIntrinsic):
* dfg/DFGCSEPhase.cpp:
(JSC::DFG::CSEPhase::performNodeCSE):
* dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
* dfg/DFGCommon.h:
* dfg/DFGConstantFoldingPhase.cpp:
(JSC::DFG::ConstantFoldingPhase::foldConstants):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
(JSC::DFG::FixupPhase::fixIntConvertingEdge):
(JSC::DFG::FixupPhase::fixIntOrBooleanEdge):
(JSC::DFG::FixupPhase::fixDoubleOrBooleanEdge):
(JSC::DFG::FixupPhase::attemptToMakeIntegerAdd):
(JSC::DFG::FixupPhase::fixIntEdge): Deleted.
* dfg/DFGGraph.h:
(JSC::DFG::Graph::addSpeculationMode):
(JSC::DFG::Graph::valueAddSpeculationMode):
(JSC::DFG::Graph::arithAddSpeculationMode):
(JSC::DFG::Graph::addShouldSpeculateInt32):
(JSC::DFG::Graph::mulShouldSpeculateInt32):
(JSC::DFG::Graph::mulShouldSpeculateMachineInt):
(JSC::DFG::Graph::negateShouldSpeculateInt32):
(JSC::DFG::Graph::negateShouldSpeculateMachineInt):
(JSC::DFG::Graph::addImmediateShouldSpeculateInt32):
(JSC::DFG::Graph::mulImmediateShouldSpeculateInt32): Deleted.
* dfg/DFGNode.h:
(JSC::DFG::Node::sawBooleans):
(JSC::DFG::Node::shouldSpeculateInt32OrBoolean):
(JSC::DFG::Node::shouldSpeculateInt32ForArithmetic):
(JSC::DFG::Node::shouldSpeculateInt32OrBooleanForArithmetic):
(JSC::DFG::Node::shouldSpeculateInt32OrBooleanExpectingDefined):
(JSC::DFG::Node::shouldSpeculateMachineInt):
(JSC::DFG::Node::shouldSpeculateDouble):
(JSC::DFG::Node::shouldSpeculateNumberOrBoolean):
(JSC::DFG::Node::shouldSpeculateNumberOrBooleanExpectingDefined):
(JSC::DFG::Node::shouldSpeculateNumber):
(JSC::DFG::Node::canSpeculateInt32):
(JSC::DFG::Node::canSpeculateInt52):
(JSC::DFG::Node::sourceFor):
(JSC::DFG::Node::shouldSpeculateInt32ExpectingDefined): Deleted.
(JSC::DFG::Node::shouldSpeculateMachineIntForArithmetic): Deleted.
(JSC::DFG::Node::shouldSpeculateMachineIntExpectingDefined): Deleted.
(JSC::DFG::Node::shouldSpeculateDoubleForArithmetic): Deleted.
(JSC::DFG::Node::shouldSpeculateNumberExpectingDefined): Deleted.
* dfg/DFGNodeFlags.cpp:
(JSC::DFG::dumpNodeFlags):
* dfg/DFGNodeFlags.h:
(JSC::DFG::nodeMayOverflow):
(JSC::DFG::nodeMayNegZero):
(JSC::DFG::nodeCanSpeculateInt32):
(JSC::DFG::nodeCanSpeculateInt52):
* dfg/DFGNodeType.h:
* dfg/DFGPredictionPropagationPhase.cpp:
(JSC::DFG::PredictionPropagationPhase::run):
(JSC::DFG::PredictionPropagationPhase::propagateToFixpoint):
(JSC::DFG::PredictionPropagationPhase::speculatedDoubleTypeForPrediction):
(JSC::DFG::PredictionPropagationPhase::propagate):
(JSC::DFG::PredictionPropagationPhase::doDoubleVoting):
* dfg/DFGSafeToExecute.h:
(JSC::DFG::safeToExecute):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileValueToInt32):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::LowerDFGToLLVM::compileNode):
(JSC::FTL::LowerDFGToLLVM::compileValueToInt32):
(JSC::FTL::LowerDFGToLLVM::compileBooleanToNumber):
* runtime/JSCJSValue.h:
* runtime/JSCJSValueInlines.h:
(JSC::JSValue::asInt32ForArithmetic):
* tests/stress/max-boolean-exit.js: Added.
(foo):
(test):
* tests/stress/mul-boolean-exit.js: Added.
(foo):
(test):
* tests/stress/plus-boolean-exit.js: Added.
(foo):
(test):
* tests/stress/plus-boolean-or-double.js: Added.
(foo):
(test):
* tests/stress/plus-boolean-or-int.js: Added.
(foo):
(test):
LayoutTests:
* js/regress/abs-boolean-expected.txt: Added.
* js/regress/abs-boolean.html: Added.
* js/regress/div-boolean-double-expected.txt: Added.
* js/regress/div-boolean-double.html: Added.
* js/regress/div-boolean-expected.txt: Added.
* js/regress/div-boolean.html: Added.
* js/regress/max-boolean-expected.txt: Added.
* js/regress/max-boolean.html: Added.
* js/regress/min-boolean-expected.txt: Added.
* js/regress/min-boolean.html: Added.
* js/regress/minus-boolean-double-expected.txt: Added.
* js/regress/minus-boolean-double.html: Added.
* js/regress/minus-boolean-expected.txt: Added.
* js/regress/minus-boolean.html: Added.
* js/regress/mod-boolean-double-expected.txt: Added.
* js/regress/mod-boolean-double.html: Added.
* js/regress/mod-boolean-expected.txt: Added.
* js/regress/mod-boolean.html: Added.
* js/regress/mul-boolean-double-expected.txt: Added.
* js/regress/mul-boolean-double.html: Added.
* js/regress/mul-boolean-expected.txt: Added.
* js/regress/mul-boolean.html: Added.
* js/regress/neg-boolean-expected.txt: Added.
* js/regress/neg-boolean.html: Added.
* js/regress/plus-boolean-arith-expected.txt: Added.
* js/regress/plus-boolean-arith.html: Added.
* js/regress/plus-boolean-double-expected.txt: Added.
* js/regress/plus-boolean-double.html: Added.
* js/regress/plus-boolean-expected.txt: Added.
* js/regress/plus-boolean.html: Added.
* js/regress/script-tests/abs-boolean.js: Added.
* js/regress/script-tests/div-boolean-double.js: Added.
* js/regress/script-tests/div-boolean.js: Added.
* js/regress/script-tests/max-boolean.js: Added.
* js/regress/script-tests/min-boolean.js: Added.
* js/regress/script-tests/minus-boolean-double.js: Added.
* js/regress/script-tests/minus-boolean.js: Added.
* js/regress/script-tests/mod-boolean-double.js: Added.
* js/regress/script-tests/mod-boolean.js: Added.
* js/regress/script-tests/mul-boolean-double.js: Added.
* js/regress/script-tests/mul-boolean.js: Added.
* js/regress/script-tests/neg-boolean.js: Added.
* js/regress/script-tests/plus-boolean-arith.js: Added.
* js/regress/script-tests/plus-boolean-double.js: Added.
* js/regress/script-tests/plus-boolean.js: Added.
* js/regress/script-tests/sin-boolean.js: Added.
* js/regress/sin-boolean-expected.txt: Added.
* js/regress/sin-boolean.html: Added.</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeSpeculatedTypeh">trunk/Source/JavaScriptCore/bytecode/SpeculatedType.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh">trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGAllocatorh">trunk/Source/JavaScriptCore/dfg/DFGAllocator.h</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="#trunkSourceJavaScriptCoredfgDFGFixupPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGGraphh">trunk/Source/JavaScriptCore/dfg/DFGGraph.h</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="#trunkSourceJavaScriptCoredfgDFGPredictionPropagationPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.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="#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="#trunkSourceJavaScriptCoreftlFTLCapabilitiescpp">trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLLowerDFGToLLVMcpp">trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSCJSValueh">trunk/Source/JavaScriptCore/runtime/JSCJSValue.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSCJSValueInlinesh">trunk/Source/JavaScriptCore/runtime/JSCJSValueInlines.h</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsjsregressabsbooleanexpectedtxt">trunk/LayoutTests/js/regress/abs-boolean-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsregressabsbooleanhtml">trunk/LayoutTests/js/regress/abs-boolean.html</a></li>
<li><a href="#trunkLayoutTestsjsregressdivbooleandoubleexpectedtxt">trunk/LayoutTests/js/regress/div-boolean-double-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsregressdivbooleandoublehtml">trunk/LayoutTests/js/regress/div-boolean-double.html</a></li>
<li><a href="#trunkLayoutTestsjsregressdivbooleanexpectedtxt">trunk/LayoutTests/js/regress/div-boolean-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsregressdivbooleanhtml">trunk/LayoutTests/js/regress/div-boolean.html</a></li>
<li><a href="#trunkLayoutTestsjsregressmaxbooleanexpectedtxt">trunk/LayoutTests/js/regress/max-boolean-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsregressmaxbooleanhtml">trunk/LayoutTests/js/regress/max-boolean.html</a></li>
<li><a href="#trunkLayoutTestsjsregressminbooleanexpectedtxt">trunk/LayoutTests/js/regress/min-boolean-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsregressminbooleanhtml">trunk/LayoutTests/js/regress/min-boolean.html</a></li>
<li><a href="#trunkLayoutTestsjsregressminusbooleandoubleexpectedtxt">trunk/LayoutTests/js/regress/minus-boolean-double-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsregressminusbooleandoublehtml">trunk/LayoutTests/js/regress/minus-boolean-double.html</a></li>
<li><a href="#trunkLayoutTestsjsregressminusbooleanexpectedtxt">trunk/LayoutTests/js/regress/minus-boolean-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsregressminusbooleanhtml">trunk/LayoutTests/js/regress/minus-boolean.html</a></li>
<li><a href="#trunkLayoutTestsjsregressmodbooleandoubleexpectedtxt">trunk/LayoutTests/js/regress/mod-boolean-double-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsregressmodbooleandoublehtml">trunk/LayoutTests/js/regress/mod-boolean-double.html</a></li>
<li><a href="#trunkLayoutTestsjsregressmodbooleanexpectedtxt">trunk/LayoutTests/js/regress/mod-boolean-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsregressmodbooleanhtml">trunk/LayoutTests/js/regress/mod-boolean.html</a></li>
<li><a href="#trunkLayoutTestsjsregressmulbooleandoubleexpectedtxt">trunk/LayoutTests/js/regress/mul-boolean-double-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsregressmulbooleandoublehtml">trunk/LayoutTests/js/regress/mul-boolean-double.html</a></li>
<li><a href="#trunkLayoutTestsjsregressmulbooleanexpectedtxt">trunk/LayoutTests/js/regress/mul-boolean-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsregressmulbooleanhtml">trunk/LayoutTests/js/regress/mul-boolean.html</a></li>
<li><a href="#trunkLayoutTestsjsregressnegbooleanexpectedtxt">trunk/LayoutTests/js/regress/neg-boolean-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsregressnegbooleanhtml">trunk/LayoutTests/js/regress/neg-boolean.html</a></li>
<li><a href="#trunkLayoutTestsjsregressplusbooleanarithexpectedtxt">trunk/LayoutTests/js/regress/plus-boolean-arith-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsregressplusbooleanarithhtml">trunk/LayoutTests/js/regress/plus-boolean-arith.html</a></li>
<li><a href="#trunkLayoutTestsjsregressplusbooleandoubleexpectedtxt">trunk/LayoutTests/js/regress/plus-boolean-double-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsregressplusbooleandoublehtml">trunk/LayoutTests/js/regress/plus-boolean-double.html</a></li>
<li><a href="#trunkLayoutTestsjsregressplusbooleanexpectedtxt">trunk/LayoutTests/js/regress/plus-boolean-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsregressplusbooleanhtml">trunk/LayoutTests/js/regress/plus-boolean.html</a></li>
<li><a href="#trunkLayoutTestsjsregressscripttestsabsbooleanjs">trunk/LayoutTests/js/regress/script-tests/abs-boolean.js</a></li>
<li><a href="#trunkLayoutTestsjsregressscripttestsdivbooleandoublejs">trunk/LayoutTests/js/regress/script-tests/div-boolean-double.js</a></li>
<li><a href="#trunkLayoutTestsjsregressscripttestsdivbooleanjs">trunk/LayoutTests/js/regress/script-tests/div-boolean.js</a></li>
<li><a href="#trunkLayoutTestsjsregressscripttestsmaxbooleanjs">trunk/LayoutTests/js/regress/script-tests/max-boolean.js</a></li>
<li><a href="#trunkLayoutTestsjsregressscripttestsminbooleanjs">trunk/LayoutTests/js/regress/script-tests/min-boolean.js</a></li>
<li><a href="#trunkLayoutTestsjsregressscripttestsminusbooleandoublejs">trunk/LayoutTests/js/regress/script-tests/minus-boolean-double.js</a></li>
<li><a href="#trunkLayoutTestsjsregressscripttestsminusbooleanjs">trunk/LayoutTests/js/regress/script-tests/minus-boolean.js</a></li>
<li><a href="#trunkLayoutTestsjsregressscripttestsmodbooleandoublejs">trunk/LayoutTests/js/regress/script-tests/mod-boolean-double.js</a></li>
<li><a href="#trunkLayoutTestsjsregressscripttestsmodbooleanjs">trunk/LayoutTests/js/regress/script-tests/mod-boolean.js</a></li>
<li><a href="#trunkLayoutTestsjsregressscripttestsmulbooleandoublejs">trunk/LayoutTests/js/regress/script-tests/mul-boolean-double.js</a></li>
<li><a href="#trunkLayoutTestsjsregressscripttestsmulbooleanjs">trunk/LayoutTests/js/regress/script-tests/mul-boolean.js</a></li>
<li><a href="#trunkLayoutTestsjsregressscripttestsnegbooleanjs">trunk/LayoutTests/js/regress/script-tests/neg-boolean.js</a></li>
<li><a href="#trunkLayoutTestsjsregressscripttestsplusbooleanarithjs">trunk/LayoutTests/js/regress/script-tests/plus-boolean-arith.js</a></li>
<li><a href="#trunkLayoutTestsjsregressscripttestsplusbooleandoublejs">trunk/LayoutTests/js/regress/script-tests/plus-boolean-double.js</a></li>
<li><a href="#trunkLayoutTestsjsregressscripttestsplusbooleanjs">trunk/LayoutTests/js/regress/script-tests/plus-boolean.js</a></li>
<li><a href="#trunkLayoutTestsjsregressscripttestssinbooleanjs">trunk/LayoutTests/js/regress/script-tests/sin-boolean.js</a></li>
<li><a href="#trunkLayoutTestsjsregresssinbooleanexpectedtxt">trunk/LayoutTests/js/regress/sin-boolean-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsregresssinbooleanhtml">trunk/LayoutTests/js/regress/sin-boolean.html</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressmaxbooleanexitjs">trunk/Source/JavaScriptCore/tests/stress/max-boolean-exit.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressmulbooleanexitjs">trunk/Source/JavaScriptCore/tests/stress/mul-boolean-exit.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressplusbooleanexitjs">trunk/Source/JavaScriptCore/tests/stress/plus-boolean-exit.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressplusbooleanordoublejs">trunk/Source/JavaScriptCore/tests/stress/plus-boolean-or-double.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressplusbooleanorintjs">trunk/Source/JavaScriptCore/tests/stress/plus-boolean-or-int.js</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (169353 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2014-05-26 17:30:23 UTC (rev 169353)
+++ trunk/LayoutTests/ChangeLog        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -1,3 +1,59 @@
</span><ins>+2014-05-25 Filip Pizlo <fpizlo@apple.com>
+
+ Latest emscripten life benchmark is 4x slower because the DFG doesn't realize that arithmetic on booleans is a thing
+ https://bugs.webkit.org/show_bug.cgi?id=133136
+
+ Reviewed by Oliver Hunt.
+
+ * js/regress/abs-boolean-expected.txt: Added.
+ * js/regress/abs-boolean.html: Added.
+ * js/regress/div-boolean-double-expected.txt: Added.
+ * js/regress/div-boolean-double.html: Added.
+ * js/regress/div-boolean-expected.txt: Added.
+ * js/regress/div-boolean.html: Added.
+ * js/regress/max-boolean-expected.txt: Added.
+ * js/regress/max-boolean.html: Added.
+ * js/regress/min-boolean-expected.txt: Added.
+ * js/regress/min-boolean.html: Added.
+ * js/regress/minus-boolean-double-expected.txt: Added.
+ * js/regress/minus-boolean-double.html: Added.
+ * js/regress/minus-boolean-expected.txt: Added.
+ * js/regress/minus-boolean.html: Added.
+ * js/regress/mod-boolean-double-expected.txt: Added.
+ * js/regress/mod-boolean-double.html: Added.
+ * js/regress/mod-boolean-expected.txt: Added.
+ * js/regress/mod-boolean.html: Added.
+ * js/regress/mul-boolean-double-expected.txt: Added.
+ * js/regress/mul-boolean-double.html: Added.
+ * js/regress/mul-boolean-expected.txt: Added.
+ * js/regress/mul-boolean.html: Added.
+ * js/regress/neg-boolean-expected.txt: Added.
+ * js/regress/neg-boolean.html: Added.
+ * js/regress/plus-boolean-arith-expected.txt: Added.
+ * js/regress/plus-boolean-arith.html: Added.
+ * js/regress/plus-boolean-double-expected.txt: Added.
+ * js/regress/plus-boolean-double.html: Added.
+ * js/regress/plus-boolean-expected.txt: Added.
+ * js/regress/plus-boolean.html: Added.
+ * js/regress/script-tests/abs-boolean.js: Added.
+ * js/regress/script-tests/div-boolean-double.js: Added.
+ * js/regress/script-tests/div-boolean.js: Added.
+ * js/regress/script-tests/max-boolean.js: Added.
+ * js/regress/script-tests/min-boolean.js: Added.
+ * js/regress/script-tests/minus-boolean-double.js: Added.
+ * js/regress/script-tests/minus-boolean.js: Added.
+ * js/regress/script-tests/mod-boolean-double.js: Added.
+ * js/regress/script-tests/mod-boolean.js: Added.
+ * js/regress/script-tests/mul-boolean-double.js: Added.
+ * js/regress/script-tests/mul-boolean.js: Added.
+ * js/regress/script-tests/neg-boolean.js: Added.
+ * js/regress/script-tests/plus-boolean-arith.js: Added.
+ * js/regress/script-tests/plus-boolean-double.js: Added.
+ * js/regress/script-tests/plus-boolean.js: Added.
+ * js/regress/script-tests/sin-boolean.js: Added.
+ * js/regress/sin-boolean-expected.txt: Added.
+ * js/regress/sin-boolean.html: Added.
+
</ins><span class="cx"> 2014-05-26 Javier Fernandez <jfernandez@igalia.com>
</span><span class="cx">
</span><span class="cx"> [CSS Grid Layout] Implementation of the "grid" shorthand.
</span></span></pre></div>
<a id="trunkLayoutTestsjsregressabsbooleanexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/abs-boolean-expected.txt (0 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/abs-boolean-expected.txt         (rev 0)
+++ trunk/LayoutTests/js/regress/abs-boolean-expected.txt        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+JSRegress/abs-boolean
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressabsbooleanhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/abs-boolean.html (0 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/abs-boolean.html         (rev 0)
+++ trunk/LayoutTests/js/regress/abs-boolean.html        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -0,0 +1,12 @@
</span><ins>+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="../../resources/regress-pre.js"></script>
+<script src="script-tests/abs-boolean.js"></script>
+<script src="../../resources/regress-post.js"></script>
+<script src="../../resources/js-test-post.js"></script>
+</body>
+</html>
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressdivbooleandoubleexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/div-boolean-double-expected.txt (0 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/div-boolean-double-expected.txt         (rev 0)
+++ trunk/LayoutTests/js/regress/div-boolean-double-expected.txt        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+JSRegress/div-boolean-double
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressdivbooleandoublehtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/div-boolean-double.html (0 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/div-boolean-double.html         (rev 0)
+++ trunk/LayoutTests/js/regress/div-boolean-double.html        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -0,0 +1,12 @@
</span><ins>+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="../../resources/regress-pre.js"></script>
+<script src="script-tests/div-boolean-double.js"></script>
+<script src="../../resources/regress-post.js"></script>
+<script src="../../resources/js-test-post.js"></script>
+</body>
+</html>
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressdivbooleanexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/div-boolean-expected.txt (0 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/div-boolean-expected.txt         (rev 0)
+++ trunk/LayoutTests/js/regress/div-boolean-expected.txt        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+JSRegress/div-boolean
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressdivbooleanhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/div-boolean.html (0 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/div-boolean.html         (rev 0)
+++ trunk/LayoutTests/js/regress/div-boolean.html        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -0,0 +1,12 @@
</span><ins>+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="../../resources/regress-pre.js"></script>
+<script src="script-tests/div-boolean.js"></script>
+<script src="../../resources/regress-post.js"></script>
+<script src="../../resources/js-test-post.js"></script>
+</body>
+</html>
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressmaxbooleanexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/max-boolean-expected.txt (0 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/max-boolean-expected.txt         (rev 0)
+++ trunk/LayoutTests/js/regress/max-boolean-expected.txt        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+JSRegress/max-boolean
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressmaxbooleanhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/max-boolean.html (0 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/max-boolean.html         (rev 0)
+++ trunk/LayoutTests/js/regress/max-boolean.html        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -0,0 +1,12 @@
</span><ins>+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="../../resources/regress-pre.js"></script>
+<script src="script-tests/max-boolean.js"></script>
+<script src="../../resources/regress-post.js"></script>
+<script src="../../resources/js-test-post.js"></script>
+</body>
+</html>
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressminbooleanexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/min-boolean-expected.txt (0 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/min-boolean-expected.txt         (rev 0)
+++ trunk/LayoutTests/js/regress/min-boolean-expected.txt        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+JSRegress/min-boolean
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressminbooleanhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/min-boolean.html (0 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/min-boolean.html         (rev 0)
+++ trunk/LayoutTests/js/regress/min-boolean.html        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -0,0 +1,12 @@
</span><ins>+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="../../resources/regress-pre.js"></script>
+<script src="script-tests/min-boolean.js"></script>
+<script src="../../resources/regress-post.js"></script>
+<script src="../../resources/js-test-post.js"></script>
+</body>
+</html>
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressminusbooleandoubleexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/minus-boolean-double-expected.txt (0 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/minus-boolean-double-expected.txt         (rev 0)
+++ trunk/LayoutTests/js/regress/minus-boolean-double-expected.txt        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+JSRegress/minus-boolean-double
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressminusbooleandoublehtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/minus-boolean-double.html (0 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/minus-boolean-double.html         (rev 0)
+++ trunk/LayoutTests/js/regress/minus-boolean-double.html        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -0,0 +1,12 @@
</span><ins>+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="../../resources/regress-pre.js"></script>
+<script src="script-tests/minus-boolean-double.js"></script>
+<script src="../../resources/regress-post.js"></script>
+<script src="../../resources/js-test-post.js"></script>
+</body>
+</html>
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressminusbooleanexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/minus-boolean-expected.txt (0 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/minus-boolean-expected.txt         (rev 0)
+++ trunk/LayoutTests/js/regress/minus-boolean-expected.txt        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+JSRegress/minus-boolean
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressminusbooleanhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/minus-boolean.html (0 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/minus-boolean.html         (rev 0)
+++ trunk/LayoutTests/js/regress/minus-boolean.html        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -0,0 +1,12 @@
</span><ins>+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="../../resources/regress-pre.js"></script>
+<script src="script-tests/minus-boolean.js"></script>
+<script src="../../resources/regress-post.js"></script>
+<script src="../../resources/js-test-post.js"></script>
+</body>
+</html>
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressmodbooleandoubleexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/mod-boolean-double-expected.txt (0 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/mod-boolean-double-expected.txt         (rev 0)
+++ trunk/LayoutTests/js/regress/mod-boolean-double-expected.txt        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+JSRegress/mod-boolean-double
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressmodbooleandoublehtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/mod-boolean-double.html (0 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/mod-boolean-double.html         (rev 0)
+++ trunk/LayoutTests/js/regress/mod-boolean-double.html        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -0,0 +1,12 @@
</span><ins>+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="../../resources/regress-pre.js"></script>
+<script src="script-tests/mod-boolean-double.js"></script>
+<script src="../../resources/regress-post.js"></script>
+<script src="../../resources/js-test-post.js"></script>
+</body>
+</html>
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressmodbooleanexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/mod-boolean-expected.txt (0 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/mod-boolean-expected.txt         (rev 0)
+++ trunk/LayoutTests/js/regress/mod-boolean-expected.txt        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+JSRegress/mod-boolean
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressmodbooleanhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/mod-boolean.html (0 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/mod-boolean.html         (rev 0)
+++ trunk/LayoutTests/js/regress/mod-boolean.html        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -0,0 +1,12 @@
</span><ins>+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="../../resources/regress-pre.js"></script>
+<script src="script-tests/mod-boolean.js"></script>
+<script src="../../resources/regress-post.js"></script>
+<script src="../../resources/js-test-post.js"></script>
+</body>
+</html>
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressmulbooleandoubleexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/mul-boolean-double-expected.txt (0 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/mul-boolean-double-expected.txt         (rev 0)
+++ trunk/LayoutTests/js/regress/mul-boolean-double-expected.txt        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+JSRegress/mul-boolean-double
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressmulbooleandoublehtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/mul-boolean-double.html (0 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/mul-boolean-double.html         (rev 0)
+++ trunk/LayoutTests/js/regress/mul-boolean-double.html        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -0,0 +1,12 @@
</span><ins>+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="../../resources/regress-pre.js"></script>
+<script src="script-tests/mul-boolean-double.js"></script>
+<script src="../../resources/regress-post.js"></script>
+<script src="../../resources/js-test-post.js"></script>
+</body>
+</html>
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressmulbooleanexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/mul-boolean-expected.txt (0 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/mul-boolean-expected.txt         (rev 0)
+++ trunk/LayoutTests/js/regress/mul-boolean-expected.txt        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+JSRegress/mul-boolean
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressmulbooleanhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/mul-boolean.html (0 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/mul-boolean.html         (rev 0)
+++ trunk/LayoutTests/js/regress/mul-boolean.html        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -0,0 +1,12 @@
</span><ins>+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="../../resources/regress-pre.js"></script>
+<script src="script-tests/mul-boolean.js"></script>
+<script src="../../resources/regress-post.js"></script>
+<script src="../../resources/js-test-post.js"></script>
+</body>
+</html>
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressnegbooleanexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/neg-boolean-expected.txt (0 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/neg-boolean-expected.txt         (rev 0)
+++ trunk/LayoutTests/js/regress/neg-boolean-expected.txt        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+JSRegress/neg-boolean
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressnegbooleanhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/neg-boolean.html (0 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/neg-boolean.html         (rev 0)
+++ trunk/LayoutTests/js/regress/neg-boolean.html        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -0,0 +1,12 @@
</span><ins>+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="../../resources/regress-pre.js"></script>
+<script src="script-tests/neg-boolean.js"></script>
+<script src="../../resources/regress-post.js"></script>
+<script src="../../resources/js-test-post.js"></script>
+</body>
+</html>
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressplusbooleanarithexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/plus-boolean-arith-expected.txt (0 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/plus-boolean-arith-expected.txt         (rev 0)
+++ trunk/LayoutTests/js/regress/plus-boolean-arith-expected.txt        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+JSRegress/plus-boolean-arith
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressplusbooleanarithhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/plus-boolean-arith.html (0 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/plus-boolean-arith.html         (rev 0)
+++ trunk/LayoutTests/js/regress/plus-boolean-arith.html        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -0,0 +1,12 @@
</span><ins>+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="../../resources/regress-pre.js"></script>
+<script src="script-tests/plus-boolean-arith.js"></script>
+<script src="../../resources/regress-post.js"></script>
+<script src="../../resources/js-test-post.js"></script>
+</body>
+</html>
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressplusbooleandoubleexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/plus-boolean-double-expected.txt (0 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/plus-boolean-double-expected.txt         (rev 0)
+++ trunk/LayoutTests/js/regress/plus-boolean-double-expected.txt        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+JSRegress/plus-boolean-double
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressplusbooleandoublehtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/plus-boolean-double.html (0 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/plus-boolean-double.html         (rev 0)
+++ trunk/LayoutTests/js/regress/plus-boolean-double.html        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -0,0 +1,12 @@
</span><ins>+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="../../resources/regress-pre.js"></script>
+<script src="script-tests/plus-boolean-double.js"></script>
+<script src="../../resources/regress-post.js"></script>
+<script src="../../resources/js-test-post.js"></script>
+</body>
+</html>
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressplusbooleanexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/plus-boolean-expected.txt (0 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/plus-boolean-expected.txt         (rev 0)
+++ trunk/LayoutTests/js/regress/plus-boolean-expected.txt        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+JSRegress/plus-boolean
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressplusbooleanhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/plus-boolean.html (0 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/plus-boolean.html         (rev 0)
+++ trunk/LayoutTests/js/regress/plus-boolean.html        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -0,0 +1,12 @@
</span><ins>+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="../../resources/regress-pre.js"></script>
+<script src="script-tests/plus-boolean.js"></script>
+<script src="../../resources/regress-post.js"></script>
+<script src="../../resources/js-test-post.js"></script>
+</body>
+</html>
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressscripttestsabsbooleanjs"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/script-tests/abs-boolean.js (0 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/script-tests/abs-boolean.js         (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/abs-boolean.js        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -0,0 +1,8 @@
</span><ins>+(function(True) {
+ var x = 0;
+ var n = 1000000
+ for (var i = 0; i < n; ++i)
+ x += Math.abs(True);
+ if (x != n)
+ throw "Error: bad result: " + x;
+})(true);
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressscripttestsdivbooleandoublejs"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/script-tests/div-boolean-double.js (0 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/script-tests/div-boolean-double.js         (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/div-boolean-double.js        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -0,0 +1,8 @@
</span><ins>+(function(True) {
+ var x = 42.5;
+ var n = 1000000
+ for (var i = 0; i < n; ++i)
+ x /= True;
+ if (x != 42.5)
+ throw "Error: bad result: " + x;
+})(true);
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressscripttestsdivbooleanjs"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/script-tests/div-boolean.js (0 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/script-tests/div-boolean.js         (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/div-boolean.js        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -0,0 +1,8 @@
</span><ins>+(function(True) {
+ var x = 42;
+ var n = 1000000
+ for (var i = 0; i < n; ++i)
+ x /= True;
+ if (x != 42)
+ throw "Error: bad result: " + x;
+})(true);
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressscripttestsmaxbooleanjs"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/script-tests/max-boolean.js (0 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/script-tests/max-boolean.js         (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/max-boolean.js        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -0,0 +1,8 @@
</span><ins>+(function(True) {
+ var x = 0;
+ var n = 1000000
+ for (var i = 0; i < n; ++i)
+ x += Math.max(True, 0);
+ if (x != n)
+ throw "Error: bad result: " + x;
+})(true);
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressscripttestsminbooleanjs"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/script-tests/min-boolean.js (0 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/script-tests/min-boolean.js         (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/min-boolean.js        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -0,0 +1,8 @@
</span><ins>+(function(True) {
+ var x = 0;
+ var n = 1000000
+ for (var i = 0; i < n; ++i)
+ x += Math.min(True, 42);
+ if (x != n)
+ throw "Error: bad result: " + x;
+})(true);
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressscripttestsminusbooleandoublejs"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/script-tests/minus-boolean-double.js (0 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/script-tests/minus-boolean-double.js         (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/minus-boolean-double.js        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -0,0 +1,8 @@
</span><ins>+(function(True) {
+ var x = 0.5;
+ var n = 1000000
+ for (var i = 0; i < n; ++i)
+ x -= True;
+ if (x != 0.5 - n)
+ throw "Error: bad result: " + x;
+})(true);
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressscripttestsminusbooleanjs"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/script-tests/minus-boolean.js (0 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/script-tests/minus-boolean.js         (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/minus-boolean.js        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -0,0 +1,8 @@
</span><ins>+(function(True) {
+ var x = 0;
+ var n = 1000000
+ for (var i = 0; i < n; ++i)
+ x -= True;
+ if (x != -n)
+ throw "Error: bad result: " + x;
+})(true);
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressscripttestsmodbooleandoublejs"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/script-tests/mod-boolean-double.js (0 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/script-tests/mod-boolean-double.js         (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/mod-boolean-double.js        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -0,0 +1,8 @@
</span><ins>+(function(True) {
+ var x = 42.5;
+ var n = 1000000
+ for (var i = 0; i < n; ++i)
+ x %= True;
+ if (x != 0.5)
+ throw "Error: bad result: " + x;
+})(true);
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressscripttestsmodbooleanjs"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/script-tests/mod-boolean.js (0 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/script-tests/mod-boolean.js         (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/mod-boolean.js        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -0,0 +1,8 @@
</span><ins>+(function(True) {
+ var x = 42;
+ var n = 1000000
+ for (var i = 0; i < n; ++i)
+ x %= True;
+ if (x != 0)
+ throw "Error: bad result: " + x;
+})(true);
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressscripttestsmulbooleandoublejs"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/script-tests/mul-boolean-double.js (0 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/script-tests/mul-boolean-double.js         (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/mul-boolean-double.js        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -0,0 +1,8 @@
</span><ins>+(function(True) {
+ var x = 42.5;
+ var n = 1000000
+ for (var i = 0; i < n; ++i)
+ x *= True;
+ if (x != 42.5)
+ throw "Error: bad result: " + x;
+})(true);
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressscripttestsmulbooleanjs"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/script-tests/mul-boolean.js (0 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/script-tests/mul-boolean.js         (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/mul-boolean.js        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -0,0 +1,8 @@
</span><ins>+(function(True) {
+ var x = 42;
+ var n = 1000000
+ for (var i = 0; i < n; ++i)
+ x *= True;
+ if (x != 42)
+ throw "Error: bad result: " + x;
+})(true);
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressscripttestsnegbooleanjs"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/script-tests/neg-boolean.js (0 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/script-tests/neg-boolean.js         (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/neg-boolean.js        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -0,0 +1,8 @@
</span><ins>+(function(True) {
+ var x = 0.5;
+ var n = 1000000
+ for (var i = 0; i < n; ++i)
+ x += -True;
+ if (x != 0.5 - n)
+ throw "Error: bad result: " + x;
+})(true);
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressscripttestsplusbooleanarithjs"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/script-tests/plus-boolean-arith.js (0 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/script-tests/plus-boolean-arith.js         (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/plus-boolean-arith.js        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -0,0 +1,11 @@
</span><ins>+(function(True) {
+ var x = 0;
+ var n = 1000000
+ for (var i = 0; i < n; ++i) {
+ var y = True;
+ y++;
+ x += y;
+ }
+ if (x != n * 2)
+ throw "Error: bad result: " + x;
+})(true);
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressscripttestsplusbooleandoublejs"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/script-tests/plus-boolean-double.js (0 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/script-tests/plus-boolean-double.js         (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/plus-boolean-double.js        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -0,0 +1,8 @@
</span><ins>+(function(True) {
+ var x = 0.5;
+ var n = 1000000
+ for (var i = 0; i < n; ++i)
+ x += True;
+ if (x != n + 0.5)
+ throw "Error: bad result: " + x;
+})(true);
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressscripttestsplusbooleanjs"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/script-tests/plus-boolean.js (0 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/script-tests/plus-boolean.js         (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/plus-boolean.js        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -0,0 +1,8 @@
</span><ins>+(function(True) {
+ var x = 0;
+ var n = 1000000
+ for (var i = 0; i < n; ++i)
+ x += True;
+ if (x != n)
+ throw "Error: bad result: " + x;
+})(true);
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregressscripttestssinbooleanjs"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/script-tests/sin-boolean.js (0 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/script-tests/sin-boolean.js         (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/sin-boolean.js        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -0,0 +1,8 @@
</span><ins>+(function(True) {
+ var x = 0;
+ var n = 1000000
+ for (var i = 0; i < n; ++i)
+ x = Math.sin(True);
+ if (x != Math.sin(1))
+ throw "Error: bad result: " + x;
+})(true);
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregresssinbooleanexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/sin-boolean-expected.txt (0 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/sin-boolean-expected.txt         (rev 0)
+++ trunk/LayoutTests/js/regress/sin-boolean-expected.txt        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+JSRegress/sin-boolean
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregresssinbooleanhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/sin-boolean.html (0 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/sin-boolean.html         (rev 0)
+++ trunk/LayoutTests/js/regress/sin-boolean.html        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -0,0 +1,12 @@
</span><ins>+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="../../resources/regress-pre.js"></script>
+<script src="script-tests/sin-boolean.js"></script>
+<script src="../../resources/regress-post.js"></script>
+<script src="../../resources/js-test-post.js"></script>
+</body>
+</html>
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (169353 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2014-05-26 17:30:23 UTC (rev 169353)
+++ trunk/Source/JavaScriptCore/ChangeLog        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -1,3 +1,142 @@
</span><ins>+2014-05-25 Filip Pizlo <fpizlo@apple.com>
+
+ Latest emscripten life benchmark is 4x slower because the DFG doesn't realize that arithmetic on booleans is a thing
+ https://bugs.webkit.org/show_bug.cgi?id=133136
+
+ Reviewed by Oliver Hunt.
+
+ Some key concepts:
+
+ - Except for the prediction propagation and type fixup phases, which are super early in
+ the pipeline, nobody has to know about the fact that booleans may flow into numerical
+ operations because there will just be a BooleanToNumber node that will take a value
+ and, if that value is a boolean, will convert it to the equivalent numerical value. It
+ will have a BooleanUse mode where it will also speculate that the input is a boolean
+ but it can also do UntypedUse in which case it will pass through any non-booleans.
+ This operation is very easy to model in all of the compiler tiers.
+
+ - No changes to the baseline JIT. The Baseline JIT will still believe that boolean
+ inputs require taking the slow path and it will still report that it took slow path
+ for any such operations. The DFG will now be smart enough to ignore baseline JIT slow
+ path profiling on operations that were known to have had boolean inputs. That's a
+ little quirky, but it's probably easier than modifying the baseline JIT to track
+ booleans correctly.
+
+ 4.1x speed-up on the emscripten "life" benchmark. Up to 10x speed-up on microbenchmarks.
+
+ * bytecode/SpeculatedType.h:
+ (JSC::isInt32OrBooleanSpeculation):
+ (JSC::isInt32SpeculationForArithmetic):
+ (JSC::isInt32OrBooleanSpeculationForArithmetic):
+ (JSC::isInt32OrBooleanSpeculationExpectingDefined):
+ (JSC::isInt52Speculation):
+ (JSC::isMachineIntSpeculation):
+ (JSC::isFullNumberOrBooleanSpeculation):
+ (JSC::isFullNumberOrBooleanSpeculationExpectingDefined):
+ (JSC::isInt32SpeculationExpectingDefined): Deleted.
+ (JSC::isMachineIntSpeculationExpectingDefined): Deleted.
+ (JSC::isMachineIntSpeculationForArithmetic): Deleted.
+ (JSC::isBytecodeNumberSpeculationExpectingDefined): Deleted.
+ (JSC::isFullNumberSpeculationExpectingDefined): Deleted.
+ * dfg/DFGAbstractInterpreterInlines.h:
+ (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+ * dfg/DFGAllocator.h:
+ (JSC::DFG::Allocator<T>::indexOf):
+ * dfg/DFGByteCodeParser.cpp:
+ (JSC::DFG::ByteCodeParser::makeSafe):
+ (JSC::DFG::ByteCodeParser::makeDivSafe):
+ (JSC::DFG::ByteCodeParser::handleIntrinsic):
+ * dfg/DFGCSEPhase.cpp:
+ (JSC::DFG::CSEPhase::performNodeCSE):
+ * dfg/DFGClobberize.h:
+ (JSC::DFG::clobberize):
+ * dfg/DFGCommon.h:
+ * dfg/DFGConstantFoldingPhase.cpp:
+ (JSC::DFG::ConstantFoldingPhase::foldConstants):
+ * dfg/DFGFixupPhase.cpp:
+ (JSC::DFG::FixupPhase::fixupNode):
+ (JSC::DFG::FixupPhase::fixIntConvertingEdge):
+ (JSC::DFG::FixupPhase::fixIntOrBooleanEdge):
+ (JSC::DFG::FixupPhase::fixDoubleOrBooleanEdge):
+ (JSC::DFG::FixupPhase::attemptToMakeIntegerAdd):
+ (JSC::DFG::FixupPhase::fixIntEdge): Deleted.
+ * dfg/DFGGraph.h:
+ (JSC::DFG::Graph::addSpeculationMode):
+ (JSC::DFG::Graph::valueAddSpeculationMode):
+ (JSC::DFG::Graph::arithAddSpeculationMode):
+ (JSC::DFG::Graph::addShouldSpeculateInt32):
+ (JSC::DFG::Graph::mulShouldSpeculateInt32):
+ (JSC::DFG::Graph::mulShouldSpeculateMachineInt):
+ (JSC::DFG::Graph::negateShouldSpeculateInt32):
+ (JSC::DFG::Graph::negateShouldSpeculateMachineInt):
+ (JSC::DFG::Graph::addImmediateShouldSpeculateInt32):
+ (JSC::DFG::Graph::mulImmediateShouldSpeculateInt32): Deleted.
+ * dfg/DFGNode.h:
+ (JSC::DFG::Node::sawBooleans):
+ (JSC::DFG::Node::shouldSpeculateInt32OrBoolean):
+ (JSC::DFG::Node::shouldSpeculateInt32ForArithmetic):
+ (JSC::DFG::Node::shouldSpeculateInt32OrBooleanForArithmetic):
+ (JSC::DFG::Node::shouldSpeculateInt32OrBooleanExpectingDefined):
+ (JSC::DFG::Node::shouldSpeculateMachineInt):
+ (JSC::DFG::Node::shouldSpeculateDouble):
+ (JSC::DFG::Node::shouldSpeculateNumberOrBoolean):
+ (JSC::DFG::Node::shouldSpeculateNumberOrBooleanExpectingDefined):
+ (JSC::DFG::Node::shouldSpeculateNumber):
+ (JSC::DFG::Node::canSpeculateInt32):
+ (JSC::DFG::Node::canSpeculateInt52):
+ (JSC::DFG::Node::sourceFor):
+ (JSC::DFG::Node::shouldSpeculateInt32ExpectingDefined): Deleted.
+ (JSC::DFG::Node::shouldSpeculateMachineIntForArithmetic): Deleted.
+ (JSC::DFG::Node::shouldSpeculateMachineIntExpectingDefined): Deleted.
+ (JSC::DFG::Node::shouldSpeculateDoubleForArithmetic): Deleted.
+ (JSC::DFG::Node::shouldSpeculateNumberExpectingDefined): Deleted.
+ * dfg/DFGNodeFlags.cpp:
+ (JSC::DFG::dumpNodeFlags):
+ * dfg/DFGNodeFlags.h:
+ (JSC::DFG::nodeMayOverflow):
+ (JSC::DFG::nodeMayNegZero):
+ (JSC::DFG::nodeCanSpeculateInt32):
+ (JSC::DFG::nodeCanSpeculateInt52):
+ * dfg/DFGNodeType.h:
+ * dfg/DFGPredictionPropagationPhase.cpp:
+ (JSC::DFG::PredictionPropagationPhase::run):
+ (JSC::DFG::PredictionPropagationPhase::propagateToFixpoint):
+ (JSC::DFG::PredictionPropagationPhase::speculatedDoubleTypeForPrediction):
+ (JSC::DFG::PredictionPropagationPhase::propagate):
+ (JSC::DFG::PredictionPropagationPhase::doDoubleVoting):
+ * dfg/DFGSafeToExecute.h:
+ (JSC::DFG::safeToExecute):
+ * dfg/DFGSpeculativeJIT.cpp:
+ (JSC::DFG::SpeculativeJIT::compileValueToInt32):
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGSpeculativeJIT64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * ftl/FTLCapabilities.cpp:
+ (JSC::FTL::canCompile):
+ * ftl/FTLLowerDFGToLLVM.cpp:
+ (JSC::FTL::LowerDFGToLLVM::compileNode):
+ (JSC::FTL::LowerDFGToLLVM::compileValueToInt32):
+ (JSC::FTL::LowerDFGToLLVM::compileBooleanToNumber):
+ * runtime/JSCJSValue.h:
+ * runtime/JSCJSValueInlines.h:
+ (JSC::JSValue::asInt32ForArithmetic):
+ * tests/stress/max-boolean-exit.js: Added.
+ (foo):
+ (test):
+ * tests/stress/mul-boolean-exit.js: Added.
+ (foo):
+ (test):
+ * tests/stress/plus-boolean-exit.js: Added.
+ (foo):
+ (test):
+ * tests/stress/plus-boolean-or-double.js: Added.
+ (foo):
+ (test):
+ * tests/stress/plus-boolean-or-int.js: Added.
+ (foo):
+ (test):
+
</ins><span class="cx"> 2014-05-26 Zsolt Borbely <zsborbely.u-szeged@partner.samsung.com>
</span><span class="cx">
</span><span class="cx"> Remove dead code from VM.cpp
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeSpeculatedTypeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/SpeculatedType.h (169353 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/SpeculatedType.h        2014-05-26 17:30:23 UTC (rev 169353)
+++ trunk/Source/JavaScriptCore/bytecode/SpeculatedType.h        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -249,16 +249,26 @@
</span><span class="cx"> return value == SpecInt32;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+inline bool isInt32OrBooleanSpeculation(SpeculatedType value)
+{
+ return value && !(value & ~(SpecBoolean | SpecInt32));
+}
+
</ins><span class="cx"> inline bool isInt32SpeculationForArithmetic(SpeculatedType value)
</span><span class="cx"> {
</span><span class="cx"> return !(value & (SpecFullDouble | SpecInt52));
</span><span class="cx"> }
</span><span class="cx">
</span><del>-inline bool isInt32SpeculationExpectingDefined(SpeculatedType value)
</del><ins>+inline bool isInt32OrBooleanSpeculationForArithmetic(SpeculatedType value)
</ins><span class="cx"> {
</span><del>- return isInt32Speculation(value & ~SpecOther);
</del><ins>+ return !(value & (SpecFullDouble | SpecInt52));
</ins><span class="cx"> }
</span><span class="cx">
</span><ins>+inline bool isInt32OrBooleanSpeculationExpectingDefined(SpeculatedType value)
+{
+ return isInt32OrBooleanSpeculation(value & ~SpecOther);
+}
+
</ins><span class="cx"> inline bool isInt52Speculation(SpeculatedType value)
</span><span class="cx"> {
</span><span class="cx"> return value == SpecInt52;
</span><span class="lines">@@ -269,16 +279,6 @@
</span><span class="cx"> return !!value && (value & SpecMachineInt) == value;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-inline bool isMachineIntSpeculationExpectingDefined(SpeculatedType value)
-{
- return isMachineIntSpeculation(value & ~SpecOther);
-}
-
-inline bool isMachineIntSpeculationForArithmetic(SpeculatedType value)
-{
- return !(value & SpecFullDouble);
-}
-
</del><span class="cx"> inline bool isInt52AsDoubleSpeculation(SpeculatedType value)
</span><span class="cx"> {
</span><span class="cx"> return value == SpecInt52AsDouble;
</span><span class="lines">@@ -324,14 +324,14 @@
</span><span class="cx"> return !!(value & SpecFullNumber) && !(value & ~SpecFullNumber);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-inline bool isBytecodeNumberSpeculationExpectingDefined(SpeculatedType value)
</del><ins>+inline bool isFullNumberOrBooleanSpeculation(SpeculatedType value)
</ins><span class="cx"> {
</span><del>- return isBytecodeNumberSpeculation(value & ~SpecOther);
</del><ins>+ return value && !(value & ~(SpecFullNumber | SpecBoolean));
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-inline bool isFullNumberSpeculationExpectingDefined(SpeculatedType value)
</del><ins>+inline bool isFullNumberOrBooleanSpeculationExpectingDefined(SpeculatedType value)
</ins><span class="cx"> {
</span><del>- return isFullNumberSpeculation(value & ~SpecOther);
</del><ins>+ return isFullNumberOrBooleanSpeculation(value & ~SpecOther);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> inline bool isBooleanSpeculation(SpeculatedType value)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h (169353 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2014-05-26 17:30:23 UTC (rev 169353)
+++ trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -265,6 +265,26 @@
</span><span class="cx"> node->setCanExit(true);
</span><span class="cx"> break;
</span><span class="cx"> }
</span><ins>+
+ case BooleanToNumber: {
+ JSValue concreteValue = forNode(node->child1()).value();
+ if (concreteValue) {
+ if (concreteValue.isBoolean())
+ setConstant(node, jsNumber(concreteValue.asBoolean()));
+ else
+ setConstant(node, concreteValue);
+ break;
+ }
+ AbstractValue& value = forNode(node);
+ value = forNode(node->child1());
+ if (node->child1().useKind() == UntypedUse && !(value.m_type & ~SpecBoolean))
+ m_state.setFoundConstants(true);
+ if (value.m_type & SpecBoolean) {
+ value.merge(SpecInt32);
+ value.filter(~SpecBoolean);
+ }
+ break;
+ }
</ins><span class="cx">
</span><span class="cx"> case DoubleAsInt32: {
</span><span class="cx"> JSValue child = forNode(node->child1()).value();
</span><span class="lines">@@ -292,7 +312,7 @@
</span><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx"> if (child.isBoolean()) {
</span><del>- setConstant(node, JSValue(child.asBoolean()));
</del><ins>+ setConstant(node, jsNumber(child.asBoolean()));
</ins><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx"> if (child.isUndefinedOrNull()) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGAllocatorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGAllocator.h (169353 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGAllocator.h        2014-05-26 17:30:23 UTC (rev 169353)
+++ trunk/Source/JavaScriptCore/dfg/DFGAllocator.h        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -153,11 +153,14 @@
</span><span class="cx"> template<typename T>
</span><span class="cx"> unsigned Allocator<T>::indexOf(const T* object)
</span><span class="cx"> {
</span><del>- unsigned baseIndex = 0;
</del><ins>+ unsigned numRegions = 0;
+ for (Region* region = m_regionHead; region; region = region->m_next)
+ numRegions++;
+ unsigned regionIndex = 0;
</ins><span class="cx"> for (Region* region = m_regionHead; region; region = region->m_next) {
</span><span class="cx"> if (region->isInThisRegion(object))
</span><del>- return baseIndex + (object - region->data());
- baseIndex += Region::numberOfThingsPerRegion();
</del><ins>+ return (numRegions - 1 - regionIndex) * Region::numberOfThingsPerRegion() + (object - region->data());
+ regionIndex++;
</ins><span class="cx"> }
</span><span class="cx"> CRASH();
</span><span class="cx"> return 0;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp (169353 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2014-05-26 17:30:23 UTC (rev 169353)
+++ trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -899,16 +899,16 @@
</span><span class="cx">
</span><span class="cx"> Node* makeSafe(Node* node)
</span><span class="cx"> {
</span><del>- bool likelyToTakeSlowCase;
</del><ins>+ if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow))
+ node->mergeFlags(NodeMayOverflowInDFG);
+ if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, NegativeZero))
+ node->mergeFlags(NodeMayNegZeroInDFG);
+
</ins><span class="cx"> if (!isX86() && node->op() == ArithMod)
</span><del>- likelyToTakeSlowCase = false;
- else
- likelyToTakeSlowCase = m_inlineStackTop->m_profiledBlock->likelyToTakeSlowCase(m_currentIndex);
-
- if (!likelyToTakeSlowCase
- && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow)
- && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, NegativeZero))
</del><span class="cx"> return node;
</span><ins>+
+ if (!m_inlineStackTop->m_profiledBlock->likelyToTakeSlowCase(m_currentIndex))
+ return node;
</ins><span class="cx">
</span><span class="cx"> switch (node->op()) {
</span><span class="cx"> case UInt32ToNumber:
</span><span class="lines">@@ -916,15 +916,15 @@
</span><span class="cx"> case ArithSub:
</span><span class="cx"> case ValueAdd:
</span><span class="cx"> case ArithMod: // for ArithMod "MayOverflow" means we tried to divide by zero, or we saw double.
</span><del>- node->mergeFlags(NodeMayOverflow);
</del><ins>+ node->mergeFlags(NodeMayOverflowInBaseline);
</ins><span class="cx"> break;
</span><span class="cx">
</span><span class="cx"> case ArithNegate:
</span><span class="cx"> // Currently we can't tell the difference between a negation overflowing
</span><span class="cx"> // (i.e. -(1 << 31)) or generating negative zero (i.e. -0). If it took slow
</span><span class="cx"> // path then we assume that it did both of those things.
</span><del>- node->mergeFlags(NodeMayOverflow);
- node->mergeFlags(NodeMayNegZero);
</del><ins>+ node->mergeFlags(NodeMayOverflowInBaseline);
+ node->mergeFlags(NodeMayNegZeroInBaseline);
</ins><span class="cx"> break;
</span><span class="cx">
</span><span class="cx"> case ArithMul:
</span><span class="lines">@@ -933,10 +933,10 @@
</span><span class="cx"> // https://bugs.webkit.org/show_bug.cgi?id=132470
</span><span class="cx"> if (m_inlineStackTop->m_profiledBlock->likelyToTakeDeepestSlowCase(m_currentIndex)
</span><span class="cx"> || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow))
</span><del>- node->mergeFlags(NodeMayOverflow | NodeMayNegZero);
</del><ins>+ node->mergeFlags(NodeMayOverflowInBaseline | NodeMayNegZeroInBaseline);
</ins><span class="cx"> else if (m_inlineStackTop->m_profiledBlock->likelyToTakeSlowCase(m_currentIndex)
</span><span class="cx"> || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, NegativeZero))
</span><del>- node->mergeFlags(NodeMayNegZero);
</del><ins>+ node->mergeFlags(NodeMayNegZeroInBaseline);
</ins><span class="cx"> break;
</span><span class="cx">
</span><span class="cx"> default:
</span><span class="lines">@@ -951,20 +951,22 @@
</span><span class="cx"> {
</span><span class="cx"> ASSERT(node->op() == ArithDiv);
</span><span class="cx">
</span><ins>+ if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow))
+ node->mergeFlags(NodeMayOverflowInDFG);
+ if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, NegativeZero))
+ node->mergeFlags(NodeMayNegZeroInDFG);
+
</ins><span class="cx"> // The main slow case counter for op_div in the old JIT counts only when
</span><span class="cx"> // the operands are not numbers. We don't care about that since we already
</span><span class="cx"> // have speculations in place that take care of that separately. We only
</span><span class="cx"> // care about when the outcome of the division is not an integer, which
</span><span class="cx"> // is what the special fast case counter tells us.
</span><span class="cx">
</span><del>- if (!m_inlineStackTop->m_profiledBlock->couldTakeSpecialFastCase(m_currentIndex)
- && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow)
- && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, NegativeZero))
</del><ins>+ if (!m_inlineStackTop->m_profiledBlock->couldTakeSpecialFastCase(m_currentIndex))
</ins><span class="cx"> return node;
</span><span class="cx">
</span><del>- // FIXME: It might be possible to make this more granular. The DFG certainly can
- // distinguish between negative zero and overflow in its exit profiles.
- node->mergeFlags(NodeMayOverflow | NodeMayNegZero);
</del><ins>+ // FIXME: It might be possible to make this more granular.
+ node->mergeFlags(NodeMayOverflowInBaseline | NodeMayNegZeroInBaseline);
</ins><span class="cx">
</span><span class="cx"> return node;
</span><span class="cx"> }
</span><span class="lines">@@ -1559,7 +1561,7 @@
</span><span class="cx">
</span><span class="cx"> Node* node = addToGraph(ArithAbs, get(virtualRegisterForArgument(1, registerOffset)));
</span><span class="cx"> if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow))
</span><del>- node->mergeFlags(NodeMayOverflow);
</del><ins>+ node->mergeFlags(NodeMayOverflowInDFG);
</ins><span class="cx"> set(VirtualRegister(resultOperand), node);
</span><span class="cx"> return true;
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGCSEPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp (169353 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp        2014-05-26 17:30:23 UTC (rev 169353)
+++ trunk/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -1133,6 +1133,7 @@
</span><span class="cx"> case DoubleRep:
</span><span class="cx"> case ValueRep:
</span><span class="cx"> case Int52Rep:
</span><ins>+ case BooleanToNumber:
</ins><span class="cx"> if (cseMode == StoreElimination)
</span><span class="cx"> break;
</span><span class="cx"> setReplacement(pureCSE(node));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGClobberizeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGClobberize.h (169353 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGClobberize.h        2014-05-26 17:30:23 UTC (rev 169353)
+++ trunk/Source/JavaScriptCore/dfg/DFGClobberize.h        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -131,6 +131,7 @@
</span><span class="cx"> case DoubleRep:
</span><span class="cx"> case ValueRep:
</span><span class="cx"> case Int52Rep:
</span><ins>+ case BooleanToNumber:
</ins><span class="cx"> return;
</span><span class="cx">
</span><span class="cx"> case MovHint:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGCommonh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGCommon.h (169353 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGCommon.h        2014-05-26 17:30:23 UTC (rev 169353)
+++ trunk/Source/JavaScriptCore/dfg/DFGCommon.h        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -98,6 +98,54 @@
</span><span class="cx">
</span><span class="cx"> enum NoResultTag { NoResult };
</span><span class="cx">
</span><ins>+// The prediction propagator effectively does four passes, with the last pass
+// being done by the separate FixuPhase.
+enum PredictionPass {
+ // We're converging in a straght-forward forward flow fixpoint. This is the
+ // most conventional part of the propagator - it makes only monotonic decisions
+ // based on value profiles and rare case profiles. It ignores baseline JIT rare
+ // case profiles. The goal here is to develop a good guess of which variables
+ // are likely to be purely numerical, which generally doesn't require knowing
+ // the rare case profiles.
+ PrimaryPass,
+
+ // At this point we know what is numerical and what isn't. Non-numerical inputs
+ // to arithmetic operations will not have useful information in the Baseline JIT
+ // rare case profiles because Baseline may take slow path on non-numerical
+ // inputs even if the DFG could handle the input on the fast path. Boolean
+ // inputs are the most obvious example. This pass of prediction propagation will
+ // use Baseline rare case profiles for purely numerical operations and it will
+ // ignore them for everything else. The point of this pass is to develop a good
+ // guess of which variables are likely to be doubles.
+ //
+ // This pass is intentionally weird and goes against what is considered good
+ // form when writing a static analysis: a new data flow of booleans will cause
+ // us to ignore rare case profiles except that by then, we will have already
+ // propagated double types based on our prior assumption that we shouldn't
+ // ignore rare cases. This probably won't happen because the PrimaryPass is
+ // almost certainly going to establish what is and isn't numerical. But it's
+ // conceivable that during this pass we will discover a new boolean data flow.
+ // This ends up being sound because the prediction propagator could literally
+ // make any guesses it wants and still be sound (worst case, we OSR exit more
+ // often or use too general of types are run a bit slower). This will converge
+ // because we force monotonicity on the types of nodes and variables. So, the
+ // worst thing that can happen is that we violate basic laws of theoretical
+ // decency.
+ RareCasePass,
+
+ // At this point we know what is numerical and what isn't, and we also know what
+ // is a double and what isn't. So, we start forcing variables to be double.
+ // Doing so may have a cascading effect so this is a fixpoint. It's monotonic
+ // in the sense that once a variable is forced double, it cannot be forced in
+ // the other direction.
+ DoubleVotingPass,
+
+ // This pass occurs once we have converged. At this point we are just installing
+ // type checks based on the conclusions we have already reached. It's important
+ // for this pass to reach the same conclusions that DoubleVotingPass reached.
+ FixupPass
+};
+
</ins><span class="cx"> enum OptimizationFixpointState { BeforeFixpoint, FixpointNotConverged, FixpointConverged };
</span><span class="cx">
</span><span class="cx"> // Describes the form you can expect the entire graph to be in.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGConstantFoldingPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp (169353 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp        2014-05-26 17:30:23 UTC (rev 169353)
+++ trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -79,6 +79,13 @@
</span><span class="cx"> bool eliminated = false;
</span><span class="cx">
</span><span class="cx"> switch (node->op()) {
</span><ins>+ case BooleanToNumber: {
+ if (node->child1().useKind() == UntypedUse
+ && !m_interpreter.needsTypeCheck(node->child1(), SpecBoolean))
+ node->child1().setUseKind(BooleanUse);
+ break;
+ }
+
</ins><span class="cx"> case CheckArgumentsNotCreated: {
</span><span class="cx"> if (!isEmptySpeculation(
</span><span class="cx"> m_state.variables().operand(
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGFixupPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp (169353 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2014-05-26 17:30:23 UTC (rev 169353)
+++ trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -102,14 +102,14 @@
</span><span class="cx"> case BitRShift:
</span><span class="cx"> case BitLShift:
</span><span class="cx"> case BitURShift: {
</span><del>- fixIntEdge(node->child1());
- fixIntEdge(node->child2());
</del><ins>+ fixIntConvertingEdge(node->child1());
+ fixIntConvertingEdge(node->child2());
</ins><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> case ArithIMul: {
</span><del>- fixIntEdge(node->child1());
- fixIntEdge(node->child2());
</del><ins>+ fixIntConvertingEdge(node->child1());
+ fixIntConvertingEdge(node->child2());
</ins><span class="cx"> node->setOp(ArithMul);
</span><span class="cx"> node->setArithMode(Arith::Unchecked);
</span><span class="cx"> node->child1().setUseKind(Int32Use);
</span><span class="lines">@@ -118,10 +118,10 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> case UInt32ToNumber: {
</span><del>- fixIntEdge(node->child1());
</del><ins>+ fixIntConvertingEdge(node->child1());
</ins><span class="cx"> if (bytecodeCanTruncateInteger(node->arithNodeFlags()))
</span><span class="cx"> node->convertToIdentity();
</span><del>- else if (nodeCanSpeculateInt32(node->arithNodeFlags()))
</del><ins>+ else if (node->canSpeculateInt32(FixupPass))
</ins><span class="cx"> node->setArithMode(Arith::CheckOverflow);
</span><span class="cx"> else {
</span><span class="cx"> node->setArithMode(Arith::DoOverflow);
</span><span class="lines">@@ -136,9 +136,9 @@
</span><span class="cx"> node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
</span><span class="cx"> break;
</span><span class="cx"> }
</span><del>- if (Node::shouldSpeculateNumberExpectingDefined(node->child1().node(), node->child2().node())) {
- fixEdge<DoubleRepUse>(node->child1());
- fixEdge<DoubleRepUse>(node->child2());
</del><ins>+ if (Node::shouldSpeculateNumberOrBooleanExpectingDefined(node->child1().node(), node->child2().node())) {
+ fixDoubleOrBooleanEdge(node->child1());
+ fixDoubleOrBooleanEdge(node->child2());
</ins><span class="cx"> node->setOp(ArithAdd);
</span><span class="cx"> node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
</span><span class="cx"> node->setResult(NodeResultDouble);
</span><span class="lines">@@ -180,15 +180,15 @@
</span><span class="cx"> case ArithSub: {
</span><span class="cx"> if (attemptToMakeIntegerAdd(node))
</span><span class="cx"> break;
</span><del>- fixEdge<DoubleRepUse>(node->child1());
- fixEdge<DoubleRepUse>(node->child2());
</del><ins>+ fixDoubleOrBooleanEdge(node->child1());
+ fixDoubleOrBooleanEdge(node->child2());
</ins><span class="cx"> node->setResult(NodeResultDouble);
</span><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> case ArithNegate: {
</span><del>- if (m_graph.negateShouldSpeculateInt32(node)) {
- fixEdge<Int32Use>(node->child1());
</del><ins>+ if (m_graph.negateShouldSpeculateInt32(node, FixupPass)) {
+ fixIntOrBooleanEdge(node->child1());
</ins><span class="cx"> if (bytecodeCanTruncateInteger(node->arithNodeFlags()))
</span><span class="cx"> node->setArithMode(Arith::Unchecked);
</span><span class="cx"> else if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
</span><span class="lines">@@ -197,7 +197,7 @@
</span><span class="cx"> node->setArithMode(Arith::CheckOverflowAndNegativeZero);
</span><span class="cx"> break;
</span><span class="cx"> }
</span><del>- if (m_graph.negateShouldSpeculateMachineInt(node)) {
</del><ins>+ if (m_graph.negateShouldSpeculateMachineInt(node, FixupPass)) {
</ins><span class="cx"> fixEdge<Int52RepUse>(node->child1());
</span><span class="cx"> if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
</span><span class="cx"> node->setArithMode(Arith::CheckOverflow);
</span><span class="lines">@@ -206,15 +206,15 @@
</span><span class="cx"> node->setResult(NodeResultInt52);
</span><span class="cx"> break;
</span><span class="cx"> }
</span><del>- fixEdge<DoubleRepUse>(node->child1());
</del><ins>+ fixDoubleOrBooleanEdge(node->child1());
</ins><span class="cx"> node->setResult(NodeResultDouble);
</span><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> case ArithMul: {
</span><del>- if (m_graph.mulShouldSpeculateInt32(node)) {
- fixEdge<Int32Use>(node->child1());
- fixEdge<Int32Use>(node->child2());
</del><ins>+ if (m_graph.mulShouldSpeculateInt32(node, FixupPass)) {
+ fixIntOrBooleanEdge(node->child1());
+ fixIntOrBooleanEdge(node->child2());
</ins><span class="cx"> if (bytecodeCanTruncateInteger(node->arithNodeFlags()))
</span><span class="cx"> node->setArithMode(Arith::Unchecked);
</span><span class="cx"> else if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
</span><span class="lines">@@ -223,7 +223,7 @@
</span><span class="cx"> node->setArithMode(Arith::CheckOverflowAndNegativeZero);
</span><span class="cx"> break;
</span><span class="cx"> }
</span><del>- if (m_graph.mulShouldSpeculateMachineInt(node)) {
</del><ins>+ if (m_graph.mulShouldSpeculateMachineInt(node, FixupPass)) {
</ins><span class="cx"> fixEdge<Int52RepUse>(node->child1());
</span><span class="cx"> fixEdge<Int52RepUse>(node->child2());
</span><span class="cx"> if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
</span><span class="lines">@@ -233,19 +233,19 @@
</span><span class="cx"> node->setResult(NodeResultInt52);
</span><span class="cx"> break;
</span><span class="cx"> }
</span><del>- fixEdge<DoubleRepUse>(node->child1());
- fixEdge<DoubleRepUse>(node->child2());
</del><ins>+ fixDoubleOrBooleanEdge(node->child1());
+ fixDoubleOrBooleanEdge(node->child2());
</ins><span class="cx"> node->setResult(NodeResultDouble);
</span><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> case ArithDiv:
</span><span class="cx"> case ArithMod: {
</span><del>- if (Node::shouldSpeculateInt32ForArithmetic(node->child1().node(), node->child2().node())
- && node->canSpeculateInt32()) {
</del><ins>+ if (Node::shouldSpeculateInt32OrBooleanForArithmetic(node->child1().node(), node->child2().node())
+ && node->canSpeculateInt32(FixupPass)) {
</ins><span class="cx"> if (optimizeForX86() || optimizeForARM64() || optimizeForARMv7s()) {
</span><del>- fixEdge<Int32Use>(node->child1());
- fixEdge<Int32Use>(node->child2());
</del><ins>+ fixIntOrBooleanEdge(node->child1());
+ fixIntOrBooleanEdge(node->child2());
</ins><span class="cx"> if (bytecodeCanTruncateInteger(node->arithNodeFlags()))
</span><span class="cx"> node->setArithMode(Arith::Unchecked);
</span><span class="cx"> else if (bytecodeCanIgnoreNegativeZero(node->arithNodeFlags()))
</span><span class="lines">@@ -256,8 +256,8 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> // This will cause conversion nodes to be inserted later.
</span><del>- fixEdge<DoubleRepUse>(node->child1());
- fixEdge<DoubleRepUse>(node->child2());
</del><ins>+ fixDoubleOrBooleanEdge(node->child1());
+ fixDoubleOrBooleanEdge(node->child2());
</ins><span class="cx">
</span><span class="cx"> // But we have to make sure that everything is phantom'd until after the
</span><span class="cx"> // DoubleAsInt32 node, which occurs after the Div/Mod node that the conversions
</span><span class="lines">@@ -279,33 +279,33 @@
</span><span class="cx"> node->setArithMode(Arith::CheckOverflowAndNegativeZero);
</span><span class="cx"> break;
</span><span class="cx"> }
</span><del>- fixEdge<DoubleRepUse>(node->child1());
- fixEdge<DoubleRepUse>(node->child2());
</del><ins>+ fixDoubleOrBooleanEdge(node->child1());
+ fixDoubleOrBooleanEdge(node->child2());
</ins><span class="cx"> node->setResult(NodeResultDouble);
</span><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> case ArithMin:
</span><span class="cx"> case ArithMax: {
</span><del>- if (Node::shouldSpeculateInt32ForArithmetic(node->child1().node(), node->child2().node())
- && node->canSpeculateInt32()) {
- fixEdge<Int32Use>(node->child1());
- fixEdge<Int32Use>(node->child2());
</del><ins>+ if (Node::shouldSpeculateInt32OrBooleanForArithmetic(node->child1().node(), node->child2().node())
+ && node->canSpeculateInt32(FixupPass)) {
+ fixIntOrBooleanEdge(node->child1());
+ fixIntOrBooleanEdge(node->child2());
</ins><span class="cx"> break;
</span><span class="cx"> }
</span><del>- fixEdge<DoubleRepUse>(node->child1());
- fixEdge<DoubleRepUse>(node->child2());
</del><ins>+ fixDoubleOrBooleanEdge(node->child1());
+ fixDoubleOrBooleanEdge(node->child2());
</ins><span class="cx"> node->setResult(NodeResultDouble);
</span><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> case ArithAbs: {
</span><del>- if (node->child1()->shouldSpeculateInt32ForArithmetic()
- && node->canSpeculateInt32()) {
- fixEdge<Int32Use>(node->child1());
</del><ins>+ if (node->child1()->shouldSpeculateInt32OrBooleanForArithmetic()
+ && node->canSpeculateInt32(FixupPass)) {
+ fixIntOrBooleanEdge(node->child1());
</ins><span class="cx"> break;
</span><span class="cx"> }
</span><del>- fixEdge<DoubleRepUse>(node->child1());
</del><ins>+ fixDoubleOrBooleanEdge(node->child1());
</ins><span class="cx"> node->setResult(NodeResultDouble);
</span><span class="cx"> break;
</span><span class="cx"> }
</span><span class="lines">@@ -314,7 +314,7 @@
</span><span class="cx"> case ArithFRound:
</span><span class="cx"> case ArithSin:
</span><span class="cx"> case ArithCos: {
</span><del>- fixEdge<DoubleRepUse>(node->child1());
</del><ins>+ fixDoubleOrBooleanEdge(node->child1());
</ins><span class="cx"> node->setResult(NodeResultDouble);
</span><span class="cx"> break;
</span><span class="cx"> }
</span><span class="lines">@@ -324,8 +324,8 @@
</span><span class="cx"> fixEdge<BooleanUse>(node->child1());
</span><span class="cx"> else if (node->child1()->shouldSpeculateObjectOrOther())
</span><span class="cx"> fixEdge<ObjectOrOtherUse>(node->child1());
</span><del>- else if (node->child1()->shouldSpeculateInt32())
- fixEdge<Int32Use>(node->child1());
</del><ins>+ else if (node->child1()->shouldSpeculateInt32OrBoolean())
+ fixIntOrBooleanEdge(node->child1());
</ins><span class="cx"> else if (node->child1()->shouldSpeculateNumber())
</span><span class="cx"> fixEdge<DoubleRepUse>(node->child1());
</span><span class="cx"> else if (node->child1()->shouldSpeculateString())
</span><span class="lines">@@ -350,12 +350,19 @@
</span><span class="cx"> case CompareLessEq:
</span><span class="cx"> case CompareGreater:
</span><span class="cx"> case CompareGreaterEq: {
</span><del>- if (Node::shouldSpeculateInt32(node->child1().node(), node->child2().node())) {
- fixEdge<Int32Use>(node->child1());
- fixEdge<Int32Use>(node->child2());
</del><ins>+ if (node->op() == CompareEq
+ && Node::shouldSpeculateBoolean(node->child1().node(), node->child2().node())) {
+ fixEdge<BooleanUse>(node->child1());
+ fixEdge<BooleanUse>(node->child2());
</ins><span class="cx"> node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
</span><span class="cx"> break;
</span><span class="cx"> }
</span><ins>+ if (Node::shouldSpeculateInt32OrBoolean(node->child1().node(), node->child2().node())) {
+ fixIntOrBooleanEdge(node->child1());
+ fixIntOrBooleanEdge(node->child2());
+ node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
+ break;
+ }
</ins><span class="cx"> if (enableInt52()
</span><span class="cx"> && Node::shouldSpeculateMachineInt(node->child1().node(), node->child2().node())) {
</span><span class="cx"> fixEdge<Int52RepUse>(node->child1());
</span><span class="lines">@@ -363,20 +370,14 @@
</span><span class="cx"> node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
</span><span class="cx"> break;
</span><span class="cx"> }
</span><del>- if (Node::shouldSpeculateNumber(node->child1().node(), node->child2().node())) {
- fixEdge<DoubleRepUse>(node->child1());
- fixEdge<DoubleRepUse>(node->child2());
</del><ins>+ if (Node::shouldSpeculateNumberOrBoolean(node->child1().node(), node->child2().node())) {
+ fixDoubleOrBooleanEdge(node->child1());
+ fixDoubleOrBooleanEdge(node->child2());
</ins><span class="cx"> node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
</span><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx"> if (node->op() != CompareEq)
</span><span class="cx"> break;
</span><del>- if (Node::shouldSpeculateBoolean(node->child1().node(), node->child2().node())) {
- fixEdge<BooleanUse>(node->child1());
- fixEdge<BooleanUse>(node->child2());
- node->clearFlags(NodeMustGenerate | NodeClobbersWorld);
- break;
- }
</del><span class="cx"> if (node->child1()->shouldSpeculateStringIdent() && node->child2()->shouldSpeculateStringIdent()) {
</span><span class="cx"> fixEdge<StringIdentUse>(node->child1());
</span><span class="cx"> fixEdge<StringIdentUse>(node->child2());
</span><span class="lines">@@ -604,10 +605,6 @@
</span><span class="cx"> fixEdge<KnownCellUse>(child1);
</span><span class="cx"> fixEdge<Int32Use>(child2);
</span><span class="cx"> fixEdge<Int32Use>(child3);
</span><del>- if (child3->prediction() & SpecInt52)
- fixEdge<Int52RepUse>(child3);
- else
- fixEdge<Int32Use>(child3);
</del><span class="cx"> break;
</span><span class="cx"> case Array::Double:
</span><span class="cx"> fixEdge<KnownCellUse>(child1);
</span><span class="lines">@@ -624,17 +621,17 @@
</span><span class="cx"> fixEdge<KnownCellUse>(child1);
</span><span class="cx"> fixEdge<Int32Use>(child2);
</span><span class="cx"> if (child3->shouldSpeculateInt32())
</span><del>- fixEdge<Int32Use>(child3);
</del><ins>+ fixIntOrBooleanEdge(child3);
</ins><span class="cx"> else if (child3->shouldSpeculateMachineInt())
</span><span class="cx"> fixEdge<Int52RepUse>(child3);
</span><span class="cx"> else
</span><del>- fixEdge<DoubleRepUse>(child3);
</del><ins>+ fixDoubleOrBooleanEdge(child3);
</ins><span class="cx"> break;
</span><span class="cx"> case Array::Float32Array:
</span><span class="cx"> case Array::Float64Array:
</span><span class="cx"> fixEdge<KnownCellUse>(child1);
</span><span class="cx"> fixEdge<Int32Use>(child2);
</span><del>- fixEdge<DoubleRepUse>(child3);
</del><ins>+ fixDoubleOrBooleanEdge(child3);
</ins><span class="cx"> break;
</span><span class="cx"> case Array::Contiguous:
</span><span class="cx"> case Array::ArrayStorage:
</span><span class="lines">@@ -706,10 +703,10 @@
</span><span class="cx"> fixEdge<BooleanUse>(node->child1());
</span><span class="cx"> else if (node->child1()->shouldSpeculateObjectOrOther())
</span><span class="cx"> fixEdge<ObjectOrOtherUse>(node->child1());
</span><del>- else if (node->child1()->shouldSpeculateInt32())
- fixEdge<Int32Use>(node->child1());
- else if (node->child1()->shouldSpeculateNumber())
- fixEdge<DoubleRepUse>(node->child1());
</del><ins>+ else if (node->child1()->shouldSpeculateInt32OrBoolean())
+ fixIntOrBooleanEdge(node->child1());
+ else if (node->child1()->shouldSpeculateNumberOrBoolean())
+ fixDoubleOrBooleanEdge(node->child1());
</ins><span class="cx">
</span><span class="cx"> Node* logicalNot = node->child1().node();
</span><span class="cx"> if (logicalNot->op() == LogicalNot) {
</span><span class="lines">@@ -1019,6 +1016,7 @@
</span><span class="cx"> case DoubleConstant:
</span><span class="cx"> case Int52Constant:
</span><span class="cx"> case Identity: // This should have been cleaned up.
</span><ins>+ case BooleanToNumber:
</ins><span class="cx"> // These are just nodes that we don't currently expect to see during fixup.
</span><span class="cx"> // If we ever wanted to insert them prior to fixup, then we just have to create
</span><span class="cx"> // fixup rules for them.
</span><span class="lines">@@ -1579,11 +1577,11 @@
</span><span class="cx"> m_insertionSet.insert(indexInBlock, barrierNode);
</span><span class="cx"> }
</span><span class="cx">
</span><del>- void fixIntEdge(Edge& edge)
</del><ins>+ void fixIntConvertingEdge(Edge& edge)
</ins><span class="cx"> {
</span><span class="cx"> Node* node = edge.node();
</span><del>- if (node->shouldSpeculateInt32()) {
- fixEdge<Int32Use>(edge);
</del><ins>+ if (node->shouldSpeculateInt32OrBoolean()) {
+ fixIntOrBooleanEdge(edge);
</ins><span class="cx"> return;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -1592,8 +1590,6 @@
</span><span class="cx"> useKind = Int52RepUse;
</span><span class="cx"> else if (node->shouldSpeculateNumber())
</span><span class="cx"> useKind = DoubleRepUse;
</span><del>- else if (node->shouldSpeculateBoolean())
- useKind = BooleanUse;
</del><span class="cx"> else
</span><span class="cx"> useKind = NotCellUse;
</span><span class="cx"> Node* newNode = m_insertionSet.insertNode(
</span><span class="lines">@@ -1605,6 +1601,50 @@
</span><span class="cx"> addRequiredPhantom(node);
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+ void fixIntOrBooleanEdge(Edge& edge)
+ {
+ Node* node = edge.node();
+ if (!node->sawBooleans()) {
+ fixEdge<Int32Use>(edge);
+ return;
+ }
+
+ UseKind useKind;
+ if (node->shouldSpeculateBoolean())
+ useKind = BooleanUse;
+ else
+ useKind = UntypedUse;
+ Node* newNode = m_insertionSet.insertNode(
+ m_indexInBlock, SpecInt32, BooleanToNumber, m_currentNode->origin,
+ Edge(node, useKind));
+ observeUseKindOnNode(node, useKind);
+
+ edge = Edge(newNode, Int32Use);
+ addRequiredPhantom(node);
+ }
+
+ void fixDoubleOrBooleanEdge(Edge& edge)
+ {
+ Node* node = edge.node();
+ if (!node->sawBooleans()) {
+ fixEdge<DoubleRepUse>(edge);
+ return;
+ }
+
+ UseKind useKind;
+ if (node->shouldSpeculateBoolean())
+ useKind = BooleanUse;
+ else
+ useKind = UntypedUse;
+ Node* newNode = m_insertionSet.insertNode(
+ m_indexInBlock, SpecInt32, BooleanToNumber, m_currentNode->origin,
+ Edge(node, useKind));
+ observeUseKindOnNode(node, useKind);
+
+ edge = Edge(newNode, DoubleRepUse);
+ addRequiredPhantom(node);
+ }
+
</ins><span class="cx"> void truncateConstantToInt32(Edge& edge)
</span><span class="cx"> {
</span><span class="cx"> Node* oldNode = edge.node();
</span><span class="lines">@@ -1646,11 +1686,11 @@
</span><span class="cx">
</span><span class="cx"> bool attemptToMakeIntegerAdd(Node* node)
</span><span class="cx"> {
</span><del>- AddSpeculationMode mode = m_graph.addSpeculationMode(node);
</del><ins>+ AddSpeculationMode mode = m_graph.addSpeculationMode(node, FixupPass);
</ins><span class="cx"> if (mode != DontSpeculateInt32) {
</span><span class="cx"> truncateConstantsIfNecessary(node, mode);
</span><del>- fixEdge<Int32Use>(node->child1());
- fixEdge<Int32Use>(node->child2());
</del><ins>+ fixIntOrBooleanEdge(node->child1());
+ fixIntOrBooleanEdge(node->child2());
</ins><span class="cx"> if (bytecodeCanTruncateInteger(node->arithNodeFlags()))
</span><span class="cx"> node->setArithMode(Arith::Unchecked);
</span><span class="cx"> else
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGGraphh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGGraph.h (169353 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGGraph.h        2014-05-26 17:30:23 UTC (rev 169353)
+++ trunk/Source/JavaScriptCore/dfg/DFGGraph.h        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -195,42 +195,52 @@
</span><span class="cx"> return speculationFromValue(node->valueOfJSConstant(m_codeBlock));
</span><span class="cx"> }
</span><span class="cx">
</span><del>- AddSpeculationMode addSpeculationMode(Node* add, bool leftShouldSpeculateInt32, bool rightShouldSpeculateInt32)
</del><ins>+ AddSpeculationMode addSpeculationMode(Node* add, bool leftShouldSpeculateInt32, bool rightShouldSpeculateInt32, PredictionPass pass)
</ins><span class="cx"> {
</span><span class="cx"> ASSERT(add->op() == ValueAdd || add->op() == ArithAdd || add->op() == ArithSub);
</span><span class="cx">
</span><ins>+ RareCaseProfilingSource source = add->sourceFor(pass);
+
</ins><span class="cx"> Node* left = add->child1().node();
</span><span class="cx"> Node* right = add->child2().node();
</span><span class="cx">
</span><span class="cx"> if (left->hasConstant())
</span><del>- return addImmediateShouldSpeculateInt32(add, rightShouldSpeculateInt32, left);
</del><ins>+ return addImmediateShouldSpeculateInt32(add, rightShouldSpeculateInt32, left, source);
</ins><span class="cx"> if (right->hasConstant())
</span><del>- return addImmediateShouldSpeculateInt32(add, leftShouldSpeculateInt32, right);
</del><ins>+ return addImmediateShouldSpeculateInt32(add, leftShouldSpeculateInt32, right, source);
</ins><span class="cx">
</span><del>- return (leftShouldSpeculateInt32 && rightShouldSpeculateInt32 && add->canSpeculateInt32()) ? SpeculateInt32 : DontSpeculateInt32;
</del><ins>+ return (leftShouldSpeculateInt32 && rightShouldSpeculateInt32 && add->canSpeculateInt32(source)) ? SpeculateInt32 : DontSpeculateInt32;
</ins><span class="cx"> }
</span><span class="cx">
</span><del>- AddSpeculationMode valueAddSpeculationMode(Node* add)
</del><ins>+ AddSpeculationMode valueAddSpeculationMode(Node* add, PredictionPass pass)
</ins><span class="cx"> {
</span><del>- return addSpeculationMode(add, add->child1()->shouldSpeculateInt32ExpectingDefined(), add->child2()->shouldSpeculateInt32ExpectingDefined());
</del><ins>+ return addSpeculationMode(
+ add,
+ add->child1()->shouldSpeculateInt32OrBooleanExpectingDefined(),
+ add->child2()->shouldSpeculateInt32OrBooleanExpectingDefined(),
+ pass);
</ins><span class="cx"> }
</span><span class="cx">
</span><del>- AddSpeculationMode arithAddSpeculationMode(Node* add)
</del><ins>+ AddSpeculationMode arithAddSpeculationMode(Node* add, PredictionPass pass)
</ins><span class="cx"> {
</span><del>- return addSpeculationMode(add, add->child1()->shouldSpeculateInt32ForArithmetic(), add->child2()->shouldSpeculateInt32ForArithmetic());
</del><ins>+ return addSpeculationMode(
+ add,
+ add->child1()->shouldSpeculateInt32OrBooleanForArithmetic(),
+ add->child2()->shouldSpeculateInt32OrBooleanForArithmetic(),
+ pass);
</ins><span class="cx"> }
</span><span class="cx">
</span><del>- AddSpeculationMode addSpeculationMode(Node* add)
</del><ins>+ AddSpeculationMode addSpeculationMode(Node* add, PredictionPass pass)
</ins><span class="cx"> {
</span><span class="cx"> if (add->op() == ValueAdd)
</span><del>- return valueAddSpeculationMode(add);
</del><ins>+ return valueAddSpeculationMode(add, pass);
</ins><span class="cx">
</span><del>- return arithAddSpeculationMode(add);
</del><ins>+ return arithAddSpeculationMode(add, pass);
</ins><span class="cx"> }
</span><span class="cx">
</span><del>- bool addShouldSpeculateInt32(Node* add)
</del><ins>+ bool addShouldSpeculateInt32(Node* add, PredictionPass pass)
</ins><span class="cx"> {
</span><del>- return addSpeculationMode(add) != DontSpeculateInt32;
</del><ins>+ return addSpeculationMode(add, pass) != DontSpeculateInt32;
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> bool addShouldSpeculateMachineInt(Node* add)
</span><span class="lines">@@ -250,18 +260,18 @@
</span><span class="cx"> return speculation && !hasExitSite(add, Int52Overflow);
</span><span class="cx"> }
</span><span class="cx">
</span><del>- bool mulShouldSpeculateInt32(Node* mul)
</del><ins>+ bool mulShouldSpeculateInt32(Node* mul, PredictionPass pass)
</ins><span class="cx"> {
</span><span class="cx"> ASSERT(mul->op() == ArithMul);
</span><span class="cx">
</span><span class="cx"> Node* left = mul->child1().node();
</span><span class="cx"> Node* right = mul->child2().node();
</span><span class="cx">
</span><del>- return Node::shouldSpeculateInt32ForArithmetic(left, right)
- && mul->canSpeculateInt32();
</del><ins>+ return Node::shouldSpeculateInt32OrBooleanForArithmetic(left, right)
+ && mul->canSpeculateInt32(mul->sourceFor(pass));
</ins><span class="cx"> }
</span><span class="cx">
</span><del>- bool mulShouldSpeculateMachineInt(Node* mul)
</del><ins>+ bool mulShouldSpeculateMachineInt(Node* mul, PredictionPass pass)
</ins><span class="cx"> {
</span><span class="cx"> ASSERT(mul->op() == ArithMul);
</span><span class="cx">
</span><span class="lines">@@ -272,24 +282,25 @@
</span><span class="cx"> Node* right = mul->child2().node();
</span><span class="cx">
</span><span class="cx"> return Node::shouldSpeculateMachineInt(left, right)
</span><del>- && mul->canSpeculateInt52()
</del><ins>+ && mul->canSpeculateInt52(pass)
</ins><span class="cx"> && !hasExitSite(mul, Int52Overflow);
</span><span class="cx"> }
</span><span class="cx">
</span><del>- bool negateShouldSpeculateInt32(Node* negate)
</del><ins>+ bool negateShouldSpeculateInt32(Node* negate, PredictionPass pass)
</ins><span class="cx"> {
</span><span class="cx"> ASSERT(negate->op() == ArithNegate);
</span><del>- return negate->child1()->shouldSpeculateInt32ForArithmetic() && negate->canSpeculateInt32();
</del><ins>+ return negate->child1()->shouldSpeculateInt32OrBooleanForArithmetic()
+ && negate->canSpeculateInt32(pass);
</ins><span class="cx"> }
</span><span class="cx">
</span><del>- bool negateShouldSpeculateMachineInt(Node* negate)
</del><ins>+ bool negateShouldSpeculateMachineInt(Node* negate, PredictionPass pass)
</ins><span class="cx"> {
</span><span class="cx"> ASSERT(negate->op() == ArithNegate);
</span><span class="cx"> if (!enableInt52())
</span><span class="cx"> return false;
</span><span class="cx"> return negate->child1()->shouldSpeculateMachineInt()
</span><span class="cx"> && !hasExitSite(negate, Int52Overflow)
</span><del>- && negate->canSpeculateInt52();
</del><ins>+ && negate->canSpeculateInt52(pass);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> VirtualRegister bytecodeRegisterForArgument(CodeOrigin codeOrigin, int argument)
</span><span class="lines">@@ -856,19 +867,19 @@
</span><span class="cx"> void handleSuccessor(Vector<BasicBlock*, 16>& worklist, BasicBlock*, BasicBlock* successor);
</span><span class="cx"> void addForDepthFirstSort(Vector<BasicBlock*>& result, Vector<BasicBlock*, 16>& worklist, HashSet<BasicBlock*>& seen, BasicBlock*);
</span><span class="cx">
</span><del>- AddSpeculationMode addImmediateShouldSpeculateInt32(Node* add, bool variableShouldSpeculateInt32, Node* immediate)
</del><ins>+ AddSpeculationMode addImmediateShouldSpeculateInt32(Node* add, bool variableShouldSpeculateInt32, Node* immediate, RareCaseProfilingSource source)
</ins><span class="cx"> {
</span><span class="cx"> ASSERT(immediate->hasConstant());
</span><span class="cx">
</span><span class="cx"> JSValue immediateValue = immediate->valueOfJSConstant(m_codeBlock);
</span><del>- if (!immediateValue.isNumber())
</del><ins>+ if (!immediateValue.isNumber() && !immediateValue.isBoolean())
</ins><span class="cx"> return DontSpeculateInt32;
</span><span class="cx">
</span><span class="cx"> if (!variableShouldSpeculateInt32)
</span><span class="cx"> return DontSpeculateInt32;
</span><span class="cx">
</span><del>- if (immediateValue.isInt32())
- return add->canSpeculateInt32() ? SpeculateInt32 : DontSpeculateInt32;
</del><ins>+ if (immediateValue.isInt32() || immediateValue.isBoolean())
+ return add->canSpeculateInt32(source) ? SpeculateInt32 : DontSpeculateInt32;
</ins><span class="cx">
</span><span class="cx"> double doubleImmediate = immediateValue.asDouble();
</span><span class="cx"> const double twoToThe48 = 281474976710656.0;
</span><span class="lines">@@ -877,30 +888,6 @@
</span><span class="cx">
</span><span class="cx"> return bytecodeCanTruncateInteger(add->arithNodeFlags()) ? SpeculateInt32AndTruncateConstants : DontSpeculateInt32;
</span><span class="cx"> }
</span><del>-
- bool mulImmediateShouldSpeculateInt32(Node* mul, Node* variable, Node* immediate)
- {
- ASSERT(immediate->hasConstant());
-
- JSValue immediateValue = immediate->valueOfJSConstant(m_codeBlock);
- if (!immediateValue.isInt32())
- return false;
-
- if (!variable->shouldSpeculateInt32ForArithmetic())
- return false;
-
- int32_t intImmediate = immediateValue.asInt32();
- // Doubles have a 53 bit mantissa so we expect a multiplication of 2^31 (the highest
- // magnitude possible int32 value) and any value less than 2^22 to not result in any
- // rounding in a double multiplication - hence it will be equivalent to an integer
- // multiplication, if we are doing int32 truncation afterwards (which is what
- // canSpeculateInt32() implies).
- const int32_t twoToThe22 = 1 << 22;
- if (intImmediate <= -twoToThe22 || intImmediate >= twoToThe22)
- return mul->canSpeculateInt32() && !nodeMayOverflow(mul->arithNodeFlags());
-
- return mul->canSpeculateInt32();
- }
</del><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> #define DFG_NODE_DO_TO_CHILDREN(graph, node, thingToDo) do { \
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGNodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGNode.h (169353 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNode.h        2014-05-26 17:30:23 UTC (rev 169353)
+++ trunk/Source/JavaScriptCore/dfg/DFGNode.h        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -1437,39 +1437,39 @@
</span><span class="cx"> return isInt32Speculation(prediction());
</span><span class="cx"> }
</span><span class="cx">
</span><del>- bool shouldSpeculateInt32ForArithmetic()
</del><ins>+ bool sawBooleans()
</ins><span class="cx"> {
</span><del>- return isInt32SpeculationForArithmetic(prediction());
</del><ins>+ return !!(prediction() & SpecBoolean);
</ins><span class="cx"> }
</span><span class="cx">
</span><del>- bool shouldSpeculateInt32ExpectingDefined()
</del><ins>+ bool shouldSpeculateInt32OrBoolean()
</ins><span class="cx"> {
</span><del>- return isInt32SpeculationExpectingDefined(prediction());
</del><ins>+ return isInt32OrBooleanSpeculation(prediction());
</ins><span class="cx"> }
</span><span class="cx">
</span><del>- bool shouldSpeculateMachineInt()
</del><ins>+ bool shouldSpeculateInt32ForArithmetic()
</ins><span class="cx"> {
</span><del>- return isMachineIntSpeculation(prediction());
</del><ins>+ return isInt32SpeculationForArithmetic(prediction());
</ins><span class="cx"> }
</span><span class="cx">
</span><del>- bool shouldSpeculateMachineIntForArithmetic()
</del><ins>+ bool shouldSpeculateInt32OrBooleanForArithmetic()
</ins><span class="cx"> {
</span><del>- return isMachineIntSpeculationForArithmetic(prediction());
</del><ins>+ return isInt32OrBooleanSpeculationForArithmetic(prediction());
</ins><span class="cx"> }
</span><span class="cx">
</span><del>- bool shouldSpeculateMachineIntExpectingDefined()
</del><ins>+ bool shouldSpeculateInt32OrBooleanExpectingDefined()
</ins><span class="cx"> {
</span><del>- return isMachineIntSpeculationExpectingDefined(prediction());
</del><ins>+ return isInt32OrBooleanSpeculationExpectingDefined(prediction());
</ins><span class="cx"> }
</span><span class="cx">
</span><del>- bool shouldSpeculateDouble()
</del><ins>+ bool shouldSpeculateMachineInt()
</ins><span class="cx"> {
</span><del>- return isDoubleSpeculation(prediction());
</del><ins>+ return isMachineIntSpeculation(prediction());
</ins><span class="cx"> }
</span><span class="cx">
</span><del>- bool shouldSpeculateDoubleForArithmetic()
</del><ins>+ bool shouldSpeculateDouble()
</ins><span class="cx"> {
</span><del>- return isDoubleSpeculationForArithmetic(prediction());
</del><ins>+ return isDoubleSpeculation(prediction());
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> bool shouldSpeculateNumber()
</span><span class="lines">@@ -1477,11 +1477,16 @@
</span><span class="cx"> return isFullNumberSpeculation(prediction());
</span><span class="cx"> }
</span><span class="cx">
</span><del>- bool shouldSpeculateNumberExpectingDefined()
</del><ins>+ bool shouldSpeculateNumberOrBoolean()
</ins><span class="cx"> {
</span><del>- return isFullNumberSpeculationExpectingDefined(prediction());
</del><ins>+ return isFullNumberOrBooleanSpeculation(prediction());
</ins><span class="cx"> }
</span><span class="cx">
</span><ins>+ bool shouldSpeculateNumberOrBooleanExpectingDefined()
+ {
+ return isFullNumberOrBooleanSpeculationExpectingDefined(prediction());
+ }
+
</ins><span class="cx"> bool shouldSpeculateBoolean()
</span><span class="cx"> {
</span><span class="cx"> return isBooleanSpeculation(prediction());
</span><span class="lines">@@ -1617,46 +1622,46 @@
</span><span class="cx"> return op1->shouldSpeculateInt32() && op2->shouldSpeculateInt32();
</span><span class="cx"> }
</span><span class="cx">
</span><del>- static bool shouldSpeculateInt32ForArithmetic(Node* op1, Node* op2)
</del><ins>+ static bool shouldSpeculateInt32OrBoolean(Node* op1, Node* op2)
</ins><span class="cx"> {
</span><del>- return op1->shouldSpeculateInt32ForArithmetic() && op2->shouldSpeculateInt32ForArithmetic();
</del><ins>+ return op1->shouldSpeculateInt32OrBoolean()
+ && op2->shouldSpeculateInt32OrBoolean();
</ins><span class="cx"> }
</span><span class="cx">
</span><del>- static bool shouldSpeculateInt32ExpectingDefined(Node* op1, Node* op2)
</del><ins>+ static bool shouldSpeculateInt32OrBooleanForArithmetic(Node* op1, Node* op2)
</ins><span class="cx"> {
</span><del>- return op1->shouldSpeculateInt32ExpectingDefined() && op2->shouldSpeculateInt32ExpectingDefined();
</del><ins>+ return op1->shouldSpeculateInt32OrBooleanForArithmetic()
+ && op2->shouldSpeculateInt32OrBooleanForArithmetic();
</ins><span class="cx"> }
</span><span class="cx">
</span><del>- static bool shouldSpeculateMachineInt(Node* op1, Node* op2)
</del><ins>+ static bool shouldSpeculateInt32OrBooleanExpectingDefined(Node* op1, Node* op2)
</ins><span class="cx"> {
</span><del>- return op1->shouldSpeculateMachineInt() && op2->shouldSpeculateMachineInt();
</del><ins>+ return op1->shouldSpeculateInt32OrBooleanExpectingDefined()
+ && op2->shouldSpeculateInt32OrBooleanExpectingDefined();
</ins><span class="cx"> }
</span><span class="cx">
</span><del>- static bool shouldSpeculateMachineIntForArithmetic(Node* op1, Node* op2)
</del><ins>+ static bool shouldSpeculateMachineInt(Node* op1, Node* op2)
</ins><span class="cx"> {
</span><del>- return op1->shouldSpeculateMachineIntForArithmetic() && op2->shouldSpeculateMachineIntForArithmetic();
</del><ins>+ return op1->shouldSpeculateMachineInt() && op2->shouldSpeculateMachineInt();
</ins><span class="cx"> }
</span><span class="cx">
</span><del>- static bool shouldSpeculateMachineIntExpectingDefined(Node* op1, Node* op2)
</del><ins>+ static bool shouldSpeculateNumber(Node* op1, Node* op2)
</ins><span class="cx"> {
</span><del>- return op1->shouldSpeculateMachineIntExpectingDefined() && op2->shouldSpeculateMachineIntExpectingDefined();
</del><ins>+ return op1->shouldSpeculateNumber() && op2->shouldSpeculateNumber();
</ins><span class="cx"> }
</span><span class="cx">
</span><del>- static bool shouldSpeculateDoubleForArithmetic(Node* op1, Node* op2)
</del><ins>+ static bool shouldSpeculateNumberOrBoolean(Node* op1, Node* op2)
</ins><span class="cx"> {
</span><del>- return op1->shouldSpeculateDoubleForArithmetic() && op2->shouldSpeculateDoubleForArithmetic();
</del><ins>+ return op1->shouldSpeculateNumberOrBoolean()
+ && op2->shouldSpeculateNumberOrBoolean();
</ins><span class="cx"> }
</span><span class="cx">
</span><del>- static bool shouldSpeculateNumber(Node* op1, Node* op2)
</del><ins>+ static bool shouldSpeculateNumberOrBooleanExpectingDefined(Node* op1, Node* op2)
</ins><span class="cx"> {
</span><del>- return op1->shouldSpeculateNumber() && op2->shouldSpeculateNumber();
</del><ins>+ return op1->shouldSpeculateNumberOrBooleanExpectingDefined()
+ && op2->shouldSpeculateNumberOrBooleanExpectingDefined();
</ins><span class="cx"> }
</span><span class="cx">
</span><del>- static bool shouldSpeculateNumberExpectingDefined(Node* op1, Node* op2)
- {
- return op1->shouldSpeculateNumberExpectingDefined() && op2->shouldSpeculateNumberExpectingDefined();
- }
-
</del><span class="cx"> static bool shouldSpeculateFinalObject(Node* op1, Node* op2)
</span><span class="cx"> {
</span><span class="cx"> return op1->shouldSpeculateFinalObject() && op2->shouldSpeculateFinalObject();
</span><span class="lines">@@ -1667,16 +1672,33 @@
</span><span class="cx"> return op1->shouldSpeculateArray() && op2->shouldSpeculateArray();
</span><span class="cx"> }
</span><span class="cx">
</span><del>- bool canSpeculateInt32()
</del><ins>+ bool canSpeculateInt32(RareCaseProfilingSource source)
</ins><span class="cx"> {
</span><del>- return nodeCanSpeculateInt32(arithNodeFlags());
</del><ins>+ return nodeCanSpeculateInt32(arithNodeFlags(), source);
</ins><span class="cx"> }
</span><span class="cx">
</span><del>- bool canSpeculateInt52()
</del><ins>+ bool canSpeculateInt52(RareCaseProfilingSource source)
</ins><span class="cx"> {
</span><del>- return nodeCanSpeculateInt52(arithNodeFlags());
</del><ins>+ return nodeCanSpeculateInt52(arithNodeFlags(), source);
</ins><span class="cx"> }
</span><span class="cx">
</span><ins>+ RareCaseProfilingSource sourceFor(PredictionPass pass)
+ {
+ if (pass == PrimaryPass || child1()->sawBooleans() || (child2() && child2()->sawBooleans()))
+ return DFGRareCase;
+ return AllRareCases;
+ }
+
+ bool canSpeculateInt32(PredictionPass pass)
+ {
+ return canSpeculateInt32(sourceFor(pass));
+ }
+
+ bool canSpeculateInt52(PredictionPass pass)
+ {
+ return canSpeculateInt52(sourceFor(pass));
+ }
+
</ins><span class="cx"> void dumpChildren(PrintStream& out)
</span><span class="cx"> {
</span><span class="cx"> if (!child1())
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGNodeFlagscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGNodeFlags.cpp (169353 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNodeFlags.cpp        2014-05-26 17:30:23 UTC (rev 169353)
+++ trunk/Source/JavaScriptCore/dfg/DFGNodeFlags.cpp        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -91,12 +91,18 @@
</span><span class="cx"> out.print(comma, "UseAsOther");
</span><span class="cx"> }
</span><span class="cx">
</span><del>- if (flags & NodeMayOverflow)
- out.print(comma, "MayOverflow");
</del><ins>+ if (flags & NodeMayOverflowInBaseline)
+ out.print(comma, "MayOverflowInBaseline");
</ins><span class="cx">
</span><del>- if (flags & NodeMayNegZero)
- out.print(comma, "MayNegZero");
</del><ins>+ if (flags & NodeMayOverflowInDFG)
+ out.print(comma, "MayOverflowInDFG");
</ins><span class="cx">
</span><ins>+ if (flags & NodeMayNegZeroInBaseline)
+ out.print(comma, "MayNegZeroInBaseline");
+
+ if (flags & NodeMayNegZeroInDFG)
+ out.print(comma, "MayNegZeroInDFG");
+
</ins><span class="cx"> if (flags & NodeBytecodeUsesAsInt)
</span><span class="cx"> out.print(comma, "UseAsInt");
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGNodeFlagsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGNodeFlags.h (169353 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNodeFlags.h        2014-05-26 17:30:23 UTC (rev 169353)
+++ trunk/Source/JavaScriptCore/dfg/DFGNodeFlags.h        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -49,26 +49,28 @@
</span><span class="cx"> #define NodeClobbersWorld 0x0020
</span><span class="cx"> #define NodeMightClobber 0x0040
</span><span class="cx">
</span><del>-#define NodeBehaviorMask 0x0180
-#define NodeMayOverflow 0x0080
-#define NodeMayNegZero 0x0100
</del><ins>+#define NodeBehaviorMask 0x0780
+#define NodeMayOverflowInBaseline 0x0080
+#define NodeMayOverflowInDFG 0x0100
+#define NodeMayNegZeroInBaseline 0x0200
+#define NodeMayNegZeroInDFG 0x0400
</ins><span class="cx">
</span><del>-#define NodeBytecodeBackPropMask 0x3E00
</del><ins>+#define NodeBytecodeBackPropMask 0xf800
</ins><span class="cx"> #define NodeBytecodeUseBottom 0x0000
</span><del>-#define NodeBytecodeUsesAsNumber 0x0200 // The result of this computation may be used in a context that observes fractional, or bigger-than-int32, results.
-#define NodeBytecodeNeedsNegZero 0x0400 // The result of this computation may be used in a context that observes -0.
-#define NodeBytecodeUsesAsOther 0x0800 // The result of this computation may be used in a context that distinguishes between NaN and other things (like undefined).
</del><ins>+#define NodeBytecodeUsesAsNumber 0x0800 // The result of this computation may be used in a context that observes fractional, or bigger-than-int32, results.
+#define NodeBytecodeNeedsNegZero 0x1000 // The result of this computation may be used in a context that observes -0.
+#define NodeBytecodeUsesAsOther 0x2000 // The result of this computation may be used in a context that distinguishes between NaN and other things (like undefined).
</ins><span class="cx"> #define NodeBytecodeUsesAsValue (NodeBytecodeUsesAsNumber | NodeBytecodeNeedsNegZero | NodeBytecodeUsesAsOther)
</span><del>-#define NodeBytecodeUsesAsInt 0x1000 // The result of this computation is known to be used in a context that prefers, but does not require, integer values.
-#define NodeBytecodeUsesAsArrayIndex 0x2000 // The result of this computation is known to be used in a context that strongly prefers integer values, to the point that we should avoid using doubles if at all possible.
</del><ins>+#define NodeBytecodeUsesAsInt 0x4000 // The result of this computation is known to be used in a context that prefers, but does not require, integer values.
+#define NodeBytecodeUsesAsArrayIndex 0x8000 // The result of this computation is known to be used in a context that strongly prefers integer values, to the point that we should avoid using doubles if at all possible.
</ins><span class="cx">
</span><span class="cx"> #define NodeArithFlagsMask (NodeBehaviorMask | NodeBytecodeBackPropMask)
</span><span class="cx">
</span><del>-#define NodeDoesNotExit 0x4000 // This flag is negated to make it natural for the default to be that a node does exit.
</del><ins>+#define NodeDoesNotExit 0x10000 // This flag is negated to make it natural for the default to be that a node does exit.
</ins><span class="cx">
</span><del>-#define NodeRelevantToOSR 0x8000
</del><ins>+#define NodeRelevantToOSR 0x20000
</ins><span class="cx">
</span><del>-#define NodeIsFlushed 0x10000 // Used by Graph::computeIsFlushed(), will tell you which local nodes are backwards-reachable from a Flush.
</del><ins>+#define NodeIsFlushed 0x40000 // Used by Graph::computeIsFlushed(), will tell you which local nodes are backwards-reachable from a Flush.
</ins><span class="cx">
</span><span class="cx"> typedef uint32_t NodeFlags;
</span><span class="cx">
</span><span class="lines">@@ -87,30 +89,60 @@
</span><span class="cx"> return !(flags & NodeBytecodeNeedsNegZero);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-static inline bool nodeMayOverflow(NodeFlags flags)
</del><ins>+enum RareCaseProfilingSource {
+ BaselineRareCase, // Comes from slow case counting in the baseline JIT.
+ DFGRareCase, // Comes from OSR exit profiles.
+ AllRareCases
+};
+
+static inline bool nodeMayOverflow(NodeFlags flags, RareCaseProfilingSource source)
</ins><span class="cx"> {
</span><del>- return !!(flags & NodeMayOverflow);
</del><ins>+ NodeFlags mask;
+ switch (source) {
+ case BaselineRareCase:
+ mask = NodeMayOverflowInBaseline;
+ break;
+ case DFGRareCase:
+ mask = NodeMayOverflowInDFG;
+ break;
+ case AllRareCases:
+ mask = NodeMayOverflowInBaseline | NodeMayOverflowInDFG;
+ break;
+ }
+ return !!(flags & mask);
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-static inline bool nodeMayNegZero(NodeFlags flags)
</del><ins>+static inline bool nodeMayNegZero(NodeFlags flags, RareCaseProfilingSource source)
</ins><span class="cx"> {
</span><del>- return !!(flags & NodeMayNegZero);
</del><ins>+ NodeFlags mask;
+ switch (source) {
+ case BaselineRareCase:
+ mask = NodeMayNegZeroInBaseline;
+ break;
+ case DFGRareCase:
+ mask = NodeMayNegZeroInDFG;
+ break;
+ case AllRareCases:
+ mask = NodeMayNegZeroInBaseline | NodeMayNegZeroInDFG;
+ break;
+ }
+ return !!(flags & mask);
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-static inline bool nodeCanSpeculateInt32(NodeFlags flags)
</del><ins>+static inline bool nodeCanSpeculateInt32(NodeFlags flags, RareCaseProfilingSource source)
</ins><span class="cx"> {
</span><del>- if (nodeMayOverflow(flags))
</del><ins>+ if (nodeMayOverflow(flags, source))
</ins><span class="cx"> return !bytecodeUsesAsNumber(flags);
</span><span class="cx">
</span><del>- if (nodeMayNegZero(flags))
</del><ins>+ if (nodeMayNegZero(flags, source))
</ins><span class="cx"> return bytecodeCanIgnoreNegativeZero(flags);
</span><span class="cx">
</span><span class="cx"> return true;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-static inline bool nodeCanSpeculateInt52(NodeFlags flags)
</del><ins>+static inline bool nodeCanSpeculateInt52(NodeFlags flags, RareCaseProfilingSource source)
</ins><span class="cx"> {
</span><del>- if (nodeMayNegZero(flags))
</del><ins>+ if (nodeMayNegZero(flags, source))
</ins><span class="cx"> return bytecodeCanIgnoreNegativeZero(flags);
</span><span class="cx">
</span><span class="cx"> return true;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGNodeTypeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGNodeType.h (169353 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNodeType.h        2014-05-26 17:30:23 UTC (rev 169353)
+++ trunk/Source/JavaScriptCore/dfg/DFGNodeType.h        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -109,6 +109,8 @@
</span><span class="cx"> macro(ValueToInt32, NodeResultInt32) \
</span><span class="cx"> /* Used to box the result of URShift nodes (result has range 0..2^32-1). */\
</span><span class="cx"> macro(UInt32ToNumber, NodeResultNumber) \
</span><ins>+ /* Converts booleans to numbers but passes everything else through. */\
+ macro(BooleanToNumber, NodeResultJS) \
</ins><span class="cx"> \
</span><span class="cx"> /* Attempt to truncate a double to int32; this will exit if it can't do it. */\
</span><span class="cx"> macro(DoubleAsInt32, NodeResultInt32) \
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGPredictionPropagationPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp (169353 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp        2014-05-26 17:30:23 UTC (rev 169353)
+++ trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -56,11 +56,31 @@
</span><span class="cx"> {
</span><span class="cx"> ASSERT(m_graph.m_form == ThreadedCPS);
</span><span class="cx"> ASSERT(m_graph.m_unificationState == GloballyUnified);
</span><ins>+
+ m_pass = PrimaryPass;
+ propagateToFixpoint();
</ins><span class="cx">
</span><del>- // 1) propagate predictions
-
</del><ins>+ m_pass = RareCasePass;
+ propagateToFixpoint();
+
+ m_pass = DoubleVotingPass;
</ins><span class="cx"> do {
</span><span class="cx"> m_changed = false;
</span><ins>+ doRoundOfDoubleVoting();
+ if (!m_changed)
+ break;
+ m_changed = false;
+ propagateForward();
+ } while (m_changed);
+
+ return true;
+ }
+
+private:
+ void propagateToFixpoint()
+ {
+ do {
+ m_changed = false;
</ins><span class="cx">
</span><span class="cx"> // Forward propagation is near-optimal for both topologically-sorted and
</span><span class="cx"> // DFS-sorted code.
</span><span class="lines">@@ -75,22 +95,8 @@
</span><span class="cx"> m_changed = false;
</span><span class="cx"> propagateBackward();
</span><span class="cx"> } while (m_changed);
</span><del>-
- // 2) repropagate predictions while doing double voting.
-
- do {
- m_changed = false;
- doRoundOfDoubleVoting();
- if (!m_changed)
- break;
- m_changed = false;
- propagateForward();
- } while (m_changed);
-
- return true;
</del><span class="cx"> }
</span><span class="cx">
</span><del>-private:
</del><span class="cx"> bool setPrediction(SpeculatedType prediction)
</span><span class="cx"> {
</span><span class="cx"> ASSERT(m_currentNode->hasResult());
</span><span class="lines">@@ -118,7 +124,7 @@
</span><span class="cx"> result |= SpecDoubleImpureNaN;
</span><span class="cx"> if (value & SpecDoublePureNaN)
</span><span class="cx"> result |= SpecDoublePureNaN;
</span><del>- if (!isFullNumberSpeculation(value))
</del><ins>+ if (!isFullNumberOrBooleanSpeculation(value))
</ins><span class="cx"> result |= SpecDoublePureNaN;
</span><span class="cx"> return result;
</span><span class="cx"> }
</span><span class="lines">@@ -197,7 +203,7 @@
</span><span class="cx"> case UInt32ToNumber: {
</span><span class="cx"> // FIXME: Support Int52.
</span><span class="cx"> // https://bugs.webkit.org/show_bug.cgi?id=125704
</span><del>- if (nodeCanSpeculateInt32(node->arithNodeFlags()))
</del><ins>+ if (node->canSpeculateInt32(m_pass))
</ins><span class="cx"> changed |= mergePrediction(SpecInt32);
</span><span class="cx"> else
</span><span class="cx"> changed |= mergePrediction(SpecBytecodeNumber);
</span><span class="lines">@@ -209,14 +215,17 @@
</span><span class="cx"> SpeculatedType right = node->child2()->prediction();
</span><span class="cx">
</span><span class="cx"> if (left && right) {
</span><del>- if (isFullNumberSpeculationExpectingDefined(left) && isFullNumberSpeculationExpectingDefined(right)) {
- if (m_graph.addSpeculationMode(node) != DontSpeculateInt32)
</del><ins>+ if (isFullNumberOrBooleanSpeculationExpectingDefined(left)
+ && isFullNumberOrBooleanSpeculationExpectingDefined(right)) {
+ if (m_graph.addSpeculationMode(node, m_pass) != DontSpeculateInt32)
</ins><span class="cx"> changed |= mergePrediction(SpecInt32);
</span><span class="cx"> else if (m_graph.addShouldSpeculateMachineInt(node))
</span><span class="cx"> changed |= mergePrediction(SpecInt52);
</span><span class="cx"> else
</span><span class="cx"> changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right));
</span><del>- } else if (!(left & SpecFullNumber) || !(right & SpecFullNumber)) {
</del><ins>+ } else if (
+ !(left & (SpecFullNumber | SpecBoolean))
+ || !(right & (SpecFullNumber | SpecBoolean))) {
</ins><span class="cx"> // left or right is definitely something other than a number.
</span><span class="cx"> changed |= mergePrediction(SpecString);
</span><span class="cx"> } else
</span><span class="lines">@@ -230,7 +239,7 @@
</span><span class="cx"> SpeculatedType right = node->child2()->prediction();
</span><span class="cx">
</span><span class="cx"> if (left && right) {
</span><del>- if (m_graph.addSpeculationMode(node) != DontSpeculateInt32)
</del><ins>+ if (m_graph.addSpeculationMode(node, m_pass) != DontSpeculateInt32)
</ins><span class="cx"> changed |= mergePrediction(SpecInt32);
</span><span class="cx"> else if (m_graph.addShouldSpeculateMachineInt(node))
</span><span class="cx"> changed |= mergePrediction(SpecInt52);
</span><span class="lines">@@ -245,7 +254,7 @@
</span><span class="cx"> SpeculatedType right = node->child2()->prediction();
</span><span class="cx">
</span><span class="cx"> if (left && right) {
</span><del>- if (m_graph.addSpeculationMode(node) != DontSpeculateInt32)
</del><ins>+ if (m_graph.addSpeculationMode(node, m_pass) != DontSpeculateInt32)
</ins><span class="cx"> changed |= mergePrediction(SpecInt32);
</span><span class="cx"> else if (m_graph.addShouldSpeculateMachineInt(node))
</span><span class="cx"> changed |= mergePrediction(SpecInt52);
</span><span class="lines">@@ -257,9 +266,9 @@
</span><span class="cx">
</span><span class="cx"> case ArithNegate:
</span><span class="cx"> if (node->child1()->prediction()) {
</span><del>- if (m_graph.negateShouldSpeculateInt32(node))
</del><ins>+ if (m_graph.negateShouldSpeculateInt32(node, m_pass))
</ins><span class="cx"> changed |= mergePrediction(SpecInt32);
</span><del>- else if (m_graph.negateShouldSpeculateMachineInt(node))
</del><ins>+ else if (m_graph.negateShouldSpeculateMachineInt(node, m_pass))
</ins><span class="cx"> changed |= mergePrediction(SpecInt52);
</span><span class="cx"> else
</span><span class="cx"> changed |= mergePrediction(speculatedDoubleTypeForPrediction(node->child1()->prediction()));
</span><span class="lines">@@ -272,8 +281,8 @@
</span><span class="cx"> SpeculatedType right = node->child2()->prediction();
</span><span class="cx">
</span><span class="cx"> if (left && right) {
</span><del>- if (Node::shouldSpeculateInt32ForArithmetic(node->child1().node(), node->child2().node())
- && nodeCanSpeculateInt32(node->arithNodeFlags()))
</del><ins>+ if (Node::shouldSpeculateInt32OrBooleanForArithmetic(node->child1().node(), node->child2().node())
+ && node->canSpeculateInt32(m_pass))
</ins><span class="cx"> changed |= mergePrediction(SpecInt32);
</span><span class="cx"> else
</span><span class="cx"> changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right));
</span><span class="lines">@@ -286,9 +295,9 @@
</span><span class="cx"> SpeculatedType right = node->child2()->prediction();
</span><span class="cx">
</span><span class="cx"> if (left && right) {
</span><del>- if (m_graph.mulShouldSpeculateInt32(node))
</del><ins>+ if (m_graph.mulShouldSpeculateInt32(node, m_pass))
</ins><span class="cx"> changed |= mergePrediction(SpecInt32);
</span><del>- else if (m_graph.mulShouldSpeculateMachineInt(node))
</del><ins>+ else if (m_graph.mulShouldSpeculateMachineInt(node, m_pass))
</ins><span class="cx"> changed |= mergePrediction(SpecInt52);
</span><span class="cx"> else
</span><span class="cx"> changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right));
</span><span class="lines">@@ -301,8 +310,8 @@
</span><span class="cx"> SpeculatedType right = node->child2()->prediction();
</span><span class="cx">
</span><span class="cx"> if (left && right) {
</span><del>- if (Node::shouldSpeculateInt32ForArithmetic(node->child1().node(), node->child2().node())
- && nodeCanSpeculateInt32(node->arithNodeFlags()))
</del><ins>+ if (Node::shouldSpeculateInt32OrBooleanForArithmetic(node->child1().node(), node->child2().node())
+ && node->canSpeculateInt32(m_pass))
</ins><span class="cx"> changed |= mergePrediction(SpecInt32);
</span><span class="cx"> else
</span><span class="cx"> changed |= mergePrediction(SpecBytecodeDouble);
</span><span class="lines">@@ -315,8 +324,8 @@
</span><span class="cx"> SpeculatedType right = node->child2()->prediction();
</span><span class="cx">
</span><span class="cx"> if (left && right) {
</span><del>- if (Node::shouldSpeculateInt32ForArithmetic(node->child1().node(), node->child2().node())
- && nodeCanSpeculateInt32(node->arithNodeFlags()))
</del><ins>+ if (Node::shouldSpeculateInt32OrBooleanForArithmetic(node->child1().node(), node->child2().node())
+ && node->canSpeculateInt32(m_pass))
</ins><span class="cx"> changed |= mergePrediction(SpecInt32);
</span><span class="cx"> else
</span><span class="cx"> changed |= mergePrediction(SpecBytecodeDouble);
</span><span class="lines">@@ -334,8 +343,8 @@
</span><span class="cx">
</span><span class="cx"> case ArithAbs: {
</span><span class="cx"> SpeculatedType child = node->child1()->prediction();
</span><del>- if (isInt32SpeculationForArithmetic(child)
- && nodeCanSpeculateInt32(node->arithNodeFlags()))
</del><ins>+ if (isInt32OrBooleanSpeculationForArithmetic(child)
+ && node->canSpeculateInt32(m_pass))
</ins><span class="cx"> changed |= mergePrediction(SpecInt32);
</span><span class="cx"> else
</span><span class="cx"> changed |= mergePrediction(speculatedDoubleTypeForPrediction(child));
</span><span class="lines">@@ -532,7 +541,8 @@
</span><span class="cx"> case ValueRep:
</span><span class="cx"> case DoubleConstant:
</span><span class="cx"> case Int52Constant:
</span><del>- case Identity: {
</del><ins>+ case Identity:
+ case BooleanToNumber: {
</ins><span class="cx"> // This node should never be visible at this stage of compilation. It is
</span><span class="cx"> // inserted by fixup(), which follows this phase.
</span><span class="cx"> RELEASE_ASSERT_NOT_REACHED();
</span><span class="lines">@@ -675,8 +685,9 @@
</span><span class="cx">
</span><span class="cx"> DoubleBallot ballot;
</span><span class="cx">
</span><del>- if (isFullNumberSpeculationExpectingDefined(left) && isFullNumberSpeculationExpectingDefined(right)
- && !m_graph.addShouldSpeculateInt32(node)
</del><ins>+ if (isFullNumberSpeculation(left)
+ && isFullNumberSpeculation(right)
+ && !m_graph.addShouldSpeculateInt32(node, m_pass)
</ins><span class="cx"> && !m_graph.addShouldSpeculateMachineInt(node))
</span><span class="cx"> ballot = VoteDouble;
</span><span class="cx"> else
</span><span class="lines">@@ -693,9 +704,10 @@
</span><span class="cx">
</span><span class="cx"> DoubleBallot ballot;
</span><span class="cx">
</span><del>- if (isFullNumberSpeculation(left) && isFullNumberSpeculation(right)
- && !m_graph.mulShouldSpeculateInt32(node)
- && !m_graph.mulShouldSpeculateMachineInt(node))
</del><ins>+ if (isFullNumberSpeculation(left)
+ && isFullNumberSpeculation(right)
+ && !m_graph.mulShouldSpeculateInt32(node, m_pass)
+ && !m_graph.mulShouldSpeculateMachineInt(node, m_pass))
</ins><span class="cx"> ballot = VoteDouble;
</span><span class="cx"> else
</span><span class="cx"> ballot = VoteValue;
</span><span class="lines">@@ -714,8 +726,9 @@
</span><span class="cx">
</span><span class="cx"> DoubleBallot ballot;
</span><span class="cx">
</span><del>- if (isFullNumberSpeculation(left) && isFullNumberSpeculation(right)
- && !(Node::shouldSpeculateInt32ForArithmetic(node->child1().node(), node->child2().node()) && node->canSpeculateInt32()))
</del><ins>+ if (isFullNumberSpeculation(left)
+ && isFullNumberSpeculation(right)
+ && !(Node::shouldSpeculateInt32OrBooleanForArithmetic(node->child1().node(), node->child2().node()) && node->canSpeculateInt32(m_pass)))
</ins><span class="cx"> ballot = VoteDouble;
</span><span class="cx"> else
</span><span class="cx"> ballot = VoteValue;
</span><span class="lines">@@ -727,7 +740,8 @@
</span><span class="cx">
</span><span class="cx"> case ArithAbs:
</span><span class="cx"> DoubleBallot ballot;
</span><del>- if (!(node->child1()->shouldSpeculateInt32ForArithmetic() && node->canSpeculateInt32()))
</del><ins>+ if (node->child1()->shouldSpeculateNumber()
+ && !(node->child1()->shouldSpeculateInt32OrBooleanForArithmetic() && node->canSpeculateInt32(m_pass)))
</ins><span class="cx"> ballot = VoteDouble;
</span><span class="cx"> else
</span><span class="cx"> ballot = VoteValue;
</span><span class="lines">@@ -738,7 +752,10 @@
</span><span class="cx"> case ArithSqrt:
</span><span class="cx"> case ArithCos:
</span><span class="cx"> case ArithSin:
</span><del>- m_graph.voteNode(node->child1(), VoteDouble, weight);
</del><ins>+ if (node->child1()->shouldSpeculateNumber())
+ m_graph.voteNode(node->child1(), VoteDouble, weight);
+ else
+ m_graph.voteNode(node->child1(), VoteValue, weight);
</ins><span class="cx"> break;
</span><span class="cx">
</span><span class="cx"> case SetLocal: {
</span><span class="lines">@@ -813,6 +830,7 @@
</span><span class="cx">
</span><span class="cx"> Node* m_currentNode;
</span><span class="cx"> bool m_changed;
</span><ins>+ PredictionPass m_pass; // We use different logic for considering predictions depending on how far along we are in propagation.
</ins><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> bool performPredictionPropagation(Graph& graph)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSafeToExecuteh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h (169353 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h        2014-05-26 17:30:23 UTC (rev 169353)
+++ trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -253,6 +253,7 @@
</span><span class="cx"> case ValueRep:
</span><span class="cx"> case DoubleRep:
</span><span class="cx"> case Int52Rep:
</span><ins>+ case BooleanToNumber:
</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 (169353 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2014-05-26 17:30:23 UTC (rev 169353)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -1853,14 +1853,6 @@
</span><span class="cx"> void SpeculativeJIT::compileValueToInt32(Node* node)
</span><span class="cx"> {
</span><span class="cx"> switch (node->child1().useKind()) {
</span><del>- case Int32Use: {
- SpeculateInt32Operand op1(this, node->child1());
- GPRTemporary result(this, Reuse, op1);
- m_jit.move(op1.gpr(), result.gpr());
- int32Result(result.gpr(), node, op1.format());
- return;
- }
-
</del><span class="cx"> #if USE(JSVALUE64)
</span><span class="cx"> case Int52RepUse: {
</span><span class="cx"> SpeculateStrictInt52Operand op1(this, node->child1());
</span><span class="lines">@@ -2013,17 +2005,6 @@
</span><span class="cx"> return;
</span><span class="cx"> }
</span><span class="cx">
</span><del>- case BooleanUse: {
- SpeculateBooleanOperand op1(this, node->child1());
- GPRTemporary result(this, Reuse, op1);
-
- m_jit.move(op1.gpr(), result.gpr());
- m_jit.and32(JITCompiler::TrustedImm32(1), result.gpr());
-
- int32Result(result.gpr(), node);
- return;
- }
-
</del><span class="cx"> default:
</span><span class="cx"> ASSERT(!m_compileOkay);
</span><span class="cx"> return;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp (169353 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2014-05-26 17:30:23 UTC (rev 169353)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -2948,6 +2948,48 @@
</span><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+ case BooleanToNumber: {
+ switch (node->child1().useKind()) {
+ case BooleanUse: {
+ SpeculateBooleanOperand value(this, node->child1());
+ GPRTemporary result(this); // FIXME: We could reuse, but on speculation fail would need recovery to restore tag (akin to add).
+
+ m_jit.move(value.gpr(), result.gpr());
+
+ int32Result(result.gpr(), node);
+ break;
+ }
+
+ case UntypedUse: {
+ JSValueOperand value(this, node->child1());
+ GPRTemporary resultTag(this);
+ GPRTemporary resultPayload(this);
+
+ GPRReg valueTagGPR = value.tagGPR();
+ GPRReg valuePayloadGPR = value.payloadGPR();
+ GPRReg resultTagGPR = resultTag.gpr();
+ GPRReg resultPayloadGPR = resultPayload.gpr();
+
+ m_jit.move(valuePayloadGPR, resultPayloadGPR);
+ JITCompiler::Jump isBoolean = m_jit.branch32(
+ JITCompiler::Equal, valueTagGPR, TrustedImm32(JSValue::BooleanTag));
+ m_jit.move(valueTagGPR, resultTagGPR);
+ JITCompiler::Jump done = m_jit.jump();
+ isBoolean.link(&m_jit);
+ m_jit.move(TrustedImm32(JSValue::Int32Tag), resultTagGPR);
+ done.link(&m_jit);
+
+ jsValueResult(resultTagGPR, resultPayloadGPR, node);
+ break;
+ }
+
+ default:
+ RELEASE_ASSERT_NOT_REACHED();
+ break;
+ }
+ break;
+ }
+
</ins><span class="cx"> case ToPrimitive: {
</span><span class="cx"> RELEASE_ASSERT(node->child1().useKind() == UntypedUse);
</span><span class="cx"> JSValueOperand op1(this, node->child1());
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (169353 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2014-05-26 17:30:23 UTC (rev 169353)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -3053,6 +3053,47 @@
</span><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+ case BooleanToNumber: {
+ switch (node->child1().useKind()) {
+ case BooleanUse: {
+ JSValueOperand value(this, node->child1(), ManualOperandSpeculation);
+ GPRTemporary result(this); // FIXME: We could reuse, but on speculation fail would need recovery to restore tag (akin to add).
+
+ m_jit.move(value.gpr(), result.gpr());
+ m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), result.gpr());
+ DFG_TYPE_CHECK(
+ JSValueRegs(value.gpr()), node->child1(), SpecBoolean, m_jit.branchTest64(
+ JITCompiler::NonZero, result.gpr(), TrustedImm32(static_cast<int32_t>(~1))));
+
+ int32Result(result.gpr(), node);
+ break;
+ }
+
+ case UntypedUse: {
+ JSValueOperand value(this, node->child1());
+ GPRTemporary result(this);
+
+ m_jit.move(value.gpr(), result.gpr());
+ m_jit.xor64(TrustedImm32(static_cast<int32_t>(ValueFalse)), result.gpr());
+ JITCompiler::Jump isBoolean = m_jit.branchTest64(
+ JITCompiler::Zero, result.gpr(), TrustedImm32(static_cast<int32_t>(~1)));
+ m_jit.move(value.gpr(), result.gpr());
+ JITCompiler::Jump done = m_jit.jump();
+ isBoolean.link(&m_jit);
+ m_jit.or64(GPRInfo::tagTypeNumberRegister, result.gpr());
+ done.link(&m_jit);
+
+ jsValueResult(result.gpr(), node);
+ break;
+ }
+
+ default:
+ RELEASE_ASSERT_NOT_REACHED();
+ break;
+ }
+ break;
+ }
+
</ins><span class="cx"> case ToPrimitive: {
</span><span class="cx"> RELEASE_ASSERT(node->child1().useKind() == UntypedUse);
</span><span class="cx"> JSValueOperand op1(this, node->child1());
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLCapabilitiescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp (169353 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp        2014-05-26 17:30:23 UTC (rev 169353)
+++ trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -155,6 +155,7 @@
</span><span class="cx"> case Int52Rep:
</span><span class="cx"> case DoubleConstant:
</span><span class="cx"> case Int52Constant:
</span><ins>+ case BooleanToNumber:
</ins><span class="cx"> // These are OK.
</span><span class="cx"> break;
</span><span class="cx"> case Identity:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLLowerDFGToLLVMcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp (169353 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2014-05-26 17:30:23 UTC (rev 169353)
+++ trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -306,6 +306,9 @@
</span><span class="cx"> case ValueToInt32:
</span><span class="cx"> compileValueToInt32();
</span><span class="cx"> break;
</span><ins>+ case BooleanToNumber:
+ compileBooleanToNumber();
+ break;
</ins><span class="cx"> case GetArgument:
</span><span class="cx"> compileGetArgument();
</span><span class="cx"> break;
</span><span class="lines">@@ -774,10 +777,6 @@
</span><span class="cx"> void compileValueToInt32()
</span><span class="cx"> {
</span><span class="cx"> switch (m_node->child1().useKind()) {
</span><del>- case Int32Use:
- setInt32(lowInt32(m_node->child1()));
- break;
-
</del><span class="cx"> case Int52RepUse:
</span><span class="cx"> setInt32(m_out.castToInt32(lowStrictInt52(m_node->child1())));
</span><span class="cx"> break;
</span><span class="lines">@@ -809,13 +808,42 @@
</span><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx">
</span><del>- case BooleanUse:
</del><ins>+ default:
+ RELEASE_ASSERT_NOT_REACHED();
+ break;
+ }
+ }
+
+ void compileBooleanToNumber()
+ {
+ switch (m_node->child1().useKind()) {
+ case BooleanUse: {
</ins><span class="cx"> setInt32(m_out.zeroExt(lowBoolean(m_node->child1()), m_out.int32));
</span><del>- break;
</del><ins>+ return;
+ }
</ins><span class="cx">
</span><ins>+ case UntypedUse: {
+ LValue value = lowJSValue(m_node->child1());
+
+ LBasicBlock booleanCase = FTL_NEW_BLOCK(m_out, ("BooleanToNumber boolean case"));
+ LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("BooleanToNumber continuation"));
+
+ ValueFromBlock notBooleanResult = m_out.anchor(value);
+ m_out.branch(isBoolean(value), unsure(booleanCase), unsure(continuation));
+
+ LBasicBlock lastNext = m_out.appendTo(booleanCase, continuation);
+ ValueFromBlock booleanResult = m_out.anchor(m_out.bitOr(
+ m_out.zeroExt(unboxBoolean(value), m_out.int64), m_tagTypeNumber));
+ m_out.jump(continuation);
+
+ m_out.appendTo(continuation, lastNext);
+ setJSValue(m_out.phi(m_out.int64, booleanResult, notBooleanResult));
+ return;
+ }
+
</ins><span class="cx"> default:
</span><span class="cx"> RELEASE_ASSERT_NOT_REACHED();
</span><del>- break;
</del><ins>+ return;
</ins><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSCJSValueh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSCJSValue.h (169353 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSCJSValue.h        2014-05-26 17:30:23 UTC (rev 169353)
+++ trunk/Source/JavaScriptCore/runtime/JSCJSValue.h        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -199,6 +199,8 @@
</span><span class="cx"> double asDouble() const;
</span><span class="cx"> bool asBoolean() const;
</span><span class="cx"> double asNumber() const;
</span><ins>+
+ int32_t asInt32ForArithmetic() const; // Boolean becomes an int, but otherwise like asInt32().
</ins><span class="cx">
</span><span class="cx"> // Querying the type.
</span><span class="cx"> bool isEmpty() const;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSCJSValueInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSCJSValueInlines.h (169353 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSCJSValueInlines.h        2014-05-26 17:30:23 UTC (rev 169353)
+++ trunk/Source/JavaScriptCore/runtime/JSCJSValueInlines.h        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -831,6 +831,13 @@
</span><span class="cx"> return strictEqualSlowCaseInline(exec, v1, v2);
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+inline int32_t JSValue::asInt32ForArithmetic() const
+{
+ if (isBoolean())
+ return asBoolean();
+ return asInt32();
+}
+
</ins><span class="cx"> inline TriState JSValue::pureStrictEqual(JSValue v1, JSValue v2)
</span><span class="cx"> {
</span><span class="cx"> if (v1.isInt32() && v2.isInt32())
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressmaxbooleanexitjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/max-boolean-exit.js (0 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/max-boolean-exit.js         (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/max-boolean-exit.js        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -0,0 +1,22 @@
</span><ins>+function foo(a, b) {
+ return Math.max(a.f, b.f);
+}
+
+noInline(foo);
+
+function test(a, b, c) {
+ var result = foo({f:a}, {f:b});
+ if (result != c)
+ throw "Error: expected " + c + " but got: " + result;
+}
+
+for (var i = 0; i < 100000; ++i)
+ test(true, 42, 42);
+
+// Now try some unexpected things, in descending order of possible badness.
+test(true, 2147483647, 2147483647);
+test(false, 42, 42);
+test(1, 2, 2);
+test(true, true, 1);
+test(1.5, 1.5, 1.5);
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressmulbooleanexitjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/mul-boolean-exit.js (0 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/mul-boolean-exit.js         (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/mul-boolean-exit.js        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -0,0 +1,30 @@
</span><ins>+function foo(a, b) {
+ return Math.max(a.f, b.f);
+}
+
+noInline(foo);
+
+var f = new Float64Array(1);
+var i = new Int32Array(f.buffer);
+
+function test(a, b, c) {
+ var result = foo({f:a}, {f:b});
+ f[0] = c;
+ var expectedA = i[0];
+ var expectedB = i[1];
+ f[0] = result;
+ if (i[0] != expectedA || i[1] != expectedB)
+ throw "Error: expected " + c + " but got: " + result;
+}
+
+for (var i = 0; i < 100000; ++i)
+ test(true, 42, 42);
+
+// Now try some unexpected things, in descending order of possible badness.
+test(true, 2147483647, 2147483647);
+test(false, 42, 42);
+test(false, -42, -0);
+test(1, 2, 2);
+test(true, true, 1);
+test(1.5, 1.5, 2.25);
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressplusbooleanexitjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/plus-boolean-exit.js (0 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/plus-boolean-exit.js         (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/plus-boolean-exit.js        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -0,0 +1,22 @@
</span><ins>+function foo(a, b) {
+ return a.f + b.f;
+}
+
+noInline(foo);
+
+function test(a, b, c) {
+ var result = foo({f:a}, {f:b});
+ if (result != c)
+ throw "Error: expected " + c + " but got: " + result;
+}
+
+for (var i = 0; i < 100000; ++i)
+ test(true, 42, 43);
+
+// Now try some unexpected things, in descending order of possible badness.
+test(true, 2147483647, 2147483648);
+test(false, 42, 42);
+test(1, 2, 3);
+test(true, true, 2);
+test(1.5, 1.5, 3);
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressplusbooleanordoublejs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/plus-boolean-or-double.js (0 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/plus-boolean-or-double.js         (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/plus-boolean-or-double.js        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -0,0 +1,24 @@
</span><ins>+function foo(a, b) {
+ return a.f + b.f;
+}
+
+noInline(foo);
+
+function test(a, b, c) {
+ var result = foo({f:a}, {f:b});
+ if (result != c)
+ throw "Error: expected " + c + " but got: " + result;
+}
+
+for (var i = 0; i < 100000; ++i) {
+ test(true, 42, 43);
+ test(42.5, 10, 52.5);
+}
+
+// Now try some unexpected things, in descending order of possible badness.
+test(true, 2147483647, 2147483648);
+test(false, 42, 42);
+test(1, 2, 3);
+test(true, true, 2);
+test(1.5, 1.5, 3);
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressplusbooleanorintjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/plus-boolean-or-int.js (0 => 169354)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/plus-boolean-or-int.js         (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/plus-boolean-or-int.js        2014-05-26 17:43:41 UTC (rev 169354)
</span><span class="lines">@@ -0,0 +1,24 @@
</span><ins>+function foo(a, b) {
+ return a.f + b.f;
+}
+
+noInline(foo);
+
+function test(a, b, c) {
+ var result = foo({f:a}, {f:b});
+ if (result != c)
+ throw "Error: expected " + c + " but got: " + result;
+}
+
+for (var i = 0; i < 100000; ++i) {
+ test(true, 42, 43);
+ test(42, 10, 52);
+}
+
+// Now try some unexpected things, in descending order of possible badness.
+test(true, 2147483647, 2147483648);
+test(false, 42, 42);
+test(1, 2, 3);
+test(true, true, 2);
+test(1.5, 1.5, 3);
+
</ins></span></pre>
</div>
</div>
</body>
</html>