<!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>[184527] branches/safari-601.1.32-branch/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/184527">184527</a></dd>
<dt>Author</dt> <dd>matthew_hanson@apple.com</dd>
<dt>Date</dt> <dd>2015-05-18 17:09:01 -0700 (Mon, 18 May 2015)</dd>
</dl>
<h3>Log Message</h3>
<pre>Merge <a href="http://trac.webkit.org/projects/webkit/changeset/184445">r184445</a>. rdar://problem/20979071</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#branchessafari601132branchSourceJavaScriptCoreCMakeListstxt">branches/safari-601.1.32-branch/Source/JavaScriptCore/CMakeLists.txt</a></li>
<li><a href="#branchessafari601132branchSourceJavaScriptCoreChangeLog">branches/safari-601.1.32-branch/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#branchessafari601132branchSourceJavaScriptCoreJavaScriptCorevcxprojJavaScriptCorevcxproj">branches/safari-601.1.32-branch/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj</a></li>
<li><a href="#branchessafari601132branchSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj">branches/safari-601.1.32-branch/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#branchessafari601132branchSourceJavaScriptCoredfgDFGBlockMaph">branches/safari-601.1.32-branch/Source/JavaScriptCore/dfg/DFGBlockMap.h</a></li>
<li><a href="#branchessafari601132branchSourceJavaScriptCoredfgDFGConstantFoldingPhasecpp">branches/safari-601.1.32-branch/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp</a></li>
<li><a href="#branchessafari601132branchSourceJavaScriptCoredfgDFGEpochh">branches/safari-601.1.32-branch/Source/JavaScriptCore/dfg/DFGEpoch.h</a></li>
<li><a href="#branchessafari601132branchSourceJavaScriptCoredfgDFGFixupPhasecpp">branches/safari-601.1.32-branch/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp</a></li>
<li><a href="#branchessafari601132branchSourceJavaScriptCoredfgDFGObjectAllocationSinkingPhasecpp">branches/safari-601.1.32-branch/Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp</a></li>
<li><a href="#branchessafari601132branchSourceJavaScriptCoredfgDFGPlancpp">branches/safari-601.1.32-branch/Source/JavaScriptCore/dfg/DFGPlan.cpp</a></li>
<li><a href="#branchessafari601132branchSourceJavaScriptCoredfgDFGPredictionPropagationPhasecpp">branches/safari-601.1.32-branch/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp</a></li>
<li><a href="#branchessafari601132branchSourceJavaScriptCoreftlFTLOperationscpp">branches/safari-601.1.32-branch/Source/JavaScriptCore/ftl/FTLOperations.cpp</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li><a href="#branchessafari601132branchSourceJavaScriptCoredfgDFGStoreBarrierInsertionPhasecpp">branches/safari-601.1.32-branch/Source/JavaScriptCore/dfg/DFGStoreBarrierInsertionPhase.cpp</a></li>
<li><a href="#branchessafari601132branchSourceJavaScriptCoredfgDFGStoreBarrierInsertionPhaseh">branches/safari-601.1.32-branch/Source/JavaScriptCore/dfg/DFGStoreBarrierInsertionPhase.h</a></li>
<li><a href="#branchessafari601132branchSourceJavaScriptCoretestsstressloadvarargstheninlinedcallandexitstrictjs">branches/safari-601.1.32-branch/Source/JavaScriptCore/tests/stress/load-varargs-then-inlined-call-and-exit-strict.js</a></li>
<li><a href="#branchessafari601132branchSourceJavaScriptCoretestsstressloadvarargstheninlinedcallandexitjs">branches/safari-601.1.32-branch/Source/JavaScriptCore/tests/stress/load-varargs-then-inlined-call-and-exit.js</a></li>
</ul>
<h3>Removed Paths</h3>
<ul>
<li><a href="#branchessafari601132branchSourceJavaScriptCoredfgDFGStoreBarrierElisionPhasecpp">branches/safari-601.1.32-branch/Source/JavaScriptCore/dfg/DFGStoreBarrierElisionPhase.cpp</a></li>
<li><a href="#branchessafari601132branchSourceJavaScriptCoredfgDFGStoreBarrierElisionPhaseh">branches/safari-601.1.32-branch/Source/JavaScriptCore/dfg/DFGStoreBarrierElisionPhase.h</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="branchessafari601132branchSourceJavaScriptCoreCMakeListstxt"></a>
<div class="modfile"><h4>Modified: branches/safari-601.1.32-branch/Source/JavaScriptCore/CMakeLists.txt (184526 => 184527)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601.1.32-branch/Source/JavaScriptCore/CMakeLists.txt        2015-05-19 00:08:44 UTC (rev 184526)
+++ branches/safari-601.1.32-branch/Source/JavaScriptCore/CMakeLists.txt        2015-05-19 00:09:01 UTC (rev 184527)
</span><span class="lines">@@ -226,7 +226,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="branchessafari601132branchSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: branches/safari-601.1.32-branch/Source/JavaScriptCore/ChangeLog (184526 => 184527)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601.1.32-branch/Source/JavaScriptCore/ChangeLog        2015-05-19 00:08:44 UTC (rev 184526)
+++ branches/safari-601.1.32-branch/Source/JavaScriptCore/ChangeLog        2015-05-19 00:09:01 UTC (rev 184527)
</span><span class="lines">@@ -1,5 +1,73 @@
</span><span class="cx"> 2015-05-18 Matthew Hanson <matthew_hanson@apple.com>
</span><span class="cx">
</span><ins>+ Merge r184445. rdar://problem/20979071
+
+ 2015-05-17 Filip Pizlo <fpizlo@apple.com>
+
+ 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.
+
+ Rolling back in after fixing some debug build test failures.
+
+ * 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<):
+ (JSC::DFG::Epoch::operator>):
+ (JSC::DFG::Epoch::operator<=):
+ (JSC::DFG::Epoch::operator>=):
+ * 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.
+ * ftl/FTLOperations.cpp:
+ (JSC::FTL::operationMaterializeObjectInOSR): Fix an unrelated debug-only bug.
+ * tests/stress/load-varargs-then-inlined-call-and-exit.js: Test for that debug-only bug.
+ * tests/stress/load-varargs-then-inlined-call-and-exit-strict.js: Strict version of that test.
+
+2015-05-18 Matthew Hanson <matthew_hanson@apple.com>
+
</ins><span class="cx"> Merge r184397. rdar://problem/20979071
</span><span class="cx">
</span><span class="cx"> 2015-05-14 Filip Pizlo <fpizlo@apple.com>
</span></span></pre></div>
<a id="branchessafari601132branchSourceJavaScriptCoreJavaScriptCorevcxprojJavaScriptCorevcxproj"></a>
<div class="modfile"><h4>Modified: branches/safari-601.1.32-branch/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj (184526 => 184527)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601.1.32-branch/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj        2015-05-19 00:08:44 UTC (rev 184526)
+++ branches/safari-601.1.32-branch/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj        2015-05-19 00:09:01 UTC (rev 184527)
</span><span class="lines">@@ -466,7 +466,7 @@
</span><span class="cx"> <ClCompile Include="..\dfg\DFGSSALoweringPhase.cpp" />
</span><span class="cx"> <ClCompile Include="..\dfg\DFGStackLayoutPhase.cpp" />
</span><span class="cx"> <ClCompile Include="..\dfg\DFGStaticExecutionCountEstimationPhase.cpp" />
</span><del>- <ClCompile Include="..\dfg\DFGStoreBarrierElisionPhase.cpp" />
</del><ins>+ <ClCompile Include="..\dfg\DFGStoreBarrierInsertionPhase.cpp" />
</ins><span class="cx"> <ClCompile Include="..\dfg\DFGStrengthReductionPhase.cpp" />
</span><span class="cx"> <ClCompile Include="..\dfg\DFGStructureAbstractValue.cpp" />
</span><span class="cx"> <ClCompile Include="..\dfg\DFGStructureRegistrationPhase.cpp" />
</span><span class="lines">@@ -1170,7 +1170,7 @@
</span><span class="cx"> <ClInclude Include="..\dfg\DFGSSALoweringPhase.h" />
</span><span class="cx"> <ClInclude Include="..\dfg\DFGStackLayoutPhase.h" />
</span><span class="cx"> <ClInclude Include="..\dfg\DFGStaticExecutionCountEstimationPhase.h" />
</span><del>- <ClInclude Include="..\dfg\DFGStoreBarrierElisionPhase.h" />
</del><ins>+ <ClInclude Include="..\dfg\DFGStoreBarrierInsertionPhase.h" />
</ins><span class="cx"> <ClInclude Include="..\dfg\DFGStrengthReductionPhase.h" />
</span><span class="cx"> <ClInclude Include="..\dfg\DFGStructureAbstractValue.h" />
</span><span class="cx"> <ClInclude Include="..\dfg\DFGStructureClobberState.h" />
</span></span></pre></div>
<a id="branchessafari601132branchSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: branches/safari-601.1.32-branch/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (184526 => 184527)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601.1.32-branch/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2015-05-19 00:08:44 UTC (rev 184526)
+++ branches/safari-601.1.32-branch/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2015-05-19 00:09:01 UTC (rev 184527)
</span><span class="lines">@@ -460,6 +460,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">@@ -927,8 +929,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">@@ -2193,6 +2193,8 @@
</span><span class="cx">                 0F9D33991803ADB70073C2BC /* FTLStackMaps.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FTLStackMaps.h; path = ftl/FTLStackMaps.h; sourceTree = "<group>"; };
</span><span class="cx">                 0F9D36921AE9CC33000D4DFB /* DFGCleanUpPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGCleanUpPhase.cpp; path = dfg/DFGCleanUpPhase.cpp; sourceTree = "<group>"; };
</span><span class="cx">                 0F9D36931AE9CC33000D4DFB /* DFGCleanUpPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGCleanUpPhase.h; path = dfg/DFGCleanUpPhase.h; sourceTree = "<group>"; };
</span><ins>+                0F9E32611B05AB0400801ED5 /* DFGStoreBarrierInsertionPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGStoreBarrierInsertionPhase.cpp; path = dfg/DFGStoreBarrierInsertionPhase.cpp; sourceTree = "<group>"; };
+                0F9E32621B05AB0400801ED5 /* DFGStoreBarrierInsertionPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGStoreBarrierInsertionPhase.h; path = dfg/DFGStoreBarrierInsertionPhase.h; sourceTree = "<group>"; };
</ins><span class="cx">                 0F9FB4F217FCB91700CB67F8 /* DFGStackLayoutPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGStackLayoutPhase.cpp; path = dfg/DFGStackLayoutPhase.cpp; sourceTree = "<group>"; };
</span><span class="cx">                 0F9FB4F317FCB91700CB67F8 /* DFGStackLayoutPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGStackLayoutPhase.h; path = dfg/DFGStackLayoutPhase.h; sourceTree = "<group>"; };
</span><span class="cx">                 0F9FC8BF14E1B5FB00D52AE0 /* PolymorphicPutByIdList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PolymorphicPutByIdList.cpp; sourceTree = "<group>"; };
</span><span class="lines">@@ -2629,8 +2631,6 @@
</span><span class="cx">                 2AAD964918569417001F93BE /* RecursiveAllocationScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RecursiveAllocationScope.h; sourceTree = "<group>"; };
</span><span class="cx">                 2AC922B918A16182003CE0FB /* FTLDWARFDebugLineInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FTLDWARFDebugLineInfo.cpp; path = ftl/FTLDWARFDebugLineInfo.cpp; sourceTree = "<group>"; };
</span><span class="cx">                 2AC922BA18A16182003CE0FB /* FTLDWARFDebugLineInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FTLDWARFDebugLineInfo.h; path = ftl/FTLDWARFDebugLineInfo.h; sourceTree = "<group>"; };
</span><del>-                2ACCF3DC185FE26B0083E2AD /* DFGStoreBarrierElisionPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGStoreBarrierElisionPhase.cpp; path = dfg/DFGStoreBarrierElisionPhase.cpp; sourceTree = "<group>"; };
-                2ACCF3DD185FE26B0083E2AD /* DFGStoreBarrierElisionPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGStoreBarrierElisionPhase.h; path = dfg/DFGStoreBarrierElisionPhase.h; sourceTree = "<group>"; };
</del><span class="cx">                 2AD2EDFA19799E38004D6478 /* EnumerationMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EnumerationMode.h; sourceTree = "<group>"; };
</span><span class="cx">                 2AD8932917E3868F00668276 /* HeapIterationScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HeapIterationScope.h; sourceTree = "<group>"; };
</span><span class="cx">                 2ADFA26218EF3540004F9FCC /* GCLogging.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GCLogging.cpp; sourceTree = "<group>"; };
</span><span class="lines">@@ -5071,8 +5071,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">@@ -5875,8 +5875,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">@@ -7158,7 +7158,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">@@ -7179,6 +7178,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="branchessafari601132branchSourceJavaScriptCoredfgDFGBlockMaph"></a>
<div class="modfile"><h4>Modified: branches/safari-601.1.32-branch/Source/JavaScriptCore/dfg/DFGBlockMap.h (184526 => 184527)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601.1.32-branch/Source/JavaScriptCore/dfg/DFGBlockMap.h        2015-05-19 00:08:44 UTC (rev 184526)
+++ branches/safari-601.1.32-branch/Source/JavaScriptCore/dfg/DFGBlockMap.h        2015-05-19 00:09:01 UTC (rev 184527)
</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& at(BlockIndex blockIndex)
+ {
+ return m_vector[blockIndex];
+ }
+
+ const T& at(BlockIndex blockIndex) const
+ {
+ return m_vector[blockIndex];
+ }
+
+ T& at(BasicBlock* block)
+ {
+ return m_vector[block->index];
+ }
+
+ const T& at(BasicBlock* block) const
+ {
+ return m_vector[block->index];
+ }
+
</ins><span class="cx"> T& operator[](BlockIndex blockIndex)
</span><span class="cx"> {
</span><span class="cx"> return m_vector[blockIndex];
</span></span></pre></div>
<a id="branchessafari601132branchSourceJavaScriptCoredfgDFGConstantFoldingPhasecpp"></a>
<div class="modfile"><h4>Modified: branches/safari-601.1.32-branch/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp (184526 => 184527)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601.1.32-branch/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp        2015-05-19 00:08:44 UTC (rev 184526)
+++ branches/safari-601.1.32-branch/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp        2015-05-19 00:09:01 UTC (rev 184527)
</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->child1().node(), KnownCellUse));
</del><span class="cx"> propertyStorage = Edge(allocatePropertyStorage);
</span><span class="cx"> } else {
</span><span class="cx"> ASSERT(variant.oldStructureForTransition()->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->child1().node(), KnownCellUse));
</del><span class="cx"> propertyStorage = Edge(reallocatePropertyStorage);
</span><span class="cx"> }
</span><span class="cx">
</span></span></pre></div>
<a id="branchessafari601132branchSourceJavaScriptCoredfgDFGEpochh"></a>
<div class="modfile"><h4>Modified: branches/safari-601.1.32-branch/Source/JavaScriptCore/dfg/DFGEpoch.h (184526 => 184527)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601.1.32-branch/Source/JavaScriptCore/dfg/DFGEpoch.h        2015-05-19 00:08:44 UTC (rev 184526)
+++ branches/safari-601.1.32-branch/Source/JavaScriptCore/dfg/DFGEpoch.h        2015-05-19 00:09:01 UTC (rev 184527)
</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<(const Epoch& other) const
+ {
+ return m_epoch < other.m_epoch;
+ }
+
+ bool operator>(const Epoch& other) const
+ {
+ return other < *this;
+ }
+
+ bool operator<=(const Epoch& other) const
+ {
+ return !(*this > other);
+ }
+
+ bool operator>=(const Epoch& other) const
+ {
+ return !(*this < other);
+ }
+
</ins><span class="cx"> void dump(PrintStream&) const;
</span><span class="cx">
</span><span class="cx"> private:
</span></span></pre></div>
<a id="branchessafari601132branchSourceJavaScriptCoredfgDFGFixupPhasecpp"></a>
<div class="modfile"><h4>Modified: branches/safari-601.1.32-branch/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp (184526 => 184527)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601.1.32-branch/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2015-05-19 00:08:44 UTC (rev 184526)
+++ branches/safari-601.1.32-branch/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2015-05-19 00:09:01 UTC (rev 184527)
</span><span class="lines">@@ -656,7 +656,7 @@
</span><span class="cx"> case Array::SlowPutArrayStorage:
</span><span class="cx"> fixEdge<KnownCellUse>(child1);
</span><span class="cx"> fixEdge<Int32Use>(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<KnownCellUse>(child1);
</span><span class="lines">@@ -694,7 +694,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->child1(), node->child2());
</del><ins>+ speculateForBarrier(node->child2());
</ins><span class="cx"> break;
</span><span class="cx"> default:
</span><span class="cx"> break;
</span><span class="lines">@@ -856,7 +856,6 @@
</span><span class="cx">
</span><span class="cx"> case PutStructure: {
</span><span class="cx"> fixEdge<KnownCellUse>(node->child1());
</span><del>- insertStoreBarrier(m_indexInBlock, node->child1());
</del><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -869,7 +868,7 @@
</span><span class="cx"> case PutClosureVar:
</span><span class="cx"> case PutToArguments: {
</span><span class="cx"> fixEdge<KnownCellUse>(node->child1());
</span><del>- insertStoreBarrier(m_indexInBlock, node->child1(), node->child2());
</del><ins>+ speculateForBarrier(node->child2());
</ins><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -884,7 +883,6 @@
</span><span class="cx"> case AllocatePropertyStorage:
</span><span class="cx"> case ReallocatePropertyStorage: {
</span><span class="cx"> fixEdge<KnownCellUse>(node->child1());
</span><del>- insertStoreBarrier(m_indexInBlock + 1, node->child1());
</del><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -920,7 +918,7 @@
</span><span class="cx"> case PutByIdFlush:
</span><span class="cx"> case PutByIdDirect: {
</span><span class="cx"> fixEdge<CellUse>(node->child1());
</span><del>- insertStoreBarrier(m_indexInBlock, node->child1(), node->child2());
</del><ins>+ speculateForBarrier(node->child2());
</ins><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -963,13 +961,13 @@
</span><span class="cx"> if (!node->child1()->hasStorageResult())
</span><span class="cx"> fixEdge<KnownCellUse>(node->child1());
</span><span class="cx"> fixEdge<KnownCellUse>(node->child2());
</span><del>- insertStoreBarrier(m_indexInBlock, node->child2(), node->child3());
</del><ins>+ speculateForBarrier(node->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<CellUse>(node->child1());
</span><del>- insertStoreBarrier(m_indexInBlock, node->child1(), node->child2());
</del><ins>+ speculateForBarrier(node->child2());
</ins><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -1049,16 +1047,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, "Unexpected node during fixup");
</ins><span class="cx"> break;
</span><span class="cx">
</span><span class="cx"> case PutGlobalVar: {
</span><span class="cx"> fixEdge<CellUse>(node->child1());
</span><del>- insertStoreBarrier(
- m_indexInBlock, node->child1(), node->child2());
</del><ins>+ speculateForBarrier(node->child2());
</ins><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -1232,7 +1230,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">@@ -1696,37 +1693,36 @@
</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->shouldSpeculateInt32()) {
- insertCheck<Int32Use>(indexInBlock, value.node());
- return;
- }
</del><ins>+ // Currently, the DFG won't take advantage of this speculation. But, we want to do it in
+ // the DFG anyway because if such a speculation would be wrong, we want to know before
+ // we do an expensive compile.
+
+ if (value->shouldSpeculateInt32()) {
+ insertCheck<Int32Use>(m_indexInBlock, value.node());
+ return;
+ }
</ins><span class="cx">
</span><del>- if (value->shouldSpeculateBoolean()) {
- insertCheck<BooleanUse>(indexInBlock, value.node());
- return;
- }
</del><ins>+ if (value->shouldSpeculateBoolean()) {
+ insertCheck<BooleanUse>(m_indexInBlock, value.node());
+ return;
+ }
</ins><span class="cx">
</span><del>- if (value->shouldSpeculateOther()) {
- insertCheck<OtherUse>(indexInBlock, value.node());
- return;
- }
</del><ins>+ if (value->shouldSpeculateOther()) {
+ insertCheck<OtherUse>(m_indexInBlock, value.node());
+ return;
+ }
</ins><span class="cx">
</span><del>- if (value->shouldSpeculateNumber()) {
- insertCheck<NumberUse>(indexInBlock, value.node());
- return;
- }
</del><ins>+ if (value->shouldSpeculateNumber()) {
+ insertCheck<NumberUse>(m_indexInBlock, value.node());
+ return;
+ }
</ins><span class="cx">
</span><del>- if (value->shouldSpeculateNotCell()) {
- insertCheck<NotCellUse>(indexInBlock, value.node());
- return;
- }
</del><ins>+ if (value->shouldSpeculateNotCell()) {
+ insertCheck<NotCellUse>(m_indexInBlock, value.node());
+ return;
</ins><span class="cx"> }
</span><del>-
- m_insertionSet.insertNode(
- indexInBlock, SpecNone, StoreBarrier, m_currentNode->origin, base);
</del><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> template<UseKind useKind>
</span></span></pre></div>
<a id="branchessafari601132branchSourceJavaScriptCoredfgDFGObjectAllocationSinkingPhasecpp"></a>
<div class="modfile"><h4>Modified: branches/safari-601.1.32-branch/Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp (184526 => 184527)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601.1.32-branch/Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp        2015-05-19 00:08:44 UTC (rev 184526)
+++ branches/safari-601.1.32-branch/Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp        2015-05-19 00:09:01 UTC (rev 184527)
</span><span class="lines">@@ -611,11 +611,7 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> case StoreBarrier: {
</span><del>- Node* target = node->child1().node();
- if (m_sinkCandidates.contains(target)) {
- ASSERT(target->isPhantomAllocation());
- node->remove();
- }
</del><ins>+ DFG_CRASH(m_graph, node, "Unexpected store barrier during sinking.");
</ins><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -847,7 +843,6 @@
</span><span class="cx"> case MovHint:
</span><span class="cx"> case Check:
</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="branchessafari601132branchSourceJavaScriptCoredfgDFGPlancpp"></a>
<div class="modfile"><h4>Modified: branches/safari-601.1.32-branch/Source/JavaScriptCore/dfg/DFGPlan.cpp (184526 => 184527)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601.1.32-branch/Source/JavaScriptCore/dfg/DFGPlan.cpp        2015-05-19 00:08:44 UTC (rev 184526)
+++ branches/safari-601.1.32-branch/Source/JavaScriptCore/dfg/DFGPlan.cpp        2015-05-19 00:09:01 UTC (rev 184527)
</span><span class="lines">@@ -60,7 +60,7 @@
</span><span class="cx"> #include "DFGSSALoweringPhase.h"
</span><span class="cx"> #include "DFGStackLayoutPhase.h"
</span><span class="cx"> #include "DFGStaticExecutionCountEstimationPhase.h"
</span><del>-#include "DFGStoreBarrierElisionPhase.h"
</del><ins>+#include "DFGStoreBarrierInsertionPhase.h"
</ins><span class="cx"> #include "DFGStrengthReductionPhase.h"
</span><span class="cx"> #include "DFGStructureRegistrationPhase.h"
</span><span class="cx"> #include "DFGTierUpCheckInjectionPhase.h"
</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="branchessafari601132branchSourceJavaScriptCoredfgDFGPredictionPropagationPhasecpp"></a>
<div class="modfile"><h4>Modified: branches/safari-601.1.32-branch/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp (184526 => 184527)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601.1.32-branch/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp        2015-05-19 00:08:44 UTC (rev 184526)
+++ branches/safari-601.1.32-branch/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp        2015-05-19 00:09:01 UTC (rev 184527)
</span><span class="lines">@@ -554,10 +554,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, "Unexpected node during prediction propagation");
</ins><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -609,7 +610,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="branchessafari601132branchSourceJavaScriptCoredfgDFGStoreBarrierElisionPhasecpp"></a>
<div class="delfile"><h4>Deleted: branches/safari-601.1.32-branch/Source/JavaScriptCore/dfg/DFGStoreBarrierElisionPhase.cpp (184526 => 184527)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601.1.32-branch/Source/JavaScriptCore/dfg/DFGStoreBarrierElisionPhase.cpp        2015-05-19 00:08:44 UTC (rev 184526)
+++ branches/safari-601.1.32-branch/Source/JavaScriptCore/dfg/DFGStoreBarrierElisionPhase.cpp        2015-05-19 00:09:01 UTC (rev 184527)
</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 "config.h"
-#include "DFGStoreBarrierElisionPhase.h"
-
-#if ENABLE(DFG_JIT)
-
-#include "DFGBasicBlock.h"
-#include "DFGClobberize.h"
-#include "DFGDoesGC.h"
-#include "DFGGraph.h"
-#include "DFGPhase.h"
-#include "JSCInlines.h"
-#include <wtf/HashSet.h>
-
-namespace JSC { namespace DFG {
-
-class StoreBarrierElisionPhase : public Phase {
-public:
- StoreBarrierElisionPhase(Graph& graph)
- : Phase(graph, "store barrier elision")
- , m_currentBlock(0)
- , m_currentIndex(0)
- {
- }
-
- bool run()
- {
- for (BlockIndex blockIndex = 0; blockIndex < 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->op()) {
- case NewObject:
- case NewArray:
- case NewArrayWithSize:
- case NewArrayBuffer:
- case NewTypedArray:
- case NewRegexp:
- return true;
- default:
- return false;
- }
- }
-
- void noticeFreshObject(HashSet<Node*>& dontNeedBarriers, Node* node)
- {
- ASSERT(allocatesFreshObject(node));
- dontNeedBarriers.add(node);
- }
-
- Node* getBaseOfStore(Node* barrierNode)
- {
- ASSERT(barrierNode->isStoreBarrier());
- return barrierNode->child1().node();
- }
-
- bool shouldBeElided(HashSet<Node*>& dontNeedBarriers, Node* node)
- {
- ASSERT(node->isStoreBarrier());
- return dontNeedBarriers.contains(node->child1().node());
- }
-
- void elideBarrier(Node* node)
- {
- ASSERT(node->isStoreBarrier());
- node->remove();
- }
-
- void handleNode(HashSet<Node*>& dontNeedBarriers, Node* node)
- {
- if (doesGC(m_graph, node))
- dontNeedBarriers.clear();
-
- if (allocatesFreshObject(node))
- noticeFreshObject(dontNeedBarriers, node);
-
- if (!node->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<Node*> dontNeedBarriers;
- for (unsigned indexInBlock = 0; indexInBlock < block->size(); ++indexInBlock) {
- m_currentIndex = indexInBlock;
- Node* node = block->at(indexInBlock);
- handleNode(dontNeedBarriers, node);
- }
- return true;
- }
-
- BasicBlock* m_currentBlock;
- unsigned m_currentIndex;
-};
-
-bool performStoreBarrierElision(Graph& graph)
-{
- SamplingRegion samplingRegion("DFG Store Barrier Elision Phase");
- return runPhase<StoreBarrierElisionPhase>(graph);
-}
-
-
-} } // namespace JSC::DFG
-
-#endif // ENABLE(DFG_JIT)
</del></span></pre></div>
<a id="branchessafari601132branchSourceJavaScriptCoredfgDFGStoreBarrierElisionPhaseh"></a>
<div class="delfile"><h4>Deleted: branches/safari-601.1.32-branch/Source/JavaScriptCore/dfg/DFGStoreBarrierElisionPhase.h (184526 => 184527)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601.1.32-branch/Source/JavaScriptCore/dfg/DFGStoreBarrierElisionPhase.h        2015-05-19 00:08:44 UTC (rev 184526)
+++ branches/safari-601.1.32-branch/Source/JavaScriptCore/dfg/DFGStoreBarrierElisionPhase.h        2015-05-19 00:09:01 UTC (rev 184527)
</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&);
-
-} } // namespace JSC::DFG
-
-#endif // DFGStoreBarrierElisionPhase_h
</del></span></pre></div>
<a id="branchessafari601132branchSourceJavaScriptCoredfgDFGStoreBarrierInsertionPhasecpp"></a>
<div class="addfile"><h4>Added: branches/safari-601.1.32-branch/Source/JavaScriptCore/dfg/DFGStoreBarrierInsertionPhase.cpp (0 => 184527)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601.1.32-branch/Source/JavaScriptCore/dfg/DFGStoreBarrierInsertionPhase.cpp         (rev 0)
+++ branches/safari-601.1.32-branch/Source/JavaScriptCore/dfg/DFGStoreBarrierInsertionPhase.cpp        2015-05-19 00:09:01 UTC (rev 184527)
</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 "config.h"
+#include "DFGStoreBarrierInsertionPhase.h"
+
+#if ENABLE(DFG_JIT)
+
+#include "DFGAbstractInterpreterInlines.h"
+#include "DFGBlockMapInlines.h"
+#include "DFGDoesGC.h"
+#include "DFGGraph.h"
+#include "DFGInPlaceAbstractState.h"
+#include "DFGInsertionSet.h"
+#include "DFGPhase.h"
+#include "JSCInlines.h"
+#include <wtf/CommaPrinter.h>
+#include <wtf/HashSet.h>
+
+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<PhaseMode mode>
+class StoreBarrierInsertionPhase : public Phase {
+public:
+ StoreBarrierInsertionPhase(Graph& graph)
+ : Phase(graph, mode == PhaseMode::Fast ? "fast store barrier insertion" : "global store barrier insertion")
+ , m_insertionSet(graph)
+ {
+ }
+
+ bool run()
+ {
+ if (verbose) {
+ dataLog("Starting store barrier insertion:\n");
+ 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<InPlaceAbstractState>(m_graph);
+ m_interpreter = std::make_unique<AbstractInterpreter<InPlaceAbstractState>>(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->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. "Needing a barrier" is like
+ // saying that the node is in a past epoch. "Not needing a barrier" is like saying
+ // that the node is in the current epoch.
+ m_stateAtHead = std::make_unique<BlockMap<HashSet<Node*>>>(m_graph);
+ m_stateAtTail = std::make_unique<BlockMap<HashSet<Node*>>>(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->ssa->liveAtTail) {
+ if (node->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->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->successors()) {
+ for (Node* node : m_stateAtTail->at(block))
+ m_stateAtHead->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("Dealing with block ", pointerDump(block), "\n");
+ if (reallyInsertBarriers())
+ dataLog(" Really inserting barriers.\n");
+ }
+
+ m_currentEpoch = Epoch::first();
+
+ if (mode == PhaseMode::Global) {
+ if (!block->cfaHasVisited)
+ return false;
+ m_state->beginBasicBlock(block);
+
+ for (Node* node : block->ssa->liveAtHead) {
+ if (m_stateAtHead->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->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->setEpoch(m_currentEpoch);
+ }
+ }
+ }
+
+ bool result = true;
+
+ for (m_nodeIndex = 0; m_nodeIndex < block->size(); ++m_nodeIndex) {
+ m_node = block->at(m_nodeIndex);
+
+ if (verbose) {
+ dataLog(
+ " ", m_currentEpoch, ": Looking at node ", m_node, " with children: ");
+ CommaPrinter comma;
+ m_graph.doToChildren(
+ m_node,
+ [&] (Edge edge) {
+ dataLog(comma, edge, " (", edge->epoch(), ")");
+ });
+ dataLog("\n");
+ }
+
+ 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->startExecuting();
+ m_interpreter->executeEdges(m_node);
+ }
+
+ switch (m_node->op()) {
+ case PutByValDirect:
+ case PutByVal:
+ case PutByValAlias: {
+ switch (m_node->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->arrayMode().type()) {
+ case Array::Contiguous:
+ case Array::ArrayStorage:
+ considerBarrier(m_node->child1(), m_node->child2());
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+
+ case PutStructure: {
+ considerBarrier(m_node->child1());
+ break;
+ }
+
+ case PutClosureVar:
+ case PutToArguments:
+ case PutById:
+ case PutByIdFlush:
+ case PutByIdDirect:
+ case MultiPutByOffset: {
+ considerBarrier(m_node->child1(), m_node->child2());
+ break;
+ }
+
+ case PutByOffset: {
+ considerBarrier(m_node->child2(), m_node->child3());
+ break;
+ }
+
+ case PutGlobalVar: {
+ considerBarrier(m_node->child1(), m_node->child2());
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ if (doesGC(m_graph, m_node))
+ m_currentEpoch.bump();
+
+ switch (m_node->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->setEpoch(m_currentEpoch);
+ break;
+
+ case AllocatePropertyStorage:
+ case ReallocatePropertyStorage:
+ // These allocate but then run their own barrier.
+ insertBarrier(m_nodeIndex + 1, m_node->child1().node());
+ m_node->setEpoch(Epoch());
+ break;
+
+ case Upsilon:
+ m_node->phi()->setEpoch(m_node->epoch());
+ m_node->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->setEpoch(Epoch());
+ break;
+ }
+
+ if (verbose) {
+ dataLog(
+ " ", m_currentEpoch, ": Done with node ", m_node, " (", m_node->epoch(),
+ ") with children: ");
+ CommaPrinter comma;
+ m_graph.doToChildren(
+ m_node,
+ [&] (Edge edge) {
+ dataLog(comma, edge, " (", edge->epoch(), ")");
+ });
+ dataLog("\n");
+ }
+
+ if (mode == PhaseMode::Global) {
+ if (!m_interpreter->executeEffects(m_nodeIndex, m_node)) {
+ result = false;
+ break;
+ }
+ }
+ }
+
+ if (mode == PhaseMode::Global)
+ m_state->reset();
+
+ if (reallyInsertBarriers())
+ m_insertionSet.execute(block);
+
+ return result;
+ }
+
+ void considerBarrier(Edge base, Edge child)
+ {
+ if (verbose)
+ dataLog(" Considering adding barrier ", base, " => ", child, "\n");
+
+ // 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->hasConstant()) {
+ if (!child->asJSValue().isCell()) {
+ if (verbose)
+ dataLog(" Rejecting because of constant type.\n");
+ return;
+ }
+ } else {
+ switch (child->result()) {
+ case NodeResultNumber:
+ case NodeResultDouble:
+ case NodeResultInt32:
+ case NodeResultInt52:
+ case NodeResultBoolean:
+ if (verbose)
+ dataLog(" Rejecting because of result type.\n");
+ 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->needsTypeCheck(child, ~SpecCell)) {
+ if (verbose)
+ dataLog(" Rejecting because of AI type.\n");
+ 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 >= 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 "a GC happened" with
+ // "many GCs happened").
+ //
+ // 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->epoch() && base->epoch() >= child->epoch()) {
+ if (verbose)
+ dataLog(" Rejecting because of epoch ordering.\n");
+ return;
+ }
+
+ considerBarrier(base);
+ }
+
+ void considerBarrier(Edge base)
+ {
+ if (verbose)
+ dataLog(" Considering adding barrier on ", base, "\n");
+
+ // 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->epoch() == m_currentEpoch) {
+ if (verbose)
+ dataLog(" Rejecting because it's in the current epoch.\n");
+ return;
+ }
+
+ if (verbose)
+ dataLog(" Inserting barrier.\n");
+ 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->origin, Edge(base, CellUse));
+
+ base->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<InPlaceAbstractState> m_state;
+ std::unique_ptr<AbstractInterpreter<InPlaceAbstractState>> m_interpreter;
+ std::unique_ptr<BlockMap<HashSet<Node*>>> m_stateAtHead;
+ std::unique_ptr<BlockMap<HashSet<Node*>>> m_stateAtTail;
+ bool m_isConverged;
+};
+
+} // anonymous namespace
+
+bool performFastStoreBarrierInsertion(Graph& graph)
+{
+ SamplingRegion samplingRegion("DFG Fast Store Barrier Insertion Phase");
+ return runPhase<StoreBarrierInsertionPhase<PhaseMode::Fast>>(graph);
+}
+
+bool performGlobalStoreBarrierInsertion(Graph& graph)
+{
+ SamplingRegion samplingRegion("DFG Global Store Barrier Insertion Phase");
+ return runPhase<StoreBarrierInsertionPhase<PhaseMode::Global>>(graph);
+}
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
</ins></span></pre></div>
<a id="branchessafari601132branchSourceJavaScriptCoredfgDFGStoreBarrierInsertionPhasehfromrev184526branchessafari601132branchSourceJavaScriptCoredfgDFGStoreBarrierElisionPhaseh"></a>
<div class="copfile"><h4>Copied: branches/safari-601.1.32-branch/Source/JavaScriptCore/dfg/DFGStoreBarrierInsertionPhase.h (from rev 184526, branches/safari-601.1.32-branch/Source/JavaScriptCore/dfg/DFGStoreBarrierElisionPhase.h) (0 => 184527)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601.1.32-branch/Source/JavaScriptCore/dfg/DFGStoreBarrierInsertionPhase.h         (rev 0)
+++ branches/safari-601.1.32-branch/Source/JavaScriptCore/dfg/DFGStoreBarrierInsertionPhase.h        2015-05-19 00:09:01 UTC (rev 184527)
</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&);
+
+// 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 "same
+// epoch as current" property from one block to the next. This phase requires SSA. This phase
+// also requires having valid AI and liveness.
+bool performGlobalStoreBarrierInsertion(Graph&);
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
+#endif // DFGStoreBarrierInsertionPhase_h
+
</ins></span></pre></div>
<a id="branchessafari601132branchSourceJavaScriptCoreftlFTLOperationscpp"></a>
<div class="modfile"><h4>Modified: branches/safari-601.1.32-branch/Source/JavaScriptCore/ftl/FTLOperations.cpp (184526 => 184527)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601.1.32-branch/Source/JavaScriptCore/ftl/FTLOperations.cpp        2015-05-19 00:08:44 UTC (rev 184526)
+++ branches/safari-601.1.32-branch/Source/JavaScriptCore/ftl/FTLOperations.cpp        2015-05-19 00:09:01 UTC (rev 184527)
</span><span class="lines">@@ -205,7 +205,18 @@
</span><span class="cx"> unsigned index = property.location().info();
</span><span class="cx"> if (index >= capacity)
</span><span class="cx"> continue;
</span><del>- result->setIndexQuickly(vm, index, JSValue::decode(values[i]));
</del><ins>+
+ // We don't want to use setIndexQuickly(), since that's only for the passed-in
+ // arguments but sometimes the number of named arguments is greater. For
+ // example:
+ //
+ // function foo(a, b, c) { ... }
+ // foo();
+ //
+ // setIndexQuickly() would fail for indices 0, 1, 2 - but we need to recover
+ // those here.
+ result->argument(DirectArgumentsOffset(index)).set(
+ vm, result, JSValue::decode(values[i]));
</ins><span class="cx"> }
</span><span class="cx"> return result;
</span><span class="cx"> }
</span></span></pre></div>
<a id="branchessafari601132branchSourceJavaScriptCoretestsstressloadvarargstheninlinedcallandexitstrictjs"></a>
<div class="addfile"><h4>Added: branches/safari-601.1.32-branch/Source/JavaScriptCore/tests/stress/load-varargs-then-inlined-call-and-exit-strict.js (0 => 184527)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601.1.32-branch/Source/JavaScriptCore/tests/stress/load-varargs-then-inlined-call-and-exit-strict.js         (rev 0)
+++ branches/safari-601.1.32-branch/Source/JavaScriptCore/tests/stress/load-varargs-then-inlined-call-and-exit-strict.js        2015-05-19 00:09:01 UTC (rev 184527)
</span><span class="lines">@@ -0,0 +1,43 @@
</span><ins>+"use strict";
+
+function foo(a, b) {
+ var array = [];
+ for (var i = 0; i < arguments.length; ++i)
+ array.push(arguments[i]);
+ return {a:a + 1, b:b, c:array};
+}
+
+function bar(array) {
+ return foo.apply(this, array);
+}
+
+noInline(bar);
+
+function checkEqual(a, b) {
+ if (a.a != b.a)
+ throw "Error: bad value of a: " + a.a + " versus " + b.a;
+ if (a.b != b.b)
+ throw "Error: bad value of b: " + a.b + " versus " + b.b;
+ if (a.c.length != b.c.length)
+ throw "Error: bad value of c, length mismatch: " + a.c + " versus " + b.c;
+ for (var i = a.c.length; i--;) {
+ if (a.c[i] != b.c[i])
+ throw "Error: bad value of c, mismatch at i = " + i + ": " + a.c + " versus " + b.c;
+ }
+}
+
+function test(array) {
+ var expected = {a:array[0] + 1, b:array[1], c:array};
+ var actual = bar(array);
+ checkEqual(actual, expected);
+}
+
+for (var i = 0; i < 10000; ++i) {
+ var array = [];
+ for (var j = 0; j < 1 + (i % 5); ++j)
+ array.push(j);
+ test(array);
+}
+
+var array = [2147483647];
+test(array);
</ins></span></pre></div>
<a id="branchessafari601132branchSourceJavaScriptCoretestsstressloadvarargstheninlinedcallandexitjs"></a>
<div class="addfile"><h4>Added: branches/safari-601.1.32-branch/Source/JavaScriptCore/tests/stress/load-varargs-then-inlined-call-and-exit.js (0 => 184527)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601.1.32-branch/Source/JavaScriptCore/tests/stress/load-varargs-then-inlined-call-and-exit.js         (rev 0)
+++ branches/safari-601.1.32-branch/Source/JavaScriptCore/tests/stress/load-varargs-then-inlined-call-and-exit.js        2015-05-19 00:09:01 UTC (rev 184527)
</span><span class="lines">@@ -0,0 +1,41 @@
</span><ins>+function foo(a, b) {
+ var array = [];
+ for (var i = 0; i < arguments.length; ++i)
+ array.push(arguments[i]);
+ return {a:a + 1, b:b, c:array};
+}
+
+function bar(array) {
+ return foo.apply(this, array);
+}
+
+noInline(bar);
+
+function checkEqual(a, b) {
+ if (a.a != b.a)
+ throw "Error: bad value of a: " + a.a + " versus " + b.a;
+ if (a.b != b.b)
+ throw "Error: bad value of b: " + a.b + " versus " + b.b;
+ if (a.c.length != b.c.length)
+ throw "Error: bad value of c, length mismatch: " + a.c + " versus " + b.c;
+ for (var i = a.c.length; i--;) {
+ if (a.c[i] != b.c[i])
+ throw "Error: bad value of c, mismatch at i = " + i + ": " + a.c + " versus " + b.c;
+ }
+}
+
+function test(array) {
+ var expected = {a:array[0] + 1, b:array[1], c:array};
+ var actual = bar(array);
+ checkEqual(actual, expected);
+}
+
+for (var i = 0; i < 10000; ++i) {
+ var array = [];
+ for (var j = 0; j < 1 + (i % 5); ++j)
+ array.push(j);
+ test(array);
+}
+
+var array = [2147483647];
+test(array);
</ins></span></pre>
</div>
</div>
</body>
</html>