<!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>[205850] 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/205850">205850</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2016-09-12 21:33:19 -0700 (Mon, 12 Sep 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>MarkedBlock should be able to use flipIfNecessary() as the &quot;I'm not empty&quot; trigger
https://bugs.webkit.org/show_bug.cgi?id=161869

Reviewed by Saam Barati.
        
In bug 161581, I'm going to use flipIfNecessary() during marking to trigger the &quot;I'm not
empty&quot; hook, which will set a bit in the markingNotEmpty bitvector.
        
For this to work, we need to ensure that nobody else uses flipIfNecessary() during marking.
If anyone else does it but they aren't marking new objects, then this prevents
flipIfNecessary() from triggering when the first object is marked, which means we won't
always detect when a block became non-empty.
        
I addressed this by adding a isMarking flag, and asserting in flipIfNecessary() that the flag
isn't set. flipIfNecessaryDuringMarking() is used only on the marking path, so that code
knows that it can trigger something like noteMarked(). The only places that were using
flipIfNecessary() should have been using needsFlip() anyway.

* heap/CellContainer.h:
* heap/CellContainerInlines.h:
(JSC::CellContainer::needsFlip):
* heap/Heap.cpp:
(JSC::Heap::markRoots):
(JSC::Heap::beginMarking):
(JSC::Heap::endMarking):
(JSC::Heap::clearLivenessData): Deleted.
(JSC::Heap::converge): Deleted.
(JSC::Heap::resetVisitors): Deleted.
* heap/Heap.h:
* heap/HeapInlines.h:
(JSC::Heap::testAndSetMarked):
* heap/LargeAllocation.h:
(JSC::LargeAllocation::flipIfNecessaryDuringMarking):
(JSC::LargeAllocation::flipIfNecessaryConcurrently): Deleted.
* heap/MarkedBlock.cpp:
(JSC::MarkedBlock::flipIfNecessarySlow):
(JSC::MarkedBlock::flipIfNecessaryDuringMarkingSlow):
(JSC::MarkedBlock::flipIfNecessaryConcurrentlySlow): Deleted.
* heap/MarkedBlock.h:
(JSC::MarkedBlock::flipIfNecessaryDuringMarking):
(JSC::MarkedBlock::Handle::flipIfNecessaryDuringMarking):
(JSC::MarkedBlock::flipIfNecessaryConcurrently): Deleted.
(JSC::MarkedBlock::Handle::flipIfNecessaryConcurrently): Deleted.
* heap/MarkedSpace.h:
(JSC::MarkedSpace::isMarking):
(JSC::MarkedSpace::setIsMarking):
(JSC::MarkedSpace::largeAllocationsForThisCollectionSize): Deleted.
* heap/SlotVisitor.cpp:
(JSC::SlotVisitor::setMarkedAndAppendToMarkStack):
* heap/WeakBlock.cpp:
(JSC::WeakBlock::visit):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapCellContainerh">trunk/Source/JavaScriptCore/heap/CellContainer.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapCellContainerInlinesh">trunk/Source/JavaScriptCore/heap/CellContainerInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapHeapcpp">trunk/Source/JavaScriptCore/heap/Heap.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapHeaph">trunk/Source/JavaScriptCore/heap/Heap.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapHeapInlinesh">trunk/Source/JavaScriptCore/heap/HeapInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapLargeAllocationh">trunk/Source/JavaScriptCore/heap/LargeAllocation.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapMarkedBlockcpp">trunk/Source/JavaScriptCore/heap/MarkedBlock.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapMarkedBlockh">trunk/Source/JavaScriptCore/heap/MarkedBlock.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapMarkedSpaceh">trunk/Source/JavaScriptCore/heap/MarkedSpace.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapSlotVisitorcpp">trunk/Source/JavaScriptCore/heap/SlotVisitor.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapSlotVisitorh">trunk/Source/JavaScriptCore/heap/SlotVisitor.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapWeakBlockcpp">trunk/Source/JavaScriptCore/heap/WeakBlock.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapWeakBlockh">trunk/Source/JavaScriptCore/heap/WeakBlock.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (205849 => 205850)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-09-13 04:32:06 UTC (rev 205849)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-09-13 04:33:19 UTC (rev 205850)
</span><span class="lines">@@ -1,3 +1,57 @@
</span><ins>+2016-09-12  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        MarkedBlock should be able to use flipIfNecessary() as the &quot;I'm not empty&quot; trigger
+        https://bugs.webkit.org/show_bug.cgi?id=161869
+
+        Reviewed by Saam Barati.
+        
+        In bug 161581, I'm going to use flipIfNecessary() during marking to trigger the &quot;I'm not
+        empty&quot; hook, which will set a bit in the markingNotEmpty bitvector.
+        
+        For this to work, we need to ensure that nobody else uses flipIfNecessary() during marking.
+        If anyone else does it but they aren't marking new objects, then this prevents
+        flipIfNecessary() from triggering when the first object is marked, which means we won't
+        always detect when a block became non-empty.
+        
+        I addressed this by adding a isMarking flag, and asserting in flipIfNecessary() that the flag
+        isn't set. flipIfNecessaryDuringMarking() is used only on the marking path, so that code
+        knows that it can trigger something like noteMarked(). The only places that were using
+        flipIfNecessary() should have been using needsFlip() anyway.
+
+        * heap/CellContainer.h:
+        * heap/CellContainerInlines.h:
+        (JSC::CellContainer::needsFlip):
+        * heap/Heap.cpp:
+        (JSC::Heap::markRoots):
+        (JSC::Heap::beginMarking):
+        (JSC::Heap::endMarking):
+        (JSC::Heap::clearLivenessData): Deleted.
+        (JSC::Heap::converge): Deleted.
+        (JSC::Heap::resetVisitors): Deleted.
+        * heap/Heap.h:
+        * heap/HeapInlines.h:
+        (JSC::Heap::testAndSetMarked):
+        * heap/LargeAllocation.h:
+        (JSC::LargeAllocation::flipIfNecessaryDuringMarking):
+        (JSC::LargeAllocation::flipIfNecessaryConcurrently): Deleted.
+        * heap/MarkedBlock.cpp:
+        (JSC::MarkedBlock::flipIfNecessarySlow):
+        (JSC::MarkedBlock::flipIfNecessaryDuringMarkingSlow):
+        (JSC::MarkedBlock::flipIfNecessaryConcurrentlySlow): Deleted.
+        * heap/MarkedBlock.h:
+        (JSC::MarkedBlock::flipIfNecessaryDuringMarking):
+        (JSC::MarkedBlock::Handle::flipIfNecessaryDuringMarking):
+        (JSC::MarkedBlock::flipIfNecessaryConcurrently): Deleted.
+        (JSC::MarkedBlock::Handle::flipIfNecessaryConcurrently): Deleted.
+        * heap/MarkedSpace.h:
+        (JSC::MarkedSpace::isMarking):
+        (JSC::MarkedSpace::setIsMarking):
+        (JSC::MarkedSpace::largeAllocationsForThisCollectionSize): Deleted.
+        * heap/SlotVisitor.cpp:
+        (JSC::SlotVisitor::setMarkedAndAppendToMarkStack):
+        * heap/WeakBlock.cpp:
+        (JSC::WeakBlock::visit):
+
</ins><span class="cx"> 2016-09-12  Saam Barati  &lt;sbarati@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         HashMapImpl should take into account m_deleteCount in its load factor and it should be able to rehash the table to be smaller
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapCellContainerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/CellContainer.h (205849 => 205850)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/CellContainer.h        2016-09-13 04:32:06 UTC (rev 205849)
+++ trunk/Source/JavaScriptCore/heap/CellContainer.h        2016-09-13 04:33:19 UTC (rev 205850)
</span><span class="lines">@@ -75,6 +75,7 @@
</span><span class="cx">     
</span><span class="cx">     void flipIfNecessary(HeapVersion);
</span><span class="cx">     void flipIfNecessary();
</span><ins>+    bool needsFlip() const;
</ins><span class="cx">     
</span><span class="cx">     bool isMarked() const;
</span><span class="cx">     bool isMarked(HeapCell*) const;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapCellContainerInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/CellContainerInlines.h (205849 => 205850)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/CellContainerInlines.h        2016-09-13 04:32:06 UTC (rev 205849)
+++ trunk/Source/JavaScriptCore/heap/CellContainerInlines.h        2016-09-13 04:33:19 UTC (rev 205850)
</span><span class="lines">@@ -85,5 +85,12 @@
</span><span class="cx">         markedBlock().flipIfNecessary();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+inline bool CellContainer::needsFlip() const
+{
+    if (isLargeAllocation())
+        return false;
+    return markedBlock().needsFlip();
+}
+
</ins><span class="cx"> } // namespace JSC
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapHeapcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/Heap.cpp (205849 => 205850)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/Heap.cpp        2016-09-13 04:32:06 UTC (rev 205849)
+++ trunk/Source/JavaScriptCore/heap/Heap.cpp        2016-09-13 04:33:19 UTC (rev 205850)
</span><span class="lines">@@ -419,7 +419,7 @@
</span><span class="cx">             m_slotVisitor.clearMarkStack();
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        clearLivenessData();
</del><ins>+        beginMarking();
</ins><span class="cx"> 
</span><span class="cx">         m_parallelMarkersShouldExit = false;
</span><span class="cx"> 
</span><span class="lines">@@ -471,7 +471,7 @@
</span><span class="cx">         visitSamplingProfiler();
</span><span class="cx">         visitShadowChicken();
</span><span class="cx">         traceCodeBlocksAndJITStubRoutines();
</span><del>-        converge();
</del><ins>+        m_slotVisitor.drainFromShared(SlotVisitor::MasterDrain);
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     TimingScope postConvergenceTimingScope(*this, &quot;Heap::markRoots after convergence&quot;);
</span><span class="lines">@@ -487,7 +487,7 @@
</span><span class="cx">     }
</span><span class="cx">     m_helperClient.finish();
</span><span class="cx">     updateObjectCounts(gcStartTime);
</span><del>-    resetVisitors();
</del><ins>+    endMarking();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void Heap::gatherStackRoots(ConservativeRoots&amp; roots, void* stackOrigin, void* stackTop, MachineThreads::RegisterState&amp; calleeSavedRegisters)
</span><span class="lines">@@ -514,9 +514,9 @@
</span><span class="cx"> #endif
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void Heap::clearLivenessData()
</del><ins>+void Heap::beginMarking()
</ins><span class="cx"> {
</span><del>-    TimingScope timingScope(*this, &quot;Heap::clearLivenessData&quot;);
</del><ins>+    TimingScope timingScope(*this, &quot;Heap::beginMarking&quot;);
</ins><span class="cx">     if (m_operationInProgress == FullCollection)
</span><span class="cx">         m_codeBlocks-&gt;clearMarksForFullCollection();
</span><span class="cx">     
</span><span class="lines">@@ -529,6 +529,8 @@
</span><span class="cx">         TimingScope clearMarksTimingScope(*this, &quot;m_objectSpace.clearMarks&quot;);
</span><span class="cx">         m_objectSpace.flip();
</span><span class="cx">     }
</span><ins>+    
+    m_objectSpace.setIsMarking(true);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void Heap::visitExternalRememberedSet()
</span><span class="lines">@@ -727,11 +729,6 @@
</span><span class="cx">     m_slotVisitor.donateAndDrain();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void Heap::converge()
-{
-    m_slotVisitor.drainFromShared(SlotVisitor::MasterDrain);
-}
-
</del><span class="cx"> void Heap::visitWeakHandles(HeapRootVisitor&amp; visitor)
</span><span class="cx"> {
</span><span class="cx">     TimingScope timingScope(*this, &quot;Heap::visitWeakHandles&quot;);
</span><span class="lines">@@ -772,7 +769,7 @@
</span><span class="cx">     m_totalBytesVisited += m_totalBytesVisitedThisCycle;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void Heap::resetVisitors()
</del><ins>+void Heap::endMarking()
</ins><span class="cx"> {
</span><span class="cx">     m_slotVisitor.reset();
</span><span class="cx"> 
</span><span class="lines">@@ -781,6 +778,8 @@
</span><span class="cx"> 
</span><span class="cx">     ASSERT(m_sharedMarkStack.isEmpty());
</span><span class="cx">     m_weakReferenceHarvesters.removeAll();
</span><ins>+    
+    m_objectSpace.setIsMarking(false);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> size_t Heap::objectCount()
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapHeaph"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/Heap.h (205849 => 205850)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/Heap.h        2016-09-13 04:32:06 UTC (rev 205849)
+++ trunk/Source/JavaScriptCore/heap/Heap.h        2016-09-13 04:33:19 UTC (rev 205850)
</span><span class="lines">@@ -308,7 +308,7 @@
</span><span class="cx">     void gatherStackRoots(ConservativeRoots&amp;, void* stackOrigin, void* stackTop, MachineThreads::RegisterState&amp;);
</span><span class="cx">     void gatherJSStackRoots(ConservativeRoots&amp;);
</span><span class="cx">     void gatherScratchBufferRoots(ConservativeRoots&amp;);
</span><del>-    void clearLivenessData();
</del><ins>+    void beginMarking();
</ins><span class="cx">     void visitExternalRememberedSet();
</span><span class="cx">     void visitSmallStrings();
</span><span class="cx">     void visitConservativeRoots(ConservativeRoots&amp;);
</span><span class="lines">@@ -322,10 +322,9 @@
</span><span class="cx">     void visitSamplingProfiler();
</span><span class="cx">     void visitShadowChicken();
</span><span class="cx">     void traceCodeBlocksAndJITStubRoutines();
</span><del>-    void converge();
</del><span class="cx">     void visitWeakHandles(HeapRootVisitor&amp;);
</span><span class="cx">     void updateObjectCounts(double gcStartTime);
</span><del>-    void resetVisitors();
</del><ins>+    void endMarking();
</ins><span class="cx"> 
</span><span class="cx">     void reapWeakHandles();
</span><span class="cx">     void pruneStaleEntriesFromWeakGCMaps();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapHeapInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/HeapInlines.h (205849 => 205850)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/HeapInlines.h        2016-09-13 04:32:06 UTC (rev 205849)
+++ trunk/Source/JavaScriptCore/heap/HeapInlines.h        2016-09-13 04:33:19 UTC (rev 205850)
</span><span class="lines">@@ -115,7 +115,7 @@
</span><span class="cx">     if (cell-&gt;isLargeAllocation())
</span><span class="cx">         return cell-&gt;largeAllocation().testAndSetMarked();
</span><span class="cx">     MarkedBlock&amp; block = cell-&gt;markedBlock();
</span><del>-    block.flipIfNecessaryConcurrently(version);
</del><ins>+    block.flipIfNecessaryDuringMarking(version);
</ins><span class="cx">     return block.testAndSetMarked(cell);
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapLargeAllocationh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/LargeAllocation.h (205849 => 205850)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/LargeAllocation.h        2016-09-13 04:32:06 UTC (rev 205849)
+++ trunk/Source/JavaScriptCore/heap/LargeAllocation.h        2016-09-13 04:33:19 UTC (rev 205850)
</span><span class="lines">@@ -71,6 +71,8 @@
</span><span class="cx">     bool isNewlyAllocated() const { return m_isNewlyAllocated; }
</span><span class="cx">     ALWAYS_INLINE bool isMarked() { return m_isMarked.load(std::memory_order_relaxed); }
</span><span class="cx">     bool isMarkedOrNewlyAllocated() { return isMarked() || isNewlyAllocated(); }
</span><ins>+    bool isMarkedOrNewlyAllocated(HeapCell*) { return isMarkedOrNewlyAllocated(); }
+    bool isMarkedOrNewlyAllocatedDuringWeakVisiting(HeapVersion, HeapCell*) { return isMarkedOrNewlyAllocated(); }
</ins><span class="cx">     bool isLive() { return isMarkedOrNewlyAllocated(); }
</span><span class="cx">     
</span><span class="cx">     bool hasValidCell() const { return m_hasValidCell; }
</span><span class="lines">@@ -105,7 +107,7 @@
</span><span class="cx">     const AllocatorAttributes&amp; attributes() const { return m_attributes; }
</span><span class="cx">     
</span><span class="cx">     void flipIfNecessary(uint64_t) { }
</span><del>-    void flipIfNecessaryConcurrently(uint64_t) { }
</del><ins>+    void flipIfNecessaryDuringMarking(uint64_t) { }
</ins><span class="cx">     
</span><span class="cx">     ALWAYS_INLINE bool testAndSetMarked()
</span><span class="cx">     {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapMarkedBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/MarkedBlock.cpp (205849 => 205850)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/MarkedBlock.cpp        2016-09-13 04:32:06 UTC (rev 205849)
+++ trunk/Source/JavaScriptCore/heap/MarkedBlock.cpp        2016-09-13 04:33:19 UTC (rev 205850)
</span><span class="lines">@@ -358,11 +358,13 @@
</span><span class="cx"> void MarkedBlock::flipIfNecessarySlow()
</span><span class="cx"> {
</span><span class="cx">     ASSERT(needsFlip());
</span><ins>+    ASSERT(!vm()-&gt;heap.objectSpace().isMarking());
</ins><span class="cx">     clearMarks();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void MarkedBlock::flipIfNecessaryConcurrentlySlow()
</del><ins>+void MarkedBlock::flipIfNecessaryDuringMarkingSlow()
</ins><span class="cx"> {
</span><ins>+    ASSERT(vm()-&gt;heap.objectSpace().isMarking());
</ins><span class="cx">     LockHolder locker(m_lock);
</span><span class="cx">     if (needsFlip())
</span><span class="cx">         clearMarks();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapMarkedBlockh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/MarkedBlock.h (205849 => 205850)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/MarkedBlock.h        2016-09-13 04:32:06 UTC (rev 205849)
+++ trunk/Source/JavaScriptCore/heap/MarkedBlock.h        2016-09-13 04:33:19 UTC (rev 205850)
</span><span class="lines">@@ -186,7 +186,7 @@
</span><span class="cx">             
</span><span class="cx">         bool needsFlip();
</span><span class="cx">             
</span><del>-        void flipIfNecessaryConcurrently(HeapVersion);
</del><ins>+        void flipIfNecessaryDuringMarking(HeapVersion);
</ins><span class="cx">         void flipIfNecessary(HeapVersion);
</span><span class="cx">         void flipIfNecessary();
</span><span class="cx">             
</span><span class="lines">@@ -251,6 +251,7 @@
</span><span class="cx">     bool testAndSetMarked(const void*);
</span><span class="cx">         
</span><span class="cx">     bool isMarkedOrNewlyAllocated(const HeapCell*);
</span><ins>+    bool isMarkedOrNewlyAllocatedDuringWeakVisiting(HeapVersion, const HeapCell*);
</ins><span class="cx"> 
</span><span class="cx">     bool isAtom(const void*);
</span><span class="cx">     void setMarked(const void*);
</span><span class="lines">@@ -267,7 +268,7 @@
</span><span class="cx">     bool needsFlip(HeapVersion);
</span><span class="cx">     bool needsFlip();
</span><span class="cx">         
</span><del>-    void flipIfNecessaryConcurrently(HeapVersion);
</del><ins>+    void flipIfNecessaryDuringMarking(HeapVersion);
</ins><span class="cx">     void flipIfNecessary(HeapVersion);
</span><span class="cx">     void flipIfNecessary();
</span><span class="cx">         
</span><span class="lines">@@ -283,7 +284,7 @@
</span><span class="cx">     MarkedBlock(VM&amp;, Handle&amp;);
</span><span class="cx">     Atom* atoms();
</span><span class="cx">         
</span><del>-    void flipIfNecessaryConcurrentlySlow();
</del><ins>+    void flipIfNecessaryDuringMarkingSlow();
</ins><span class="cx">     void flipIfNecessarySlow();
</span><span class="cx">     void clearMarks();
</span><span class="cx">     void clearHasAnyMarked();
</span><span class="lines">@@ -474,10 +475,10 @@
</span><span class="cx">         flipIfNecessarySlow();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline void MarkedBlock::flipIfNecessaryConcurrently(HeapVersion heapVersion)
</del><ins>+inline void MarkedBlock::flipIfNecessaryDuringMarking(HeapVersion heapVersion)
</ins><span class="cx"> {
</span><span class="cx">     if (UNLIKELY(needsFlip(heapVersion)))
</span><del>-        flipIfNecessaryConcurrentlySlow();
</del><ins>+        flipIfNecessaryDuringMarkingSlow();
</ins><span class="cx">     WTF::loadLoadFence();
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -486,9 +487,9 @@
</span><span class="cx">     block().flipIfNecessary(heapVersion);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline void MarkedBlock::Handle::flipIfNecessaryConcurrently(HeapVersion heapVersion)
</del><ins>+inline void MarkedBlock::Handle::flipIfNecessaryDuringMarking(HeapVersion heapVersion)
</ins><span class="cx"> {
</span><del>-    block().flipIfNecessaryConcurrently(heapVersion);
</del><ins>+    block().flipIfNecessaryDuringMarking(heapVersion);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> inline void MarkedBlock::Handle::flipForEdenCollection()
</span><span class="lines">@@ -561,6 +562,13 @@
</span><span class="cx">     return isMarked(cell) || (m_handle.m_newlyAllocated &amp;&amp; m_handle.isNewlyAllocated(cell));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+inline bool MarkedBlock::isMarkedOrNewlyAllocatedDuringWeakVisiting(HeapVersion heapVersion, const HeapCell* cell)
+{
+    if (needsFlip(heapVersion))
+        return false;
+    return isMarkedOrNewlyAllocated(cell);
+}
+
</ins><span class="cx"> inline bool MarkedBlock::Handle::isLive(const HeapCell* cell)
</span><span class="cx"> {
</span><span class="cx">     assertFlipped();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapMarkedSpaceh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/MarkedSpace.h (205849 => 205850)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/MarkedSpace.h        2016-09-13 04:32:06 UTC (rev 205849)
+++ trunk/Source/JavaScriptCore/heap/MarkedSpace.h        2016-09-13 04:33:19 UTC (rev 205850)
</span><span class="lines">@@ -168,6 +168,13 @@
</span><span class="cx">     LargeAllocation** largeAllocationsForThisCollectionBegin() const { return m_largeAllocationsForThisCollectionBegin; }
</span><span class="cx">     LargeAllocation** largeAllocationsForThisCollectionEnd() const { return m_largeAllocationsForThisCollectionEnd; }
</span><span class="cx">     unsigned largeAllocationsForThisCollectionSize() const { return m_largeAllocationsForThisCollectionSize; }
</span><ins>+    
+    // When this is true it means that we have flipped but the mark bits haven't converged yet.
+    bool isMarking() const { return m_isMarking; }
+    
+    // FIXME: After https://bugs.webkit.org/show_bug.cgi?id=161581, MarkedSpace will control this
+    // flag directly.
+    void setIsMarking(bool value) { m_isMarking = value; }
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     friend class LLIntOffsetsExtractor;
</span><span class="lines">@@ -196,6 +203,7 @@
</span><span class="cx">     HeapVersion m_version { initialVersion };
</span><span class="cx">     size_t m_capacity;
</span><span class="cx">     bool m_isIterating;
</span><ins>+    bool m_isMarking { false };
</ins><span class="cx">     MarkedBlockSet m_blocks;
</span><span class="cx">     Vector&lt;MarkedBlock::Handle*&gt; m_blocksWithNewObjects;
</span><span class="cx">     Vector&lt;LargeAllocation*&gt; m_largeAllocations;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapSlotVisitorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/SlotVisitor.cpp (205849 => 205850)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/SlotVisitor.cpp        2016-09-13 04:32:06 UTC (rev 205849)
+++ trunk/Source/JavaScriptCore/heap/SlotVisitor.cpp        2016-09-13 04:33:19 UTC (rev 205850)
</span><span class="lines">@@ -198,7 +198,7 @@
</span><span class="cx"> template&lt;typename ContainerType&gt;
</span><span class="cx"> ALWAYS_INLINE void SlotVisitor::setMarkedAndAppendToMarkStack(ContainerType&amp; container, JSCell* cell)
</span><span class="cx"> {
</span><del>-    container.flipIfNecessaryConcurrently(m_version);
</del><ins>+    container.flipIfNecessaryDuringMarking(m_version);
</ins><span class="cx">     
</span><span class="cx">     if (container.testAndSetMarked(cell))
</span><span class="cx">         return;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapSlotVisitorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/SlotVisitor.h (205849 => 205850)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/SlotVisitor.h        2016-09-13 04:32:06 UTC (rev 205849)
+++ trunk/Source/JavaScriptCore/heap/SlotVisitor.h        2016-09-13 04:33:19 UTC (rev 205850)
</span><span class="lines">@@ -123,6 +123,8 @@
</span><span class="cx">     void dump(PrintStream&amp;) const;
</span><span class="cx"> 
</span><span class="cx">     bool isBuildingHeapSnapshot() const { return !!m_heapSnapshotBuilder; }
</span><ins>+    
+    HeapVersion version() const { return m_version; }
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     friend class ParallelModeEnabler;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapWeakBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/WeakBlock.cpp (205849 => 205850)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/WeakBlock.cpp        2016-09-13 04:32:06 UTC (rev 205849)
+++ trunk/Source/JavaScriptCore/heap/WeakBlock.cpp        2016-09-13 04:33:19 UTC (rev 205850)
</span><span class="lines">@@ -96,22 +96,13 @@
</span><span class="cx">     ASSERT(!m_sweepResult.isNull());
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void WeakBlock::visit(HeapRootVisitor&amp; heapRootVisitor)
</del><ins>+template&lt;typename ContainerType&gt;
+void WeakBlock::specializedVisit(ContainerType&amp; container, HeapRootVisitor&amp; heapRootVisitor)
</ins><span class="cx"> {
</span><del>-    // If a block is completely empty, a visit won't have any effect.
-    if (isEmpty())
-        return;
-
-    // If this WeakBlock doesn't belong to a CellContainer, we won't even be here.
-    ASSERT(m_container);
</del><ins>+    SlotVisitor&amp; visitor = heapRootVisitor.visitor();
</ins><span class="cx">     
</span><del>-    m_container.flipIfNecessary();
</del><ins>+    HeapVersion version = visitor.version();
</ins><span class="cx"> 
</span><del>-    // We only visit after marking.
-    ASSERT(m_container.isMarked());
-
-    SlotVisitor&amp; visitor = heapRootVisitor.visitor();
-
</del><span class="cx">     for (size_t i = 0; i &lt; weakImplCount(); ++i) {
</span><span class="cx">         WeakImpl* weakImpl = &amp;weakImpls()[i];
</span><span class="cx">         if (weakImpl-&gt;state() != WeakImpl::Live)
</span><span class="lines">@@ -122,7 +113,7 @@
</span><span class="cx">             continue;
</span><span class="cx"> 
</span><span class="cx">         const JSValue&amp; jsValue = weakImpl-&gt;jsValue();
</span><del>-        if (m_container.isMarkedOrNewlyAllocated(jsValue.asCell()))
</del><ins>+        if (container.isMarkedOrNewlyAllocatedDuringWeakVisiting(version, jsValue.asCell()))
</ins><span class="cx">             continue;
</span><span class="cx">         
</span><span class="cx">         if (!weakHandleOwner-&gt;isReachableFromOpaqueRoots(Handle&lt;Unknown&gt;::wrapSlot(&amp;const_cast&lt;JSValue&amp;&gt;(jsValue)), weakImpl-&gt;context(), visitor))
</span><span class="lines">@@ -132,6 +123,21 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void WeakBlock::visit(HeapRootVisitor&amp; heapRootVisitor)
+{
+    // If a block is completely empty, a visit won't have any effect.
+    if (isEmpty())
+        return;
+
+    // If this WeakBlock doesn't belong to a CellContainer, we won't even be here.
+    ASSERT(m_container);
+    
+    if (m_container.isLargeAllocation())
+        specializedVisit(m_container.largeAllocation(), heapRootVisitor);
+    else
+        specializedVisit(m_container.markedBlock(), heapRootVisitor);
+}
+
</ins><span class="cx"> void WeakBlock::reap()
</span><span class="cx"> {
</span><span class="cx">     // If a block is completely empty, a reaping won't have any effect.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapWeakBlockh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/WeakBlock.h (205849 => 205850)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/WeakBlock.h        2016-09-13 04:32:06 UTC (rev 205849)
+++ trunk/Source/JavaScriptCore/heap/WeakBlock.h        2016-09-13 04:33:19 UTC (rev 205850)
</span><span class="lines">@@ -72,6 +72,9 @@
</span><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     static FreeCell* asFreeCell(WeakImpl*);
</span><ins>+    
+    template&lt;typename ContainerType&gt;
+    void specializedVisit(ContainerType&amp;, HeapRootVisitor&amp;);
</ins><span class="cx"> 
</span><span class="cx">     explicit WeakBlock(CellContainer);
</span><span class="cx">     void finalize(WeakImpl*);
</span></span></pre>
</div>
</div>

</body>
</html>