diff options
author | Simon Hausmann <simon.hausmann@digia.com> | 2012-11-22 09:09:45 +0100 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@digia.com> | 2012-11-22 09:10:13 +0100 |
commit | 470286ecfe79d59df14944e5b5d34630fc739391 (patch) | |
tree | 43983212872e06cebefd2ae474418fa2908ca54c /Source/JavaScriptCore/heap | |
parent | 23037105e948c2065da5a937d3a2396b0ff45c1e (diff) | |
download | qtwebkit-470286ecfe79d59df14944e5b5d34630fc739391.tar.gz |
Imported WebKit commit e89504fa9195b2063b2530961d4b73dd08de3242 (http://svn.webkit.org/repository/webkit/trunk@135485)
Change-Id: I03774e5ac79721c13ffa30d152537a74d0b12e66
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Diffstat (limited to 'Source/JavaScriptCore/heap')
26 files changed, 199 insertions, 210 deletions
diff --git a/Source/JavaScriptCore/heap/BlockAllocator.cpp b/Source/JavaScriptCore/heap/BlockAllocator.cpp index daba93805..2d7b57f9a 100644 --- a/Source/JavaScriptCore/heap/BlockAllocator.cpp +++ b/Source/JavaScriptCore/heap/BlockAllocator.cpp @@ -36,7 +36,7 @@ namespace JSC { BlockAllocator::BlockAllocator() : m_copiedRegionSet(CopiedBlock::blockSize) , m_markedRegionSet(MarkedBlock::blockSize) - , m_weakRegionSet(WeakBlock::blockSize) + , m_weakAndMarkStackRegionSet(WeakBlock::blockSize) , m_numberOfEmptyRegions(0) , m_isCurrentlyAllocating(false) , m_blockFreeingThreadShouldQuit(false) diff --git a/Source/JavaScriptCore/heap/BlockAllocator.h b/Source/JavaScriptCore/heap/BlockAllocator.h index f8ce39530..75c59b783 100644 --- a/Source/JavaScriptCore/heap/BlockAllocator.h +++ b/Source/JavaScriptCore/heap/BlockAllocator.h @@ -37,6 +37,7 @@ namespace JSC { class BlockAllocator; class CopiedBlock; +class MarkStackSegment; class MarkedBlock; class Region; class WeakBlock; @@ -185,7 +186,8 @@ private: RegionSet m_copiedRegionSet; RegionSet m_markedRegionSet; - RegionSet m_weakRegionSet; + // WeakBlocks and MarkStackSegments use the same RegionSet since they're the same size. + RegionSet m_weakAndMarkStackRegionSet; DoublyLinkedList<Region> m_emptyRegions; size_t m_numberOfEmptyRegions; @@ -315,7 +317,13 @@ inline BlockAllocator::RegionSet& BlockAllocator::regionSetFor<MarkedBlock>() template <> inline BlockAllocator::RegionSet& BlockAllocator::regionSetFor<WeakBlock>() { - return m_weakRegionSet; + return m_weakAndMarkStackRegionSet; +} + +template <> +inline BlockAllocator::RegionSet& BlockAllocator::regionSetFor<MarkStackSegment>() +{ + return m_weakAndMarkStackRegionSet; } template <> @@ -333,7 +341,13 @@ inline BlockAllocator::RegionSet& BlockAllocator::regionSetFor<HeapBlock<MarkedB template <> inline BlockAllocator::RegionSet& BlockAllocator::regionSetFor<HeapBlock<WeakBlock> >() { - return m_weakRegionSet; + return m_weakAndMarkStackRegionSet; +} + +template <> +inline BlockAllocator::RegionSet& BlockAllocator::regionSetFor<HeapBlock<MarkStackSegment> >() +{ + return m_weakAndMarkStackRegionSet; } template <typename T> diff --git a/Source/JavaScriptCore/heap/ConservativeRoots.cpp b/Source/JavaScriptCore/heap/ConservativeRoots.cpp index 7fe22dfff..752ce2775 100644 --- a/Source/JavaScriptCore/heap/ConservativeRoots.cpp +++ b/Source/JavaScriptCore/heap/ConservativeRoots.cpp @@ -26,9 +26,9 @@ #include "config.h" #include "ConservativeRoots.h" -#include "CopiedSpace.h" -#include "CopiedSpaceInlineMethods.h" #include "CodeBlock.h" +#include "CopiedSpace.h" +#include "CopiedSpaceInlines.h" #include "DFGCodeBlocks.h" #include "JSCell.h" #include "JSObject.h" diff --git a/Source/JavaScriptCore/heap/CopiedBlock.h b/Source/JavaScriptCore/heap/CopiedBlock.h index af36f55df..83fdb08da 100644 --- a/Source/JavaScriptCore/heap/CopiedBlock.h +++ b/Source/JavaScriptCore/heap/CopiedBlock.h @@ -29,7 +29,7 @@ #include "BlockAllocator.h" #include "HeapBlock.h" #include "JSValue.h" -#include "JSValueInlineMethods.h" +#include "JSValueInlines.h" #include "Options.h" #include <wtf/Atomics.h> diff --git a/Source/JavaScriptCore/heap/CopiedSpace.cpp b/Source/JavaScriptCore/heap/CopiedSpace.cpp index c228f9460..e4141c1d7 100644 --- a/Source/JavaScriptCore/heap/CopiedSpace.cpp +++ b/Source/JavaScriptCore/heap/CopiedSpace.cpp @@ -26,7 +26,7 @@ #include "config.h" #include "CopiedSpace.h" -#include "CopiedSpaceInlineMethods.h" +#include "CopiedSpaceInlines.h" #include "GCActivityCallback.h" #include "Options.h" diff --git a/Source/JavaScriptCore/heap/CopiedSpaceInlineMethods.h b/Source/JavaScriptCore/heap/CopiedSpaceInlines.h index c244015e7..9d222f549 100644 --- a/Source/JavaScriptCore/heap/CopiedSpaceInlineMethods.h +++ b/Source/JavaScriptCore/heap/CopiedSpaceInlines.h @@ -23,8 +23,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef CopiedSpaceInlineMethods_h -#define CopiedSpaceInlineMethods_h +#ifndef CopiedSpaceInlines_h +#define CopiedSpaceInlines_h #include "CopiedBlock.h" #include "CopiedSpace.h" @@ -182,4 +182,5 @@ inline CopiedBlock* CopiedSpace::blockFor(void* ptr) } // namespace JSC -#endif +#endif // CopiedSpaceInlines_h + diff --git a/Source/JavaScriptCore/heap/CopyVisitor.cpp b/Source/JavaScriptCore/heap/CopyVisitor.cpp index ae826f0d2..22ab57882 100644 --- a/Source/JavaScriptCore/heap/CopyVisitor.cpp +++ b/Source/JavaScriptCore/heap/CopyVisitor.cpp @@ -26,7 +26,7 @@ #include "config.h" #include "CopyVisitor.h" -#include "CopyVisitorInlineMethods.h" +#include "CopyVisitorInlines.h" #include "GCThreadSharedData.h" #include "JSCell.h" #include "JSObject.h" diff --git a/Source/JavaScriptCore/heap/CopyVisitorInlineMethods.h b/Source/JavaScriptCore/heap/CopyVisitorInlines.h index eb7bd2e82..bd7879429 100644 --- a/Source/JavaScriptCore/heap/CopyVisitorInlineMethods.h +++ b/Source/JavaScriptCore/heap/CopyVisitorInlines.h @@ -23,8 +23,8 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef CopyVisitorInlineMethods_h -#define CopyVisitorInlineMethods_h +#ifndef CopyVisitorInlines_h +#define CopyVisitorInlines_h #include "ClassInfo.h" #include "CopyVisitor.h" @@ -116,4 +116,5 @@ inline void CopyVisitor::didCopy(void* ptr, size_t bytes) } // namespace JSC -#endif +#endif // CopyVisitorInlines_h + diff --git a/Source/JavaScriptCore/heap/GCThread.cpp b/Source/JavaScriptCore/heap/GCThread.cpp index ce3bbedc9..7caa7d588 100644 --- a/Source/JavaScriptCore/heap/GCThread.cpp +++ b/Source/JavaScriptCore/heap/GCThread.cpp @@ -27,7 +27,7 @@ #include "GCThread.h" #include "CopyVisitor.h" -#include "CopyVisitorInlineMethods.h" +#include "CopyVisitorInlines.h" #include "GCThreadSharedData.h" #include "SlotVisitor.h" #include <wtf/MainThread.h> diff --git a/Source/JavaScriptCore/heap/GCThreadSharedData.cpp b/Source/JavaScriptCore/heap/GCThreadSharedData.cpp index 446b41c2f..f513fafab 100644 --- a/Source/JavaScriptCore/heap/GCThreadSharedData.cpp +++ b/Source/JavaScriptCore/heap/GCThreadSharedData.cpp @@ -27,12 +27,12 @@ #include "GCThreadSharedData.h" #include "CopyVisitor.h" -#include "CopyVisitorInlineMethods.h" +#include "CopyVisitorInlines.h" #include "GCThread.h" #include "JSGlobalData.h" #include "MarkStack.h" #include "SlotVisitor.h" -#include "SlotVisitorInlineMethods.h" +#include "SlotVisitorInlines.h" namespace JSC { @@ -56,7 +56,7 @@ GCThreadSharedData::GCThreadSharedData(JSGlobalData* globalData) : m_globalData(globalData) , m_copiedSpace(&globalData->heap.m_storageSpace) , m_shouldHashConst(false) - , m_sharedMarkStack(m_segmentAllocator) + , m_sharedMarkStack(globalData->heap.blockAllocator()) , m_numberOfActiveParallelMarkers(0) , m_parallelMarkersShouldExit(false) , m_blocksToCopy(globalData->heap.m_blockSnapshot) @@ -110,7 +110,6 @@ void GCThreadSharedData::reset() ASSERT(m_sharedMarkStack.isEmpty()); #if ENABLE(PARALLEL_GC) - m_segmentAllocator.shrinkReserve(); m_opaqueRoots.clear(); #else ASSERT(m_opaqueRoots.isEmpty()); diff --git a/Source/JavaScriptCore/heap/GCThreadSharedData.h b/Source/JavaScriptCore/heap/GCThreadSharedData.h index f341afc04..b80cc5af2 100644 --- a/Source/JavaScriptCore/heap/GCThreadSharedData.h +++ b/Source/JavaScriptCore/heap/GCThreadSharedData.h @@ -80,8 +80,6 @@ private: JSGlobalData* m_globalData; CopiedSpace* m_copiedSpace; - MarkStackSegmentAllocator m_segmentAllocator; - bool m_shouldHashConst; Vector<GCThread*> m_gcThreads; diff --git a/Source/JavaScriptCore/heap/HandleStack.cpp b/Source/JavaScriptCore/heap/HandleStack.cpp index 42eb326a5..a5653c748 100644 --- a/Source/JavaScriptCore/heap/HandleStack.cpp +++ b/Source/JavaScriptCore/heap/HandleStack.cpp @@ -27,8 +27,8 @@ #include "HandleStack.h" #include "HeapRootVisitor.h" -#include "JSValueInlineMethods.h" #include "JSObject.h" +#include "JSValueInlines.h" namespace JSC { diff --git a/Source/JavaScriptCore/heap/Heap.cpp b/Source/JavaScriptCore/heap/Heap.cpp index c455fc2b1..9ff318b08 100644 --- a/Source/JavaScriptCore/heap/Heap.cpp +++ b/Source/JavaScriptCore/heap/Heap.cpp @@ -24,8 +24,8 @@ #include "CodeBlock.h" #include "ConservativeRoots.h" #include "CopiedSpace.h" -#include "CopiedSpaceInlineMethods.h" -#include "CopyVisitorInlineMethods.h" +#include "CopiedSpaceInlines.h" +#include "CopyVisitorInlines.h" #include "GCActivityCallback.h" #include "HeapRootVisitor.h" #include "HeapStatistics.h" @@ -76,7 +76,7 @@ struct GCTimer { } ~GCTimer() { - dataLog("%s: %.2lfms (avg. %.2lf, min. %.2lf, max. %.2lf)\n", m_name, m_time * 1000, m_time * 1000 / m_count, m_min*1000, m_max*1000); + dataLogF("%s: %.2lfms (avg. %.2lf, min. %.2lf, max. %.2lf)\n", m_name, m_time * 1000, m_time * 1000 / m_count, m_min*1000, m_max*1000); } double m_time; double m_min; @@ -126,7 +126,7 @@ struct GCCounter { } ~GCCounter() { - dataLog("%s: %zu values (avg. %zu, min. %zu, max. %zu)\n", m_name, m_total, m_total / m_count, m_min, m_max); + dataLogF("%s: %zu values (avg. %zu, min. %zu, max. %zu)\n", m_name, m_total, m_total / m_count, m_min, m_max); } const char* m_name; size_t m_count; diff --git a/Source/JavaScriptCore/heap/Heap.h b/Source/JavaScriptCore/heap/Heap.h index d0d03959b..90c9f2ab1 100644 --- a/Source/JavaScriptCore/heap/Heap.h +++ b/Source/JavaScriptCore/heap/Heap.h @@ -174,6 +174,8 @@ namespace JSC { bool isPagedOut(double deadline); void didStartVMShutdown(); + + const JITStubRoutineSet& jitStubRoutines() { return m_jitStubRoutines; } private: friend class CodeBlock; diff --git a/Source/JavaScriptCore/heap/HeapRootVisitor.h b/Source/JavaScriptCore/heap/HeapRootVisitor.h index 9849d7c39..5b11a5ead 100644 --- a/Source/JavaScriptCore/heap/HeapRootVisitor.h +++ b/Source/JavaScriptCore/heap/HeapRootVisitor.h @@ -27,7 +27,7 @@ #define HeapRootVisitor_h #include "SlotVisitor.h" -#include "SlotVisitorInlineMethods.h" +#include "SlotVisitorInlines.h" namespace JSC { diff --git a/Source/JavaScriptCore/heap/HeapStatistics.cpp b/Source/JavaScriptCore/heap/HeapStatistics.cpp index 8340bfa37..2b98fe711 100644 --- a/Source/JavaScriptCore/heap/HeapStatistics.cpp +++ b/Source/JavaScriptCore/heap/HeapStatistics.cpp @@ -41,8 +41,8 @@ namespace JSC { double HeapStatistics::s_startTime = 0.0; double HeapStatistics::s_endTime = 0.0; -Deque<double>* HeapStatistics::s_pauseTimeStarts = 0; -Deque<double>* HeapStatistics::s_pauseTimeEnds = 0; +Vector<double>* HeapStatistics::s_pauseTimeStarts = 0; +Vector<double>* HeapStatistics::s_pauseTimeEnds = 0; #if OS(UNIX) @@ -50,8 +50,8 @@ void HeapStatistics::initialize() { ASSERT(Options::recordGCPauseTimes()); s_startTime = WTF::monotonicallyIncreasingTime(); - s_pauseTimeStarts = new Deque<double>(); - s_pauseTimeEnds = new Deque<double>(); + s_pauseTimeStarts = new Vector<double>(); + s_pauseTimeEnds = new Vector<double>(); } void HeapStatistics::recordGCPauseTime(double start, double end) @@ -75,28 +75,28 @@ void HeapStatistics::logStatistics() #error "The HeapStatistics module is not supported on this platform." #endif if (!vmName || !suiteName || !benchmarkName) - dataLog("HeapStatistics: {\"max_rss\": %ld", usage.ru_maxrss); + dataLogF("HeapStatistics: {\"max_rss\": %ld", usage.ru_maxrss); else - dataLog("HeapStatistics: {\"max_rss\": %ld, \"vm_name\": \"%s\", \"suite_name\": \"%s\", \"benchmark_name\": \"%s\"", + dataLogF("HeapStatistics: {\"max_rss\": %ld, \"vm_name\": \"%s\", \"suite_name\": \"%s\", \"benchmark_name\": \"%s\"", usage.ru_maxrss, vmName, suiteName, benchmarkName); if (Options::recordGCPauseTimes()) { - dataLog(", \"pause_times\": ["); - Deque<double>::iterator startIt = s_pauseTimeStarts->begin(); - Deque<double>::iterator endIt = s_pauseTimeEnds->begin(); + dataLogF(", \"pause_times\": ["); + Vector<double>::iterator startIt = s_pauseTimeStarts->begin(); + Vector<double>::iterator endIt = s_pauseTimeEnds->begin(); if (startIt != s_pauseTimeStarts->end() && endIt != s_pauseTimeEnds->end()) { - dataLog("[%f, %f]", *startIt, *endIt); + dataLogF("[%f, %f]", *startIt, *endIt); ++startIt; ++endIt; } while (startIt != s_pauseTimeStarts->end() && endIt != s_pauseTimeEnds->end()) { - dataLog(", [%f, %f]", *startIt, *endIt); + dataLogF(", [%f, %f]", *startIt, *endIt); ++startIt; ++endIt; } - dataLog("], \"start_time\": %f, \"end_time\": %f", s_startTime, s_endTime); + dataLogF("], \"start_time\": %f, \"end_time\": %f", s_startTime, s_endTime); } - dataLog("}\n"); + dataLogF("}\n"); } void HeapStatistics::exitWithFailure() @@ -228,20 +228,20 @@ inline size_t StorageStatistics::storageCapacity() void HeapStatistics::showObjectStatistics(Heap* heap) { - dataLog("\n=== Heap Statistics: ===\n"); - dataLog("size: %ldkB\n", static_cast<long>(heap->m_sizeAfterLastCollect / KB)); - dataLog("capacity: %ldkB\n", static_cast<long>(heap->capacity() / KB)); - dataLog("pause time: %lfms\n\n", heap->m_lastGCLength); + dataLogF("\n=== Heap Statistics: ===\n"); + dataLogF("size: %ldkB\n", static_cast<long>(heap->m_sizeAfterLastCollect / KB)); + dataLogF("capacity: %ldkB\n", static_cast<long>(heap->capacity() / KB)); + dataLogF("pause time: %lfms\n\n", heap->m_lastGCLength); StorageStatistics storageStatistics; heap->m_objectSpace.forEachLiveCell(storageStatistics); - dataLog("wasted .property storage: %ldkB (%ld%%)\n", + dataLogF("wasted .property storage: %ldkB (%ld%%)\n", static_cast<long>( (storageStatistics.storageCapacity() - storageStatistics.storageSize()) / KB), static_cast<long>( (storageStatistics.storageCapacity() - storageStatistics.storageSize()) * 100 / storageStatistics.storageCapacity())); - dataLog("objects with out-of-line .property storage: %ld (%ld%%)\n", + dataLogF("objects with out-of-line .property storage: %ld (%ld%%)\n", static_cast<long>( storageStatistics.objectWithOutOfLineStorageCount()), static_cast<long>( diff --git a/Source/JavaScriptCore/heap/HeapStatistics.h b/Source/JavaScriptCore/heap/HeapStatistics.h index 0800f0c16..ce7a40a79 100644 --- a/Source/JavaScriptCore/heap/HeapStatistics.h +++ b/Source/JavaScriptCore/heap/HeapStatistics.h @@ -49,8 +49,8 @@ public: private: static void logStatistics(); - static Deque<double>* s_pauseTimeStarts; - static Deque<double>* s_pauseTimeEnds; + static Vector<double>* s_pauseTimeStarts; + static Vector<double>* s_pauseTimeEnds; static double s_startTime; static double s_endTime; }; diff --git a/Source/JavaScriptCore/heap/JITStubRoutineSet.h b/Source/JavaScriptCore/heap/JITStubRoutineSet.h index cb76ac8bd..2c2e9fa86 100644 --- a/Source/JavaScriptCore/heap/JITStubRoutineSet.h +++ b/Source/JavaScriptCore/heap/JITStubRoutineSet.h @@ -65,6 +65,9 @@ public: void traceMarkedStubRoutines(SlotVisitor&); + unsigned size() const { return m_listOfRoutines.size(); } + GCAwareJITStubRoutine* at(unsigned i) const { return m_listOfRoutines[i]; } + private: void markSlow(uintptr_t address); diff --git a/Source/JavaScriptCore/heap/MarkStack.cpp b/Source/JavaScriptCore/heap/MarkStack.cpp index 582439fd2..755a0ad50 100644 --- a/Source/JavaScriptCore/heap/MarkStack.cpp +++ b/Source/JavaScriptCore/heap/MarkStack.cpp @@ -25,18 +25,18 @@ #include "config.h" #include "MarkStack.h" -#include "MarkStackInlineMethods.h" +#include "MarkStackInlines.h" -#include "CopiedSpace.h" -#include "CopiedSpaceInlineMethods.h" #include "ConservativeRoots.h" +#include "CopiedSpace.h" +#include "CopiedSpaceInlines.h" #include "Heap.h" #include "Options.h" #include "JSArray.h" #include "JSCell.h" #include "JSObject.h" -#include "SlotVisitorInlineMethods.h" +#include "SlotVisitorInlines.h" #include "Structure.h" #include "WriteBarrier.h" #include <wtf/Atomics.h> @@ -45,84 +45,35 @@ namespace JSC { -MarkStackSegmentAllocator::MarkStackSegmentAllocator() - : m_nextFreeSegment(0) -{ - m_lock.Init(); -} - -MarkStackSegmentAllocator::~MarkStackSegmentAllocator() -{ - shrinkReserve(); -} - -MarkStackSegment* MarkStackSegmentAllocator::allocate() -{ - { - SpinLockHolder locker(&m_lock); - if (m_nextFreeSegment) { - MarkStackSegment* result = m_nextFreeSegment; - m_nextFreeSegment = result->m_previous; - return result; - } - } - - return static_cast<MarkStackSegment*>(OSAllocator::reserveAndCommit(Options::gcMarkStackSegmentSize())); -} - -void MarkStackSegmentAllocator::release(MarkStackSegment* segment) -{ - SpinLockHolder locker(&m_lock); - segment->m_previous = m_nextFreeSegment; - m_nextFreeSegment = segment; -} - -void MarkStackSegmentAllocator::shrinkReserve() -{ - MarkStackSegment* segments; - { - SpinLockHolder locker(&m_lock); - segments = m_nextFreeSegment; - m_nextFreeSegment = 0; - } - while (segments) { - MarkStackSegment* toFree = segments; - segments = segments->m_previous; - OSAllocator::decommitAndRelease(toFree, Options::gcMarkStackSegmentSize()); - } -} - -MarkStackArray::MarkStackArray(MarkStackSegmentAllocator& allocator) - : m_allocator(allocator) +MarkStackArray::MarkStackArray(BlockAllocator& blockAllocator) + : m_blockAllocator(blockAllocator) , m_segmentCapacity(MarkStackSegment::capacityFromSize(Options::gcMarkStackSegmentSize())) , m_top(0) - , m_numberOfPreviousSegments(0) + , m_numberOfSegments(0) { - m_topSegment = m_allocator.allocate(); -#if !ASSERT_DISABLED - m_topSegment->m_top = 0; -#endif - m_topSegment->m_previous = 0; + ASSERT(MarkStackSegment::blockSize == WeakBlock::blockSize); + m_segments.push(MarkStackSegment::create(m_blockAllocator.allocate<MarkStackSegment>())); + m_numberOfSegments++; } MarkStackArray::~MarkStackArray() { - ASSERT(!m_topSegment->m_previous); - m_allocator.release(m_topSegment); + ASSERT(m_numberOfSegments == 1 && m_segments.size() == 1); + m_blockAllocator.deallocate(MarkStackSegment::destroy(m_segments.removeHead())); } void MarkStackArray::expand() { - ASSERT(m_topSegment->m_top == m_segmentCapacity); + ASSERT(m_segments.head()->m_top == m_segmentCapacity); - m_numberOfPreviousSegments++; + MarkStackSegment* nextSegment = MarkStackSegment::create(m_blockAllocator.allocate<MarkStackSegment>()); + m_numberOfSegments++; - MarkStackSegment* nextSegment = m_allocator.allocate(); #if !ASSERT_DISABLED nextSegment->m_top = 0; #endif - nextSegment->m_previous = m_topSegment; - m_topSegment = nextSegment; + + m_segments.push(nextSegment); setTopForEmptySegment(); validatePrevious(); } @@ -132,14 +83,9 @@ bool MarkStackArray::refill() validatePrevious(); if (top()) return true; - MarkStackSegment* toFree = m_topSegment; - MarkStackSegment* previous = m_topSegment->m_previous; - if (!previous) - return false; - ASSERT(m_numberOfPreviousSegments); - m_numberOfPreviousSegments--; - m_topSegment = previous; - m_allocator.release(toFree); + m_blockAllocator.deallocate(MarkStackSegment::destroy(m_segments.removeHead())); + ASSERT(m_numberOfSegments > 1); + m_numberOfSegments--; setTopForFullSegment(); validatePrevious(); return true; @@ -153,7 +99,7 @@ void MarkStackArray::donateSomeCellsTo(MarkStackArray& other) ASSERT(m_segmentCapacity == other.m_segmentCapacity); - size_t segmentsToDonate = (m_numberOfPreviousSegments + 2 - 1) / 2; // Round up to donate 1 / 1 previous segments. + size_t segmentsToDonate = m_numberOfSegments / 2; // If we only have one segment (our head) we don't donate any segments. if (!segmentsToDonate) { size_t cellsToDonate = m_top / 2; // Round down to donate 0 / 1 cells. @@ -167,21 +113,23 @@ void MarkStackArray::donateSomeCellsTo(MarkStackArray& other) validatePrevious(); other.validatePrevious(); - MarkStackSegment* previous = m_topSegment->m_previous; + // Remove our head and the head of the other list before we start moving segments around. + // We'll add them back on once we're done donating. + MarkStackSegment* myHead = m_segments.removeHead(); + MarkStackSegment* otherHead = other.m_segments.removeHead(); + while (segmentsToDonate--) { - ASSERT(previous); - ASSERT(m_numberOfPreviousSegments); - - MarkStackSegment* current = previous; - previous = current->m_previous; - - current->m_previous = other.m_topSegment->m_previous; - other.m_topSegment->m_previous = current; - - m_numberOfPreviousSegments--; - other.m_numberOfPreviousSegments++; + MarkStackSegment* current = m_segments.removeHead(); + ASSERT(current); + ASSERT(m_numberOfSegments > 1); + other.m_segments.push(current); + m_numberOfSegments--; + other.m_numberOfSegments++; } - m_topSegment->m_previous = previous; + + // Put the original heads back in their places. + m_segments.push(myHead); + other.m_segments.push(otherHead); validatePrevious(); other.validatePrevious(); @@ -198,21 +146,21 @@ void MarkStackArray::stealSomeCellsFrom(MarkStackArray& other, size_t idleThread other.validatePrevious(); // If other has an entire segment, steal it and return. - if (other.m_topSegment->m_previous) { - ASSERT(other.m_topSegment->m_previous->m_top == m_segmentCapacity); - - // First remove a segment from other. - MarkStackSegment* current = other.m_topSegment->m_previous; - other.m_topSegment->m_previous = current->m_previous; - other.m_numberOfPreviousSegments--; - - ASSERT(!!other.m_numberOfPreviousSegments == !!other.m_topSegment->m_previous); - - // Now add it to this. - current->m_previous = m_topSegment->m_previous; - m_topSegment->m_previous = current; - m_numberOfPreviousSegments++; - + if (other.m_numberOfSegments > 1) { + // Move the heads of the lists aside. We'll push them back on after. + MarkStackSegment* otherHead = other.m_segments.removeHead(); + MarkStackSegment* myHead = m_segments.removeHead(); + + ASSERT(other.m_segments.head()->m_top == m_segmentCapacity); + + m_segments.push(other.m_segments.removeHead()); + + m_numberOfSegments++; + other.m_numberOfSegments--; + + m_segments.push(myHead); + other.m_segments.push(otherHead); + validatePrevious(); other.validatePrevious(); return; diff --git a/Source/JavaScriptCore/heap/MarkStack.h b/Source/JavaScriptCore/heap/MarkStack.h index 0245e4be5..2a7f04450 100644 --- a/Source/JavaScriptCore/heap/MarkStack.h +++ b/Source/JavaScriptCore/heap/MarkStack.h @@ -27,19 +27,19 @@ #define MarkStack_h #if ENABLE(OBJECT_MARK_LOGGING) -#define MARK_LOG_MESSAGE0(message) dataLog(message) -#define MARK_LOG_MESSAGE1(message, arg1) dataLog(message, arg1) -#define MARK_LOG_MESSAGE2(message, arg1, arg2) dataLog(message, arg1, arg2) +#define MARK_LOG_MESSAGE0(message) dataLogF(message) +#define MARK_LOG_MESSAGE1(message, arg1) dataLogF(message, arg1) +#define MARK_LOG_MESSAGE2(message, arg1, arg2) dataLogF(message, arg1, arg2) #define MARK_LOG_ROOT(visitor, rootName) \ - dataLog("\n%s: ", rootName); \ + dataLogF("\n%s: ", rootName); \ (visitor).resetChildCount() #define MARK_LOG_PARENT(visitor, parent) \ - dataLog("\n%p (%s): ", parent, parent->className() ? parent->className() : "unknown"); \ + dataLogF("\n%p (%s): ", parent, parent->className() ? parent->className() : "unknown"); \ (visitor).resetChildCount() #define MARK_LOG_CHILD(visitor, child) \ if ((visitor).childCount()) \ - dataLogString(", "); \ - dataLog("%p", child); \ + dataLogFString(", "); \ + dataLogF("%p", child); \ (visitor).incrementChildCount() #else #define MARK_LOG_MESSAGE0(message) do { } while (false) @@ -50,19 +50,27 @@ #define MARK_LOG_CHILD(visitor, child) do { } while (false) #endif +#include "HeapBlock.h" #include <wtf/StdLibExtras.h> -#include <wtf/TCSpinLock.h> namespace JSC { +class BlockAllocator; +class DeadBlock; class JSCell; -struct MarkStackSegment { - MarkStackSegment* m_previous; +class MarkStackSegment : public HeapBlock<MarkStackSegment> { +public: + MarkStackSegment(Region* region) + : HeapBlock<MarkStackSegment>(region) #if !ASSERT_DISABLED - size_t m_top; + , m_top(0) #endif - + { + } + + static MarkStackSegment* create(DeadBlock*); + const JSCell** data() { return bitwise_cast<const JSCell**>(this + 1); @@ -77,26 +85,17 @@ struct MarkStackSegment { { return sizeof(MarkStackSegment) + capacity * sizeof(const JSCell*); } -}; -class MarkStackSegmentAllocator { -public: - MarkStackSegmentAllocator(); - ~MarkStackSegmentAllocator(); - - MarkStackSegment* allocate(); - void release(MarkStackSegment*); - - void shrinkReserve(); - -private: - SpinLock m_lock; - MarkStackSegment* m_nextFreeSegment; + static const size_t blockSize = 4 * KB; + +#if !ASSERT_DISABLED + size_t m_top; +#endif }; class MarkStackArray { public: - MarkStackArray(MarkStackSegmentAllocator&); + MarkStackArray(BlockAllocator&); ~MarkStackArray(); void append(const JSCell*); @@ -122,12 +121,12 @@ private: void validatePrevious(); - MarkStackSegment* m_topSegment; - MarkStackSegmentAllocator& m_allocator; + DoublyLinkedList<MarkStackSegment> m_segments; + BlockAllocator& m_blockAllocator; size_t m_segmentCapacity; size_t m_top; - size_t m_numberOfPreviousSegments; + size_t m_numberOfSegments; }; diff --git a/Source/JavaScriptCore/heap/MarkStackInlineMethods.h b/Source/JavaScriptCore/heap/MarkStackInlines.h index d3276d7fa..1595e843e 100644 --- a/Source/JavaScriptCore/heap/MarkStackInlineMethods.h +++ b/Source/JavaScriptCore/heap/MarkStackInlines.h @@ -23,43 +23,48 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef MarkStackInlineMethods_h -#define MarkStackInlineMethods_h +#ifndef MarkStackInlines_h +#define MarkStackInlines_h #include "GCThreadSharedData.h" #include "MarkStack.h" namespace JSC { +inline MarkStackSegment* MarkStackSegment::create(DeadBlock* block) +{ + return new (NotNull, block) MarkStackSegment(block->region()); +} + inline size_t MarkStackArray::postIncTop() { size_t result = m_top++; - ASSERT(result == m_topSegment->m_top++); + ASSERT(result == m_segments.head()->m_top++); return result; } - + inline size_t MarkStackArray::preDecTop() { size_t result = --m_top; - ASSERT(result == --m_topSegment->m_top); + ASSERT(result == --m_segments.head()->m_top); return result; } - + inline void MarkStackArray::setTopForFullSegment() { - ASSERT(m_topSegment->m_top == m_segmentCapacity); + ASSERT(m_segments.head()->m_top == m_segmentCapacity); m_top = m_segmentCapacity; } inline void MarkStackArray::setTopForEmptySegment() { - ASSERT(!m_topSegment->m_top); + ASSERT(!m_segments.head()->m_top); m_top = 0; } inline size_t MarkStackArray::top() { - ASSERT(m_top == m_topSegment->m_top); + ASSERT(m_top == m_segments.head()->m_top); return m_top; } @@ -69,9 +74,9 @@ inline void MarkStackArray::validatePrevious() { } inline void MarkStackArray::validatePrevious() { unsigned count = 0; - for (MarkStackSegment* current = m_topSegment->m_previous; current; current = current->m_previous) + for (MarkStackSegment* current = m_segments.head(); current; current = current->next()) count++; - ASSERT(count == m_numberOfPreviousSegments); + ASSERT(m_segments.size() == m_numberOfSegments); } #endif @@ -79,7 +84,7 @@ inline void MarkStackArray::append(const JSCell* cell) { if (m_top == m_segmentCapacity) expand(); - m_topSegment->data()[postIncTop()] = cell; + m_segments.head()->data()[postIncTop()] = cell; } inline bool MarkStackArray::canRemoveLast() @@ -89,15 +94,15 @@ inline bool MarkStackArray::canRemoveLast() inline const JSCell* MarkStackArray::removeLast() { - return m_topSegment->data()[preDecTop()]; + return m_segments.head()->data()[preDecTop()]; } inline bool MarkStackArray::isEmpty() { if (m_top) return false; - if (m_topSegment->m_previous) { - ASSERT(m_topSegment->m_previous->m_top == m_segmentCapacity); + if (m_segments.head()->next()) { + ASSERT(m_segments.head()->next()->m_top == m_segmentCapacity); return false; } return true; @@ -105,9 +110,10 @@ inline bool MarkStackArray::isEmpty() inline size_t MarkStackArray::size() { - return m_top + m_segmentCapacity * m_numberOfPreviousSegments; + return m_top + m_segmentCapacity * (m_numberOfSegments - 1); } } // namespace JSC -#endif +#endif // MarkStackInlines_h + diff --git a/Source/JavaScriptCore/heap/MarkedBlock.h b/Source/JavaScriptCore/heap/MarkedBlock.h index f2f2a720d..9080aaef4 100644 --- a/Source/JavaScriptCore/heap/MarkedBlock.h +++ b/Source/JavaScriptCore/heap/MarkedBlock.h @@ -40,7 +40,7 @@ #if HEAP_LOG_BLOCK_STATE_TRANSITIONS #define HEAP_LOG_BLOCK_STATE_TRANSITION(block) do { \ - dataLog( \ + dataLogF( \ "%s:%d %s: block %s = %p, %d\n", \ __FILE__, __LINE__, __FUNCTION__, \ #block, (block), (block)->m_state); \ diff --git a/Source/JavaScriptCore/heap/SlotVisitor.cpp b/Source/JavaScriptCore/heap/SlotVisitor.cpp index 3919705d0..3ff4b48fa 100644 --- a/Source/JavaScriptCore/heap/SlotVisitor.cpp +++ b/Source/JavaScriptCore/heap/SlotVisitor.cpp @@ -1,9 +1,10 @@ #include "config.h" #include "SlotVisitor.h" +#include "SlotVisitorInlines.h" #include "ConservativeRoots.h" #include "CopiedSpace.h" -#include "CopiedSpaceInlineMethods.h" +#include "CopiedSpaceInlines.h" #include "GCThread.h" #include "JSArray.h" #include "JSDestructibleObject.h" @@ -15,7 +16,7 @@ namespace JSC { SlotVisitor::SlotVisitor(GCThreadSharedData& shared) - : m_stack(shared.m_segmentAllocator) + : m_stack(shared.m_globalData->heap.blockAllocator()) , m_visitCount(0) , m_isInParallelMode(false) , m_shared(shared) @@ -335,12 +336,12 @@ void SlotVisitor::finalizeUnconditionalFinalizers() void SlotVisitor::validate(JSCell* cell) { if (!cell) { - dataLog("cell is NULL\n"); + dataLogF("cell is NULL\n"); CRASH(); } if (!cell->structure()) { - dataLog("cell at %p has a null structure\n" , cell); + dataLogF("cell at %p has a null structure\n" , cell); CRASH(); } @@ -353,7 +354,7 @@ void SlotVisitor::validate(JSCell* cell) parentClassName = cell->structure()->structure()->JSCell::classInfo()->className; if (cell->structure()->JSCell::classInfo()) ourClassName = cell->structure()->JSCell::classInfo()->className; - dataLog("parent structure (%p <%s>) of cell at %p doesn't match cell's structure (%p <%s>)\n", + dataLogF("parent structure (%p <%s>) of cell at %p doesn't match cell's structure (%p <%s>)\n", cell->structure()->structure(), parentClassName, cell, cell->structure(), ourClassName); CRASH(); } diff --git a/Source/JavaScriptCore/heap/SlotVisitor.h b/Source/JavaScriptCore/heap/SlotVisitor.h index dcd4b75ef..53c7de64f 100644 --- a/Source/JavaScriptCore/heap/SlotVisitor.h +++ b/Source/JavaScriptCore/heap/SlotVisitor.h @@ -27,7 +27,7 @@ #define SlotVisitor_h #include "HandleTypes.h" -#include "MarkStackInlineMethods.h" +#include "MarkStackInlines.h" #include <wtf/text/StringHash.h> @@ -36,6 +36,7 @@ namespace JSC { class ConservativeRoots; class GCThreadSharedData; class Heap; +template<typename T> class Weak; template<typename T> class WriteBarrierBase; template<typename T> class JITWriteBarrier; @@ -56,6 +57,8 @@ public: template<typename T> void appendUnbarrieredPointer(T**); void appendUnbarrieredValue(JSValue*); + template<typename T> + void appendUnbarrieredWeak(Weak<T>*); void addOpaqueRoot(void*); bool containsOpaqueRoot(void*); diff --git a/Source/JavaScriptCore/heap/SlotVisitorInlineMethods.h b/Source/JavaScriptCore/heap/SlotVisitorInlines.h index e5908bf36..ea8126f87 100644 --- a/Source/JavaScriptCore/heap/SlotVisitorInlineMethods.h +++ b/Source/JavaScriptCore/heap/SlotVisitorInlines.h @@ -23,12 +23,13 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef SlotVisitorInlineMethods_h -#define SlotVisitorInlineMethods_h +#ifndef SlotVisitorInlines_h +#define SlotVisitorInlines_h -#include "CopiedSpaceInlineMethods.h" +#include "CopiedSpaceInlines.h" #include "Options.h" #include "SlotVisitor.h" +#include "Weak.h" namespace JSC { @@ -66,6 +67,14 @@ ALWAYS_INLINE void SlotVisitor::append(JSCell** slot) internalAppend(*slot); } +template<typename T> +ALWAYS_INLINE void SlotVisitor::appendUnbarrieredWeak(Weak<T>* weak) +{ + ASSERT(weak); + if (weak->get()) + internalAppend(weak->get()); +} + ALWAYS_INLINE void SlotVisitor::internalAppend(JSValue value) { if (!value || !value.isCell()) @@ -170,5 +179,5 @@ inline void SlotVisitor::copyLater(void* ptr, size_t bytes) } // namespace JSC -#endif // SlotVisitorInlineMethods_h +#endif // SlotVisitorInlines_h diff --git a/Source/JavaScriptCore/heap/Weak.h b/Source/JavaScriptCore/heap/Weak.h index 3c3d1d0ce..efb2a9a56 100644 --- a/Source/JavaScriptCore/heap/Weak.h +++ b/Source/JavaScriptCore/heap/Weak.h @@ -151,6 +151,11 @@ template<typename T> inline WeakImpl* Weak<T>::hashTableDeletedValue() return reinterpret_cast<WeakImpl*>(-1); } +template <typename T> inline bool operator==(const Weak<T>& lhs, const Weak<T>& rhs) +{ + return lhs.get() == rhs.get(); +} + // This function helps avoid modifying a weak table while holding an iterator into it. (Object allocation // can run a finalizer that modifies the table. We avoid that by requiring a pre-constructed object as our value.) template<typename Map, typename Key, typename Value> inline void weakAdd(Map& map, const Key& key, Value value) |