<!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>[184540] trunk/Source/JavaScriptCore</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/184540">184540</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2015-05-18 19:30:00 -0700 (Mon, 18 May 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>Add SpecBoolInt32 type that means &quot;I'm an int and I'm either 0 or 1&quot;
https://bugs.webkit.org/show_bug.cgi?id=145137

Reviewed by Benjamin Poulain.
        
It's super useful to know if an integer value could be either zero or one. We have an
immediate need for this because of Int32|Boolean uses, where knowing that the Int32 is
either 0 or 1 means that there is no actual polymorphism if you just look at the low bit
(1 behaves like true, 0 behaves like false, and the low bit of 1|true is 1, and the low
bit of 0|false is 0).
        
We do this by splitting the SpecInt32 type into SpecBoolInt32 and SpecNonBoolInt32. This
change doesn't have any effect on behavior, yet. But it does give us the ability to
predict and prove when values are SpecBoolInt32; it's just we don't leverage this yet.
        
This is perf-neutral.

* bytecode/SpeculatedType.cpp:
(JSC::dumpSpeculation):
(JSC::speculationToAbbreviatedString):
(JSC::speculationFromValue):
* bytecode/SpeculatedType.h:
(JSC::isStringOrStringObjectSpeculation):
(JSC::isBoolInt32Speculation):
(JSC::isInt32Speculation):
(JSC::isInt32OrBooleanSpeculation):
* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter&lt;AbstractStateType&gt;::executeEffects):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeSpeculatedTypecpp">trunk/Source/JavaScriptCore/bytecode/SpeculatedType.cpp</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>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (184539 => 184540)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-05-19 02:02:10 UTC (rev 184539)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-05-19 02:30:00 UTC (rev 184540)
</span><span class="lines">@@ -1,3 +1,34 @@
</span><ins>+2015-05-18  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        Add SpecBoolInt32 type that means &quot;I'm an int and I'm either 0 or 1&quot;
+        https://bugs.webkit.org/show_bug.cgi?id=145137
+
+        Reviewed by Benjamin Poulain.
+        
+        It's super useful to know if an integer value could be either zero or one. We have an
+        immediate need for this because of Int32|Boolean uses, where knowing that the Int32 is
+        either 0 or 1 means that there is no actual polymorphism if you just look at the low bit
+        (1 behaves like true, 0 behaves like false, and the low bit of 1|true is 1, and the low
+        bit of 0|false is 0).
+        
+        We do this by splitting the SpecInt32 type into SpecBoolInt32 and SpecNonBoolInt32. This
+        change doesn't have any effect on behavior, yet. But it does give us the ability to
+        predict and prove when values are SpecBoolInt32; it's just we don't leverage this yet.
+        
+        This is perf-neutral.
+
+        * bytecode/SpeculatedType.cpp:
+        (JSC::dumpSpeculation):
+        (JSC::speculationToAbbreviatedString):
+        (JSC::speculationFromValue):
+        * bytecode/SpeculatedType.h:
+        (JSC::isStringOrStringObjectSpeculation):
+        (JSC::isBoolInt32Speculation):
+        (JSC::isInt32Speculation):
+        (JSC::isInt32OrBooleanSpeculation):
+        * dfg/DFGAbstractInterpreterInlines.h:
+        (JSC::DFG::AbstractInterpreter&lt;AbstractStateType&gt;::executeEffects):
+
</ins><span class="cx"> 2015-05-18  Michael Catanzaro  &lt;mcatanzaro@igalia.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [CMake] Ignore warnings in system headers
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeSpeculatedTypecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/SpeculatedType.cpp (184539 => 184540)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/SpeculatedType.cpp        2015-05-19 02:02:10 UTC (rev 184539)
+++ trunk/Source/JavaScriptCore/bytecode/SpeculatedType.cpp        2015-05-19 02:30:00 UTC (rev 184540)
</span><span class="lines">@@ -163,10 +163,19 @@
</span><span class="cx">             isTop = false;
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    if (value &amp; SpecInt32)
</del><ins>+    if (value == SpecInt32)
</ins><span class="cx">         myOut.print(&quot;Int32&quot;);
</span><del>-    else
-        isTop = false;
</del><ins>+    else {
+        if (value &amp; SpecBoolInt32)
+            myOut.print(&quot;Boolint32&quot;);
+        else
+            isTop = false;
+        
+        if (value &amp; SpecNonBoolInt32)
+            myOut.print(&quot;Nonboolint32&quot;);
+        else
+            isTop = false;
+    }
</ins><span class="cx">     
</span><span class="cx">     if (value &amp; SpecInt52)
</span><span class="cx">         myOut.print(&quot;Int52&quot;);
</span><span class="lines">@@ -254,6 +263,8 @@
</span><span class="cx">         return &quot;&lt;Object&gt;&quot;;
</span><span class="cx">     if (isCellSpeculation(prediction))
</span><span class="cx">         return &quot;&lt;Cell&gt;&quot;;
</span><ins>+    if (isBoolInt32Speculation(prediction))
+        return &quot;&lt;BoolInt32&gt;&quot;;
</ins><span class="cx">     if (isInt32Speculation(prediction))
</span><span class="cx">         return &quot;&lt;Int32&gt;&quot;;
</span><span class="cx">     if (isInt52AsDoubleSpeculation(prediction))
</span><span class="lines">@@ -363,8 +374,11 @@
</span><span class="cx"> {
</span><span class="cx">     if (value.isEmpty())
</span><span class="cx">         return SpecEmpty;
</span><del>-    if (value.isInt32())
-        return SpecInt32;
</del><ins>+    if (value.isInt32()) {
+        if (value.asInt32() &amp; ~1)
+            return SpecNonBoolInt32;
+        return SpecBoolInt32;
+    }
</ins><span class="cx">     if (value.isDouble()) {
</span><span class="cx">         double number = value.asNumber();
</span><span class="cx">         if (number != number)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeSpeculatedTypeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/SpeculatedType.h (184539 => 184540)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/SpeculatedType.h        2015-05-19 02:02:10 UTC (rev 184539)
+++ trunk/Source/JavaScriptCore/bytecode/SpeculatedType.h        2015-05-19 02:30:00 UTC (rev 184540)
</span><span class="lines">@@ -63,11 +63,13 @@
</span><span class="cx"> static const SpeculatedType SpecSymbol             = 0x00040000; // It's definitely a Symbol.
</span><span class="cx"> static const SpeculatedType SpecCellOther          = 0x00080000; // It's definitely a JSCell but not a subclass of JSObject and definitely not a JSString or a Symbol. FIXME: This shouldn't be part of heap-top or bytecode-top. https://bugs.webkit.org/show_bug.cgi?id=133078
</span><span class="cx"> static const SpeculatedType SpecCell               = 0x000fffff; // It's definitely a JSCell.
</span><del>-static const SpeculatedType SpecInt32              = 0x00200000; // It's definitely an Int32.
</del><ins>+static const SpeculatedType SpecBoolInt32          = 0x00100000; // It's definitely an Int32 with value 0 or 1.
+static const SpeculatedType SpecNonBoolInt32       = 0x00200000; // It's definitely an Int32 with value other than 0 or 1.
+static const SpeculatedType SpecInt32              = 0x00300000; // It's definitely an Int32.
</ins><span class="cx"> static const SpeculatedType SpecInt52              = 0x00400000; // It's definitely an Int52 and we intend it to unbox it.
</span><del>-static const SpeculatedType SpecMachineInt         = 0x00600000; // It's something that we can do machine int arithmetic on.
</del><ins>+static const SpeculatedType SpecMachineInt         = 0x00700000; // It's something that we can do machine int arithmetic on.
</ins><span class="cx"> static const SpeculatedType SpecInt52AsDouble      = 0x00800000; // It's definitely an Int52 and it's inside a double.
</span><del>-static const SpeculatedType SpecInteger            = 0x00e00000; // It's definitely some kind of integer.
</del><ins>+static const SpeculatedType SpecInteger            = 0x00f00000; // It's definitely some kind of integer.
</ins><span class="cx"> static const SpeculatedType SpecNonIntAsDouble     = 0x01000000; // It's definitely not an Int52 but it's a real number and it's a double.
</span><span class="cx"> static const SpeculatedType SpecDoubleReal         = 0x01800000; // It's definitely a non-NaN double.
</span><span class="cx"> static const SpeculatedType SpecDoublePureNaN      = 0x02000000; // It's definitely a NaN that is sae to tag (i.e. pure).
</span><span class="lines">@@ -75,10 +77,10 @@
</span><span class="cx"> static const SpeculatedType SpecDoubleNaN          = 0x06000000; // It's definitely some kind of NaN.
</span><span class="cx"> static const SpeculatedType SpecBytecodeDouble     = 0x03800000; // It's either a non-NaN or a NaN double, but it's definitely not impure NaN.
</span><span class="cx"> static const SpeculatedType SpecFullDouble         = 0x07800000; // It's either a non-NaN or a NaN double.
</span><del>-static const SpeculatedType SpecBytecodeRealNumber = 0x01a00000; // It's either an Int32 or a DoubleReal.
-static const SpeculatedType SpecFullRealNumber     = 0x01e00000; // It's either an Int32 or a DoubleReal, or a Int52.
-static const SpeculatedType SpecBytecodeNumber     = 0x03a00000; // It's either an Int32 or a Double, and the Double cannot be an impure NaN.
-static const SpeculatedType SpecFullNumber         = 0x07e00000; // It's either an Int32, Int52, or a Double, and the Double can be impure NaN.
</del><ins>+static const SpeculatedType SpecBytecodeRealNumber = 0x01b00000; // It's either an Int32 or a DoubleReal.
+static const SpeculatedType SpecFullRealNumber     = 0x01f00000; // It's either an Int32 or a DoubleReal, or a Int52.
+static const SpeculatedType SpecBytecodeNumber     = 0x03b00000; // It's either an Int32 or a Double, and the Double cannot be an impure NaN.
+static const SpeculatedType SpecFullNumber         = 0x07f00000; // It's either an Int32, Int52, or a Double, and the Double can be impure NaN.
</ins><span class="cx"> static const SpeculatedType SpecBoolean            = 0x10000000; // It's definitely a Boolean.
</span><span class="cx"> static const SpeculatedType SpecOther              = 0x20000000; // It's definitely either Null or Undefined.
</span><span class="cx"> static const SpeculatedType SpecMisc               = 0x30000000; // It's definitely either a boolean, Null, or Undefined.
</span><span class="lines">@@ -262,9 +264,14 @@
</span><span class="cx">     return !!value &amp;&amp; !(value &amp; ~(SpecString | SpecStringObject));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+inline bool isBoolInt32Speculation(SpeculatedType value)
+{
+    return value == SpecBoolInt32;
+}
+
</ins><span class="cx"> inline bool isInt32Speculation(SpeculatedType value)
</span><span class="cx"> {
</span><del>-    return value == SpecInt32;
</del><ins>+    return value &amp;&amp; !(value &amp; ~SpecInt32);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> inline bool isInt32OrBooleanSpeculation(SpeculatedType value)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h (184539 => 184540)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2015-05-19 02:02:10 UTC (rev 184539)
+++ trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2015-05-19 02:30:00 UTC (rev 184540)
</span><span class="lines">@@ -257,6 +257,14 @@
</span><span class="cx">             }
</span><span class="cx">             break;
</span><span class="cx">         }
</span><ins>+        
+        if (node-&gt;op() == BitAnd
+            &amp;&amp; (isBoolInt32Speculation(forNode(node-&gt;child1()).m_type) ||
+                isBoolInt32Speculation(forNode(node-&gt;child2()).m_type))) {
+            forNode(node).setType(SpecBoolInt32);
+            break;
+        }
+        
</ins><span class="cx">         forNode(node).setType(SpecInt32);
</span><span class="cx">         break;
</span><span class="cx">     }
</span><span class="lines">@@ -297,7 +305,7 @@
</span><span class="cx">         if (node-&gt;child1().useKind() == UntypedUse &amp;&amp; !(value.m_type &amp; ~SpecBoolean))
</span><span class="cx">             m_state.setFoundConstants(true);
</span><span class="cx">         if (value.m_type &amp; SpecBoolean) {
</span><del>-            value.merge(SpecInt32);
</del><ins>+            value.merge(SpecBoolInt32);
</ins><span class="cx">             value.filter(~SpecBoolean);
</span><span class="cx">         }
</span><span class="cx">         break;
</span><span class="lines">@@ -337,6 +345,11 @@
</span><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx">         
</span><ins>+        if (isBooleanSpeculation(forNode(node-&gt;child1()).m_type)) {
+            forNode(node).setType(SpecBoolInt32);
+            break;
+        }
+        
</ins><span class="cx">         forNode(node).setType(SpecInt32);
</span><span class="cx">         break;
</span><span class="cx">     }
</span></span></pre>
</div>
</div>

</body>
</html>