<!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>[184747] 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/184747">184747</a></dd>
<dt>Author</dt> <dd>saambarati1@gmail.com</dd>
<dt>Date</dt> <dd>2015-05-21 19:39:25 -0700 (Thu, 21 May 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>Object allocation sinking phase should explicitly create bottom values for CreateActivation sink candidates and CreateActivation should have SymbolTable as a child node
https://bugs.webkit.org/show_bug.cgi?id=145192

Reviewed by Filip Pizlo.

When we sink CreateActivation and generate MaterializeCreateActivation
in the object allocation sinking phase, we now explictly add PutHints for
all variables on the activation setting those variables to their default value
(undefined for Function activations and soon to be JS Empty Value for block scope activations).
This allows us to remove code that fills FTL fast activation allocations with Undefined.

This patch also adds the constant SymbolTable as an OpInfo of CreateActivation and MaterializeCreateActivation
nodes. This is in preparation for ES6 block scoping which will introduce a new
op code that gets lowered to CreateActivation.

* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
* dfg/DFGNode.h:
(JSC::DFG::Node::hasCellOperand):
(JSC::DFG::Node::cellOperand):
* dfg/DFGObjectAllocationSinkingPhase.cpp:
(JSC::DFG::ObjectAllocationSinkingPhase::lowerNonReadingOperationsOnPhantomAllocations):
(JSC::DFG::ObjectAllocationSinkingPhase::handleNode):
(JSC::DFG::ObjectAllocationSinkingPhase::createMaterialize):
(JSC::DFG::ObjectAllocationSinkingPhase::populateMaterialize):
* dfg/DFGPromotedHeapLocation.cpp:
(WTF::printInternal):
* dfg/DFGPromotedHeapLocation.h:
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileCreateActivation):
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::LowerDFGToLLVM::compileCreateActivation):
(JSC::FTL::LowerDFGToLLVM::compileMaterializeCreateActivation):
* ftl/FTLOperations.cpp:
(JSC::FTL::operationMaterializeObjectInOSR):
* tests/stress/activation-sink-default-value.js: Added.
(bar):
* tests/stress/activation-sink-osrexit-default-value.js: Added.
(foo.set result):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp">trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGClobberizeh">trunk/Source/JavaScriptCore/dfg/DFGClobberize.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGNodeh">trunk/Source/JavaScriptCore/dfg/DFGNode.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGObjectAllocationSinkingPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGPromotedHeapLocationcpp">trunk/Source/JavaScriptCore/dfg/DFGPromotedHeapLocation.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGPromotedHeapLocationh">trunk/Source/JavaScriptCore/dfg/DFGPromotedHeapLocation.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLLowerDFGToLLVMcpp">trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLOperationscpp">trunk/Source/JavaScriptCore/ftl/FTLOperations.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoretestsstressactivationsinkdefaultvaluejs">trunk/Source/JavaScriptCore/tests/stress/activation-sink-default-value.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressactivationsinkosrexitdefaultvaluejs">trunk/Source/JavaScriptCore/tests/stress/activation-sink-osrexit-default-value.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (184746 => 184747)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-05-22 01:22:19 UTC (rev 184746)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-05-22 02:39:25 UTC (rev 184747)
</span><span class="lines">@@ -1,3 +1,47 @@
</span><ins>+2015-05-21  Saam Barati  &lt;saambarati1@gmail.com&gt;
+
+        Object allocation sinking phase should explicitly create bottom values for CreateActivation sink candidates and CreateActivation should have SymbolTable as a child node
+        https://bugs.webkit.org/show_bug.cgi?id=145192
+
+        Reviewed by Filip Pizlo.
+
+        When we sink CreateActivation and generate MaterializeCreateActivation
+        in the object allocation sinking phase, we now explictly add PutHints for 
+        all variables on the activation setting those variables to their default value 
+        (undefined for Function activations and soon to be JS Empty Value for block scope activations). 
+        This allows us to remove code that fills FTL fast activation allocations with Undefined.
+
+        This patch also adds the constant SymbolTable as an OpInfo of CreateActivation and MaterializeCreateActivation
+        nodes. This is in preparation for ES6 block scoping which will introduce a new 
+        op code that gets lowered to CreateActivation.
+
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::parseBlock):
+        * dfg/DFGClobberize.h:
+        (JSC::DFG::clobberize):
+        * dfg/DFGNode.h:
+        (JSC::DFG::Node::hasCellOperand):
+        (JSC::DFG::Node::cellOperand):
+        * dfg/DFGObjectAllocationSinkingPhase.cpp:
+        (JSC::DFG::ObjectAllocationSinkingPhase::lowerNonReadingOperationsOnPhantomAllocations):
+        (JSC::DFG::ObjectAllocationSinkingPhase::handleNode):
+        (JSC::DFG::ObjectAllocationSinkingPhase::createMaterialize):
+        (JSC::DFG::ObjectAllocationSinkingPhase::populateMaterialize):
+        * dfg/DFGPromotedHeapLocation.cpp:
+        (WTF::printInternal):
+        * dfg/DFGPromotedHeapLocation.h:
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compileCreateActivation):
+        * ftl/FTLLowerDFGToLLVM.cpp:
+        (JSC::FTL::LowerDFGToLLVM::compileCreateActivation):
+        (JSC::FTL::LowerDFGToLLVM::compileMaterializeCreateActivation):
+        * ftl/FTLOperations.cpp:
+        (JSC::FTL::operationMaterializeObjectInOSR):
+        * tests/stress/activation-sink-default-value.js: Added.
+        (bar):
+        * tests/stress/activation-sink-osrexit-default-value.js: Added.
+        (foo.set result):
+
</ins><span class="cx"> 2015-05-21  Per Arne Vollan  &lt;peavo@outlook.com&gt;
</span><span class="cx"> 
</span><span class="cx">         MSVC internal compiler error when compiling TemplateRegistryKey class.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp (184746 => 184747)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2015-05-22 01:22:19 UTC (rev 184746)
+++ trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2015-05-22 02:39:25 UTC (rev 184747)
</span><span class="lines">@@ -3733,7 +3733,8 @@
</span><span class="cx">         }
</span><span class="cx">             
</span><span class="cx">         case op_create_lexical_environment: {
</span><del>-            Node* lexicalEnvironment = addToGraph(CreateActivation, get(VirtualRegister(currentInstruction[2].u.operand)));
</del><ins>+            FrozenValue* symbolTable = m_graph.freezeStrong(m_graph.symbolTableFor(currentNodeOrigin().semantic));
+            Node* lexicalEnvironment = addToGraph(CreateActivation, OpInfo(symbolTable), get(VirtualRegister(currentInstruction[2].u.operand)));
</ins><span class="cx">             set(VirtualRegister(currentInstruction[1].u.operand), lexicalEnvironment);
</span><span class="cx">             set(VirtualRegister(currentInstruction[2].u.operand), lexicalEnvironment);
</span><span class="cx">             NEXT_OPCODE(op_create_lexical_environment);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGClobberizeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGClobberize.h (184746 => 184747)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGClobberize.h        2015-05-22 01:22:19 UTC (rev 184746)
+++ trunk/Source/JavaScriptCore/dfg/DFGClobberize.h        2015-05-22 02:39:25 UTC (rev 184747)
</span><span class="lines">@@ -317,7 +317,7 @@
</span><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     case CreateActivation: {
</span><del>-        SymbolTable* table = graph.symbolTableFor(node-&gt;origin.semantic);
</del><ins>+        SymbolTable* table = node-&gt;castOperand&lt;SymbolTable*&gt;();
</ins><span class="cx">         if (table-&gt;singletonScope()-&gt;isStillValid())
</span><span class="cx">             write(Watchpoint_fire);
</span><span class="cx">         read(HeapObjectCount);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGNodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGNode.h (184746 => 184747)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNode.h        2015-05-22 01:22:19 UTC (rev 184746)
+++ trunk/Source/JavaScriptCore/dfg/DFGNode.h        2015-05-22 02:39:25 UTC (rev 184747)
</span><span class="lines">@@ -1282,6 +1282,8 @@
</span><span class="cx">         case NativeConstruct:
</span><span class="cx">         case NativeCall:
</span><span class="cx">         case NewFunction:
</span><ins>+        case CreateActivation:
+        case MaterializeCreateActivation:
</ins><span class="cx">             return true;
</span><span class="cx">         default:
</span><span class="cx">             return false;
</span><span class="lines">@@ -1291,7 +1293,13 @@
</span><span class="cx">     FrozenValue* cellOperand()
</span><span class="cx">     {
</span><span class="cx">         ASSERT(hasCellOperand());
</span><del>-        return reinterpret_cast&lt;FrozenValue*&gt;(m_opInfo);
</del><ins>+        switch (op()) {
+        case MaterializeCreateActivation:
+            return reinterpret_cast&lt;FrozenValue*&gt;(m_opInfo2);
+        default:
+            return reinterpret_cast&lt;FrozenValue*&gt;(m_opInfo);
+        }
+        RELEASE_ASSERT_NOT_REACHED();
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     template&lt;typename T&gt;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGObjectAllocationSinkingPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp (184746 => 184747)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp        2015-05-22 01:22:19 UTC (rev 184746)
+++ trunk/Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp        2015-05-22 02:39:25 UTC (rev 184747)
</span><span class="lines">@@ -586,6 +586,27 @@
</span><span class="cx">                             nodeIndex + 1,
</span><span class="cx">                             PromotedHeapLocation(ActivationScopePLoc, node).createHint(
</span><span class="cx">                                 m_graph, node-&gt;origin, node-&gt;child1().node()));
</span><ins>+                        Node* symbolTableNode = m_insertionSet.insertConstant(
+                            nodeIndex + 1, node-&gt;origin, node-&gt;cellOperand());
+                        m_insertionSet.insert(
+                            nodeIndex + 1,
+                            PromotedHeapLocation(ActivationSymbolTablePLoc, node).createHint(
+                                m_graph, node-&gt;origin, symbolTableNode));
+
+                        {
+                            SymbolTable* symbolTable = node-&gt;castOperand&lt;SymbolTable*&gt;();
+                            Node* undefined = m_insertionSet.insertConstant(
+                                nodeIndex + 1, node-&gt;origin, jsUndefined());
+                            ConcurrentJITLocker locker(symbolTable-&gt;m_lock);
+                            for (auto iter = symbolTable-&gt;begin(locker), end = symbolTable-&gt;end(locker); iter != end; ++iter) {
+                                m_insertionSet.insert(
+                                    nodeIndex + 1,
+                                    PromotedHeapLocation(
+                                        ClosureVarPLoc, node, iter-&gt;value.scopeOffset().offset()).createHint(
+                                        m_graph, node-&gt;origin, undefined));
+                            }
+                        }
+
</ins><span class="cx">                         node-&gt;convertToPhantomCreateActivation();
</span><span class="cx">                     }
</span><span class="cx">                     break;
</span><span class="lines">@@ -597,6 +618,12 @@
</span><span class="cx">                             nodeIndex + 1,
</span><span class="cx">                             PromotedHeapLocation(ActivationScopePLoc, node).createHint(
</span><span class="cx">                                 m_graph, node-&gt;origin, m_graph.varArgChild(node, 0).node()));
</span><ins>+                        Node* symbolTableNode = m_insertionSet.insertConstant(
+                            nodeIndex + 1, node-&gt;origin, node-&gt;cellOperand());
+                        m_insertionSet.insert(
+                            nodeIndex + 1,
+                            PromotedHeapLocation(ActivationSymbolTablePLoc, node).createHint(
+                                m_graph, node-&gt;origin, symbolTableNode));
</ins><span class="cx">                         ObjectMaterializationData&amp; data = node-&gt;objectMaterializationData();
</span><span class="cx">                         for (unsigned i = 0; i &lt; data.m_properties.size(); ++i) {
</span><span class="cx">                             unsigned identifierNumber = data.m_properties[i].m_identifierNumber;
</span><span class="lines">@@ -829,7 +856,7 @@
</span><span class="cx">             break;
</span><span class="cx"> 
</span><span class="cx">         case CreateActivation:
</span><del>-            if (!m_graph.symbolTableFor(node-&gt;origin.semantic)-&gt;singletonScope()-&gt;isStillValid())
</del><ins>+            if (!node-&gt;castOperand&lt;SymbolTable*&gt;()-&gt;singletonScope()-&gt;isStillValid())
</ins><span class="cx">                 sinkCandidate();
</span><span class="cx">             escape(node-&gt;child1().node());
</span><span class="cx">             break;
</span><span class="lines">@@ -932,13 +959,13 @@
</span><span class="cx">         case CreateActivation:
</span><span class="cx">         case MaterializeCreateActivation: {
</span><span class="cx">             ObjectMaterializationData* data = m_graph.m_objectMaterializationData.add();
</span><del>-
</del><ins>+            FrozenValue* symbolTable = escapee-&gt;cellOperand();
</ins><span class="cx">             result = m_graph.addNode(
</span><span class="cx">                 escapee-&gt;prediction(), Node::VarArg, MaterializeCreateActivation,
</span><span class="cx">                 NodeOrigin(
</span><span class="cx">                     escapee-&gt;origin.semantic,
</span><span class="cx">                     where-&gt;origin.forExit),
</span><del>-                OpInfo(data), OpInfo(), 0, 0);
</del><ins>+                OpInfo(data), OpInfo(symbolTable), 0, 0);
</ins><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="lines">@@ -1009,6 +1036,7 @@
</span><span class="cx">             Vector&lt;PromotedHeapLocation&gt; locations = m_locationsForAllocation.get(escapee);
</span><span class="cx"> 
</span><span class="cx">             PromotedHeapLocation scope(ActivationScopePLoc, escapee);
</span><ins>+            PromotedHeapLocation symbolTable(ActivationSymbolTablePLoc, escapee);
</ins><span class="cx">             ASSERT(locations.contains(scope));
</span><span class="cx"> 
</span><span class="cx">             m_graph.m_varArgChildren.append(Edge(resolve(block, scope), KnownCellUse));
</span><span class="lines">@@ -1020,6 +1048,11 @@
</span><span class="cx">                     break;
</span><span class="cx">                 }
</span><span class="cx"> 
</span><ins>+                case ActivationSymbolTablePLoc: {
+                    ASSERT(locations[i] == symbolTable);
+                    break;
+                }
+
</ins><span class="cx">                 case ClosureVarPLoc: {
</span><span class="cx">                     Node* value = resolve(block, locations[i]);
</span><span class="cx">                     if (value-&gt;op() == BottomValue)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGPromotedHeapLocationcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGPromotedHeapLocation.cpp (184746 => 184747)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGPromotedHeapLocation.cpp        2015-05-22 01:22:19 UTC (rev 184746)
+++ trunk/Source/JavaScriptCore/dfg/DFGPromotedHeapLocation.cpp        2015-05-22 02:39:25 UTC (rev 184747)
</span><span class="lines">@@ -66,6 +66,10 @@
</span><span class="cx">     case StructurePLoc:
</span><span class="cx">         out.print(&quot;StructurePLoc&quot;);
</span><span class="cx">         return;
</span><ins>+
+    case ActivationSymbolTablePLoc:
+        out.print(&quot;ActivationSymbolTablePLoc&quot;);
+        return;
</ins><span class="cx">         
</span><span class="cx">     case NamedPropertyPLoc:
</span><span class="cx">         out.print(&quot;NamedPropertyPLoc&quot;);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGPromotedHeapLocationh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGPromotedHeapLocation.h (184746 => 184747)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGPromotedHeapLocation.h        2015-05-22 01:22:19 UTC (rev 184746)
+++ trunk/Source/JavaScriptCore/dfg/DFGPromotedHeapLocation.h        2015-05-22 02:39:25 UTC (rev 184747)
</span><span class="lines">@@ -37,6 +37,7 @@
</span><span class="cx">     InvalidPromotedLocationKind,
</span><span class="cx">     
</span><span class="cx">     StructurePLoc,
</span><ins>+    ActivationSymbolTablePLoc,
</ins><span class="cx">     NamedPropertyPLoc,
</span><span class="cx">     ArgumentPLoc,
</span><span class="cx">     ArgumentCountPLoc,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp (184746 => 184747)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2015-05-22 01:22:19 UTC (rev 184746)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2015-05-22 02:39:25 UTC (rev 184747)
</span><span class="lines">@@ -4521,7 +4521,7 @@
</span><span class="cx"> 
</span><span class="cx"> void SpeculativeJIT::compileCreateActivation(Node* node)
</span><span class="cx"> {
</span><del>-    SymbolTable* table = m_jit.graph().symbolTableFor(node-&gt;origin.semantic);
</del><ins>+    SymbolTable* table = node-&gt;castOperand&lt;SymbolTable*&gt;();
</ins><span class="cx">     Structure* structure = m_jit.graph().globalObjectFor(
</span><span class="cx">         node-&gt;origin.semantic)-&gt;activationStructure();
</span><span class="cx">         
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLLowerDFGToLLVMcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp (184746 => 184747)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2015-05-22 01:22:19 UTC (rev 184746)
+++ trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2015-05-22 02:39:25 UTC (rev 184747)
</span><span class="lines">@@ -2947,7 +2947,7 @@
</span><span class="cx">     void compileCreateActivation()
</span><span class="cx">     {
</span><span class="cx">         LValue scope = lowCell(m_node-&gt;child1());
</span><del>-        SymbolTable* table = m_graph.symbolTableFor(m_node-&gt;origin.semantic);
</del><ins>+        SymbolTable* table = m_node-&gt;castOperand&lt;SymbolTable*&gt;();
</ins><span class="cx">         Structure* structure = m_graph.globalObjectFor(m_node-&gt;origin.semantic)-&gt;activationStructure();
</span><span class="cx">         
</span><span class="cx">         if (table-&gt;singletonScope()-&gt;isStillValid()) {
</span><span class="lines">@@ -5264,7 +5264,7 @@
</span><span class="cx">             values.append(lowJSValue(m_graph.varArgChild(m_node, 1 + i)));
</span><span class="cx"> 
</span><span class="cx">         LValue scope = lowCell(m_graph.varArgChild(m_node, 0));
</span><del>-        SymbolTable* table = m_graph.symbolTableFor(m_node-&gt;origin.semantic);
</del><ins>+        SymbolTable* table = m_node-&gt;castOperand&lt;SymbolTable*&gt;();
</ins><span class="cx">         Structure* structure = m_graph.globalObjectFor(m_node-&gt;origin.semantic)-&gt;activationStructure();
</span><span class="cx"> 
</span><span class="cx">         LBasicBlock slowPath = FTL_NEW_BLOCK(m_out, (&quot;MaterializeCreateActivation slow path&quot;));
</span><span class="lines">@@ -5278,11 +5278,6 @@
</span><span class="cx">         m_out.storePtr(scope, fastObject, m_heaps.JSScope_next);
</span><span class="cx">         m_out.storePtr(weakPointer(table), fastObject, m_heaps.JSSymbolTableObject_symbolTable);
</span><span class="cx"> 
</span><del>-        for (unsigned i = 0; i &lt; table-&gt;scopeSize(); ++i) {
-            m_out.store64(
-                m_out.constInt64(JSValue::encode(jsUndefined())),
-                fastObject, m_heaps.JSEnvironmentRecord_variables[i]);
-        }
</del><span class="cx"> 
</span><span class="cx">         ValueFromBlock fastResult = m_out.anchor(fastObject);
</span><span class="cx">         m_out.jump(continuation);
</span><span class="lines">@@ -5296,11 +5291,28 @@
</span><span class="cx"> 
</span><span class="cx">         m_out.appendTo(continuation, lastNext);
</span><span class="cx">         LValue activation = m_out.phi(m_out.intPtr, fastResult, slowResult);
</span><ins>+        RELEASE_ASSERT(data.m_properties.size() == table-&gt;scopeSize());
</ins><span class="cx">         for (unsigned i = 0; i &lt; data.m_properties.size(); ++i) {
</span><span class="cx">             m_out.store64(values[i],
</span><span class="cx">                 activation,
</span><span class="cx">                 m_heaps.JSEnvironmentRecord_variables[data.m_properties[i].m_identifierNumber]);
</span><span class="cx">         }
</span><ins>+
+        if (validationEnabled()) {
+            // Validate to make sure every slot in the scope has one value.
+            ConcurrentJITLocker locker(table-&gt;m_lock);
+            for (auto iter = table-&gt;begin(locker), end = table-&gt;end(locker); iter != end; ++iter) {
+                bool found = false;
+                for (unsigned i = 0; i &lt; data.m_properties.size(); ++i) {
+                    if (iter-&gt;value.scopeOffset().offset() == data.m_properties[i].m_identifierNumber) {
+                        found = true;
+                        break;
+                    }
+                }
+                ASSERT(found);
+            }
+        }
+
</ins><span class="cx">         setJSValue(activation);
</span><span class="cx">     }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLOperationscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLOperations.cpp (184746 => 184747)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLOperations.cpp        2015-05-22 01:22:19 UTC (rev 184746)
+++ trunk/Source/JavaScriptCore/ftl/FTLOperations.cpp        2015-05-22 02:39:25 UTC (rev 184747)
</span><span class="lines">@@ -115,21 +115,24 @@
</span><span class="cx">     case PhantomCreateActivation: {
</span><span class="cx">         // Figure out where the scope is
</span><span class="cx">         JSScope* scope = nullptr;
</span><ins>+        SymbolTable* table = nullptr;
</ins><span class="cx">         for (unsigned i = materialization-&gt;properties().size(); i--;) {
</span><span class="cx">             const ExitPropertyValue&amp; property = materialization-&gt;properties()[i];
</span><del>-            if (property.location() != PromotedLocationDescriptor(ActivationScopePLoc))
-                continue;
-            scope = jsCast&lt;JSScope*&gt;(JSValue::decode(values[i]));
</del><ins>+            if (property.location() == PromotedLocationDescriptor(ActivationScopePLoc))
+                scope = jsCast&lt;JSScope*&gt;(JSValue::decode(values[i]));
+            else if (property.location() == PromotedLocationDescriptor(ActivationSymbolTablePLoc))
+                table = jsCast&lt;SymbolTable*&gt;(JSValue::decode(values[i]));
</ins><span class="cx">         }
</span><span class="cx">         RELEASE_ASSERT(scope);
</span><ins>+        RELEASE_ASSERT(table);
</ins><span class="cx"> 
</span><span class="cx">         CodeBlock* codeBlock = baselineCodeBlockForOriginAndBaselineCodeBlock(
</span><span class="cx">             materialization-&gt;origin(), exec-&gt;codeBlock());
</span><del>-        SymbolTable* table = codeBlock-&gt;symbolTable();
</del><span class="cx">         Structure* structure = codeBlock-&gt;globalObject()-&gt;activationStructure();
</span><span class="cx"> 
</span><span class="cx">         JSLexicalEnvironment* result = JSLexicalEnvironment::create(vm, structure, scope, table);
</span><span class="cx"> 
</span><ins>+        RELEASE_ASSERT(materialization-&gt;properties().size() - 2 == table-&gt;scopeSize());
</ins><span class="cx">         // Figure out what to populate the activation with
</span><span class="cx">         for (unsigned i = materialization-&gt;properties().size(); i--;) {
</span><span class="cx">             const ExitPropertyValue&amp; property = materialization-&gt;properties()[i];
</span><span class="lines">@@ -139,6 +142,31 @@
</span><span class="cx">             result-&gt;variableAt(ScopeOffset(property.location().info())).set(exec-&gt;vm(), result, JSValue::decode(values[i]));
</span><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        if (validationEnabled()) {
+            // Validate to make sure every slot in the scope has one value.
+            ConcurrentJITLocker locker(table-&gt;m_lock);
+            for (auto iter = table-&gt;begin(locker), end = table-&gt;end(locker); iter != end; ++iter) {
+                bool found = false;
+                for (unsigned i = materialization-&gt;properties().size(); i--;) {
+                    const ExitPropertyValue&amp; property = materialization-&gt;properties()[i];
+                    if (property.location().kind() != ClosureVarPLoc)
+                        continue;
+                    if (ScopeOffset(property.location().info()) == iter-&gt;value.scopeOffset()) {
+                        found = true;
+                        break;
+                    }
+                }
+                ASSERT(found);
+            }
+            unsigned numberOfClosureVarPloc = 0;
+            for (unsigned i = materialization-&gt;properties().size(); i--;) {
+                const ExitPropertyValue&amp; property = materialization-&gt;properties()[i];
+                if (property.location().kind() == ClosureVarPLoc)
+                    numberOfClosureVarPloc++;
+            }
+            ASSERT(numberOfClosureVarPloc == table-&gt;scopeSize());
+        }
+
</ins><span class="cx">         return result;
</span><span class="cx">     }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressactivationsinkdefaultvaluejs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/activation-sink-default-value.js (0 => 184747)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/activation-sink-default-value.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/activation-sink-default-value.js        2015-05-22 02:39:25 UTC (rev 184747)
</span><span class="lines">@@ -0,0 +1,31 @@
</span><ins>+var n = 10000000;
+
+function bar(f) { f(10); }
+
+function foo(b) {
+    var result = 0;
+    var imUndefined;
+    var baz;
+    var set = function (x) { result = x; return (imUndefined, baz); }
+    baz = 40;
+    if (b) {
+        bar(set);
+        if (result != 10)
+            throw &quot;Error: bad: &quot; + result;
+        if (baz !== 40)
+            throw &quot;Error: bad: &quot; + baz;
+        if (imUndefined !== void 0)
+            throw &quot;Error: bad value: &quot; + imUndefined;
+        return 0;
+    }
+    return result;
+}
+
+noInline(bar);
+noInline(foo);
+
+for (var i = 0; i &lt; n; i++) {
+    var result = foo(!(i % 100));
+    if (result != 0)
+        throw &quot;Error: bad result: &quot; + result;
+}
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressactivationsinkosrexitdefaultvaluejs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/activation-sink-osrexit-default-value.js (0 => 184747)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/activation-sink-osrexit-default-value.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/activation-sink-osrexit-default-value.js        2015-05-22 02:39:25 UTC (rev 184747)
</span><span class="lines">@@ -0,0 +1,37 @@
</span><ins>+var n = 10000000;
+
+function bar(set) { 
+    var result = set(0);
+    if (result !== void 0)
+        throw &quot;Error: bad value: &quot; + result;
+}
+
+function foo(b) {
+    var result = 0;
+    var imUndefined;
+    var baz;
+    var set = function (x) { 
+        result = x; 
+        if (baz !== 50)
+            throw &quot;Error: bad value: &quot; + baz;
+        return imUndefined;
+    }
+    baz = 50;
+    if (b) {
+        OSRExit();
+        if (b) {
+            bar(set);
+        }
+        return 0;
+    }
+    return result;
+}
+
+noInline(bar);
+noInline(foo);
+
+for (var i = 0; i &lt; n; i++) {
+    var result = foo(!(i % 100));
+    if (result != 0)
+        throw &quot;Error: bad result: &quot; + result;
+}
</ins></span></pre>
</div>
</div>

</body>
</html>