<!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>[190563] 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/190563">190563</a></dd>
<dt>Author</dt> <dd>ggaren@apple.com</dd>
<dt>Date</dt> <dd>2015-10-05 10:22:20 -0700 (Mon, 05 Oct 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>JSC::SlotVisitor should not be a hot mess
https://bugs.webkit.org/show_bug.cgi?id=149798

Reviewed by Andreas Kling.

I had to debug JSC::SlotVisitor the other day. It was hard to follow.
Let's make it easy to follow.

* heap/Heap.cpp:
(JSC::Heap::markRoots):
(JSC::Heap::resetVisitors):
(JSC::Heap::objectCount):
(JSC::Heap::addToRememberedSet):
(JSC::Heap::collectAndSweep):
* heap/Heap.h: Deleted the string hash-consing code. It
was dead code.

Since no benchmark noticed the commit that broke this feature, perhaps
it's not worth having.

Either way, the best thing to do with dead code is to delete it.
It's still there in svn if we ever want to pick it up again.

* heap/HeapRootVisitor.h:
(JSC::HeapRootVisitor::visit):
(JSC::HeapRootVisitor::visitor): Removed the private append functions
for unsafe pointers and switched HeapRootVisitor over to the public
specially named functions for unsafe pointers.

In future, we should either remove the public specially named functions
or remove HeapRootVisitor, since they serve the same purpose. At least
for now we don't have pairs of functions on SlotVisitor that do the
exact same thing.

* heap/SlotVisitor.cpp:
(JSC::validate): Moved this static function to the top of the file.

(JSC::SlotVisitor::SlotVisitor):
(JSC::SlotVisitor::didStartMarking):
(JSC::SlotVisitor::reset): More hash cons removal.

(JSC::SlotVisitor::append):

(JSC::SlotVisitor::setMarkedAndAppendToMarkStack):
(JSC::SlotVisitor::appendToMarkStack): Renamed these functions to 
distinguish them from the up-front helper functions that just do type
conversions. These are the functions that actually do stuff.

Moved these functions out of line to make it easier to set breakpoints,
and to enable code changes for debugging, like printf and synchronous
marking, without recompiling the world.

setMarkedAndAppendToMarkStack is roughly 258 bytes long (not including
function prologue and epilogue), so inlining it was probably not a
great idea in the first place.

(JSC::SlotVisitor::donateKnownParallel):
(JSC::SlotVisitor::drain):
(JSC::SlotVisitor::drainFromShared): Removed some stack probing code.
It was also dead.

(JSC::SlotVisitor::addOpaqueRoot):
(JSC::SlotVisitor::containsOpaqueRoot):
(JSC::SlotVisitor::containsOpaqueRootTriState):
(JSC::SlotVisitor::opaqueRootCount):
(JSC::SlotVisitor::mergeOpaqueRootsIfNecessary):
(JSC::SlotVisitor::mergeOpaqueRootsIfProfitable):
(JSC::SlotVisitor::donate):
(JSC::SlotVisitor::donateAndDrain):
(JSC::SlotVisitor::copyLater):
(JSC::SlotVisitor::mergeOpaqueRoots):
(JSC::SlotVisitor::harvestWeakReferences):
(JSC::SlotVisitor::finalizeUnconditionalFinalizers):
(JSC::SlotVisitor::dump): Moved more code out-of-line. These code paths
are not hot and/or not small, so we need more evidence before we inline
them. The SlotVisitor headers are included everywhere, so we should
make them include less.

Removed &quot;internal&quot; from all function names because it wasn't applied in
any consistent way that would mean anything.

(JSC::JSString::tryHashConsLock): Deleted.
(JSC::JSString::releaseHashConsLock): Deleted.
(JSC::JSString::shouldTryHashCons): Deleted.
(JSC::SlotVisitor::internalAppend): Deleted.
(JSC::SlotVisitor::validate): Deleted.

* heap/SlotVisitor.h:
(JSC::SlotVisitor::resetChildCount): Deleted.
(JSC::SlotVisitor::childCount): Deleted.
(JSC::SlotVisitor::incrementChildCount): Deleted. Removed this child
count thing. It was dead code.

* heap/SlotVisitorInlines.h:
(JSC::SlotVisitor::appendUnbarrieredPointer):
(JSC::SlotVisitor::appendUnbarrieredReadOnlyPointer):
(JSC::SlotVisitor::appendUnbarrieredValue):
(JSC::SlotVisitor::appendUnbarrieredReadOnlyValue): Some renaming and un-inlining.

(JSC::SlotVisitor::appendUnbarrieredWeak): Don't null check our input.
The one true place where null checking happens is our out-of-line
code. All inline functions do only type conversions.

(JSC::SlotVisitor::append):
(JSC::SlotVisitor::appendValues):
(JSC::SlotVisitor::addWeakReferenceHarvester):
(JSC::SlotVisitor::addUnconditionalFinalizer):
(JSC::SlotVisitor::reportExtraMemoryVisited): Some renaming and un-inlining.

(JSC::SlotVisitor::internalAppend): Deleted.
(JSC::SlotVisitor::unconditionallyAppend): Deleted.
(JSC::SlotVisitor::addOpaqueRoot): Deleted.
(JSC::SlotVisitor::containsOpaqueRoot): Deleted.
(JSC::SlotVisitor::containsOpaqueRootTriState): Deleted.
(JSC::SlotVisitor::opaqueRootCount): Deleted.
(JSC::SlotVisitor::mergeOpaqueRootsIfNecessary): Deleted.
(JSC::SlotVisitor::mergeOpaqueRootsIfProfitable): Deleted.
(JSC::SlotVisitor::donate): Deleted.
(JSC::SlotVisitor::donateAndDrain): Deleted.
(JSC::SlotVisitor::copyLater): Deleted.

* runtime/JSString.h:
(JSC::JSString::finishCreation):
(JSC::JSString::setIs8Bit):
(JSC::JSString::isHashConsSingleton): Deleted.
(JSC::JSString::clearHashConsSingleton): Deleted.
(JSC::JSString::setHashConsSingleton): Deleted. More hash cons removal.

* runtime/VM.cpp:
(JSC::VM::VM):
* runtime/VM.h:
(JSC::VM::currentThreadIsHoldingAPILock):
(JSC::VM::apiLock):
(JSC::VM::haveEnoughNewStringsToHashCons): Deleted.
(JSC::VM::resetNewStringsSinceLastHashCons): Deleted. More hash cons removal.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</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="#trunkSourceJavaScriptCoreheapHeapRootVisitorh">trunk/Source/JavaScriptCore/heap/HeapRootVisitor.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="#trunkSourceJavaScriptCoreheapSlotVisitorInlinesh">trunk/Source/JavaScriptCore/heap/SlotVisitorInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeDirectArgumentscpp">trunk/Source/JavaScriptCore/runtime/DirectArguments.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSMapcpp">trunk/Source/JavaScriptCore/runtime/JSMap.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSObjectcpp">trunk/Source/JavaScriptCore/runtime/JSObject.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSSetcpp">trunk/Source/JavaScriptCore/runtime/JSSet.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSStringh">trunk/Source/JavaScriptCore/runtime/JSString.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSTypedArrayscpp">trunk/Source/JavaScriptCore/runtime/JSTypedArrays.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeVMcpp">trunk/Source/JavaScriptCore/runtime/VM.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeVMh">trunk/Source/JavaScriptCore/runtime/VM.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (190562 => 190563)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-10-05 17:18:26 UTC (rev 190562)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-10-05 17:22:20 UTC (rev 190563)
</span><span class="lines">@@ -1,3 +1,141 @@
</span><ins>+2015-10-05  Geoffrey Garen  &lt;ggaren@apple.com&gt;
+
+        JSC::SlotVisitor should not be a hot mess
+        https://bugs.webkit.org/show_bug.cgi?id=149798
+
+        Reviewed by Andreas Kling.
+
+        I had to debug JSC::SlotVisitor the other day. It was hard to follow.
+        Let's make it easy to follow.
+
+        * heap/Heap.cpp:
+        (JSC::Heap::markRoots):
+        (JSC::Heap::resetVisitors):
+        (JSC::Heap::objectCount):
+        (JSC::Heap::addToRememberedSet):
+        (JSC::Heap::collectAndSweep):
+        * heap/Heap.h: Deleted the string hash-consing code. It
+        was dead code.
+
+        Since no benchmark noticed the commit that broke this feature, perhaps
+        it's not worth having.
+
+        Either way, the best thing to do with dead code is to delete it.
+        It's still there in svn if we ever want to pick it up again.
+
+        * heap/HeapRootVisitor.h:
+        (JSC::HeapRootVisitor::visit):
+        (JSC::HeapRootVisitor::visitor): Removed the private append functions
+        for unsafe pointers and switched HeapRootVisitor over to the public
+        specially named functions for unsafe pointers.
+
+        In future, we should either remove the public specially named functions
+        or remove HeapRootVisitor, since they serve the same purpose. At least
+        for now we don't have pairs of functions on SlotVisitor that do the
+        exact same thing.
+
+        * heap/SlotVisitor.cpp:
+        (JSC::validate): Moved this static function to the top of the file.
+
+        (JSC::SlotVisitor::SlotVisitor):
+        (JSC::SlotVisitor::didStartMarking):
+        (JSC::SlotVisitor::reset): More hash cons removal.
+
+        (JSC::SlotVisitor::append):
+
+        (JSC::SlotVisitor::setMarkedAndAppendToMarkStack):
+        (JSC::SlotVisitor::appendToMarkStack): Renamed these functions to 
+        distinguish them from the up-front helper functions that just do type
+        conversions. These are the functions that actually do stuff.
+
+        Moved these functions out of line to make it easier to set breakpoints,
+        and to enable code changes for debugging, like printf and synchronous
+        marking, without recompiling the world.
+
+        setMarkedAndAppendToMarkStack is roughly 258 bytes long (not including
+        function prologue and epilogue), so inlining it was probably not a
+        great idea in the first place.
+
+        (JSC::SlotVisitor::donateKnownParallel):
+        (JSC::SlotVisitor::drain):
+        (JSC::SlotVisitor::drainFromShared): Removed some stack probing code.
+        It was also dead.
+
+        (JSC::SlotVisitor::addOpaqueRoot):
+        (JSC::SlotVisitor::containsOpaqueRoot):
+        (JSC::SlotVisitor::containsOpaqueRootTriState):
+        (JSC::SlotVisitor::opaqueRootCount):
+        (JSC::SlotVisitor::mergeOpaqueRootsIfNecessary):
+        (JSC::SlotVisitor::mergeOpaqueRootsIfProfitable):
+        (JSC::SlotVisitor::donate):
+        (JSC::SlotVisitor::donateAndDrain):
+        (JSC::SlotVisitor::copyLater):
+        (JSC::SlotVisitor::mergeOpaqueRoots):
+        (JSC::SlotVisitor::harvestWeakReferences):
+        (JSC::SlotVisitor::finalizeUnconditionalFinalizers):
+        (JSC::SlotVisitor::dump): Moved more code out-of-line. These code paths
+        are not hot and/or not small, so we need more evidence before we inline
+        them. The SlotVisitor headers are included everywhere, so we should
+        make them include less.
+
+        Removed &quot;internal&quot; from all function names because it wasn't applied in
+        any consistent way that would mean anything.
+
+        (JSC::JSString::tryHashConsLock): Deleted.
+        (JSC::JSString::releaseHashConsLock): Deleted.
+        (JSC::JSString::shouldTryHashCons): Deleted.
+        (JSC::SlotVisitor::internalAppend): Deleted.
+        (JSC::SlotVisitor::validate): Deleted.
+
+        * heap/SlotVisitor.h:
+        (JSC::SlotVisitor::resetChildCount): Deleted.
+        (JSC::SlotVisitor::childCount): Deleted.
+        (JSC::SlotVisitor::incrementChildCount): Deleted. Removed this child
+        count thing. It was dead code.
+
+        * heap/SlotVisitorInlines.h:
+        (JSC::SlotVisitor::appendUnbarrieredPointer):
+        (JSC::SlotVisitor::appendUnbarrieredReadOnlyPointer):
+        (JSC::SlotVisitor::appendUnbarrieredValue):
+        (JSC::SlotVisitor::appendUnbarrieredReadOnlyValue): Some renaming and un-inlining.
+
+        (JSC::SlotVisitor::appendUnbarrieredWeak): Don't null check our input.
+        The one true place where null checking happens is our out-of-line
+        code. All inline functions do only type conversions.
+
+        (JSC::SlotVisitor::append):
+        (JSC::SlotVisitor::appendValues):
+        (JSC::SlotVisitor::addWeakReferenceHarvester):
+        (JSC::SlotVisitor::addUnconditionalFinalizer):
+        (JSC::SlotVisitor::reportExtraMemoryVisited): Some renaming and un-inlining.
+
+        (JSC::SlotVisitor::internalAppend): Deleted.
+        (JSC::SlotVisitor::unconditionallyAppend): Deleted.
+        (JSC::SlotVisitor::addOpaqueRoot): Deleted.
+        (JSC::SlotVisitor::containsOpaqueRoot): Deleted.
+        (JSC::SlotVisitor::containsOpaqueRootTriState): Deleted.
+        (JSC::SlotVisitor::opaqueRootCount): Deleted.
+        (JSC::SlotVisitor::mergeOpaqueRootsIfNecessary): Deleted.
+        (JSC::SlotVisitor::mergeOpaqueRootsIfProfitable): Deleted.
+        (JSC::SlotVisitor::donate): Deleted.
+        (JSC::SlotVisitor::donateAndDrain): Deleted.
+        (JSC::SlotVisitor::copyLater): Deleted.
+
+        * runtime/JSString.h:
+        (JSC::JSString::finishCreation):
+        (JSC::JSString::setIs8Bit):
+        (JSC::JSString::isHashConsSingleton): Deleted.
+        (JSC::JSString::clearHashConsSingleton): Deleted.
+        (JSC::JSString::setHashConsSingleton): Deleted. More hash cons removal.
+
+        * runtime/VM.cpp:
+        (JSC::VM::VM):
+        * runtime/VM.h:
+        (JSC::VM::currentThreadIsHoldingAPILock):
+        (JSC::VM::apiLock):
+        (JSC::VM::haveEnoughNewStringsToHashCons): Deleted.
+        (JSC::VM::resetNewStringsSinceLastHashCons): Deleted. More hash cons removal.
+
</ins><span class="cx"> 2015-10-04  Filip Pizlo  &lt;fpizlo@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Inline cache repatching should be throttled if it happens a lot
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapHeapcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/Heap.cpp (190562 => 190563)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/Heap.cpp        2015-10-05 17:18:26 UTC (rev 190562)
+++ trunk/Source/JavaScriptCore/heap/Heap.cpp        2015-10-05 17:22:20 UTC (rev 190563)
</span><span class="lines">@@ -543,8 +543,6 @@
</span><span class="cx">     if (m_operationInProgress == FullCollection)
</span><span class="cx">         m_opaqueRoots.clear();
</span><span class="cx"> 
</span><del>-    m_shouldHashCons = m_vm-&gt;haveEnoughNewStringsToHashCons();
-
</del><span class="cx">     m_parallelMarkersShouldExit = false;
</span><span class="cx"> 
</span><span class="cx">     m_helperClient.setFunction(
</span><span class="lines">@@ -895,10 +893,6 @@
</span><span class="cx"> 
</span><span class="cx">     ASSERT(m_sharedMarkStack.isEmpty());
</span><span class="cx">     m_weakReferenceHarvesters.removeAll();
</span><del>-    if (m_shouldHashCons) {
-        m_vm-&gt;resetNewStringsSinceLastHashCons();
-        m_shouldHashCons = false;
-    }
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> size_t Heap::objectCount()
</span><span class="lines">@@ -1017,7 +1011,7 @@
</span><span class="cx">     if (isRemembered(cell))
</span><span class="cx">         return;
</span><span class="cx">     const_cast&lt;JSCell*&gt;(cell)-&gt;setRemembered(true);
</span><del>-    m_slotVisitor.unconditionallyAppend(const_cast&lt;JSCell*&gt;(cell));
</del><ins>+    m_slotVisitor.appendToMarkStack(const_cast&lt;JSCell*&gt;(cell));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void Heap::collectAndSweep(HeapOperation collectionType)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapHeaph"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/Heap.h (190562 => 190563)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/Heap.h        2015-10-05 17:18:26 UTC (rev 190562)
+++ trunk/Source/JavaScriptCore/heap/Heap.h        2015-10-05 17:22:20 UTC (rev 190563)
</span><span class="lines">@@ -423,8 +423,6 @@
</span><span class="cx"> 
</span><span class="cx">     HashMap&lt;void*, std::function&lt;void()&gt;&gt; m_weakGCMaps;
</span><span class="cx"> 
</span><del>-    bool m_shouldHashCons { false };
-
</del><span class="cx">     Lock m_markingMutex;
</span><span class="cx">     Condition m_markingConditionVariable;
</span><span class="cx">     MarkStackArray m_sharedMarkStack;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapHeapRootVisitorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/HeapRootVisitor.h (190562 => 190563)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/HeapRootVisitor.h        2015-10-05 17:18:26 UTC (rev 190562)
+++ trunk/Source/JavaScriptCore/heap/HeapRootVisitor.h        2015-10-05 17:22:20 UTC (rev 190563)
</span><span class="lines">@@ -58,22 +58,23 @@
</span><span class="cx"> 
</span><span class="cx">     inline void HeapRootVisitor::visit(JSValue* slot)
</span><span class="cx">     {
</span><del>-        m_visitor.append(slot);
</del><ins>+        m_visitor.appendUnbarrieredValue(slot);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     inline void HeapRootVisitor::visit(JSValue* slot, size_t count)
</span><span class="cx">     {
</span><del>-        m_visitor.append(slot, count);
</del><ins>+        for (size_t i = 0; i &lt; count; ++i)
+            m_visitor.appendUnbarrieredValue(&amp;slot[i]);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     inline void HeapRootVisitor::visit(JSString** slot)
</span><span class="cx">     {
</span><del>-        m_visitor.append(reinterpret_cast&lt;JSCell**&gt;(slot));
</del><ins>+        m_visitor.appendUnbarrieredPointer(slot);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     inline void HeapRootVisitor::visit(JSCell** slot)
</span><span class="cx">     {
</span><del>-        m_visitor.append(slot);
</del><ins>+        m_visitor.appendUnbarrieredPointer(slot);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     inline SlotVisitor&amp; HeapRootVisitor::visitor()
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapSlotVisitorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/SlotVisitor.cpp (190562 => 190563)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/SlotVisitor.cpp        2015-10-05 17:18:26 UTC (rev 190562)
+++ trunk/Source/JavaScriptCore/heap/SlotVisitor.cpp        2015-10-05 17:22:20 UTC (rev 190563)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> #include &quot;SlotVisitorInlines.h&quot;
</span><span class="cx"> 
</span><span class="cx"> #include &quot;ConservativeRoots.h&quot;
</span><ins>+#include &quot;CopiedBlockInlines.h&quot;
</ins><span class="cx"> #include &quot;CopiedSpace.h&quot;
</span><span class="cx"> #include &quot;CopiedSpaceInlines.h&quot;
</span><span class="cx"> #include &quot;JSArray.h&quot;
</span><span class="lines">@@ -37,10 +38,39 @@
</span><span class="cx"> #include &quot;JSString.h&quot;
</span><span class="cx"> #include &quot;JSCInlines.h&quot;
</span><span class="cx"> #include &lt;wtf/Lock.h&gt;
</span><del>-#include &lt;wtf/StackStats.h&gt;
</del><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><ins>+#if ENABLE(GC_VALIDATION)
+static void validate(JSCell* cell)
+{
+    RELEASE_ASSERT(cell);
+
+    if (!cell-&gt;structure()) {
+        dataLogF(&quot;cell at %p has a null structure\n&quot; , cell);
+        CRASH();
+    }
+
+    // Both the cell's structure, and the cell's structure's structure should be the Structure Structure.
+    // I hate this sentence.
+    if (cell-&gt;structure()-&gt;structure()-&gt;JSCell::classInfo() != cell-&gt;structure()-&gt;JSCell::classInfo()) {
+        const char* parentClassName = 0;
+        const char* ourClassName = 0;
+        if (cell-&gt;structure()-&gt;structure() &amp;&amp; cell-&gt;structure()-&gt;structure()-&gt;JSCell::classInfo())
+            parentClassName = cell-&gt;structure()-&gt;structure()-&gt;JSCell::classInfo()-&gt;className;
+        if (cell-&gt;structure()-&gt;JSCell::classInfo())
+            ourClassName = cell-&gt;structure()-&gt;JSCell::classInfo()-&gt;className;
+        dataLogF(&quot;parent structure (%p &lt;%s&gt;) of cell at %p doesn't match cell's structure (%p &lt;%s&gt;)\n&quot;,
+            cell-&gt;structure()-&gt;structure(), parentClassName, cell, cell-&gt;structure(), ourClassName);
+        CRASH();
+    }
+
+    // Make sure we can walk the ClassInfo chain
+    const ClassInfo* info = cell-&gt;classInfo();
+    do { } while ((info = info-&gt;parentClass));
+}
+#endif
+
</ins><span class="cx"> SlotVisitor::SlotVisitor(Heap&amp; heap)
</span><span class="cx">     : m_stack()
</span><span class="cx">     , m_bytesVisited(0)
</span><span class="lines">@@ -48,7 +78,6 @@
</span><span class="cx">     , m_visitCount(0)
</span><span class="cx">     , m_isInParallelMode(false)
</span><span class="cx">     , m_heap(heap)
</span><del>-    , m_shouldHashCons(false)
</del><span class="cx"> #if !ASSERT_DISABLED
</span><span class="cx">     , m_isCheckingForDefaultMarkViolation(false)
</span><span class="cx">     , m_isDraining(false)
</span><span class="lines">@@ -65,8 +94,6 @@
</span><span class="cx"> {
</span><span class="cx">     if (heap()-&gt;operationInProgress() == FullCollection)
</span><span class="cx">         ASSERT(m_opaqueRoots.isEmpty()); // Should have merged by now.
</span><del>-
-    m_shouldHashCons = m_heap.m_shouldHashCons;
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void SlotVisitor::reset()
</span><span class="lines">@@ -75,10 +102,6 @@
</span><span class="cx">     m_bytesCopied = 0;
</span><span class="cx">     m_visitCount = 0;
</span><span class="cx">     ASSERT(m_stack.isEmpty());
</span><del>-    if (m_shouldHashCons) {
-        m_uniqueStrings.clear();
-        m_shouldHashCons = false;
-    }
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void SlotVisitor::clearMarkStack()
</span><span class="lines">@@ -88,18 +111,51 @@
</span><span class="cx"> 
</span><span class="cx"> void SlotVisitor::append(ConservativeRoots&amp; conservativeRoots)
</span><span class="cx"> {
</span><del>-    StackStats::probe();
</del><span class="cx">     JSCell** roots = conservativeRoots.roots();
</span><span class="cx">     size_t size = conservativeRoots.size();
</span><span class="cx">     for (size_t i = 0; i &lt; size; ++i)
</span><del>-        internalAppend(0, roots[i]);
</del><ins>+        append(roots[i]);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-ALWAYS_INLINE static void visitChildren(SlotVisitor&amp; visitor, const JSCell* cell)
</del><ins>+void SlotVisitor::append(JSValue value)
</ins><span class="cx"> {
</span><del>-    StackStats::probe();
</del><ins>+    if (!value || !value.isCell())
+        return;
+    setMarkedAndAppendToMarkStack(value.asCell());
+}
</ins><span class="cx"> 
</span><ins>+void SlotVisitor::setMarkedAndAppendToMarkStack(JSCell* cell)
+{
+    ASSERT(!m_isCheckingForDefaultMarkViolation);
+    if (!cell)
+        return;
+
+#if ENABLE(GC_VALIDATION)
+    validate(cell);
+#endif
+
+    if (Heap::testAndSetMarked(cell) || !cell-&gt;structure()) {
+        ASSERT(cell-&gt;structure());
+        return;
+    }
+
+    cell-&gt;setMarked();
+    appendToMarkStack(cell);
+}
+
+void SlotVisitor::appendToMarkStack(JSCell* cell)
+{
</ins><span class="cx">     ASSERT(Heap::isMarked(cell));
</span><ins>+    ASSERT(!cell-&gt;isZapped());
+
+    m_visitCount++;
+    m_bytesVisited += MarkedBlock::blockFor(cell)-&gt;cellSize();
+    m_stack.append(cell);
+}
+
+ALWAYS_INLINE static void visitChildren(SlotVisitor&amp; visitor, const JSCell* cell)
+{
+    ASSERT(Heap::isMarked(cell));
</ins><span class="cx">     
</span><span class="cx">     if (isJSString(cell)) {
</span><span class="cx">         JSString::visitChildren(const_cast&lt;JSCell*&gt;(cell), visitor);
</span><span class="lines">@@ -121,7 +177,6 @@
</span><span class="cx"> 
</span><span class="cx"> void SlotVisitor::donateKnownParallel()
</span><span class="cx"> {
</span><del>-    StackStats::probe();
</del><span class="cx">     // NOTE: Because we re-try often, we can afford to be conservative, and
</span><span class="cx">     // assume that donating is not profitable.
</span><span class="cx"> 
</span><span class="lines">@@ -148,7 +203,6 @@
</span><span class="cx"> 
</span><span class="cx"> void SlotVisitor::drain()
</span><span class="cx"> {
</span><del>-    StackStats::probe();
</del><span class="cx">     ASSERT(m_isInParallelMode);
</span><span class="cx">    
</span><span class="cx">     while (!m_stack.isEmpty()) {
</span><span class="lines">@@ -163,7 +217,6 @@
</span><span class="cx"> 
</span><span class="cx"> void SlotVisitor::drainFromShared(SharedDrainMode sharedDrainMode)
</span><span class="cx"> {
</span><del>-    StackStats::probe();
</del><span class="cx">     ASSERT(m_isInParallelMode);
</span><span class="cx">     
</span><span class="cx">     ASSERT(Options::numberOfGCMarkers());
</span><span class="lines">@@ -228,133 +281,118 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SlotVisitor::mergeOpaqueRoots()
</del><ins>+void SlotVisitor::addOpaqueRoot(void* root)
</ins><span class="cx"> {
</span><del>-    StackStats::probe();
-    ASSERT(!m_opaqueRoots.isEmpty()); // Should only be called when opaque roots are non-empty.
-    {
-        std::lock_guard&lt;Lock&gt; lock(m_heap.m_opaqueRootsMutex);
-        for (auto* root : m_opaqueRoots)
-            m_heap.m_opaqueRoots.add(root);
</del><ins>+    if (Options::numberOfGCMarkers() == 1) {
+        // Put directly into the shared HashSet.
+        m_heap.m_opaqueRoots.add(root);
+        return;
</ins><span class="cx">     }
</span><del>-    m_opaqueRoots.clear();
</del><ins>+    // Put into the local set, but merge with the shared one every once in
+    // a while to make sure that the local sets don't grow too large.
+    mergeOpaqueRootsIfProfitable();
+    m_opaqueRoots.add(root);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-ALWAYS_INLINE bool JSString::tryHashConsLock()
</del><ins>+bool SlotVisitor::containsOpaqueRoot(void* root) const
</ins><span class="cx"> {
</span><del>-    unsigned currentFlags = m_flags;
-
-    if (currentFlags &amp; HashConsLock)
-        return false;
-
-    unsigned newFlags = currentFlags | HashConsLock;
-
-    if (!WTF::weakCompareAndSwap(&amp;m_flags, currentFlags, newFlags))
-        return false;
-
-    WTF::memoryBarrierAfterLock();
-    return true;
</del><ins>+    ASSERT(!m_isInParallelMode);
+    ASSERT(m_opaqueRoots.isEmpty());
+    return m_heap.m_opaqueRoots.contains(root);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-ALWAYS_INLINE void JSString::releaseHashConsLock()
</del><ins>+TriState SlotVisitor::containsOpaqueRootTriState(void* root) const
</ins><span class="cx"> {
</span><del>-    WTF::memoryBarrierBeforeUnlock();
-    m_flags &amp;= ~HashConsLock;
</del><ins>+    if (m_opaqueRoots.contains(root))
+        return TrueTriState;
+    std::lock_guard&lt;Lock&gt; lock(m_heap.m_opaqueRootsMutex);
+    if (m_heap.m_opaqueRoots.contains(root))
+        return TrueTriState;
+    return MixedTriState;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-ALWAYS_INLINE bool JSString::shouldTryHashCons()
</del><ins>+int SlotVisitor::opaqueRootCount()
</ins><span class="cx"> {
</span><del>-    return ((length() &gt; 1) &amp;&amp; !isRope() &amp;&amp; !isHashConsSingleton());
</del><ins>+    ASSERT(!m_isInParallelMode);
+    ASSERT(m_opaqueRoots.isEmpty());
+    return m_heap.m_opaqueRoots.size();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-ALWAYS_INLINE void SlotVisitor::internalAppend(void* from, JSValue* slot)
</del><ins>+void SlotVisitor::mergeOpaqueRootsIfNecessary()
</ins><span class="cx"> {
</span><del>-    // This internalAppend is only intended for visits to object and array backing stores.
-    // as it can change the JSValue pointed to be the argument when the original JSValue
-    // is a string that contains the same contents as another string.
-
-    StackStats::probe();
-    ASSERT(slot);
-    JSValue value = *slot;
-    ASSERT(value);
-    if (!value.isCell())
</del><ins>+    if (m_opaqueRoots.isEmpty())
</ins><span class="cx">         return;
</span><del>-
-    JSCell* cell = value.asCell();
-    if (!cell)
</del><ins>+    mergeOpaqueRoots();
+}
+    
+void SlotVisitor::mergeOpaqueRootsIfProfitable()
+{
+    if (static_cast&lt;unsigned&gt;(m_opaqueRoots.size()) &lt; Options::opaqueRootMergeThreshold())
</ins><span class="cx">         return;
</span><ins>+    mergeOpaqueRoots();
+}
+    
+void SlotVisitor::donate()
+{
+    ASSERT(m_isInParallelMode);
+    if (Options::numberOfGCMarkers() == 1)
+        return;
+    
+    donateKnownParallel();
+}
</ins><span class="cx"> 
</span><del>-    validate(cell);
</del><ins>+void SlotVisitor::donateAndDrain()
+{
+    donate();
+    drain();
+}
</ins><span class="cx"> 
</span><del>-    if (m_shouldHashCons &amp;&amp; cell-&gt;isString()) {
-        JSString* string = jsCast&lt;JSString*&gt;(cell);
-        if (string-&gt;shouldTryHashCons() &amp;&amp; string-&gt;tryHashConsLock()) {
-            UniqueStringMap::AddResult addResult = m_uniqueStrings.add(string-&gt;string().impl(), value);
-            if (addResult.isNewEntry)
-                string-&gt;setHashConsSingleton();
-            else {
-                JSValue existingJSValue = addResult.iterator-&gt;value;
-                if (value != existingJSValue)
-                    jsCast&lt;JSString*&gt;(existingJSValue.asCell())-&gt;clearHashConsSingleton();
-                *slot = existingJSValue;
-                string-&gt;releaseHashConsLock();
-                return;
-            }
-            string-&gt;releaseHashConsLock();
-        }
</del><ins>+void SlotVisitor::copyLater(JSCell* owner, CopyToken token, void* ptr, size_t bytes)
+{
+    ASSERT(bytes);
+    CopiedBlock* block = CopiedSpace::blockFor(ptr);
+    if (block-&gt;isOversize()) {
+        ASSERT(bytes &lt;= block-&gt;size());
+        // FIXME: We should be able to shrink the allocation if bytes went below the block size.
+        // For now, we just make sure that our accounting of how much memory we are actually using
+        // is correct.
+        // https://bugs.webkit.org/show_bug.cgi?id=144749
+        bytes = block-&gt;size();
+        m_heap.m_storageSpace.pin(block);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    internalAppend(from, cell);
</del><ins>+    ASSERT(heap()-&gt;m_storageSpace.contains(block));
+
+    LockHolder locker(&amp;block-&gt;workListLock());
+    if (heap()-&gt;operationInProgress() == FullCollection || block-&gt;shouldReportLiveBytes(locker, owner)) {
+        m_bytesCopied += bytes;
+        block-&gt;reportLiveBytes(locker, owner, token, bytes);
+    }
</ins><span class="cx"> }
</span><ins>+    
+void SlotVisitor::mergeOpaqueRoots()
+{
+    ASSERT(!m_opaqueRoots.isEmpty()); // Should only be called when opaque roots are non-empty.
+    {
+        std::lock_guard&lt;Lock&gt; lock(m_heap.m_opaqueRootsMutex);
+        for (auto* root : m_opaqueRoots)
+            m_heap.m_opaqueRoots.add(root);
+    }
+    m_opaqueRoots.clear();
+}
</ins><span class="cx"> 
</span><span class="cx"> void SlotVisitor::harvestWeakReferences()
</span><span class="cx"> {
</span><del>-    StackStats::probe();
</del><span class="cx">     for (WeakReferenceHarvester* current = m_heap.m_weakReferenceHarvesters.head(); current; current = current-&gt;next())
</span><span class="cx">         current-&gt;visitWeakReferences(*this);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void SlotVisitor::finalizeUnconditionalFinalizers()
</span><span class="cx"> {
</span><del>-    StackStats::probe();
</del><span class="cx">     while (m_heap.m_unconditionalFinalizers.hasNext())
</span><span class="cx">         m_heap.m_unconditionalFinalizers.removeNext()-&gt;finalizeUnconditionally();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-#if ENABLE(GC_VALIDATION)
-void SlotVisitor::validate(JSCell* cell)
-{
-    RELEASE_ASSERT(cell);
-
-    if (!cell-&gt;structure()) {
-        dataLogF(&quot;cell at %p has a null structure\n&quot; , cell);
-        CRASH();
-    }
-
-    // Both the cell's structure, and the cell's structure's structure should be the Structure Structure.
-    // I hate this sentence.
-    if (cell-&gt;structure()-&gt;structure()-&gt;JSCell::classInfo() != cell-&gt;structure()-&gt;JSCell::classInfo()) {
-        const char* parentClassName = 0;
-        const char* ourClassName = 0;
-        if (cell-&gt;structure()-&gt;structure() &amp;&amp; cell-&gt;structure()-&gt;structure()-&gt;JSCell::classInfo())
-            parentClassName = cell-&gt;structure()-&gt;structure()-&gt;JSCell::classInfo()-&gt;className;
-        if (cell-&gt;structure()-&gt;JSCell::classInfo())
-            ourClassName = cell-&gt;structure()-&gt;JSCell::classInfo()-&gt;className;
-        dataLogF(&quot;parent structure (%p &lt;%s&gt;) of cell at %p doesn't match cell's structure (%p &lt;%s&gt;)\n&quot;,
-                cell-&gt;structure()-&gt;structure(), parentClassName, cell, cell-&gt;structure(), ourClassName);
-        CRASH();
-    }
-
-    // Make sure we can walk the ClassInfo chain
-    const ClassInfo* info = cell-&gt;classInfo();
-    do { } while ((info = info-&gt;parentClass));
-}
-#else
-void SlotVisitor::validate(JSCell*)
-{
-}
-#endif
-
</del><span class="cx"> void SlotVisitor::dump(PrintStream&amp;) const
</span><span class="cx"> {
</span><span class="cx">     for (const JSCell* cell : markStack())
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapSlotVisitorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/SlotVisitor.h (190562 => 190563)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/SlotVisitor.h        2015-10-05 17:18:26 UTC (rev 190562)
+++ trunk/Source/JavaScriptCore/heap/SlotVisitor.h        2015-10-05 17:22:20 UTC (rev 190563)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2011, 2012, 2013 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2011, 2012, 2013, 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">@@ -31,9 +31,6 @@
</span><span class="cx"> #include &quot;MarkStack.h&quot;
</span><span class="cx"> #include &quot;OpaqueRootSet.h&quot;
</span><span class="cx"> 
</span><del>-#include &lt;wtf/HashSet.h&gt;
-#include &lt;wtf/text/StringHash.h&gt;
-
</del><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><span class="cx"> class ConservativeRoots;
</span><span class="lines">@@ -46,8 +43,11 @@
</span><span class="cx"> template&lt;typename T&gt; class WriteBarrierBase;
</span><span class="cx"> 
</span><span class="cx"> class SlotVisitor {
</span><del>-    WTF_MAKE_NONCOPYABLE(SlotVisitor); WTF_MAKE_FAST_ALLOCATED;
</del><ins>+    WTF_MAKE_NONCOPYABLE(SlotVisitor);
+    WTF_MAKE_FAST_ALLOCATED;
+
</ins><span class="cx">     friend class HeapRootVisitor; // Allowed to mark a JSValue* or JSCell** directly.
</span><ins>+    friend class Heap;
</ins><span class="cx"> 
</span><span class="cx"> public:
</span><span class="cx">     SlotVisitor(Heap&amp;);
</span><span class="lines">@@ -75,10 +75,9 @@
</span><span class="cx">     template&lt;typename T&gt;
</span><span class="cx">     void appendUnbarrieredReadOnlyPointer(T*);
</span><span class="cx">     void appendUnbarrieredReadOnlyValue(JSValue);
</span><del>-    void unconditionallyAppend(JSCell*);
</del><span class="cx">     
</span><del>-    void addOpaqueRoot(void*);
-    bool containsOpaqueRoot(void*) const;
</del><ins>+    JS_EXPORT_PRIVATE void addOpaqueRoot(void*);
+    JS_EXPORT_PRIVATE bool containsOpaqueRoot(void*) const;
</ins><span class="cx">     TriState containsOpaqueRootTriState(void*) const;
</span><span class="cx">     int opaqueRootCount();
</span><span class="cx"> 
</span><span class="lines">@@ -109,25 +108,16 @@
</span><span class="cx">     void addWeakReferenceHarvester(WeakReferenceHarvester*);
</span><span class="cx">     void addUnconditionalFinalizer(UnconditionalFinalizer*);
</span><span class="cx"> 
</span><del>-    inline void resetChildCount() { m_logChildCount = 0; }
-    inline unsigned childCount() { return m_logChildCount; }
-    inline void incrementChildCount() { m_logChildCount++; }
-
</del><span class="cx">     void dump(PrintStream&amp;) const;
</span><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     friend class ParallelModeEnabler;
</span><span class="cx">     
</span><del>-    JS_EXPORT_PRIVATE static void validate(JSCell*);
</del><ins>+    JS_EXPORT_PRIVATE void append(JSValue); // This is private to encourage clients to use WriteBarrier&lt;T&gt;.
</ins><span class="cx"> 
</span><del>-    void append(JSValue*);
-    void append(JSValue*, size_t count);
-    void append(JSCell**);
</del><ins>+    JS_EXPORT_PRIVATE void setMarkedAndAppendToMarkStack(JSCell*);
+    void appendToMarkStack(JSCell*);
</ins><span class="cx">     
</span><del>-    void internalAppend(void* from, JSCell*);
-    void internalAppend(void* from, JSValue);
-    void internalAppend(void* from, JSValue*);
-    
</del><span class="cx">     JS_EXPORT_PRIVATE void mergeOpaqueRoots();
</span><span class="cx">     void mergeOpaqueRootsIfNecessary();
</span><span class="cx">     void mergeOpaqueRootsIfProfitable();
</span><span class="lines">@@ -144,12 +134,6 @@
</span><span class="cx">     
</span><span class="cx">     Heap&amp; m_heap;
</span><span class="cx"> 
</span><del>-    bool m_shouldHashCons; // Local per-thread copy of shared flag for performance reasons
-    typedef HashMap&lt;StringImpl*, JSValue&gt; UniqueStringMap;
-    UniqueStringMap m_uniqueStrings;
-
-    unsigned m_logChildCount;
-
</del><span class="cx"> public:
</span><span class="cx"> #if !ASSERT_DISABLED
</span><span class="cx">     bool m_isCheckingForDefaultMarkViolation;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapSlotVisitorInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/SlotVisitorInlines.h (190562 => 190563)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/SlotVisitorInlines.h        2015-10-05 17:18:26 UTC (rev 190562)
+++ trunk/Source/JavaScriptCore/heap/SlotVisitorInlines.h        2015-10-05 17:22:20 UTC (rev 190563)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2012, 2013, 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">@@ -26,124 +26,60 @@
</span><span class="cx"> #ifndef SlotVisitorInlines_h
</span><span class="cx"> #define SlotVisitorInlines_h
</span><span class="cx"> 
</span><del>-#include &quot;CopiedBlockInlines.h&quot;
-#include &quot;CopiedSpaceInlines.h&quot;
-#include &quot;Options.h&quot;
</del><span class="cx"> #include &quot;SlotVisitor.h&quot;
</span><span class="cx"> #include &quot;Weak.h&quot;
</span><span class="cx"> #include &quot;WeakInlines.h&quot;
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><del>-ALWAYS_INLINE void SlotVisitor::append(JSValue* slot, size_t count)
-{
-    for (size_t i = 0; i &lt; count; ++i) {
-        JSValue&amp; value = slot[i];
-        internalAppend(&amp;value, value);
-    }
-}
-
</del><span class="cx"> template&lt;typename T&gt;
</span><span class="cx"> inline void SlotVisitor::appendUnbarrieredPointer(T** slot)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(slot);
</span><del>-    JSCell* cell = *slot;
-    internalAppend(slot, cell);
</del><ins>+    append(*slot);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template&lt;typename T&gt;
</span><span class="cx"> inline void SlotVisitor::appendUnbarrieredReadOnlyPointer(T* cell)
</span><span class="cx"> {
</span><del>-    internalAppend(0, cell);
</del><ins>+    append(cell);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-ALWAYS_INLINE void SlotVisitor::append(JSValue* slot)
</del><ins>+inline void SlotVisitor::appendUnbarrieredValue(JSValue* slot)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(slot);
</span><del>-    internalAppend(slot, *slot);
</del><ins>+    append(*slot);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-ALWAYS_INLINE void SlotVisitor::appendUnbarrieredValue(JSValue* slot)
</del><ins>+inline void SlotVisitor::appendUnbarrieredReadOnlyValue(JSValue value)
</ins><span class="cx"> {
</span><del>-    ASSERT(slot);
-    internalAppend(slot, *slot);
</del><ins>+    append(value);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-ALWAYS_INLINE void SlotVisitor::appendUnbarrieredReadOnlyValue(JSValue value)
-{
-    internalAppend(0, value);
-}
-
-ALWAYS_INLINE void SlotVisitor::append(JSCell** slot)
-{
-    ASSERT(slot);
-    internalAppend(slot, *slot);
-}
-
</del><span class="cx"> template&lt;typename T&gt;
</span><del>-ALWAYS_INLINE void SlotVisitor::appendUnbarrieredWeak(Weak&lt;T&gt;* weak)
</del><ins>+inline void SlotVisitor::appendUnbarrieredWeak(Weak&lt;T&gt;* weak)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(weak);
</span><del>-    if (weak-&gt;get())
-        internalAppend(0, weak-&gt;get());
</del><ins>+    append(weak-&gt;get());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-ALWAYS_INLINE void SlotVisitor::internalAppend(void* from, JSValue value)
</del><ins>+template&lt;typename T&gt;
+inline void SlotVisitor::append(WriteBarrierBase&lt;T&gt;* slot)
</ins><span class="cx"> {
</span><del>-    if (!value || !value.isCell())
-        return;
-    internalAppend(from, value.asCell());
</del><ins>+    append(slot-&gt;get());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-ALWAYS_INLINE void SlotVisitor::internalAppend(void* from, JSCell* cell)
</del><ins>+template&lt;typename Iterator&gt;
+inline void SlotVisitor::append(Iterator begin, Iterator end)
</ins><span class="cx"> {
</span><del>-    ASSERT(!m_isCheckingForDefaultMarkViolation);
-    if (!cell)
-        return;
-#if ENABLE(ALLOCATION_LOGGING)
-    dataLogF(&quot;JSC GC noticing reference from %p to %p.\n&quot;, from, cell);
-#else
-    UNUSED_PARAM(from);
-#endif
-#if ENABLE(GC_VALIDATION)
-    validate(cell);
-#endif
-    if (Heap::testAndSetMarked(cell) || !cell-&gt;structure()) {
-        ASSERT(cell-&gt;structure());
-        return;
-    }
-
-    cell-&gt;setMarked();
-    m_bytesVisited += MarkedBlock::blockFor(cell)-&gt;cellSize();
-        
-    unconditionallyAppend(cell);
-}
-
-ALWAYS_INLINE void SlotVisitor::unconditionallyAppend(JSCell* cell)
-{
-    ASSERT(Heap::isMarked(cell));
-    m_visitCount++;
-        
-    // Should never attempt to mark something that is zapped.
-    ASSERT(!cell-&gt;isZapped());
-        
-    m_stack.append(cell);
-}
-
-template&lt;typename T&gt; inline void SlotVisitor::append(WriteBarrierBase&lt;T&gt;* slot)
-{
-    internalAppend(slot, *slot-&gt;slot());
-}
-
-template&lt;typename Iterator&gt; inline void SlotVisitor::append(Iterator begin, Iterator end)
-{
</del><span class="cx">     for (auto it = begin; it != end; ++it)
</span><span class="cx">         append(&amp;*it);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-ALWAYS_INLINE void SlotVisitor::appendValues(WriteBarrierBase&lt;Unknown&gt;* barriers, size_t count)
</del><ins>+inline void SlotVisitor::appendValues(WriteBarrierBase&lt;Unknown&gt;* barriers, size_t count)
</ins><span class="cx"> {
</span><del>-    append(barriers-&gt;slot(), count);
</del><ins>+    for (size_t i = 0; i &lt; count; ++i)
+        append(&amp;barriers[i]);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> inline void SlotVisitor::addWeakReferenceHarvester(WeakReferenceHarvester* weakReferenceHarvester)
</span><span class="lines">@@ -156,95 +92,6 @@
</span><span class="cx">     m_heap.m_unconditionalFinalizers.addThreadSafe(unconditionalFinalizer);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-inline void SlotVisitor::addOpaqueRoot(void* root)
-{
-    if (Options::numberOfGCMarkers() == 1) {
-        // Put directly into the shared HashSet.
-        m_heap.m_opaqueRoots.add(root);
-        return;
-    }
-    // Put into the local set, but merge with the shared one every once in
-    // a while to make sure that the local sets don't grow too large.
-    mergeOpaqueRootsIfProfitable();
-    m_opaqueRoots.add(root);
-}
-
-inline bool SlotVisitor::containsOpaqueRoot(void* root) const
-{
-    ASSERT(!m_isInParallelMode);
-    ASSERT(m_opaqueRoots.isEmpty());
-    return m_heap.m_opaqueRoots.contains(root);
-}
-
-inline TriState SlotVisitor::containsOpaqueRootTriState(void* root) const
-{
-    if (m_opaqueRoots.contains(root))
-        return TrueTriState;
-    std::lock_guard&lt;Lock&gt; lock(m_heap.m_opaqueRootsMutex);
-    if (m_heap.m_opaqueRoots.contains(root))
-        return TrueTriState;
-    return MixedTriState;
-}
-
-inline int SlotVisitor::opaqueRootCount()
-{
-    ASSERT(!m_isInParallelMode);
-    ASSERT(m_opaqueRoots.isEmpty());
-    return m_heap.m_opaqueRoots.size();
-}
-
-inline void SlotVisitor::mergeOpaqueRootsIfNecessary()
-{
-    if (m_opaqueRoots.isEmpty())
-        return;
-    mergeOpaqueRoots();
-}
-    
-inline void SlotVisitor::mergeOpaqueRootsIfProfitable()
-{
-    if (static_cast&lt;unsigned&gt;(m_opaqueRoots.size()) &lt; Options::opaqueRootMergeThreshold())
-        return;
-    mergeOpaqueRoots();
-}
-    
-inline void SlotVisitor::donate()
-{
-    ASSERT(m_isInParallelMode);
-    if (Options::numberOfGCMarkers() == 1)
-        return;
-    
-    donateKnownParallel();
-}
-
-inline void SlotVisitor::donateAndDrain()
-{
-    donate();
-    drain();
-}
-
-inline void SlotVisitor::copyLater(JSCell* owner, CopyToken token, void* ptr, size_t bytes)
-{
-    ASSERT(bytes);
-    CopiedBlock* block = CopiedSpace::blockFor(ptr);
-    if (block-&gt;isOversize()) {
-        ASSERT(bytes &lt;= block-&gt;size());
-        // FIXME: We should be able to shrink the allocation if bytes went below the block size.
-        // For now, we just make sure that our accounting of how much memory we are actually using
-        // is correct.
-        // https://bugs.webkit.org/show_bug.cgi?id=144749
-        bytes = block-&gt;size();
-        m_heap.m_storageSpace.pin(block);
-    }
-
-    ASSERT(heap()-&gt;m_storageSpace.contains(block));
-
-    LockHolder locker(&amp;block-&gt;workListLock());
-    if (heap()-&gt;operationInProgress() == FullCollection || block-&gt;shouldReportLiveBytes(locker, owner)) {
-        m_bytesCopied += bytes;
-        block-&gt;reportLiveBytes(locker, owner, token, bytes);
-    }
-}
-    
</del><span class="cx"> inline void SlotVisitor::reportExtraMemoryVisited(JSCell* owner, size_t size)
</span><span class="cx"> {
</span><span class="cx">     heap()-&gt;reportExtraMemoryVisited(owner, size);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeDirectArgumentscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/DirectArguments.cpp (190562 => 190563)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/DirectArguments.cpp        2015-10-05 17:18:26 UTC (rev 190562)
+++ trunk/Source/JavaScriptCore/runtime/DirectArguments.cpp        2015-10-05 17:22:20 UTC (rev 190563)
</span><span class="lines">@@ -27,6 +27,7 @@
</span><span class="cx"> #include &quot;DirectArguments.h&quot;
</span><span class="cx"> 
</span><span class="cx"> #include &quot;CodeBlock.h&quot;
</span><ins>+#include &quot;CopiedBlockInlines.h&quot;
</ins><span class="cx"> #include &quot;CopyVisitorInlines.h&quot;
</span><span class="cx"> #include &quot;GenericArgumentsInlines.h&quot;
</span><span class="cx"> #include &quot;JSCInlines.h&quot;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSMapcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSMap.cpp (190562 => 190563)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSMap.cpp        2015-10-05 17:18:26 UTC (rev 190562)
+++ trunk/Source/JavaScriptCore/runtime/JSMap.cpp        2015-10-05 17:22:20 UTC (rev 190563)
</span><span class="lines">@@ -26,6 +26,7 @@
</span><span class="cx"> #include &quot;config.h&quot;
</span><span class="cx"> #include &quot;JSMap.h&quot;
</span><span class="cx"> 
</span><ins>+#include &quot;CopiedBlockInlines.h&quot;
</ins><span class="cx"> #include &quot;JSCJSValueInlines.h&quot;
</span><span class="cx"> #include &quot;JSMapIterator.h&quot;
</span><span class="cx"> #include &quot;MapDataInlines.h&quot;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSObjectcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSObject.cpp (190562 => 190563)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSObject.cpp        2015-10-05 17:18:26 UTC (rev 190562)
+++ trunk/Source/JavaScriptCore/runtime/JSObject.cpp        2015-10-05 17:22:20 UTC (rev 190563)
</span><span class="lines">@@ -25,6 +25,7 @@
</span><span class="cx"> #include &quot;JSObject.h&quot;
</span><span class="cx"> 
</span><span class="cx"> #include &quot;ButterflyInlines.h&quot;
</span><ins>+#include &quot;CopiedBlockInlines.h&quot;
</ins><span class="cx"> #include &quot;CopiedSpaceInlines.h&quot;
</span><span class="cx"> #include &quot;CopyVisitor.h&quot;
</span><span class="cx"> #include &quot;CopyVisitorInlines.h&quot;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSSetcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSSet.cpp (190562 => 190563)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSSet.cpp        2015-10-05 17:18:26 UTC (rev 190562)
+++ trunk/Source/JavaScriptCore/runtime/JSSet.cpp        2015-10-05 17:22:20 UTC (rev 190563)
</span><span class="lines">@@ -26,6 +26,7 @@
</span><span class="cx"> #include &quot;config.h&quot;
</span><span class="cx"> #include &quot;JSSet.h&quot;
</span><span class="cx"> 
</span><ins>+#include &quot;CopiedBlockInlines.h&quot;
</ins><span class="cx"> #include &quot;JSCJSValueInlines.h&quot;
</span><span class="cx"> #include &quot;JSSetIterator.h&quot;
</span><span class="cx"> #include &quot;MapDataInlines.h&quot;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSStringh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSString.h (190562 => 190563)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSString.h        2015-10-05 17:18:26 UTC (rev 190562)
+++ trunk/Source/JavaScriptCore/runtime/JSString.h        2015-10-05 17:22:20 UTC (rev 190563)
</span><span class="lines">@@ -108,7 +108,6 @@
</span><span class="cx">         Base::finishCreation(vm);
</span><span class="cx">         m_length = length;
</span><span class="cx">         setIs8Bit(m_value.impl()-&gt;is8Bit());
</span><del>-        vm.m_newStringsSinceLastHashCons++;
</del><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     void finishCreation(VM&amp; vm, size_t length, size_t cost)
</span><span class="lines">@@ -118,7 +117,6 @@
</span><span class="cx">         m_length = length;
</span><span class="cx">         setIs8Bit(m_value.impl()-&gt;is8Bit());
</span><span class="cx">         Heap::heap(this)-&gt;reportExtraMemoryAllocated(cost);
</span><del>-        vm.m_newStringsSinceLastHashCons++;
</del><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> protected:
</span><span class="lines">@@ -127,7 +125,6 @@
</span><span class="cx">         Base::finishCreation(vm);
</span><span class="cx">         m_length = 0;
</span><span class="cx">         setIs8Bit(true);
</span><del>-        vm.m_newStringsSinceLastHashCons++;
</del><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> public:
</span><span class="lines">@@ -191,8 +188,6 @@
</span><span class="cx">     static void visitChildren(JSCell*, SlotVisitor&amp;);
</span><span class="cx"> 
</span><span class="cx">     enum {
</span><del>-        HashConsLock = 1u &lt;&lt; 2,
-        IsHashConsSingleton = 1u &lt;&lt; 1,
</del><span class="cx">         Is8Bit = 1u
</span><span class="cx">     };
</span><span class="cx"> 
</span><span class="lines">@@ -209,12 +204,6 @@
</span><span class="cx">         else
</span><span class="cx">             m_flags &amp;= ~Is8Bit;
</span><span class="cx">     }
</span><del>-    bool shouldTryHashCons();
-    bool isHashConsSingleton() const { return m_flags &amp; IsHashConsSingleton; }
-    void clearHashConsSingleton() { m_flags &amp;= ~IsHashConsSingleton; }
-    void setHashConsSingleton() { m_flags |= IsHashConsSingleton; }
-    bool tryHashConsLock();
-    void releaseHashConsLock();
</del><span class="cx"> 
</span><span class="cx">     mutable unsigned m_flags;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSTypedArrayscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSTypedArrays.cpp (190562 => 190563)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSTypedArrays.cpp        2015-10-05 17:18:26 UTC (rev 190562)
+++ trunk/Source/JavaScriptCore/runtime/JSTypedArrays.cpp        2015-10-05 17:22:20 UTC (rev 190563)
</span><span class="lines">@@ -26,6 +26,7 @@
</span><span class="cx"> #include &quot;config.h&quot;
</span><span class="cx"> #include &quot;JSTypedArrays.h&quot;
</span><span class="cx"> 
</span><ins>+#include &quot;CopiedBlockInlines.h&quot;
</ins><span class="cx"> #include &quot;CopyVisitorInlines.h&quot;
</span><span class="cx"> #include &quot;GenericTypedArrayViewInlines.h&quot;
</span><span class="cx"> #include &quot;JSGenericTypedArrayViewInlines.h&quot;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeVMcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/VM.cpp (190562 => 190563)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/VM.cpp        2015-10-05 17:18:26 UTC (rev 190562)
+++ trunk/Source/JavaScriptCore/runtime/VM.cpp        2015-10-05 17:22:20 UTC (rev 190563)
</span><span class="lines">@@ -166,7 +166,6 @@
</span><span class="cx"> #if ENABLE(REGEXP_TRACING)
</span><span class="cx">     , m_rtTraceList(new RTTraceList())
</span><span class="cx"> #endif
</span><del>-    , m_newStringsSinceLastHashCons(0)
</del><span class="cx"> #if ENABLE(ASSEMBLER)
</span><span class="cx">     , m_canUseAssembler(enableAssembler(executableAllocator))
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeVMh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/VM.h (190562 => 190563)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/VM.h        2015-10-05 17:18:26 UTC (rev 190562)
+++ trunk/Source/JavaScriptCore/runtime/VM.h        2015-10-05 17:22:20 UTC (rev 190563)
</span><span class="lines">@@ -538,13 +538,6 @@
</span><span class="cx">     void setInitializingObjectClass(const ClassInfo*);
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-    unsigned m_newStringsSinceLastHashCons;
-
-    static const unsigned s_minNumberOfNewStringsToHashCons = 100;
-
-    bool haveEnoughNewStringsToHashCons() { return m_newStringsSinceLastHashCons &gt; s_minNumberOfNewStringsToHashCons; }
-    void resetNewStringsSinceLastHashCons() { m_newStringsSinceLastHashCons = 0; }
-
</del><span class="cx">     bool currentThreadIsHoldingAPILock() const { return m_apiLock-&gt;currentThreadIsHoldingLock(); }
</span><span class="cx"> 
</span><span class="cx">     JSLock&amp; apiLock() { return *m_apiLock; }
</span></span></pre>
</div>
</div>

</body>
</html>