<!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>[184415] 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/184415">184415</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2015-05-15 14:11:39 -0700 (Fri, 15 May 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>Insert store barriers late so that IR transformations don't have to worry about them
https://bugs.webkit.org/show_bug.cgi?id=145015

Reviewed by Geoffrey Garen.
        
We have had three kinds of bugs with store barriers. For the sake of discussion we say
that a store barrier is needed when we have something like:
        
    base.field = value
        
- We sometimes fail to realize that we could remove a barrier when value is a non-cell.
  This might happen if we prove value to be a non-cell even though in the FixupPhase it
  wasn't predicted non-cell.
        
- We sometimes have a barrier in the wrong place after object allocation sinking. We
  might sink an allocation to just above the store, but that puts it just after the
  StoreBarrier that FixupPhase inserted.
        
- We don't remove redundant barriers across basic blocks.
        
This comprehensively fixes these issues by doing store barrier insertion late, and
removing the store barrier elision phase. Store barrier insertion uses an epoch-based
algorithm to determine when stores need barriers. Briefly, a barrier is not needed if
base is in the current GC epoch (i.e. was the last object that we allocated or had a
barrier since last GC) or if base has a newer GC epoch than value (i.e. value would have
always been allocated before base). We do conservative things when merging epoch state
between basic blocks, and we only do such inter-block removal in the FTL. FTL also
queries AI to determine what type we've proved about value, and avoids barriers when
value is not a cell. FixupPhase still inserts type checks on some stores, to maximize
the likelihood that this AI-based removal is effective.

* CMakeLists.txt:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
* JavaScriptCore.xcodeproj/project.pbxproj:
* dfg/DFGBlockMap.h:
(JSC::DFG::BlockMap::at):
* dfg/DFGConstantFoldingPhase.cpp:
(JSC::DFG::ConstantFoldingPhase::emitPutByOffset):
* dfg/DFGEpoch.h:
(JSC::DFG::Epoch::operator&lt;):
(JSC::DFG::Epoch::operator&gt;):
(JSC::DFG::Epoch::operator&lt;=):
(JSC::DFG::Epoch::operator&gt;=):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
(JSC::DFG::FixupPhase::speculateForBarrier):
(JSC::DFG::FixupPhase::insertStoreBarrier): Deleted.
* dfg/DFGPlan.cpp:
(JSC::DFG::Plan::compileInThreadImpl):
* dfg/DFGStoreBarrierElisionPhase.cpp: Removed.
* dfg/DFGStoreBarrierElisionPhase.h: Removed.
* dfg/DFGStoreBarrierInsertionPhase.cpp: Added.
(JSC::DFG::performFastStoreBarrierInsertion):
(JSC::DFG::performGlobalStoreBarrierInsertion):
* dfg/DFGStoreBarrierInsertionPhase.h: Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreCMakeListstxt">trunk/Source/JavaScriptCore/CMakeLists.txt</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreJavaScriptCorevcxprojJavaScriptCorevcxproj">trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj</a></li>
<li><a href="#trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj">trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGBlockMaph">trunk/Source/JavaScriptCore/dfg/DFGBlockMap.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGConstantFoldingPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGEpochh">trunk/Source/JavaScriptCore/dfg/DFGEpoch.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGFixupPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGObjectAllocationSinkingPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGPlancpp">trunk/Source/JavaScriptCore/dfg/DFGPlan.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGPredictionPropagationPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoredfgDFGStoreBarrierInsertionPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGStoreBarrierInsertionPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGStoreBarrierInsertionPhaseh">trunk/Source/JavaScriptCore/dfg/DFGStoreBarrierInsertionPhase.h</a></li>
</ul>

