<!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>[164862] 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/164862">164862</a></dd>
<dt>Author</dt> <dd>mhahnenberg@apple.com</dd>
<dt>Date</dt> <dd>2014-02-28 08:56:17 -0800 (Fri, 28 Feb 2014)</dd>
</dl>
<h3>Log Message</h3>
<pre>Clean up Heap::collect and Heap::markRoots
https://bugs.webkit.org/show_bug.cgi?id=129464
Reviewed by Geoffrey Garen.
These functions have built up a lot of cruft recently.
We should do a bit of cleanup to make them easier to grok.
* heap/Heap.cpp:
(JSC::Heap::finalizeUnconditionalFinalizers):
(JSC::Heap::gatherStackRoots):
(JSC::Heap::gatherJSStackRoots):
(JSC::Heap::gatherScratchBufferRoots):
(JSC::Heap::clearLivenessData):
(JSC::Heap::visitSmallStrings):
(JSC::Heap::visitConservativeRoots):
(JSC::Heap::visitCompilerWorklists):
(JSC::Heap::markProtectedObjects):
(JSC::Heap::markTempSortVectors):
(JSC::Heap::markArgumentBuffers):
(JSC::Heap::visitException):
(JSC::Heap::visitStrongHandles):
(JSC::Heap::visitHandleStack):
(JSC::Heap::traceCodeBlocksAndJITStubRoutines):
(JSC::Heap::converge):
(JSC::Heap::visitWeakHandles):
(JSC::Heap::clearRememberedSet):
(JSC::Heap::updateObjectCounts):
(JSC::Heap::resetVisitors):
(JSC::Heap::markRoots):
(JSC::Heap::copyBackingStores):
(JSC::Heap::deleteUnmarkedCompiledCode):
(JSC::Heap::collect):
(JSC::Heap::collectIfNecessaryOrDefer):
(JSC::Heap::suspendCompilerThreads):
(JSC::Heap::willStartCollection):
(JSC::Heap::deleteOldCode):
(JSC::Heap::flushOldStructureIDTables):
(JSC::Heap::flushWriteBarrierBuffer):
(JSC::Heap::stopAllocation):
(JSC::Heap::reapWeakHandles):
(JSC::Heap::sweepArrayBuffers):
(JSC::Heap::snapshotMarkedSpace):
(JSC::Heap::deleteSourceProviderCaches):
(JSC::Heap::notifyIncrementalSweeper):
(JSC::Heap::rememberCurrentlyExecutingCodeBlocks):
(JSC::Heap::resetAllocators):
(JSC::Heap::updateAllocationLimits):
(JSC::Heap::didFinishCollection):
(JSC::Heap::resumeCompilerThreads):
* heap/Heap.h:</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>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (164861 => 164862)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2014-02-28 16:35:27 UTC (rev 164861)
+++ trunk/Source/JavaScriptCore/ChangeLog        2014-02-28 16:56:17 UTC (rev 164862)
</span><span class="lines">@@ -1,3 +1,57 @@
</span><ins>+2014-02-27 Mark Hahnenberg <mhahnenberg@apple.com>
+
+ Clean up Heap::collect and Heap::markRoots
+ https://bugs.webkit.org/show_bug.cgi?id=129464
+
+ Reviewed by Geoffrey Garen.
+
+ These functions have built up a lot of cruft recently.
+ We should do a bit of cleanup to make them easier to grok.
+
+ * heap/Heap.cpp:
+ (JSC::Heap::finalizeUnconditionalFinalizers):
+ (JSC::Heap::gatherStackRoots):
+ (JSC::Heap::gatherJSStackRoots):
+ (JSC::Heap::gatherScratchBufferRoots):
+ (JSC::Heap::clearLivenessData):
+ (JSC::Heap::visitSmallStrings):
+ (JSC::Heap::visitConservativeRoots):
+ (JSC::Heap::visitCompilerWorklists):
+ (JSC::Heap::markProtectedObjects):
+ (JSC::Heap::markTempSortVectors):
+ (JSC::Heap::markArgumentBuffers):
+ (JSC::Heap::visitException):
+ (JSC::Heap::visitStrongHandles):
+ (JSC::Heap::visitHandleStack):
+ (JSC::Heap::traceCodeBlocksAndJITStubRoutines):
+ (JSC::Heap::converge):
+ (JSC::Heap::visitWeakHandles):
+ (JSC::Heap::clearRememberedSet):
+ (JSC::Heap::updateObjectCounts):
+ (JSC::Heap::resetVisitors):
+ (JSC::Heap::markRoots):
+ (JSC::Heap::copyBackingStores):
+ (JSC::Heap::deleteUnmarkedCompiledCode):
+ (JSC::Heap::collect):
+ (JSC::Heap::collectIfNecessaryOrDefer):
+ (JSC::Heap::suspendCompilerThreads):
+ (JSC::Heap::willStartCollection):
+ (JSC::Heap::deleteOldCode):
+ (JSC::Heap::flushOldStructureIDTables):
+ (JSC::Heap::flushWriteBarrierBuffer):
+ (JSC::Heap::stopAllocation):
+ (JSC::Heap::reapWeakHandles):
+ (JSC::Heap::sweepArrayBuffers):
+ (JSC::Heap::snapshotMarkedSpace):
+ (JSC::Heap::deleteSourceProviderCaches):
+ (JSC::Heap::notifyIncrementalSweeper):
+ (JSC::Heap::rememberCurrentlyExecutingCodeBlocks):
+ (JSC::Heap::resetAllocators):
+ (JSC::Heap::updateAllocationLimits):
+ (JSC::Heap::didFinishCollection):
+ (JSC::Heap::resumeCompilerThreads):
+ * heap/Heap.h:
+
</ins><span class="cx"> 2014-02-27 Ryosuke Niwa <rniwa@webkit.org>
</span><span class="cx">
</span><span class="cx"> indexOf and lastIndexOf shouldn't resolve ropes when needle is longer than haystack
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapHeapcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/Heap.cpp (164861 => 164862)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/Heap.cpp        2014-02-28 16:35:27 UTC (rev 164861)
+++ trunk/Source/JavaScriptCore/heap/Heap.cpp        2014-02-28 16:56:17 UTC (rev 164862)
</span><span class="lines">@@ -369,13 +369,6 @@
</span><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void Heap::markProtectedObjects(HeapRootVisitor& heapRootVisitor)
-{
- ProtectCountSet::iterator end = m_protectedValues.end();
- for (ProtectCountSet::iterator it = m_protectedValues.begin(); it != end; ++it)
- heapRootVisitor.visit(&it->key);
-}
-
</del><span class="cx"> void Heap::pushTempSortVector(Vector<ValueStringPair, 0, UnsafeVectorOverflow>* tempVector)
</span><span class="cx"> {
</span><span class="cx"> m_tempSortingVectors.append(tempVector);
</span><span class="lines">@@ -387,22 +380,6 @@
</span><span class="cx"> m_tempSortingVectors.removeLast();
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void Heap::markTempSortVectors(HeapRootVisitor& heapRootVisitor)
-{
- typedef Vector<Vector<ValueStringPair, 0, UnsafeVectorOverflow>* > VectorOfValueStringVectors;
-
- VectorOfValueStringVectors::iterator end = m_tempSortingVectors.end();
- for (VectorOfValueStringVectors::iterator it = m_tempSortingVectors.begin(); it != end; ++it) {
- Vector<ValueStringPair, 0, UnsafeVectorOverflow>* tempSortingVector = *it;
-
- Vector<ValueStringPair>::iterator vectorEnd = tempSortingVector->end();
- for (Vector<ValueStringPair>::iterator vectorIt = tempSortingVector->begin(); vectorIt != vectorEnd; ++vectorIt) {
- if (vectorIt->first)
- heapRootVisitor.visit(&vectorIt->first);
- }
- }
-}
-
</del><span class="cx"> void Heap::harvestWeakReferences()
</span><span class="cx"> {
</span><span class="cx"> m_slotVisitor.harvestWeakReferences();
</span><span class="lines">@@ -410,6 +387,7 @@
</span><span class="cx">
</span><span class="cx"> void Heap::finalizeUnconditionalFinalizers()
</span><span class="cx"> {
</span><ins>+ GCPHASE(FinalizeUnconditionalFinalizers);
</ins><span class="cx"> m_slotVisitor.finalizeUnconditionalFinalizers();
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -444,7 +422,7 @@
</span><span class="cx">
</span><span class="cx"> void Heap::markRoots()
</span><span class="cx"> {
</span><del>- SamplingRegion samplingRegion("Garbage Collection: Tracing");
</del><ins>+ SamplingRegion samplingRegion("Garbage Collection: Marking");
</ins><span class="cx">
</span><span class="cx"> GCPHASE(MarkRoots);
</span><span class="cx"> ASSERT(isValidThreadState(m_vm));
</span><span class="lines">@@ -454,45 +432,22 @@
</span><span class="cx"> #endif
</span><span class="cx">
</span><span class="cx"> m_codeBlocks.clearMarks();
</span><del>- void* dummy;
</del><span class="cx">
</span><span class="cx"> // We gather conservative roots before clearing mark bits because conservative
</span><span class="cx"> // gathering uses the mark bits to determine whether a reference is valid.
</span><del>- ConservativeRoots machineThreadRoots(&m_objectSpace.blocks(), &m_storageSpace);
- m_jitStubRoutines.clearMarks();
- {
- GCPHASE(GatherConservativeRoots);
- m_machineThreads.gatherConservativeRoots(machineThreadRoots, m_jitStubRoutines, m_codeBlocks, &dummy);
- }
</del><ins>+ void* dummy;
+ ConservativeRoots conservativeRoots(&m_objectSpace.blocks(), &m_storageSpace);
+ gatherStackRoots(conservativeRoots, &dummy);
+ gatherJSStackRoots(conservativeRoots);
+ gatherScratchBufferRoots(conservativeRoots);
</ins><span class="cx">
</span><del>-#if ENABLE(LLINT_C_LOOP)
- ConservativeRoots stackRoots(&m_objectSpace.blocks(), &m_storageSpace);
- {
- GCPHASE(GatherStackRoots);
- stack().gatherConservativeRoots(stackRoots, m_jitStubRoutines, m_codeBlocks);
- }
-#endif
-
</del><span class="cx"> sanitizeStackForVM(m_vm);
</span><span class="cx">
</span><del>-#if ENABLE(DFG_JIT)
- ConservativeRoots scratchBufferRoots(&m_objectSpace.blocks(), &m_storageSpace);
- {
- GCPHASE(GatherScratchBufferRoots);
- m_vm->gatherConservativeRoots(scratchBufferRoots);
- }
-#endif
</del><ins>+ clearLivenessData();
</ins><span class="cx">
</span><del>- {
- GCPHASE(ClearLivenessData);
- m_objectSpace.clearNewlyAllocated();
- m_objectSpace.clearMarks();
- }
-
</del><span class="cx"> m_sharedData.didStartMarking();
</span><del>- SlotVisitor& visitor = m_slotVisitor;
- visitor.didStartMarking();
- HeapRootVisitor heapRootVisitor(visitor);
</del><ins>+ m_slotVisitor.didStartMarking();
+ HeapRootVisitor heapRootVisitor(m_slotVisitor);
</ins><span class="cx">
</span><span class="cx"> #if ENABLE(GGC)
</span><span class="cx"> Vector<const JSCell*> rememberedSet(m_slotVisitor.markStack().size());
</span><span class="lines">@@ -500,133 +455,236 @@
</span><span class="cx"> #endif
</span><span class="cx">
</span><span class="cx"> {
</span><del>- ParallelModeEnabler enabler(visitor);
</del><ins>+ ParallelModeEnabler enabler(m_slotVisitor);
</ins><span class="cx">
</span><del>- m_vm->smallStrings.visitStrongReferences(visitor);
</del><ins>+ visitSmallStrings();
+ visitConservativeRoots(conservativeRoots);
+ visitCompilerWorklists();
+ visitProtectedObjects(heapRootVisitor);
+ visitTempSortVectors(heapRootVisitor);
+ visitArgumentBuffers(heapRootVisitor);
+ visitException(heapRootVisitor);
+ visitStrongHandles(heapRootVisitor);
+ visitHandleStack(heapRootVisitor);
+ traceCodeBlocksAndJITStubRoutines();
+ converge();
+ }
</ins><span class="cx">
</span><del>- {
- GCPHASE(VisitMachineRoots);
- MARK_LOG_ROOT(visitor, "C++ Stack");
- visitor.append(machineThreadRoots);
- visitor.donateAndDrain();
- }
</del><ins>+ // Weak references must be marked last because their liveness depends on
+ // the liveness of the rest of the object graph.
+ visitWeakHandles(heapRootVisitor);
+
+ clearRememberedSet(rememberedSet);
+ m_sharedData.didFinishMarking();
+ updateObjectCounts();
+ resetVisitors();
+}
+
+void Heap::copyBackingStores()
+{
+ if (m_operationInProgress == EdenCollection)
+ m_storageSpace.startedCopying<EdenCollection>();
+ else {
+ ASSERT(m_operationInProgress == FullCollection);
+ m_storageSpace.startedCopying<FullCollection>();
+ }
+
+ if (m_storageSpace.shouldDoCopyPhase()) {
+ m_sharedData.didStartCopying();
+ m_copyVisitor.startCopying();
+ m_copyVisitor.copyFromShared();
+ m_copyVisitor.doneCopying();
+ // We need to wait for everybody to finish and return their CopiedBlocks
+ // before signaling that the phase is complete.
+ m_storageSpace.doneCopying();
+ m_sharedData.didFinishCopying();
+ } else
+ m_storageSpace.doneCopying();
+}
+
+void Heap::gatherStackRoots(ConservativeRoots& roots, void** dummy)
+{
+ GCPHASE(GatherStackRoots);
+ m_jitStubRoutines.clearMarks();
+ m_machineThreads.gatherConservativeRoots(roots, m_jitStubRoutines, m_codeBlocks, dummy);
+}
+
+void Heap::gatherJSStackRoots(ConservativeRoots& roots)
+{
</ins><span class="cx"> #if ENABLE(LLINT_C_LOOP)
</span><del>- {
- GCPHASE(VisitStackRoots);
- MARK_LOG_ROOT(visitor, "Stack");
- visitor.append(stackRoots);
- visitor.donateAndDrain();
- }
</del><ins>+ GCPHASE(GatherStackRoots);
+ stack().gatherConservativeRoots(roots, m_jitStubRoutines, m_codeBlocks);
+#else
+ UNUSED_PARAM(roots);
</ins><span class="cx"> #endif
</span><ins>+}
+
+void Heap::gatherScratchBufferRoots(ConservativeRoots& roots)
+{
</ins><span class="cx"> #if ENABLE(DFG_JIT)
</span><del>- {
- GCPHASE(VisitScratchBufferRoots);
- MARK_LOG_ROOT(visitor, "Scratch Buffers");
- visitor.append(scratchBufferRoots);
- visitor.donateAndDrain();
- }
- {
- GCPHASE(VisitDFGWorklists);
- MARK_LOG_ROOT(visitor, "DFG Worklists");
- for (unsigned i = DFG::numberOfWorklists(); i--;) {
- if (DFG::Worklist* worklist = DFG::worklistForIndexOrNull(i))
- worklist->visitChildren(visitor, m_codeBlocks);
- }
- }
</del><ins>+ GCPHASE(GatherScratchBufferRoots);
+ m_vm->gatherConservativeRoots(roots);
+#else
+ UNUSED_PARAM(roots);
</ins><span class="cx"> #endif
</span><del>- {
- GCPHASE(VisitProtectedObjects);
- MARK_LOG_ROOT(visitor, "Protected Objects");
- markProtectedObjects(heapRootVisitor);
- visitor.donateAndDrain();
</del><ins>+}
+
+void Heap::clearLivenessData()
+{
+ GCPHASE(ClearLivenessData);
+ m_objectSpace.clearNewlyAllocated();
+ m_objectSpace.clearMarks();
+}
+
+void Heap::visitSmallStrings()
+{
+ GCPHASE(VisitSmallStrings);
+ m_vm->smallStrings.visitStrongReferences(m_slotVisitor);
+}
+
+void Heap::visitConservativeRoots(ConservativeRoots& roots)
+{
+ GCPHASE(VisitConservativeRoots);
+ MARK_LOG_ROOT(m_slotVisitor, "Conservative Roots");
+ m_slotVisitor.append(roots);
+ m_slotVisitor.donateAndDrain();
+}
+
+void Heap::visitCompilerWorklists()
+{
+#if ENABLE(DFG_JIT)
+ GCPHASE(VisitDFGWorklists);
+ MARK_LOG_ROOT(m_slotVisitor, "DFG Worklists");
+ for (unsigned i = DFG::numberOfWorklists(); i--;) {
+ if (DFG::Worklist* worklist = DFG::worklistForIndexOrNull(i))
+ worklist->visitChildren(m_slotVisitor, m_codeBlocks);
+ }
+#endif
+}
+
+void Heap::visitProtectedObjects(HeapRootVisitor& heapRootVisitor)
+{
+ GCPHASE(VisitProtectedObjects);
+ MARK_LOG_ROOT(m_slotVisitor, "Protected Objects");
+ ProtectCountSet::iterator end = m_protectedValues.end();
+ for (ProtectCountSet::iterator it = m_protectedValues.begin(); it != end; ++it)
+ heapRootVisitor.visit(&it->key);
+ m_slotVisitor.donateAndDrain();
+}
+
+void Heap::visitTempSortVectors(HeapRootVisitor& heapRootVisitor)
+{
+ GCPHASE(VisitTempSortVectors);
+ MARK_LOG_ROOT(m_slotVisitor, "Temp Sort Vectors");
+
+ typedef Vector<Vector<ValueStringPair, 0, UnsafeVectorOverflow>* > VectorOfValueStringVectors;
+
+ VectorOfValueStringVectors::iterator end = m_tempSortingVectors.end();
+ for (VectorOfValueStringVectors::iterator it = m_tempSortingVectors.begin(); it != end; ++it) {
+ Vector<ValueStringPair, 0, UnsafeVectorOverflow>* tempSortingVector = *it;
+
+ Vector<ValueStringPair>::iterator vectorEnd = tempSortingVector->end();
+ for (Vector<ValueStringPair>::iterator vectorIt = tempSortingVector->begin(); vectorIt != vectorEnd; ++vectorIt) {
+ if (vectorIt->first)
+ heapRootVisitor.visit(&vectorIt->first);
</ins><span class="cx"> }
</span><del>- {
- GCPHASE(VisitTempSortVectors);
- MARK_LOG_ROOT(visitor, "Temp Sort Vectors");
- markTempSortVectors(heapRootVisitor);
- visitor.donateAndDrain();
- }
</del><ins>+ }
+ m_slotVisitor.donateAndDrain();
+}
</ins><span class="cx">
</span><del>- {
- GCPHASE(MarkingArgumentBuffers);
- if (m_markListSet && m_markListSet->size()) {
- MARK_LOG_ROOT(visitor, "Argument Buffers");
- MarkedArgumentBuffer::markLists(heapRootVisitor, *m_markListSet);
- visitor.donateAndDrain();
- }
- }
- if (m_vm->exception()) {
- GCPHASE(MarkingException);
- MARK_LOG_ROOT(visitor, "Exceptions");
- heapRootVisitor.visit(m_vm->addressOfException());
- visitor.donateAndDrain();
- }
-
- {
- GCPHASE(VisitStrongHandles);
- MARK_LOG_ROOT(visitor, "Strong Handles");
- m_handleSet.visitStrongHandles(heapRootVisitor);
- visitor.donateAndDrain();
- }
-
- {
- GCPHASE(HandleStack);
- MARK_LOG_ROOT(visitor, "Handle Stack");
- m_handleStack.visit(heapRootVisitor);
- visitor.donateAndDrain();
- }
-
- {
- GCPHASE(TraceCodeBlocksAndJITStubRoutines);
- MARK_LOG_ROOT(visitor, "Trace Code Blocks and JIT Stub Routines");
- m_codeBlocks.traceMarked(visitor);
- m_jitStubRoutines.traceMarkedStubRoutines(visitor);
- visitor.donateAndDrain();
- }
-
</del><ins>+void Heap::visitArgumentBuffers(HeapRootVisitor& visitor)
+{
+ GCPHASE(MarkingArgumentBuffers);
+ MARK_LOG_ROOT(m_slotVisitor, "Argument Buffers");
+ if (!m_markListSet || !m_markListSet->size())
+ return;
+
+ MarkedArgumentBuffer::markLists(visitor, *m_markListSet);
+ m_slotVisitor.donateAndDrain();
+}
+
+void Heap::visitException(HeapRootVisitor& visitor)
+{
+ GCPHASE(MarkingException);
+ MARK_LOG_ROOT(m_slotVisitor, "Exceptions");
+ if (!m_vm->exception())
+ return;
+
+ visitor.visit(m_vm->addressOfException());
+ m_slotVisitor.donateAndDrain();
+}
+
+void Heap::visitStrongHandles(HeapRootVisitor& visitor)
+{
+ GCPHASE(VisitStrongHandles);
+ MARK_LOG_ROOT(m_slotVisitor, "Strong Handles");
+ m_handleSet.visitStrongHandles(visitor);
+ m_slotVisitor.donateAndDrain();
+}
+
+void Heap::visitHandleStack(HeapRootVisitor& visitor)
+{
+ GCPHASE(VisitHandleStack);
+ MARK_LOG_ROOT(m_slotVisitor, "Handle Stack");
+ m_handleStack.visit(visitor);
+ m_slotVisitor.donateAndDrain();
+}
+
+void Heap::traceCodeBlocksAndJITStubRoutines()
+{
+ GCPHASE(TraceCodeBlocksAndJITStubRoutines);
+ MARK_LOG_ROOT(m_slotVisitor, "Trace Code Blocks and JIT Stub Routines");
+ m_codeBlocks.traceMarked(m_slotVisitor);
+ m_jitStubRoutines.traceMarkedStubRoutines(m_slotVisitor);
+ m_slotVisitor.donateAndDrain();
+}
+
+void Heap::converge()
+{
</ins><span class="cx"> #if ENABLE(PARALLEL_GC)
</span><del>- {
- GCPHASE(Convergence);
- visitor.drainFromShared(SlotVisitor::MasterDrain);
- }
</del><ins>+ GCPHASE(Convergence);
+ m_slotVisitor.drainFromShared(SlotVisitor::MasterDrain);
</ins><span class="cx"> #endif
</span><del>- }
</del><ins>+}
</ins><span class="cx">
</span><del>- // Weak references must be marked last because their liveness depends on
- // the liveness of the rest of the object graph.
- {
- GCPHASE(VisitingLiveWeakHandles);
- MARK_LOG_ROOT(visitor, "Live Weak Handles");
- while (true) {
- m_objectSpace.visitWeakSets(heapRootVisitor);
- harvestWeakReferences();
- if (visitor.isEmpty())
- break;
- {
- ParallelModeEnabler enabler(visitor);
- visitor.donateAndDrain();
</del><ins>+void Heap::visitWeakHandles(HeapRootVisitor& visitor)
+{
+ GCPHASE(VisitingLiveWeakHandles);
+ MARK_LOG_ROOT(m_slotVisitor, "Live Weak Handles");
+ while (true) {
+ m_objectSpace.visitWeakSets(visitor);
+ harvestWeakReferences();
+ if (m_slotVisitor.isEmpty())
+ break;
+ {
+ ParallelModeEnabler enabler(m_slotVisitor);
+ m_slotVisitor.donateAndDrain();
</ins><span class="cx"> #if ENABLE(PARALLEL_GC)
</span><del>- visitor.drainFromShared(SlotVisitor::MasterDrain);
</del><ins>+ m_slotVisitor.drainFromShared(SlotVisitor::MasterDrain);
</ins><span class="cx"> #endif
</span><del>- }
</del><span class="cx"> }
</span><span class="cx"> }
</span><ins>+}
</ins><span class="cx">
</span><ins>+void Heap::clearRememberedSet(Vector<const JSCell*>& rememberedSet)
+{
</ins><span class="cx"> #if ENABLE(GGC)
</span><del>- {
- GCPHASE(ClearRememberedSet);
- for (unsigned i = 0; i < rememberedSet.size(); ++i) {
- const JSCell* cell = rememberedSet[i];
- MarkedBlock::blockFor(cell)->clearRemembered(cell);
- }
</del><ins>+ GCPHASE(ClearRememberedSet);
+ for (unsigned i = 0; i < rememberedSet.size(); ++i) {
+ const JSCell* cell = rememberedSet[i];
+ MarkedBlock::blockFor(cell)->clearRemembered(cell);
</ins><span class="cx"> }
</span><ins>+#else
+ UNUSED_PARAM(rememberedSet);
</ins><span class="cx"> #endif
</span><ins>+}
</ins><span class="cx">
</span><del>- GCCOUNTER(VisitedValueCount, visitor.visitCount());
</del><ins>+void Heap::updateObjectCounts()
+{
+ GCCOUNTER(VisitedValueCount, m_slotVisitor.visitCount());
</ins><span class="cx">
</span><del>- m_sharedData.didFinishMarking();
</del><span class="cx"> #if ENABLE(OBJECT_MARK_LOGGING)
</span><del>- size_t visitCount = visitor.visitCount();
</del><ins>+ size_t visitCount = m_slotVisitor.visitCount();
</ins><span class="cx"> #if ENABLE(PARALLEL_GC)
</span><span class="cx"> visitCount += m_sharedData.childVisitCount();
</span><span class="cx"> #endif
</span><span class="lines">@@ -634,42 +692,28 @@
</span><span class="cx"> #endif
</span><span class="cx">
</span><span class="cx"> if (m_operationInProgress == EdenCollection) {
</span><del>- m_totalBytesVisited += visitor.bytesVisited();
- m_totalBytesCopied += visitor.bytesCopied();
</del><ins>+ m_totalBytesVisited += m_slotVisitor.bytesVisited();
+ m_totalBytesCopied += m_slotVisitor.bytesCopied();
</ins><span class="cx"> } else {
</span><span class="cx"> ASSERT(m_operationInProgress == FullCollection);
</span><del>- m_totalBytesVisited = visitor.bytesVisited();
- m_totalBytesCopied = visitor.bytesCopied();
</del><ins>+ m_totalBytesVisited = m_slotVisitor.bytesVisited();
+ m_totalBytesCopied = m_slotVisitor.bytesCopied();
</ins><span class="cx"> }
</span><span class="cx"> #if ENABLE(PARALLEL_GC)
</span><span class="cx"> m_totalBytesVisited += m_sharedData.childBytesVisited();
</span><span class="cx"> m_totalBytesCopied += m_sharedData.childBytesCopied();
</span><span class="cx"> #endif
</span><ins>+}
</ins><span class="cx">
</span><del>- visitor.reset();
</del><ins>+void Heap::resetVisitors()
+{
+ m_slotVisitor.reset();
</ins><span class="cx"> #if ENABLE(PARALLEL_GC)
</span><span class="cx"> m_sharedData.resetChildren();
</span><span class="cx"> #endif
</span><span class="cx"> m_sharedData.reset();
</span><span class="cx"> }
</span><span class="cx">
</span><del>-template <HeapOperation collectionType>
-void Heap::copyBackingStores()
-{
- m_storageSpace.startedCopying<collectionType>();
- if (m_storageSpace.shouldDoCopyPhase()) {
- m_sharedData.didStartCopying();
- m_copyVisitor.startCopying();
- m_copyVisitor.copyFromShared();
- m_copyVisitor.doneCopying();
- // We need to wait for everybody to finish and return their CopiedBlocks
- // before signaling that the phase is complete.
- m_storageSpace.doneCopying();
- m_sharedData.didFinishCopying();
- } else
- m_storageSpace.doneCopying();
-}
-
</del><span class="cx"> size_t Heap::objectCount()
</span><span class="cx"> {
</span><span class="cx"> return m_objectSpace.objectCount();
</span><span class="lines">@@ -762,6 +806,7 @@
</span><span class="cx">
</span><span class="cx"> void Heap::deleteUnmarkedCompiledCode()
</span><span class="cx"> {
</span><ins>+ GCPHASE(DeleteCodeBlocks);
</ins><span class="cx"> ExecutableBase* next;
</span><span class="cx"> for (ExecutableBase* current = m_compiledCode.head(); current; current = next) {
</span><span class="cx"> next = current->next();
</span><span class="lines">@@ -825,14 +870,70 @@
</span><span class="cx"> ASSERT(m_isSafeToCollect);
</span><span class="cx"> JAVASCRIPTCORE_GC_BEGIN();
</span><span class="cx"> RELEASE_ASSERT(m_operationInProgress == NoOperation);
</span><del>-
</del><ins>+
+ suspendCompilerThreads();
+ willStartCollection();
+
+ double gcStartTime = WTF::monotonicallyIncreasingTime();
+
+ deleteOldCode(gcStartTime);
+ flushOldStructureIDTables();
+ stopAllocation();
+ flushWriteBarrierBuffer();
+
+ markRoots();
+
+ JAVASCRIPTCORE_GC_MARKED();
+
+ reapWeakHandles();
+ sweepArrayBuffers();
+ snapshotMarkedSpace();
+
+ copyBackingStores();
+
+ finalizeUnconditionalFinalizers();
+ deleteUnmarkedCompiledCode();
+ deleteSourceProviderCaches();
+ notifyIncrementalSweeper();
+ rememberCurrentlyExecutingCodeBlocks();
+
+ resetAllocators();
+ updateAllocationLimits();
+ didFinishCollection(gcStartTime);
+ resumeCompilerThreads();
+
+ if (Options::logGC()) {
+ double after = currentTimeMS();
+ dataLog(after - before, " ms]\n");
+ }
+}
+
+bool Heap::collectIfNecessaryOrDefer()
+{
+ if (isDeferred())
+ return false;
+
+ if (!shouldCollect())
+ return false;
+
+ collect();
+ return true;
+}
+
+void Heap::suspendCompilerThreads()
+{
</ins><span class="cx"> #if ENABLE(DFG_JIT)
</span><ins>+ GCPHASE(SuspendCompilerThreads);
</ins><span class="cx"> for (unsigned i = DFG::numberOfWorklists(); i--;) {
</span><span class="cx"> if (DFG::Worklist* worklist = DFG::worklistForIndexOrNull(i))
</span><span class="cx"> worklist->suspendAllThreads();
</span><span class="cx"> }
</span><span class="cx"> #endif
</span><ins>+}
</ins><span class="cx">
</span><ins>+void Heap::willStartCollection()
+{
+ GCPHASE(StartingCollection);
</ins><span class="cx"> if (shouldDoFullCollection()) {
</span><span class="cx"> m_operationInProgress = FullCollection;
</span><span class="cx"> m_slotVisitor.clearMarkStack();
</span><span class="lines">@@ -849,84 +950,93 @@
</span><span class="cx">
</span><span class="cx"> if (m_activityCallback)
</span><span class="cx"> m_activityCallback->willCollect();
</span><ins>+}
</ins><span class="cx">
</span><del>- double lastGCStartTime = WTF::monotonicallyIncreasingTime();
- if (lastGCStartTime - m_lastCodeDiscardTime > minute) {
</del><ins>+void Heap::deleteOldCode(double gcStartTime)
+{
+ GCPHASE(DeleteOldCode);
+ if (gcStartTime - m_lastCodeDiscardTime > minute) {
</ins><span class="cx"> deleteAllCompiledCode();
</span><span class="cx"> m_lastCodeDiscardTime = WTF::monotonicallyIncreasingTime();
</span><span class="cx"> }
</span><ins>+}
</ins><span class="cx">
</span><del>- {
- GCPHASE(StopAllocation);
- m_structureIDTable.flushOldTables();
- m_objectSpace.stopAllocating();
- if (m_operationInProgress == FullCollection)
- m_storageSpace.didStartFullCollection();
- }
</del><ins>+void Heap::flushOldStructureIDTables()
+{
+ GCPHASE(FlushOldStructureIDTables);
+ m_structureIDTable.flushOldTables();
+}
</ins><span class="cx">
</span><del>- {
- GCPHASE(FlushWriteBarrierBuffer);
- if (m_operationInProgress == EdenCollection)
- m_writeBarrierBuffer.flush(*this);
- else
- m_writeBarrierBuffer.reset();
</del><ins>+void Heap::flushWriteBarrierBuffer()
+{
+ GCPHASE(FlushWriteBarrierBuffer);
+ if (m_operationInProgress == EdenCollection) {
+ m_writeBarrierBuffer.flush(*this);
+ return;
</ins><span class="cx"> }
</span><ins>+ m_writeBarrierBuffer.reset();
+}
</ins><span class="cx">
</span><del>- markRoots();
-
- {
- GCPHASE(ReapingWeakHandles);
- m_objectSpace.reapWeakSets();
- }
</del><ins>+void Heap::stopAllocation()
+{
+ GCPHASE(StopAllocation);
+ m_objectSpace.stopAllocating();
+ if (m_operationInProgress == FullCollection)
+ m_storageSpace.didStartFullCollection();
+}
</ins><span class="cx">
</span><del>- JAVASCRIPTCORE_GC_MARKED();
-
- {
- GCPHASE(SweepingArrayBuffers);
- m_arrayBuffers.sweep();
- }
</del><ins>+void Heap::reapWeakHandles()
+{
+ GCPHASE(ReapingWeakHandles);
+ m_objectSpace.reapWeakSets();
+}
</ins><span class="cx">
</span><del>- if (m_operationInProgress == FullCollection) {
- m_blockSnapshot.resize(m_objectSpace.blocks().set().size());
- MarkedBlockSnapshotFunctor functor(m_blockSnapshot);
- m_objectSpace.forEachBlock(functor);
- }
</del><ins>+void Heap::sweepArrayBuffers()
+{
+ GCPHASE(SweepingArrayBuffers);
+ m_arrayBuffers.sweep();
+}
</ins><span class="cx">
</span><del>- if (m_operationInProgress == FullCollection)
- copyBackingStores<FullCollection>();
- else
- copyBackingStores<EdenCollection>();
</del><ins>+void Heap::snapshotMarkedSpace()
+{
+ GCPHASE(SnapshotMarkedSpace);
+ if (m_operationInProgress != FullCollection)
+ return;
</ins><span class="cx">
</span><del>- {
- GCPHASE(FinalizeUnconditionalFinalizers);
- finalizeUnconditionalFinalizers();
- }
</del><ins>+ m_blockSnapshot.resize(m_objectSpace.blocks().set().size());
+ MarkedBlockSnapshotFunctor functor(m_blockSnapshot);
+ m_objectSpace.forEachBlock(functor);
+}
</ins><span class="cx">
</span><del>- {
- GCPHASE(DeleteCodeBlocks);
- deleteUnmarkedCompiledCode();
- }
</del><ins>+void Heap::deleteSourceProviderCaches()
+{
+ GCPHASE(DeleteSourceProviderCaches);
+ m_vm->clearSourceProviderCaches();
+}
</ins><span class="cx">
</span><del>- {
- GCPHASE(DeleteSourceProviderCaches);
- m_vm->clearSourceProviderCaches();
- }
</del><ins>+void Heap::notifyIncrementalSweeper()
+{
+ GCPHASE(NotifyIncrementalSweeper);
+ if (m_operationInProgress != FullCollection)
+ return;
+ m_sweeper->startSweeping(m_blockSnapshot);
+}
</ins><span class="cx">
</span><del>- if (m_operationInProgress == FullCollection)
- m_sweeper->startSweeping(m_blockSnapshot);
</del><ins>+void Heap::rememberCurrentlyExecutingCodeBlocks()
+{
+ GCPHASE(RememberCurrentlyExecutingCodeBlocks);
+ m_codeBlocks.rememberCurrentlyExecutingCodeBlocks(this);
+}
</ins><span class="cx">
</span><del>- {
- GCPHASE(AddCurrentlyExecutingCodeBlocksToRememberedSet);
- m_codeBlocks.rememberCurrentlyExecutingCodeBlocks(this);
- }
</del><ins>+void Heap::resetAllocators()
+{
+ GCPHASE(ResetAllocators);
+ m_objectSpace.resetAllocators();
+}
</ins><span class="cx">
</span><del>- m_bytesAbandonedThisCycle = 0;
-
- {
- GCPHASE(ResetAllocators);
- m_objectSpace.resetAllocators();
- }
-
</del><ins>+void Heap::updateAllocationLimits()
+{
+ GCPHASE(UpdateAllocationLimits);
</ins><span class="cx"> size_t currentHeapSize = sizeAfterCollect();
</span><span class="cx"> if (Options::gcMaxHeapSize() && currentHeapSize > Options::gcMaxHeapSize())
</span><span class="cx"> HeapStatistics::exitWithFailure();
</span><span class="lines">@@ -949,13 +1059,21 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> m_sizeAfterLastCollect = currentHeapSize;
</span><del>-
</del><span class="cx"> m_bytesAllocatedThisCycle = 0;
</span><del>- double lastGCEndTime = WTF::monotonicallyIncreasingTime();
- m_lastGCLength = lastGCEndTime - lastGCStartTime;
</del><ins>+ m_bytesAbandonedThisCycle = 0;
</ins><span class="cx">
</span><ins>+ if (Options::logGC())
+ dataLog(currentHeapSize / 1024, " kb, ");
+}
+
+void Heap::didFinishCollection(double gcStartTime)
+{
+ GCPHASE(FinishingCollection);
+ double gcEndTime = WTF::monotonicallyIncreasingTime();
+ m_lastGCLength = gcEndTime - gcStartTime;
+
</ins><span class="cx"> if (Options::recordGCPauseTimes())
</span><del>- HeapStatistics::recordGCPauseTime(lastGCStartTime, lastGCEndTime);
</del><ins>+ HeapStatistics::recordGCPauseTime(gcStartTime, gcEndTime);
</ins><span class="cx"> RELEASE_ASSERT(m_operationInProgress == EdenCollection || m_operationInProgress == FullCollection);
</span><span class="cx">
</span><span class="cx"> m_operationInProgress = NoOperation;
</span><span class="lines">@@ -969,32 +1087,19 @@
</span><span class="cx">
</span><span class="cx"> if (Options::showObjectStatistics())
</span><span class="cx"> HeapStatistics::showObjectStatistics(this);
</span><del>-
</del><ins>+}
+
+void Heap::resumeCompilerThreads()
+{
</ins><span class="cx"> #if ENABLE(DFG_JIT)
</span><ins>+ GCPHASE(ResumeCompilerThreads);
</ins><span class="cx"> for (unsigned i = DFG::numberOfWorklists(); i--;) {
</span><span class="cx"> if (DFG::Worklist* worklist = DFG::worklistForIndexOrNull(i))
</span><span class="cx"> worklist->resumeAllThreads();
</span><span class="cx"> }
</span><span class="cx"> #endif
</span><del>-
- if (Options::logGC()) {
- double after = currentTimeMS();
- dataLog(after - before, " ms, ", currentHeapSize / 1024, " kb]\n");
- }
</del><span class="cx"> }
</span><span class="cx">
</span><del>-bool Heap::collectIfNecessaryOrDefer()
-{
- if (isDeferred())
- return false;
-
- if (!shouldCollect())
- return false;
-
- collect();
- return true;
-}
-
</del><span class="cx"> void Heap::markDeadObjects()
</span><span class="cx"> {
</span><span class="cx"> HeapIterationScope iterationScope(*this);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapHeaph"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/Heap.h (164861 => 164862)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/Heap.h        2014-02-28 16:35:27 UTC (rev 164861)
+++ trunk/Source/JavaScriptCore/heap/Heap.h        2014-02-28 16:56:17 UTC (rev 164862)
</span><span class="lines">@@ -248,14 +248,48 @@
</span><span class="cx"> JS_EXPORT_PRIVATE bool isValidAllocation(size_t);
</span><span class="cx"> JS_EXPORT_PRIVATE void reportExtraMemoryCostSlowCase(size_t);
</span><span class="cx">
</span><ins>+ void suspendCompilerThreads();
+ void willStartCollection();
+ void deleteOldCode(double gcStartTime);
+ void flushOldStructureIDTables();
+ void flushWriteBarrierBuffer();
+ void stopAllocation();
+
</ins><span class="cx"> void markRoots();
</span><del>- void markProtectedObjects(HeapRootVisitor&);
- void markTempSortVectors(HeapRootVisitor&);
- template <HeapOperation collectionType>
</del><ins>+ void gatherStackRoots(ConservativeRoots&, void** dummy);
+ void gatherJSStackRoots(ConservativeRoots&);
+ void gatherScratchBufferRoots(ConservativeRoots&);
+ void clearLivenessData();
+ void visitSmallStrings();
+ void visitConservativeRoots(ConservativeRoots&);
+ void visitCompilerWorklists();
+ void visitProtectedObjects(HeapRootVisitor&);
+ void visitTempSortVectors(HeapRootVisitor&);
+ void visitArgumentBuffers(HeapRootVisitor&);
+ void visitException(HeapRootVisitor&);
+ void visitStrongHandles(HeapRootVisitor&);
+ void visitHandleStack(HeapRootVisitor&);
+ void traceCodeBlocksAndJITStubRoutines();
+ void converge();
+ void visitWeakHandles(HeapRootVisitor&);
+ void clearRememberedSet(Vector<const JSCell*>&);
+ void updateObjectCounts();
+ void resetVisitors();
+
+ void reapWeakHandles();
+ void sweepArrayBuffers();
+ void snapshotMarkedSpace();
+ void deleteSourceProviderCaches();
+ void notifyIncrementalSweeper();
+ void rememberCurrentlyExecutingCodeBlocks();
+ void resetAllocators();
</ins><span class="cx"> void copyBackingStores();
</span><span class="cx"> void harvestWeakReferences();
</span><span class="cx"> void finalizeUnconditionalFinalizers();
</span><span class="cx"> void deleteUnmarkedCompiledCode();
</span><ins>+ void updateAllocationLimits();
+ void didFinishCollection(double gcStartTime);
+ void resumeCompilerThreads();
</ins><span class="cx"> void zombifyDeadObjects();
</span><span class="cx"> void markDeadObjects();
</span><span class="cx">
</span></span></pre>
</div>
</div>
</body>
</html>