diff options
author | Simon Hausmann <simon.hausmann@nokia.com> | 2012-07-11 13:45:28 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2012-07-11 13:45:28 +0200 |
commit | d6a599dbc9d824a462b2b206316e102bf8136446 (patch) | |
tree | ecb257a5e55b2239d74b90fdad62fccd661cf286 /Source/JavaScriptCore/heap/MarkStack.cpp | |
parent | 3ccc3a85f09a83557b391aae380d3bf5f81a2911 (diff) | |
download | qtwebkit-d6a599dbc9d824a462b2b206316e102bf8136446.tar.gz |
Imported WebKit commit 8ff1f22783a32de82fee915abd55bd1b298f2644 (http://svn.webkit.org/repository/webkit/trunk@122325)
New snapshot that should work with the latest Qt build system changes
Diffstat (limited to 'Source/JavaScriptCore/heap/MarkStack.cpp')
-rw-r--r-- | Source/JavaScriptCore/heap/MarkStack.cpp | 124 |
1 files changed, 109 insertions, 15 deletions
diff --git a/Source/JavaScriptCore/heap/MarkStack.cpp b/Source/JavaScriptCore/heap/MarkStack.cpp index 3eb02c4e8..9d9130026 100644 --- a/Source/JavaScriptCore/heap/MarkStack.cpp +++ b/Source/JavaScriptCore/heap/MarkStack.cpp @@ -38,6 +38,7 @@ #include "Structure.h" #include "UString.h" #include "WriteBarrier.h" +#include <wtf/Atomics.h> #include <wtf/DataLog.h> #include <wtf/MainThread.h> @@ -65,7 +66,7 @@ MarkStackSegment* MarkStackSegmentAllocator::allocate() } } - return static_cast<MarkStackSegment*>(OSAllocator::reserveAndCommit(Options::gcMarkStackSegmentSize)); + return static_cast<MarkStackSegment*>(OSAllocator::reserveAndCommit(Options::gcMarkStackSegmentSize())); } void MarkStackSegmentAllocator::release(MarkStackSegment* segment) @@ -86,13 +87,13 @@ void MarkStackSegmentAllocator::shrinkReserve() while (segments) { MarkStackSegment* toFree = segments; segments = segments->m_previous; - OSAllocator::decommitAndRelease(toFree, Options::gcMarkStackSegmentSize); + OSAllocator::decommitAndRelease(toFree, Options::gcMarkStackSegmentSize()); } } MarkStackArray::MarkStackArray(MarkStackSegmentAllocator& allocator) : m_allocator(allocator) - , m_segmentCapacity(MarkStackSegment::capacityFromSize(Options::gcMarkStackSegmentSize)) + , m_segmentCapacity(MarkStackSegment::capacityFromSize(Options::gcMarkStackSegmentSize())) , m_top(0) , m_numberOfPreviousSegments(0) { @@ -225,8 +226,8 @@ void MarkStackArray::stealSomeCellsFrom(MarkStackArray& other, size_t idleThread void MarkStackThreadSharedData::resetChildren() { for (unsigned i = 0; i < m_markingThreadsMarkStack.size(); ++i) - m_markingThreadsMarkStack[i]->reset(); -} + m_markingThreadsMarkStack[i]->reset(); +} size_t MarkStackThreadSharedData::childVisitCount() { @@ -257,12 +258,13 @@ void MarkStackThreadSharedData::markingThreadStartFunc(void* myVisitor) MarkStackThreadSharedData::MarkStackThreadSharedData(JSGlobalData* globalData) : m_globalData(globalData) , m_copiedSpace(&globalData->heap.m_storageSpace) + , m_shouldHashConst(false) , m_sharedMarkStack(m_segmentAllocator) , m_numberOfActiveParallelMarkers(0) , m_parallelMarkersShouldExit(false) { #if ENABLE(PARALLEL_GC) - for (unsigned i = 1; i < Options::numberOfGCMarkers; ++i) { + for (unsigned i = 1; i < Options::numberOfGCMarkers(); ++i) { SlotVisitor* slotVisitor = new SlotVisitor(*this); m_markingThreadsMarkStack.append(slotVisitor); m_markingThreads.append(createThread(markingThreadStartFunc, slotVisitor, "JavaScriptCore::Marking")); @@ -298,6 +300,21 @@ void MarkStackThreadSharedData::reset() ASSERT(m_opaqueRoots.isEmpty()); #endif m_weakReferenceHarvesters.removeAll(); + + if (m_shouldHashConst) { + m_globalData->resetNewStringsSinceLastHashConst(); + m_shouldHashConst = false; + } +} + +void MarkStack::setup() +{ + m_shared.m_shouldHashConst = m_shared.m_globalData->haveEnoughNewStringsToHashConst(); + m_shouldHashConst = m_shared.m_shouldHashConst; +#if ENABLE(PARALLEL_GC) + for (unsigned i = 0; i < m_shared.m_markingThreadsMarkStack.size(); ++i) + m_shared.m_markingThreadsMarkStack[i]->m_shouldHashConst = m_shared.m_shouldHashConst; +#endif } void MarkStack::reset() @@ -309,6 +326,10 @@ void MarkStack::reset() #else m_opaqueRoots.clear(); #endif + if (m_shouldHashConst) { + m_uniqueStrings.clear(); + m_shouldHashConst = false; + } } void MarkStack::append(ConservativeRoots& conservativeRoots) @@ -333,7 +354,7 @@ ALWAYS_INLINE static void visitChildren(SlotVisitor& visitor, const JSCell* cell } if (isJSFinalObject(cell)) { - JSObject::visitChildren(const_cast<JSCell*>(cell), visitor); + JSFinalObject::visitChildren(const_cast<JSCell*>(cell), visitor); return; } @@ -368,7 +389,7 @@ void SlotVisitor::donateKnownParallel() // Otherwise, assume that a thread will go idle soon, and donate. m_stack.donateSomeCellsTo(m_shared.m_sharedMarkStack); - if (m_shared.m_numberOfActiveParallelMarkers < Options::numberOfGCMarkers) + if (m_shared.m_numberOfActiveParallelMarkers < Options::numberOfGCMarkers()) m_shared.m_markingCondition.broadcast(); } @@ -377,10 +398,10 @@ void SlotVisitor::drain() ASSERT(m_isInParallelMode); #if ENABLE(PARALLEL_GC) - if (Options::numberOfGCMarkers > 1) { + if (Options::numberOfGCMarkers() > 1) { while (!m_stack.isEmpty()) { m_stack.refill(); - for (unsigned countdown = Options::minimumNumberOfScansBetweenRebalance; m_stack.canRemoveLast() && countdown--;) + for (unsigned countdown = Options::minimumNumberOfScansBetweenRebalance(); m_stack.canRemoveLast() && countdown--;) visitChildren(*this, m_stack.removeLast()); donateKnownParallel(); } @@ -401,14 +422,14 @@ void SlotVisitor::drainFromShared(SharedDrainMode sharedDrainMode) { ASSERT(m_isInParallelMode); - ASSERT(Options::numberOfGCMarkers); + ASSERT(Options::numberOfGCMarkers()); bool shouldBeParallel; #if ENABLE(PARALLEL_GC) - shouldBeParallel = Options::numberOfGCMarkers > 1; + shouldBeParallel = Options::numberOfGCMarkers() > 1; #else - ASSERT(Options::numberOfGCMarkers == 1); + ASSERT(Options::numberOfGCMarkers() == 1); shouldBeParallel = false; #endif @@ -469,7 +490,7 @@ void SlotVisitor::drainFromShared(SharedDrainMode sharedDrainMode) } } - size_t idleThreadCount = Options::numberOfGCMarkers - m_shared.m_numberOfActiveParallelMarkers; + size_t idleThreadCount = Options::numberOfGCMarkers() - m_shared.m_numberOfActiveParallelMarkers; m_stack.stealSomeCellsFrom(m_shared.m_sharedMarkStack, idleThreadCount); m_shared.m_numberOfActiveParallelMarkers++; } @@ -521,6 +542,79 @@ void* SlotVisitor::allocateNewSpace(void* ptr, size_t bytes) return CopiedSpace::allocateFromBlock(m_copyBlock, bytes); } +ALWAYS_INLINE bool JSString::tryHashConstLock() +{ +#if ENABLE(PARALLEL_GC) + unsigned currentFlags = m_flags; + + if (currentFlags & HashConstLock) + return false; + + unsigned newFlags = currentFlags | HashConstLock; + + if (!WTF::weakCompareAndSwap(&m_flags, currentFlags, newFlags)) + return false; + + WTF::memoryBarrierAfterLock(); + return true; +#else + if (isHashConstSingleton()) + return false; + + m_flags |= HashConstLock; + + return true; +#endif +} + +ALWAYS_INLINE void JSString::releaseHashConstLock() +{ +#if ENABLE(PARALLEL_GC) + WTF::memoryBarrierBeforeUnlock(); +#endif + m_flags &= ~HashConstLock; +} + +ALWAYS_INLINE bool JSString::shouldTryHashConst() +{ + return ((length() > 1) && !isRope() && !isHashConstSingleton()); +} + +ALWAYS_INLINE void MarkStack::internalAppend(JSValue* slot) +{ + // 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. + + ASSERT(slot); + JSValue value = *slot; + ASSERT(value); + if (!value.isCell()) + return; + + JSCell* cell = value.asCell(); + + if (m_shouldHashConst && cell->isString()) { + JSString* string = jsCast<JSString*>(cell); + if (string->shouldTryHashConst() && string->tryHashConstLock()) { + UniqueStringMap::AddResult addResult = m_uniqueStrings.add(string->string().impl(), value); + if (addResult.isNewEntry) + string->setHashConstSingleton(); + else { + JSValue existingJSValue = addResult.iterator->second; + if (value != existingJSValue) + jsCast<JSString*>(existingJSValue.asCell())->clearHashConstSingleton(); + *slot = existingJSValue; + string->releaseHashConstLock(); + return; + } + string->releaseHashConstLock(); + } + } + + internalAppend(cell); +} + void SlotVisitor::copyAndAppend(void** ptr, size_t bytes, JSValue* values, unsigned length) { void* oldPtr = *ptr; @@ -534,7 +628,7 @@ void SlotVisitor::copyAndAppend(void** ptr, size_t bytes, JSValue* values, unsig newValues[i] = value; if (!value) continue; - internalAppend(value); + internalAppend(&newValues[i]); } memcpy(newPtr, oldPtr, jsValuesOffset); |