<h3>Removed Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoredfgDFGStoreBarrierElisionPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGStoreBarrierElisionPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGStoreBarrierElisionPhaseh">trunk/Source/JavaScriptCore/dfg/DFGStoreBarrierElisionPhase.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreCMakeListstxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/CMakeLists.txt (184414 => 184415)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/CMakeLists.txt        2015-05-15 21:10:11 UTC (rev 184414)
+++ trunk/Source/JavaScriptCore/CMakeLists.txt        2015-05-15 21:11:39 UTC (rev 184415)
</span><span class="lines">@@ -227,7 +227,7 @@
</span><span class="cx">     dfg/DFGSpeculativeJIT64.cpp
</span><span class="cx">     dfg/DFGStackLayoutPhase.cpp
</span><span class="cx">     dfg/DFGStaticExecutionCountEstimationPhase.cpp
</span><del>-    dfg/DFGStoreBarrierElisionPhase.cpp
</del><ins>+    dfg/DFGStoreBarrierInsertionPhase.cpp
</ins><span class="cx">     dfg/DFGStrengthReductionPhase.cpp
</span><span class="cx">     dfg/DFGStructureAbstractValue.cpp
</span><span class="cx">     dfg/DFGStructureRegistrationPhase.cpp
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (184414 => 184415)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-05-15 21:10:11 UTC (rev 184414)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-05-15 21:11:39 UTC (rev 184415)
</span><span class="lines">@@ -1,3 +1,61 @@
</span><ins>+2015-05-14  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        Insert store barriers late so that IR transformations don't have to worry about them
+        https://bugs.webkit.org/show_bug.cgi?id=145015
+
+        Reviewed by Geoffrey Garen.
+        
+        We have had three kinds of bugs with store barriers. For the sake of discussion we say
+        that a store barrier is needed when we have something like:
+        
+            base.field = value
+        
+        - We sometimes fail to realize that we could remove a barrier when value is a non-cell.
+          This might happen if we prove value to be a non-cell even though in the FixupPhase it
+          wasn't predicted non-cell.
+        
+        - We sometimes have a barrier in the wrong place after object allocation sinking. We
+          might sink an allocation to just above the store, but that puts it just after the
+          StoreBarrier that FixupPhase inserted.
+        
+        - We don't remove redundant barriers across basic blocks.
+        
+        This comprehensively fixes these issues by doing store barrier insertion late, and
+        removing the store barrier elision phase. Store barrier insertion uses an epoch-based
+        algorithm to determine when stores need barriers. Briefly, a barrier is not needed if
+        base is in the current GC epoch (i.e. was the last object that we allocated or had a
+        barrier since last GC) or if base has a newer GC epoch than value (i.e. value would have
+        always been allocated before base). We do conservative things when merging epoch state
+        between basic blocks, and we only do such inter-block removal in the FTL. FTL also
+        queries AI to determine what type we've proved about value, and avoids barriers when
+        value is not a cell. FixupPhase still inserts type checks on some stores, to maximize
+        the likelihood that this AI-based removal is effective.
+
+        * CMakeLists.txt:
+        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * dfg/DFGBlockMap.h:
+        (JSC::DFG::BlockMap::at):
+        * dfg/DFGConstantFoldingPhase.cpp:
+        (JSC::DFG::ConstantFoldingPhase::emitPutByOffset):
+        * dfg/DFGEpoch.h:
+        (JSC::DFG::Epoch::operator&lt;):
+        (JSC::DFG::Epoch::operator&gt;):
+        (JSC::DFG::Epoch::operator&lt;=):
+        (JSC::DFG::Epoch::operator&gt;=):
+        * dfg/DFGFixupPhase.cpp:
+        (JSC::DFG::FixupPhase::fixupNode):
+        (JSC::DFG::FixupPhase::speculateForBarrier):
+        (JSC::DFG::FixupPhase::insertStoreBarrier): Deleted.
+        * dfg/DFGPlan.cpp:
+        (JSC::DFG::Plan::compileInThreadImpl):
+        * dfg/DFGStoreBarrierElisionPhase.cpp: Removed.
+        * dfg/DFGStoreBarrierElisionPhase.h: Removed.
+        * dfg/DFGStoreBarrierInsertionPhase.cpp: Added.
+        (JSC::DFG::performFastStoreBarrierInsertion):
+        (JSC::DFG::performGlobalStoreBarrierInsertion):
+        * dfg/DFGStoreBarrierInsertionPhase.h: Added.
+
</ins><span class="cx"> 2015-05-15  Benjamin Poulain  &lt;bpoulain@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [ARM64] Do not fail branchConvertDoubleToInt32 when the result is zero and not negative zero
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorevcxprojJavaScriptCorevcxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj (184414 => 184415)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj        2015-05-15 21:10:11 UTC (rev 184414)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj        2015-05-15 21:11:39 UTC (rev 184415)
</span><span class="lines">@@ -467,7 +467,7 @@
</span><span class="cx">     &lt;ClCompile Include=&quot;..\dfg\DFGSSALoweringPhase.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\dfg\DFGStackLayoutPhase.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\dfg\DFGStaticExecutionCountEstimationPhase.cpp&quot; /&gt;
</span><del>-    &lt;ClCompile Include=&quot;..\dfg\DFGStoreBarrierElisionPhase.cpp&quot; /&gt;
</del><ins>+    &lt;ClCompile Include=&quot;..\dfg\DFGStoreBarrierInsertionPhase.cpp&quot; /&gt;
</ins><span class="cx">     &lt;ClCompile Include=&quot;..\dfg\DFGStrengthReductionPhase.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\dfg\DFGStructureAbstractValue.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\dfg\DFGStructureRegistrationPhase.cpp&quot; /&gt;
</span><span class="lines">@@ -1173,7 +1173,7 @@
</span><span class="cx">     &lt;ClInclude Include=&quot;..\dfg\DFGSSALoweringPhase.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\dfg\DFGStackLayoutPhase.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\dfg\DFGStaticExecutionCountEstimationPhase.h&quot; /&gt;
</span><del>-    &lt;ClInclude Include=&quot;..\dfg\DFGStoreBarrierElisionPhase.h&quot; /&gt;
</del><ins>+    &lt;ClInclude Include=&quot;..\dfg\DFGStoreBarrierInsertionPhase.h&quot; /&gt;
</ins><span class="cx">     &lt;ClInclude Include=&quot;..\dfg\DFGStrengthReductionPhase.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\dfg\DFGStructureAbstractValue.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\dfg\DFGStructureClobberState.h&quot; /&gt;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (184414 => 184415)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2015-05-15 21:10:11 UTC (rev 184414)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2015-05-15 21:11:39 UTC (rev 184415)
</span><span class="lines">@@ -462,6 +462,8 @@
</span><span class="cx">                 0F9D339B1803ADB70073C2BC /* FTLStackMaps.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F9D33991803ADB70073C2BC /* FTLStackMaps.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0F9D36941AE9CC33000D4DFB /* DFGCleanUpPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F9D36921AE9CC33000D4DFB /* DFGCleanUpPhase.cpp */; };
</span><span class="cx">                 0F9D36951AE9CC33000D4DFB /* DFGCleanUpPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F9D36931AE9CC33000D4DFB /* DFGCleanUpPhase.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><ins>+                0F9E32631B05AB0400801ED5 /* DFGStoreBarrierInsertionPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F9E32611B05AB0400801ED5 /* DFGStoreBarrierInsertionPhase.cpp */; };
+                0F9E32641B05AB0400801ED5 /* DFGStoreBarrierInsertionPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F9E32621B05AB0400801ED5 /* DFGStoreBarrierInsertionPhase.h */; settings = {ATTRIBUTES = (Private, ); }; };
</ins><span class="cx">                 0F9FB4F417FCB91700CB67F8 /* DFGStackLayoutPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F9FB4F217FCB91700CB67F8 /* DFGStackLayoutPhase.cpp */; };
</span><span class="cx">                 0F9FB4F517FCB91700CB67F8 /* DFGStackLayoutPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F9FB4F317FCB91700CB67F8 /* DFGStackLayoutPhase.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0F9FC8C314E1B5FE00D52AE0 /* PolymorphicPutByIdList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F9FC8BF14E1B5FB00D52AE0 /* PolymorphicPutByIdList.cpp */; };
</span><span class="lines">@@ -928,8 +930,6 @@
</span><span class="cx">                 2AAD964A18569417001F93BE /* RecursiveAllocationScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 2AAD964918569417001F93BE /* RecursiveAllocationScope.h */; };
</span><span class="cx">                 2AC922BB18A16182003CE0FB /* FTLDWARFDebugLineInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2AC922B918A16182003CE0FB /* FTLDWARFDebugLineInfo.cpp */; };
</span><span class="cx">                 2AC922BC18A16182003CE0FB /* FTLDWARFDebugLineInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 2AC922BA18A16182003CE0FB /* FTLDWARFDebugLineInfo.h */; };
</span><del>-                2ACCF3DE185FE26B0083E2AD /* DFGStoreBarrierElisionPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACCF3DC185FE26B0083E2AD /* DFGStoreBarrierElisionPhase.cpp */; };
-                2ACCF3DF185FE26B0083E2AD /* DFGStoreBarrierElisionPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACCF3DD185FE26B0083E2AD /* DFGStoreBarrierElisionPhase.h */; };
</del><span class="cx">                 2AD2EDFB19799E38004D6478 /* EnumerationMode.h in Headers */ = {isa = PBXBuildFile; fileRef = 2AD2EDFA19799E38004D6478 /* EnumerationMode.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 2AD8932B17E3868F00668276 /* HeapIterationScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 2AD8932917E3868F00668276 /* HeapIterationScope.h */; };
</span><span class="cx">                 2ADFA26318EF3540004F9FCC /* GCLogging.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ADFA26218EF3540004F9FCC /* GCLogging.cpp */; };
</span><span class="lines">@@ -2201,6 +2201,8 @@
</span><span class="cx">                 0F9D33991803ADB70073C2BC /* FTLStackMaps.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FTLStackMaps.h; path = ftl/FTLStackMaps.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F9D36921AE9CC33000D4DFB /* DFGCleanUpPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGCleanUpPhase.cpp; path = dfg/DFGCleanUpPhase.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F9D36931AE9CC33000D4DFB /* DFGCleanUpPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGCleanUpPhase.h; path = dfg/DFGCleanUpPhase.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                0F9E32611B05AB0400801ED5 /* DFGStoreBarrierInsertionPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGStoreBarrierInsertionPhase.cpp; path = dfg/DFGStoreBarrierInsertionPhase.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F9E32621B05AB0400801ED5 /* DFGStoreBarrierInsertionPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGStoreBarrierInsertionPhase.h; path = dfg/DFGStoreBarrierInsertionPhase.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 0F9FB4F217FCB91700CB67F8 /* DFGStackLayoutPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGStackLayoutPhase.cpp; path = dfg/DFGStackLayoutPhase.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F9FB4F317FCB91700CB67F8 /* DFGStackLayoutPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGStackLayoutPhase.h; path = dfg/DFGStackLayoutPhase.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F9FC8BF14E1B5FB00D52AE0 /* PolymorphicPutByIdList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PolymorphicPutByIdList.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -2637,8 +2639,6 @@
</span><span class="cx">                 2AAD964918569417001F93BE /* RecursiveAllocationScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RecursiveAllocationScope.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 2AC922B918A16182003CE0FB /* FTLDWARFDebugLineInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FTLDWARFDebugLineInfo.cpp; path = ftl/FTLDWARFDebugLineInfo.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 2AC922BA18A16182003CE0FB /* FTLDWARFDebugLineInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FTLDWARFDebugLineInfo.h; path = ftl/FTLDWARFDebugLineInfo.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><del>-                2ACCF3DC185FE26B0083E2AD /* DFGStoreBarrierElisionPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGStoreBarrierElisionPhase.cpp; path = dfg/DFGStoreBarrierElisionPhase.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
-                2ACCF3DD185FE26B0083E2AD /* DFGStoreBarrierElisionPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGStoreBarrierElisionPhase.h; path = dfg/DFGStoreBarrierElisionPhase.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</del><span class="cx">                 2AD2EDFA19799E38004D6478 /* EnumerationMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EnumerationMode.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 2AD8932917E3868F00668276 /* HeapIterationScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HeapIterationScope.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 2ADFA26218EF3540004F9FCC /* GCLogging.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GCLogging.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -5089,8 +5089,8 @@
</span><span class="cx">                                 0F9FB4F317FCB91700CB67F8 /* DFGStackLayoutPhase.h */,
</span><span class="cx">                                 0F4F29DD18B6AD1C0057BC15 /* DFGStaticExecutionCountEstimationPhase.cpp */,
</span><span class="cx">                                 0F4F29DE18B6AD1C0057BC15 /* DFGStaticExecutionCountEstimationPhase.h */,
</span><del>-                                2ACCF3DC185FE26B0083E2AD /* DFGStoreBarrierElisionPhase.cpp */,
-                                2ACCF3DD185FE26B0083E2AD /* DFGStoreBarrierElisionPhase.h */,
</del><ins>+                                0F9E32611B05AB0400801ED5 /* DFGStoreBarrierInsertionPhase.cpp */,
+                                0F9E32621B05AB0400801ED5 /* DFGStoreBarrierInsertionPhase.h */,
</ins><span class="cx">                                 0FC20CB31852E2C600C9E954 /* DFGStrengthReductionPhase.cpp */,
</span><span class="cx">                                 0FC20CB41852E2C600C9E954 /* DFGStrengthReductionPhase.h */,
</span><span class="cx">                                 0F893BDA1936E23C001211F4 /* DFGStructureAbstractValue.cpp */,
</span><span class="lines">@@ -5894,8 +5894,8 @@
</span><span class="cx">                                 A7D89D0017A0B8CC00773AD8 /* DFGSSAConversionPhase.h in Headers */,
</span><span class="cx">                                 0FC20CBA18556A3500C9E954 /* DFGSSALoweringPhase.h in Headers */,
</span><span class="cx">                                 0F9FB4F517FCB91700CB67F8 /* DFGStackLayoutPhase.h in Headers */,
</span><ins>+                                0F9E32641B05AB0400801ED5 /* DFGStoreBarrierInsertionPhase.h in Headers */,
</ins><span class="cx">                                 0F4F29E018B6AD1C0057BC15 /* DFGStaticExecutionCountEstimationPhase.h in Headers */,
</span><del>-                                2ACCF3DF185FE26B0083E2AD /* DFGStoreBarrierElisionPhase.h in Headers */,
</del><span class="cx">                                 0FC20CB61852E2C600C9E954 /* DFGStrengthReductionPhase.h in Headers */,
</span><span class="cx">                                 0F63947815DCE34B006A597C /* DFGStructureAbstractValue.h in Headers */,
</span><span class="cx">                                 0F2FCCFF18A60070001A27F8 /* DFGThreadData.h in Headers */,
</span><span class="lines">@@ -7181,7 +7181,6 @@
</span><span class="cx">                                 0F9FB4F417FCB91700CB67F8 /* DFGStackLayoutPhase.cpp in Sources */,
</span><span class="cx">                                 0F4F29DF18B6AD1C0057BC15 /* DFGStaticExecutionCountEstimationPhase.cpp in Sources */,
</span><span class="cx">                                 0FE7211D193B9C590031F6ED /* DFGTransition.cpp in Sources */,
</span><del>-                                2ACCF3DE185FE26B0083E2AD /* DFGStoreBarrierElisionPhase.cpp in Sources */,
</del><span class="cx">                                 0FC20CB51852E2C600C9E954 /* DFGStrengthReductionPhase.cpp in Sources */,
</span><span class="cx">                                 0F2FCCFE18A60070001A27F8 /* DFGThreadData.cpp in Sources */,
</span><span class="cx">                                 0FC097A1146B28CA00CF2442 /* DFGThunks.cpp in Sources */,
</span><span class="lines">@@ -7202,6 +7201,7 @@
</span><span class="cx">                                 0F2BDC5115228FFD00CD8910 /* DFGVariableEvent.cpp in Sources */,
</span><span class="cx">                                 0F2BDC4A1522809A00CD8910 /* DFGVariableEventStream.cpp in Sources */,
</span><span class="cx">                                 0FFFC95F14EF90BB00C72532 /* DFGVirtualRegisterAllocationPhase.cpp in Sources */,
</span><ins>+                                0F9E32631B05AB0400801ED5 /* DFGStoreBarrierInsertionPhase.cpp in Sources */,
</ins><span class="cx">                                 0FC97F4118202119002C9B26 /* DFGWatchpointCollectionPhase.cpp in Sources */,
</span><span class="cx">                                 0FDB2CE7174830A2007B3C1B /* DFGWorklist.cpp in Sources */,
</span><span class="cx">                                 0F9D3370165DBB90005AD387 /* Disassembler.cpp in Sources */,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGBlockMaph"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGBlockMap.h (184414 => 184415)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGBlockMap.h        2015-05-15 21:10:11 UTC (rev 184414)
+++ trunk/Source/JavaScriptCore/dfg/DFGBlockMap.h        2015-05-15 21:11:39 UTC (rev 184415)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2014 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2014, 2015 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -58,6 +58,26 @@
</span><span class="cx">         return m_vector[blockIndex];
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+    T&amp; at(BlockIndex blockIndex)
+    {
+        return m_vector[blockIndex];
+    }
+    
+    const T&amp; at(BlockIndex blockIndex) const
+    {
+        return m_vector[blockIndex];
+    }
+    
+    T&amp; at(BasicBlock* block)
+    {
+        return m_vector[block-&gt;index];
+    }
+    
+    const T&amp; at(BasicBlock* block) const
+    {
+        return m_vector[block-&gt;index];
+    }
+
</ins><span class="cx">     T&amp; operator[](BlockIndex blockIndex)
</span><span class="cx">     {
</span><span class="cx">         return m_vector[blockIndex];
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGConstantFoldingPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp (184414 => 184415)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp        2015-05-15 21:10:11 UTC (rev 184414)
+++ trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp        2015-05-15 21:11:39 UTC (rev 184415)
</span><span class="lines">@@ -597,7 +597,6 @@
</span><span class="cx">             Node* allocatePropertyStorage = m_insertionSet.insertNode(
</span><span class="cx">                 indexInBlock, SpecNone, AllocatePropertyStorage,
</span><span class="cx">                 origin, OpInfo(transition), childEdge);
</span><del>-            m_insertionSet.insertNode(indexInBlock, SpecNone, StoreBarrier, origin, Edge(node-&gt;child1().node(), KnownCellUse));
</del><span class="cx">             propertyStorage = Edge(allocatePropertyStorage);
</span><span class="cx">         } else {
</span><span class="cx">             ASSERT(variant.oldStructureForTransition()-&gt;outOfLineCapacity());
</span><span class="lines">@@ -609,7 +608,6 @@
</span><span class="cx">                 OpInfo(transition), childEdge,
</span><span class="cx">                 Edge(m_insertionSet.insertNode(
</span><span class="cx">                     indexInBlock, SpecNone, GetButterfly, origin, childEdge)));
</span><del>-            m_insertionSet.insertNode(indexInBlock, SpecNone, StoreBarrier, origin, Edge(node-&gt;child1().node(), KnownCellUse));
</del><span class="cx">             propertyStorage = Edge(reallocatePropertyStorage);
</span><span class="cx">         }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGEpochh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGEpoch.h (184414 => 184415)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGEpoch.h        2015-05-15 21:10:11 UTC (rev 184414)
+++ trunk/Source/JavaScriptCore/dfg/DFGEpoch.h        2015-05-15 21:11:39 UTC (rev 184415)
</span><span class="lines">@@ -87,6 +87,26 @@
</span><span class="cx">         return !(*this == other);
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+    bool operator&lt;(const Epoch&amp; other) const
+    {
+        return m_epoch &lt; other.m_epoch;
+    }
+    
+    bool operator&gt;(const Epoch&amp; other) const
+    {
+        return other &lt; *this;
+    }
+    
+    bool operator&lt;=(const Epoch&amp; other) const
+    {
+        return !(*this &gt; other);
+    }
+    
+    bool operator&gt;=(const Epoch&amp; other) const
+    {
+        return !(*this &lt; other);
+    }
+    
</ins><span class="cx">     void dump(PrintStream&amp;) const;
</span><span class="cx">     
</span><span class="cx"> private:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGFixupPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp (184414 => 184415)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2015-05-15 21:10:11 UTC (rev 184414)
+++ trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2015-05-15 21:11:39 UTC (rev 184415)
</span><span class="lines">@@ -722,7 +722,7 @@
</span><span class="cx">             case Array::SlowPutArrayStorage:
</span><span class="cx">                 fixEdge&lt;KnownCellUse&gt;(child1);
</span><span class="cx">                 fixEdge&lt;Int32Use&gt;(child2);
</span><del>-                insertStoreBarrier(m_indexInBlock, child1, child3);
</del><ins>+                speculateForBarrier(child3);
</ins><span class="cx">                 break;
</span><span class="cx">             default:
</span><span class="cx">                 fixEdge&lt;KnownCellUse&gt;(child1);
</span><span class="lines">@@ -760,7 +760,7 @@
</span><span class="cx">                 break;
</span><span class="cx">             case Array::Contiguous:
</span><span class="cx">             case Array::ArrayStorage:
</span><del>-                insertStoreBarrier(m_indexInBlock, node-&gt;child1(), node-&gt;child2());
</del><ins>+                speculateForBarrier(node-&gt;child2());
</ins><span class="cx">                 break;
</span><span class="cx">             default:
</span><span class="cx">                 break;
</span><span class="lines">@@ -922,7 +922,6 @@
</span><span class="cx">             
</span><span class="cx">         case PutStructure: {
</span><span class="cx">             fixEdge&lt;KnownCellUse&gt;(node-&gt;child1());
</span><del>-            insertStoreBarrier(m_indexInBlock, node-&gt;child1());
</del><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">             
</span><span class="lines">@@ -935,7 +934,7 @@
</span><span class="cx">         case PutClosureVar:
</span><span class="cx">         case PutToArguments: {
</span><span class="cx">             fixEdge&lt;KnownCellUse&gt;(node-&gt;child1());
</span><del>-            insertStoreBarrier(m_indexInBlock, node-&gt;child1(), node-&gt;child2());
</del><ins>+            speculateForBarrier(node-&gt;child2());
</ins><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">             
</span><span class="lines">@@ -950,7 +949,6 @@
</span><span class="cx">         case AllocatePropertyStorage:
</span><span class="cx">         case ReallocatePropertyStorage: {
</span><span class="cx">             fixEdge&lt;KnownCellUse&gt;(node-&gt;child1());
</span><del>-            insertStoreBarrier(m_indexInBlock + 1, node-&gt;child1());
</del><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="lines">@@ -986,7 +984,7 @@
</span><span class="cx">         case PutByIdFlush:
</span><span class="cx">         case PutByIdDirect: {
</span><span class="cx">             fixEdge&lt;CellUse&gt;(node-&gt;child1());
</span><del>-            insertStoreBarrier(m_indexInBlock, node-&gt;child1(), node-&gt;child2());
</del><ins>+            speculateForBarrier(node-&gt;child2());
</ins><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="lines">@@ -1029,13 +1027,13 @@
</span><span class="cx">             if (!node-&gt;child1()-&gt;hasStorageResult())
</span><span class="cx">                 fixEdge&lt;KnownCellUse&gt;(node-&gt;child1());
</span><span class="cx">             fixEdge&lt;KnownCellUse&gt;(node-&gt;child2());
</span><del>-            insertStoreBarrier(m_indexInBlock, node-&gt;child2(), node-&gt;child3());
</del><ins>+            speculateForBarrier(node-&gt;child3());
</ins><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">             
</span><span class="cx">         case MultiPutByOffset: {
</span><span class="cx">             fixEdge&lt;CellUse&gt;(node-&gt;child1());
</span><del>-            insertStoreBarrier(m_indexInBlock, node-&gt;child1(), node-&gt;child2());
</del><ins>+            speculateForBarrier(node-&gt;child2());
</ins><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">             
</span><span class="lines">@@ -1115,16 +1113,16 @@
</span><span class="cx">         case PutStack:
</span><span class="cx">         case KillStack:
</span><span class="cx">         case GetStack:
</span><ins>+        case StoreBarrier:
</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><del>-            RELEASE_ASSERT_NOT_REACHED();
</del><ins>+            DFG_CRASH(m_graph, node, &quot;Unexpected node during fixup&quot;);
</ins><span class="cx">             break;
</span><span class="cx">         
</span><span class="cx">         case PutGlobalVar: {
</span><span class="cx">             fixEdge&lt;CellUse&gt;(node-&gt;child1());
</span><del>-            insertStoreBarrier(
-                m_indexInBlock, node-&gt;child1(), node-&gt;child2());
</del><ins>+            speculateForBarrier(node-&gt;child2());
</ins><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="lines">@@ -1298,7 +1296,6 @@
</span><span class="cx">         case Unreachable:
</span><span class="cx">         case ExtractOSREntryLocal:
</span><span class="cx">         case LoopHint:
</span><del>-        case StoreBarrier:
</del><span class="cx">         case MovHint:
</span><span class="cx">         case ZombieHint:
</span><span class="cx">         case BottomValue:
</span><span class="lines">@@ -1762,37 +1759,35 @@
</span><span class="cx">         edge.setUseKind(useKind);
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    void insertStoreBarrier(unsigned indexInBlock, Edge base, Edge value = Edge())
</del><ins>+    void speculateForBarrier(Edge value)
</ins><span class="cx">     {
</span><del>-        if (!!value) {
-            if (value-&gt;shouldSpeculateInt32()) {
-                insertCheck&lt;Int32Use&gt;(indexInBlock, value.node());
-                return;
-            }
</del><ins>+        if (!isFTL(m_graph.m_plan.mode))
+            return;
+        
+        if (value-&gt;shouldSpeculateInt32()) {
+            insertCheck&lt;Int32Use&gt;(m_indexInBlock, value.node());
+            return;
+        }
</ins><span class="cx">             
</span><del>-            if (value-&gt;shouldSpeculateBoolean()) {
-                insertCheck&lt;BooleanUse&gt;(indexInBlock, value.node());
-                return;
-            }
</del><ins>+        if (value-&gt;shouldSpeculateBoolean()) {
+            insertCheck&lt;BooleanUse&gt;(m_indexInBlock, value.node());
+            return;
+        }
</ins><span class="cx">             
</span><del>-            if (value-&gt;shouldSpeculateOther()) {
-                insertCheck&lt;OtherUse&gt;(indexInBlock, value.node());
-                return;
-            }
</del><ins>+        if (value-&gt;shouldSpeculateOther()) {
+            insertCheck&lt;OtherUse&gt;(m_indexInBlock, value.node());
+            return;
+        }
</ins><span class="cx">             
</span><del>-            if (value-&gt;shouldSpeculateNumber()) {
-                insertCheck&lt;NumberUse&gt;(indexInBlock, value.node());
-                return;
-            }
</del><ins>+        if (value-&gt;shouldSpeculateNumber()) {
+            insertCheck&lt;NumberUse&gt;(m_indexInBlock, value.node());
+            return;
+        }
</ins><span class="cx">             
</span><del>-            if (value-&gt;shouldSpeculateNotCell()) {
-                insertCheck&lt;NotCellUse&gt;(indexInBlock, value.node());
-                return;
-            }
</del><ins>+        if (value-&gt;shouldSpeculateNotCell()) {
+            insertCheck&lt;NotCellUse&gt;(m_indexInBlock, value.node());
+            return;
</ins><span class="cx">         }
</span><del>-
-        m_insertionSet.insertNode(
-            indexInBlock, SpecNone, StoreBarrier, m_currentNode-&gt;origin, base);
</del><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     template&lt;UseKind useKind&gt;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGObjectAllocationSinkingPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp (184414 => 184415)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp        2015-05-15 21:10:11 UTC (rev 184414)
+++ trunk/Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp        2015-05-15 21:11:39 UTC (rev 184415)
</span><span class="lines">@@ -613,11 +613,7 @@
</span><span class="cx">                 }
</span><span class="cx"> 
</span><span class="cx">                 case StoreBarrier: {
</span><del>-                    Node* target = node-&gt;child1().node();
-                    if (m_sinkCandidates.contains(target)) {
-                        ASSERT(target-&gt;isPhantomAllocation());
-                        node-&gt;remove();
-                    }
</del><ins>+                    DFG_CRASH(m_graph, node, &quot;Unexpected store barrier during sinking.&quot;);
</ins><span class="cx">                     break;
</span><span class="cx">                 }
</span><span class="cx">                     
</span><span class="lines">@@ -854,7 +850,6 @@
</span><span class="cx"> 
</span><span class="cx">         case MovHint:
</span><span class="cx">         case PutHint:
</span><del>-        case StoreBarrier:
</del><span class="cx">             break;
</span><span class="cx"> 
</span><span class="cx">         case PutStructure:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGPlancpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGPlan.cpp (184414 => 184415)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGPlan.cpp        2015-05-15 21:10:11 UTC (rev 184414)
+++ trunk/Source/JavaScriptCore/dfg/DFGPlan.cpp        2015-05-15 21:11:39 UTC (rev 184415)
</span><span class="lines">@@ -60,7 +60,7 @@
</span><span class="cx"> #include &quot;DFGSSALoweringPhase.h&quot;
</span><span class="cx"> #include &quot;DFGStackLayoutPhase.h&quot;
</span><span class="cx"> #include &quot;DFGStaticExecutionCountEstimationPhase.h&quot;
</span><del>-#include &quot;DFGStoreBarrierElisionPhase.h&quot;
</del><ins>+#include &quot;DFGStoreBarrierInsertionPhase.h&quot;
</ins><span class="cx"> #include &quot;DFGStrengthReductionPhase.h&quot;
</span><span class="cx"> #include &quot;DFGStructureRegistrationPhase.h&quot;
</span><span class="cx"> #include &quot;DFGTierUpCheckInjectionPhase.h&quot;
</span><span class="lines">@@ -315,7 +315,7 @@
</span><span class="cx">     
</span><span class="cx">         performTierUpCheckInjection(dfg);
</span><span class="cx"> 
</span><del>-        performStoreBarrierElision(dfg);
</del><ins>+        performFastStoreBarrierInsertion(dfg);
</ins><span class="cx">         performCleanUp(dfg);
</span><span class="cx">         performCPSRethreading(dfg);
</span><span class="cx">         performDCE(dfg);
</span><span class="lines">@@ -387,9 +387,9 @@
</span><span class="cx">         // about code motion assumes that it's OK to insert GC points in random places.
</span><span class="cx">         dfg.m_fixpointState = FixpointConverged;
</span><span class="cx">         
</span><del>-        performStoreBarrierElision(dfg);
</del><span class="cx">         performLivenessAnalysis(dfg);
</span><span class="cx">         performCFA(dfg);
</span><ins>+        performGlobalStoreBarrierInsertion(dfg);
</ins><span class="cx">         if (Options::enableMovHintRemoval())
</span><span class="cx">             performMovHintRemoval(dfg);
</span><span class="cx">         performCleanUp(dfg);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGPredictionPropagationPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp (184414 => 184415)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp        2015-05-15 21:10:11 UTC (rev 184414)
+++ trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp        2015-05-15 21:11:39 UTC (rev 184415)
</span><span class="lines">@@ -562,10 +562,11 @@
</span><span class="cx">         case MaterializeCreateActivation:
</span><span class="cx">         case PutStack:
</span><span class="cx">         case KillStack:
</span><ins>+        case StoreBarrier:
</ins><span class="cx">         case GetStack: {
</span><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><del>-            RELEASE_ASSERT_NOT_REACHED();
</del><ins>+            DFG_CRASH(m_graph, node, &quot;Unexpected node during prediction propagation&quot;);
</ins><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">         
</span><span class="lines">@@ -617,7 +618,6 @@
</span><span class="cx"> 
</span><span class="cx"> #ifndef NDEBUG
</span><span class="cx">         // These get ignored because they don't return anything.
</span><del>-        case StoreBarrier:
</del><span class="cx">         case PutByValDirect:
</span><span class="cx">         case PutByVal:
</span><span class="cx">         case PutClosureVar:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGStoreBarrierElisionPhasecpp"></a>
<div class="delfile"><h4>Deleted: trunk/Source/JavaScriptCore/dfg/DFGStoreBarrierElisionPhase.cpp (184414 => 184415)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGStoreBarrierElisionPhase.cpp        2015-05-15 21:10:11 UTC (rev 184414)
+++ trunk/Source/JavaScriptCore/dfg/DFGStoreBarrierElisionPhase.cpp        2015-05-15 21:11:39 UTC (rev 184415)
</span><span class="lines">@@ -1,150 +0,0 @@
</span><del>-/*
- * Copyright (C) 2013 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include &quot;config.h&quot;
-#include &quot;DFGStoreBarrierElisionPhase.h&quot;
-
-#if ENABLE(DFG_JIT)
-
-#include &quot;DFGBasicBlock.h&quot;
-#include &quot;DFGClobberize.h&quot;
-#include &quot;DFGDoesGC.h&quot;
-#include &quot;DFGGraph.h&quot;
-#include &quot;DFGPhase.h&quot;
-#include &quot;JSCInlines.h&quot;
-#include &lt;wtf/HashSet.h&gt;
-
-namespace JSC { namespace DFG {
-
-class StoreBarrierElisionPhase : public Phase {
-public:
-    StoreBarrierElisionPhase(Graph&amp; graph)
-        : Phase(graph, &quot;store barrier elision&quot;)
-        , m_currentBlock(0)
-        , m_currentIndex(0)
-    {
-    }
-
-    bool run()
-    {
-        for (BlockIndex blockIndex = 0; blockIndex &lt; m_graph.numBlocks(); ++blockIndex) {
-            m_currentBlock = m_graph.block(blockIndex);
-            if (!m_currentBlock)
-                continue;
-            handleBlock(m_currentBlock);
-        }
-        return true;
-    }
-
-private:
-    bool allocatesFreshObject(Node* node)
-    {
-        switch (node-&gt;op()) {
-        case NewObject:
-        case NewArray:
-        case NewArrayWithSize:
-        case NewArrayBuffer:
-        case NewTypedArray:
-        case NewRegexp:
-            return true;
-        default:
-            return false;
-        }
-    }
-
-    void noticeFreshObject(HashSet&lt;Node*&gt;&amp; dontNeedBarriers, Node* node)
-    {
-        ASSERT(allocatesFreshObject(node));
-        dontNeedBarriers.add(node);
-    }
-
-    Node* getBaseOfStore(Node* barrierNode)
-    {
-        ASSERT(barrierNode-&gt;isStoreBarrier());
-        return barrierNode-&gt;child1().node();
-    }
-
-    bool shouldBeElided(HashSet&lt;Node*&gt;&amp; dontNeedBarriers, Node* node)
-    {
-        ASSERT(node-&gt;isStoreBarrier());
-        return dontNeedBarriers.contains(node-&gt;child1().node());
-    }
-
-    void elideBarrier(Node* node)
-    {
-        ASSERT(node-&gt;isStoreBarrier());
-        node-&gt;remove();
-    }
-
-    void handleNode(HashSet&lt;Node*&gt;&amp; dontNeedBarriers, Node* node)
-    {
-        if (doesGC(m_graph, node))
-            dontNeedBarriers.clear();
-
-        if (allocatesFreshObject(node))
-            noticeFreshObject(dontNeedBarriers, node);
-
-        if (!node-&gt;isStoreBarrier())
-            return;
-
-        if (shouldBeElided(dontNeedBarriers, node)) {
-            elideBarrier(node);
-            return;
-        }
-
-        Node* base = getBaseOfStore(node);
-        if (!base)
-            return;
-
-        if (dontNeedBarriers.contains(base))
-            return;
-        dontNeedBarriers.add(base);
-    }
-
-    bool handleBlock(BasicBlock* block)
-    {
-        HashSet&lt;Node*&gt; dontNeedBarriers;
-        for (unsigned indexInBlock = 0; indexInBlock &lt; block-&gt;size(); ++indexInBlock) {
-            m_currentIndex = indexInBlock;
-            Node* node = block-&gt;at(indexInBlock);
-            handleNode(dontNeedBarriers, node);
-        }
-        return true;
-    }
-
-    BasicBlock* m_currentBlock;
-    unsigned m_currentIndex;
-};
-    
-bool performStoreBarrierElision(Graph&amp; graph)
-{
-    SamplingRegion samplingRegion(&quot;DFG Store Barrier Elision Phase&quot;);
-    return runPhase&lt;StoreBarrierElisionPhase&gt;(graph);
-}
-
-
-} } // namespace JSC::DFG
-
-#endif // ENABLE(DFG_JIT)
</del></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGStoreBarrierElisionPhaseh"></a>
<div class="delfile"><h4>Deleted: trunk/Source/JavaScriptCore/dfg/DFGStoreBarrierElisionPhase.h (184414 => 184415)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGStoreBarrierElisionPhase.h        2015-05-15 21:10:11 UTC (rev 184414)
+++ trunk/Source/JavaScriptCore/dfg/DFGStoreBarrierElisionPhase.h        2015-05-15 21:11:39 UTC (rev 184415)
</span><span class="lines">@@ -1,37 +0,0 @@
</span><del>-/*
- * Copyright (C) 2013 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef DFGStoreBarrierElisionPhase_h
-#define DFGStoreBarrierElisionPhase_h
-
-namespace JSC { namespace DFG {
-
-class Graph;
-
-bool performStoreBarrierElision(Graph&amp;);
-
-} } // namespace JSC::DFG
-
-#endif // DFGStoreBarrierElisionPhase_h
</del></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGStoreBarrierInsertionPhasecpp"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/dfg/DFGStoreBarrierInsertionPhase.cpp (0 => 184415)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGStoreBarrierInsertionPhase.cpp                                (rev 0)
+++ trunk/Source/JavaScriptCore/dfg/DFGStoreBarrierInsertionPhase.cpp        2015-05-15 21:11:39 UTC (rev 184415)
</span><span class="lines">@@ -0,0 +1,528 @@
</span><ins>+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include &quot;config.h&quot;
+#include &quot;DFGStoreBarrierInsertionPhase.h&quot;
+
+#if ENABLE(DFG_JIT)
+
+#include &quot;DFGAbstractInterpreterInlines.h&quot;
+#include &quot;DFGBlockMapInlines.h&quot;
+#include &quot;DFGDoesGC.h&quot;
+#include &quot;DFGGraph.h&quot;
+#include &quot;DFGInPlaceAbstractState.h&quot;
+#include &quot;DFGInsertionSet.h&quot;
+#include &quot;DFGPhase.h&quot;
+#include &quot;JSCInlines.h&quot;
+#include &lt;wtf/CommaPrinter.h&gt;
+#include &lt;wtf/HashSet.h&gt;
+
+namespace JSC { namespace DFG {
+
+namespace {
+
+bool verbose = false;
+
+enum class PhaseMode {
+    // Does only a local analysis for store barrier insertion and assumes that pointers live
+    // from predecessor blocks may need barriers. Assumes CPS conventions. Does not use AI for
+    // eliminating store barriers, but does a best effort to eliminate barriers when you're
+    // storing a non-cell value by using Node::result() and by looking at constants. The local
+    // analysis is based on GC epochs, so it will eliminate a lot of locally redundant barriers.
+    Fast,
+        
+    // Does a global analysis for store barrier insertion. Reuses the GC-epoch-based analysis
+    // used by Fast, but adds a conservative merge rule for propagating information from one
+    // block to the next. This will ensure for example that if a value V coming from multiple
+    // predecessors in B didn't need any more barriers at the end of each predecessor (either
+    // because it was the last allocated object in that predecessor or because it just had a
+    // barrier executed), then until we hit another GC point in B, we won't need another barrier
+    // on V. Uses AI for eliminating barriers when we know that the value being stored is not a
+    // cell. Assumes SSA conventions.
+    Global
+};
+
+template&lt;PhaseMode mode&gt;
+class StoreBarrierInsertionPhase : public Phase {
+public:
+    StoreBarrierInsertionPhase(Graph&amp; graph)
+        : Phase(graph, mode == PhaseMode::Fast ? &quot;fast store barrier insertion&quot; : &quot;global store barrier insertion&quot;)
+        , m_insertionSet(graph)
+    {
+    }
+    
+    bool run()
+    {
+        if (verbose) {
+            dataLog(&quot;Starting store barrier insertion:\n&quot;);
+            m_graph.dump();
+        }
+        
+        switch (mode) {
+        case PhaseMode::Fast: {
+            DFG_ASSERT(m_graph, nullptr, m_graph.m_form != SSA);
+            
+            m_graph.clearEpochs();
+            for (BasicBlock* block : m_graph.blocksInNaturalOrder())
+                handleBlock(block);
+            return true;
+        }
+            
+        case PhaseMode::Global: {
+            DFG_ASSERT(m_graph, nullptr, m_graph.m_form == SSA);
+
+            m_state = std::make_unique&lt;InPlaceAbstractState&gt;(m_graph);
+            m_interpreter = std::make_unique&lt;AbstractInterpreter&lt;InPlaceAbstractState&gt;&gt;(m_graph, *m_state);
+            
+            m_isConverged = false;
+            
+            // First run the analysis. Inside basic blocks we use an epoch-based analysis that
+            // is very precise. At block boundaries, we just propagate which nodes may need a
+            // barrier. This gives us a very nice bottom-&gt;top fixpoint: we start out assuming
+            // that no node needs any barriers at block boundaries, and then we converge
+            // towards believing that all nodes need barriers. &quot;Needing a barrier&quot; is like
+            // saying that the node is in a past epoch. &quot;Not needing a barrier&quot; is like saying
+            // that the node is in the current epoch.
+            m_stateAtHead = std::make_unique&lt;BlockMap&lt;HashSet&lt;Node*&gt;&gt;&gt;(m_graph);
+            m_stateAtTail = std::make_unique&lt;BlockMap&lt;HashSet&lt;Node*&gt;&gt;&gt;(m_graph);
+            
+            BlockList postOrder = m_graph.blocksInPostOrder();
+            
+            bool changed = true;
+            while (changed) {
+                changed = false;
+                
+                // Intentional backwards loop because we are using RPO.
+                for (unsigned blockIndex = postOrder.size(); blockIndex--;) {
+                    BasicBlock* block = postOrder[blockIndex];
+                    
+                    if (!handleBlock(block)) {
+                        // If the block didn't finish, then it cannot affect the fixpoint.
+                        continue;
+                    }
+                    
+                    // Construct the state-at-tail based on the epochs of live nodes and the
+                    // current epoch. We grow state-at-tail monotonically to ensure convergence.
+                    bool thisBlockChanged = false;
+                    for (Node* node : block-&gt;ssa-&gt;liveAtTail) {
+                        if (node-&gt;epoch() != m_currentEpoch) {
+                            // If the node is older than the current epoch, then we may need to
+                            // run a barrier on it in the future. So, add it to the state.
+                            thisBlockChanged |= m_stateAtTail-&gt;at(block).add(node).isNewEntry;
+                        }
+                    }
+                    
+                    if (!thisBlockChanged) {
+                        // This iteration didn't learn anything new about this block.
+                        continue;
+                    }
+                    
+                    // Changed things. Make sure that we loop one more time.
+                    changed = true;
+                    
+                    for (BasicBlock* successor : block-&gt;successors()) {
+                        for (Node* node : m_stateAtTail-&gt;at(block))
+                            m_stateAtHead-&gt;at(successor).add(node);
+                    }
+                }
+            }
+            
+            // Tell handleBlock() that it's time to actually insert barriers for real.
+            m_isConverged = true;
+            
+            for (BasicBlock* block : m_graph.blocksInNaturalOrder())
+                handleBlock(block);
+            
+            return true;
+        } }
+        
+        RELEASE_ASSERT_NOT_REACHED();
+        return false;
+    }
+
+private:
+    bool handleBlock(BasicBlock* block)
+    {
+        if (verbose) {
+            dataLog(&quot;Dealing with block &quot;, pointerDump(block), &quot;\n&quot;);
+            if (reallyInsertBarriers())
+                dataLog(&quot;    Really inserting barriers.\n&quot;);
+        }
+        
+        m_currentEpoch = Epoch::first();
+        
+        if (mode == PhaseMode::Global) {
+            if (!block-&gt;cfaHasVisited)
+                return false;
+            m_state-&gt;beginBasicBlock(block);
+            
+            for (Node* node : block-&gt;ssa-&gt;liveAtHead) {
+                if (m_stateAtHead-&gt;at(block).contains(node)) {
+                    // If previous blocks tell us that this node may need a barrier in the
+                    // future, then put it in the ancient primordial epoch. This forces us to
+                    // emit a barrier on any possibly-cell store, regardless of the epoch of the
+                    // stored value.
+                    node-&gt;setEpoch(Epoch());
+                } else {
+                    // If previous blocks aren't requiring us to run a barrier on this node,
+                    // then put it in the current epoch. This means that we will skip barriers
+                    // on this node so long as we don't allocate. It also means that we won't
+                    // run barriers on stores to on one such node into another such node. That's
+                    // fine, because nodes would be excluded from the state set if at the tails
+                    // of all predecessors they always had the current epoch.
+                    node-&gt;setEpoch(m_currentEpoch);
+                }
+            }
+        }
+
+        bool result = true;
+        
+        for (m_nodeIndex = 0; m_nodeIndex &lt; block-&gt;size(); ++m_nodeIndex) {
+            m_node = block-&gt;at(m_nodeIndex);
+            
+            if (verbose) {
+                dataLog(
+                    &quot;    &quot;, m_currentEpoch, &quot;: Looking at node &quot;, m_node, &quot; with children: &quot;);
+                CommaPrinter comma;
+                m_graph.doToChildren(
+                    m_node,
+                    [&amp;] (Edge edge) {
+                        dataLog(comma, edge, &quot; (&quot;, edge-&gt;epoch(), &quot;)&quot;);
+                    });
+                dataLog(&quot;\n&quot;);
+            }
+            
+            if (mode == PhaseMode::Global) {
+                // Execute edges separately because we don't want to insert barriers if the
+                // operation doing the store does a check that ensures that the child is not
+                // a cell.
+                m_interpreter-&gt;startExecuting();
+                m_interpreter-&gt;executeEdges(m_node);
+            }
+            
+            switch (m_node-&gt;op()) {
+            case PutByValDirect:
+            case PutByVal:
+            case PutByValAlias: {
+                switch (m_node-&gt;arrayMode().modeForPut().type()) {
+                case Array::Contiguous:
+                case Array::ArrayStorage:
+                case Array::SlowPutArrayStorage: {
+                    Edge child1 = m_graph.varArgChild(m_node, 0);
+                    Edge child3 = m_graph.varArgChild(m_node, 2);
+                    considerBarrier(child1, child3);
+                    break;
+                }
+                default:
+                    break;
+                }
+                break;
+            }
+                
+            case ArrayPush: {
+                switch (m_node-&gt;arrayMode().type()) {
+                case Array::Contiguous:
+                case Array::ArrayStorage:
+                    considerBarrier(m_node-&gt;child1(), m_node-&gt;child2());
+                    break;
+                default:
+                    break;
+                }
+                break;
+            }
+                
+            case PutStructure: {
+                considerBarrier(m_node-&gt;child1());
+                break;
+            }
+                
+            case PutClosureVar:
+            case PutToArguments:
+            case PutById:
+            case PutByIdFlush:
+            case PutByIdDirect:
+            case MultiPutByOffset: {
+                considerBarrier(m_node-&gt;child1(), m_node-&gt;child2());
+                break;
+            }
+                
+            case PutByOffset: {
+                considerBarrier(m_node-&gt;child2(), m_node-&gt;child3());
+                break;
+            }
+                
+            case PutGlobalVar: {
+                considerBarrier(m_node-&gt;child1(), m_node-&gt;child2());
+                break;
+            }
+                
+            default:
+                break;
+            }
+            
+            if (doesGC(m_graph, m_node))
+                m_currentEpoch.bump();
+            
+            switch (m_node-&gt;op()) {
+            case NewObject:
+            case NewArray:
+            case NewArrayWithSize:
+            case NewArrayBuffer:
+            case NewTypedArray:
+            case NewRegexp:
+            case MaterializeNewObject:
+            case MaterializeCreateActivation:
+            case NewStringObject:
+            case MakeRope:
+            case CreateActivation:
+            case CreateDirectArguments:
+            case CreateScopedArguments:
+            case CreateClonedArguments:
+            case NewFunction:
+                // Nodes that allocate get to set their epoch because for those nodes we know
+                // that they will be the newest object in the heap.
+                m_node-&gt;setEpoch(m_currentEpoch);
+                break;
+                
+            case AllocatePropertyStorage:
+            case ReallocatePropertyStorage:
+                // These allocate but then run their own barrier.
+                insertBarrier(m_nodeIndex + 1, m_node-&gt;child1().node());
+                m_node-&gt;setEpoch(Epoch());
+                break;
+                
+            case Upsilon:
+                m_node-&gt;phi()-&gt;setEpoch(m_node-&gt;epoch());
+                m_node-&gt;setEpoch(Epoch());
+                break;
+                
+            default:
+                // For nodes that aren't guaranteed to allocate, we say that their return value
+                // (if there is one) could be arbitrarily old.
+                m_node-&gt;setEpoch(Epoch());
+                break;
+            }
+            
+            if (verbose) {
+                dataLog(
+                    &quot;    &quot;, m_currentEpoch, &quot;: Done with node &quot;, m_node, &quot; (&quot;, m_node-&gt;epoch(),
+                    &quot;) with children: &quot;);
+                CommaPrinter comma;
+                m_graph.doToChildren(
+                    m_node,
+                    [&amp;] (Edge edge) {
+                        dataLog(comma, edge, &quot; (&quot;, edge-&gt;epoch(), &quot;)&quot;);
+                    });
+                dataLog(&quot;\n&quot;);
+            }
+            
+            if (mode == PhaseMode::Global) {
+                if (!m_interpreter-&gt;executeEffects(m_nodeIndex, m_node)) {
+                    result = false;
+                    break;
+                }
+            }
+        }
+        
+        if (mode == PhaseMode::Global)
+            m_state-&gt;reset();
+
+        if (reallyInsertBarriers())
+            m_insertionSet.execute(block);
+        
+        return result;
+    }
+    
+    void considerBarrier(Edge base, Edge child)
+    {
+        if (verbose)
+            dataLog(&quot;        Considering adding barrier &quot;, base, &quot; =&gt; &quot;, child, &quot;\n&quot;);
+        
+        // We don't need a store barrier if the child is guaranteed to not be a cell.
+        switch (mode) {
+        case PhaseMode::Fast: {
+            // Don't try too hard because it's too expensive to run AI.
+            if (child-&gt;hasConstant()) {
+                if (!child-&gt;asJSValue().isCell()) {
+                    if (verbose)
+                        dataLog(&quot;            Rejecting because of constant type.\n&quot;);
+                    return;
+                }
+            } else {
+                switch (child-&gt;result()) {
+                case NodeResultNumber:
+                case NodeResultDouble:
+                case NodeResultInt32:
+                case NodeResultInt52:
+                case NodeResultBoolean:
+                    if (verbose)
+                        dataLog(&quot;            Rejecting because of result type.\n&quot;);
+                    return;
+                default:
+                    break;
+                }
+            }
+            break;
+        }
+            
+        case PhaseMode::Global: {
+            // Go into rage mode to eliminate any chance of a barrier with a non-cell child. We
+            // can afford to keep around AI in Global mode.
+            if (!m_interpreter-&gt;needsTypeCheck(child, ~SpecCell)) {
+                if (verbose)
+                    dataLog(&quot;            Rejecting because of AI type.\n&quot;);
+                return;
+            }
+            break;
+        } }
+        
+        // We don't need a store barrier if the base is at least as new as the child. For
+        // example this won't need a barrier:
+        //
+        // var o = {}
+        // var p = {}
+        // p.f = o
+        //
+        // This is stronger than the currentEpoch rule in considerBarrier(Edge), because it will
+        // also eliminate barriers in cases like this:
+        //
+        // var o = {} // o.epoch = 1, currentEpoch = 1
+        // var p = {} // o.epoch = 1, p.epoch = 2, currentEpoch = 2
+        // var q = {} // o.epoch = 1, p.epoch = 2, q.epoch = 3, currentEpoch = 3
+        // p.f = o // p.epoch &gt;= o.epoch
+        //
+        // This relationship works because if it holds then we are in one of the following
+        // scenarios. Note that we don't know *which* of these scenarios we are in, but it's
+        // one of them (though without loss of generality, you can replace &quot;a GC happened&quot; with
+        // &quot;many GCs happened&quot;).
+        //
+        // 1) There is no GC between the allocation/last-barrier of base, child and now. Then
+        //    we definitely don't need a barrier.
+        //
+        // 2) There was a GC after child was allocated but before base was allocated. Then we
+        //    don't need a barrier, because base is still a new object.
+        //
+        // 3) There was a GC after both child and base were allocated. Then they are both old.
+        //    We don't need barriers on stores of old into old. Note that in this case it
+        //    doesn't matter if there was also a GC between the allocation of child and base.
+        //
+        // Note that barriers will lift an object into the current epoch. This is sort of weird.
+        // It means that later if you store that object into some other object, and that other
+        // object was previously newer object, you'll think that you need a barrier. We could
+        // avoid this by tracking allocation epoch and barrier epoch separately. For now I think
+        // that this would be overkill. But this does mean that there are the following
+        // possibilities when this relationship holds:
+        //
+        // 4) Base is allocated first. A GC happens and base becomes old. Then we allocate
+        //    child. (Note that alternatively the GC could happen during the allocation of
+        //    child.) Then we run a barrier on base. Base will appear to be as new as child
+        //    (same epoch). At this point, we don't need another barrier on base.
+        //
+        // 5) Base is allocated first. Then we allocate child. Then we run a GC. Then we run a
+        //    barrier on base. Base will appear newer than child. We don't need a barrier
+        //    because both objects are old.
+        //
+        // Something we watch out for here is that the null epoch is a catch-all for objects
+        // allocated before we did any epoch tracking. Two objects being in the null epoch
+        // means that we don't know their epoch relationship.
+        if (!!base-&gt;epoch() &amp;&amp; base-&gt;epoch() &gt;= child-&gt;epoch()) {
+            if (verbose)
+                dataLog(&quot;            Rejecting because of epoch ordering.\n&quot;);
+            return;
+        }
+        
+        considerBarrier(base);
+    }
+    
+    void considerBarrier(Edge base)
+    {
+        if (verbose)
+            dataLog(&quot;        Considering adding barrier on &quot;, base, &quot;\n&quot;);
+        
+        // We don't need a store barrier if the epoch of the base is identical to the current
+        // epoch. That means that we either just allocated the object and so it's guaranteed to
+        // be in newgen, or we just ran a barrier on it so it's guaranteed to be remembered
+        // already.
+        if (base-&gt;epoch() == m_currentEpoch) {
+            if (verbose)
+                dataLog(&quot;            Rejecting because it's in the current epoch.\n&quot;);
+            return;
+        }
+        
+        if (verbose)
+            dataLog(&quot;            Inserting barrier.\n&quot;);
+        insertBarrier(m_nodeIndex, base.node());
+    }
+    
+    void insertBarrier(unsigned nodeIndex, Node* base)
+    {
+        // If we're in global mode, we should only insert the barriers once we have converged.
+        if (!reallyInsertBarriers())
+            return;
+        
+        // FIXME: We could support StoreBarrier(UntypedUse:). That would be sort of cool.
+        // But right now we don't need it.
+        m_insertionSet.insertNode(
+            nodeIndex, SpecNone, StoreBarrier, m_node-&gt;origin, Edge(base, CellUse));
+
+        base-&gt;setEpoch(m_currentEpoch);
+    }
+    
+    bool reallyInsertBarriers()
+    {
+        return mode == PhaseMode::Fast || m_isConverged;
+    }
+    
+    InsertionSet m_insertionSet;
+    Epoch m_currentEpoch;
+    unsigned m_nodeIndex;
+    Node* m_node;
+    
+    // Things we only use in Global mode.
+    std::unique_ptr&lt;InPlaceAbstractState&gt; m_state;
+    std::unique_ptr&lt;AbstractInterpreter&lt;InPlaceAbstractState&gt;&gt; m_interpreter;
+    std::unique_ptr&lt;BlockMap&lt;HashSet&lt;Node*&gt;&gt;&gt; m_stateAtHead;
+    std::unique_ptr&lt;BlockMap&lt;HashSet&lt;Node*&gt;&gt;&gt; m_stateAtTail;
+    bool m_isConverged;
+};
+
+} // anonymous namespace
+
+bool performFastStoreBarrierInsertion(Graph&amp; graph)
+{
+    SamplingRegion samplingRegion(&quot;DFG Fast Store Barrier Insertion Phase&quot;);
+    return runPhase&lt;StoreBarrierInsertionPhase&lt;PhaseMode::Fast&gt;&gt;(graph);
+}
+
+bool performGlobalStoreBarrierInsertion(Graph&amp; graph)
+{
+    SamplingRegion samplingRegion(&quot;DFG Global Store Barrier Insertion Phase&quot;);
+    return runPhase&lt;StoreBarrierInsertionPhase&lt;PhaseMode::Global&gt;&gt;(graph);
+}
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGStoreBarrierInsertionPhaseh"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/dfg/DFGStoreBarrierInsertionPhase.h (0 => 184415)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGStoreBarrierInsertionPhase.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/dfg/DFGStoreBarrierInsertionPhase.h        2015-05-15 21:11:39 UTC (rev 184415)
</span><span class="lines">@@ -0,0 +1,51 @@
</span><ins>+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef DFGStoreBarrierInsertionPhase_h
+#define DFGStoreBarrierInsertionPhase_h
+
+#if ENABLE(DFG_JIT)
+
+namespace JSC { namespace DFG {
+
+class Graph;
+
+// Inserts store barriers in a block-local manner without consulting the abstract interpreter.
+// Uses a simple epoch-based analysis to avoid inserting redundant barriers. This phase requires
+// that we are not in SSA.
+bool performFastStoreBarrierInsertion(Graph&amp;);
+
+// Inserts store barriers using a global analysis and consults the abstract interpreter. Uses a
+// simple epoch-based analysis to avoid inserting redundant barriers, but only propagates &quot;same
+// epoch as current&quot; property from one block to the next. This phase requires SSA. This phase
+// also requires having valid AI and liveness.
+bool performGlobalStoreBarrierInsertion(Graph&amp;);
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
+#endif // DFGStoreBarrierInsertionPhase_h
+
</ins></span></pre>
</div>
</div>

</body>
</html>