haikuwebkit/Source/WTF/wtf/AutomaticThread.h

201 lines
8.4 KiB
C
Raw Permalink Normal View History

WTF should make it easier to create threads that die automatically after inactivity https://bugs.webkit.org/show_bug.cgi?id=163576 Reviewed by Andreas Kling. Source/JavaScriptCore: Added a sleepSeconds() function, which made it easier for me to test this change. The WTF changes in this patch change how the JSC GC manages threads: the GC threads will now shut down automatically after 1 second of inactivity. Maybe this will save some memory. * jsc.cpp: (GlobalObject::finishCreation): (functionSleepSeconds): Source/WTF: For a long time now, I've been adding threads to WTF/JSC and each time I do this, I feel guilty because those threads don't shut down when they are inactive. For example, in bug 163562, I need to add a new GC thread. There will be one of them per VM. This means that a JSC API client that starts a lot of VMs will have a lot of threads. I don't think that's good. A common pattern for all of these threads is that they have some well-defined trigger that causes them to run. This trigger has a lock, a condition variable, some logic that determines if there is work to do, and then of course the logic for the thread's actual work. The thread bodies usually look like this: void Thingy::runThread() { for (;;) { Work work; { LockHolder locker(m_lock); while (!hasWork()) m_cond.wait(m_lock); work = takeWork(); } doWork(work); } } If you look at ParallelHelperPool (the GC's threads) and DFG::Worklist (some of the JIT's threads), you will see this pattern. This change adds a new kind of thread, called AutomaticThread, that lets you write threads to this pattern while getting automatic thread shutdown for free: instead of just waiting on a condition variable, AutomaticThread will have a timeout that causes the thread to die. The condition variable associated with AutomaticThread, called AutomaticThreadCondition, is smart enough to restart any threads that have decided to stop due to inactivity. The inactivity threshold is current just 1 second. In this patch I only adopt AutomaticThread for ParallelHelperPool. I plan to adopt it in more places soon. * WTF.xcodeproj/project.pbxproj: * wtf/AutomaticThread.cpp: Added. (WTF::AutomaticThreadCondition::create): (WTF::AutomaticThreadCondition::AutomaticThreadCondition): (WTF::AutomaticThreadCondition::~AutomaticThreadCondition): (WTF::AutomaticThreadCondition::notifyAll): (WTF::AutomaticThreadCondition::add): (WTF::AutomaticThreadCondition::remove): (WTF::AutomaticThreadCondition::contains): (WTF::AutomaticThread::AutomaticThread): (WTF::AutomaticThread::~AutomaticThread): (WTF::AutomaticThread::join): (WTF::AutomaticThread::start): * wtf/AutomaticThread.h: Added. * wtf/CMakeLists.txt: * wtf/ParallelHelperPool.cpp: (WTF::ParallelHelperClient::ParallelHelperClient): (WTF::ParallelHelperClient::~ParallelHelperClient): (WTF::ParallelHelperClient::setTask): (WTF::ParallelHelperClient::finish): (WTF::ParallelHelperClient::doSomeHelping): (WTF::ParallelHelperClient::runTask): (WTF::ParallelHelperPool::ParallelHelperPool): (WTF::ParallelHelperPool::~ParallelHelperPool): (WTF::ParallelHelperPool::ensureThreads): (WTF::ParallelHelperPool::doSomeHelping): (WTF::ParallelHelperPool::Thread::Thread): (WTF::ParallelHelperPool::didMakeWorkAvailable): (WTF::ParallelHelperPool::helperThreadBody): Deleted. (WTF::ParallelHelperPool::waitForClientWithTask): Deleted. * wtf/ParallelHelperPool.h: Canonical link: https://commits.webkit.org/181393@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@207480 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-10-18 20:17:10 +00:00
/*
* Copyright (C) 2016-2020 Apple Inc. All rights reserved.
WTF should make it easier to create threads that die automatically after inactivity https://bugs.webkit.org/show_bug.cgi?id=163576 Reviewed by Andreas Kling. Source/JavaScriptCore: Added a sleepSeconds() function, which made it easier for me to test this change. The WTF changes in this patch change how the JSC GC manages threads: the GC threads will now shut down automatically after 1 second of inactivity. Maybe this will save some memory. * jsc.cpp: (GlobalObject::finishCreation): (functionSleepSeconds): Source/WTF: For a long time now, I've been adding threads to WTF/JSC and each time I do this, I feel guilty because those threads don't shut down when they are inactive. For example, in bug 163562, I need to add a new GC thread. There will be one of them per VM. This means that a JSC API client that starts a lot of VMs will have a lot of threads. I don't think that's good. A common pattern for all of these threads is that they have some well-defined trigger that causes them to run. This trigger has a lock, a condition variable, some logic that determines if there is work to do, and then of course the logic for the thread's actual work. The thread bodies usually look like this: void Thingy::runThread() { for (;;) { Work work; { LockHolder locker(m_lock); while (!hasWork()) m_cond.wait(m_lock); work = takeWork(); } doWork(work); } } If you look at ParallelHelperPool (the GC's threads) and DFG::Worklist (some of the JIT's threads), you will see this pattern. This change adds a new kind of thread, called AutomaticThread, that lets you write threads to this pattern while getting automatic thread shutdown for free: instead of just waiting on a condition variable, AutomaticThread will have a timeout that causes the thread to die. The condition variable associated with AutomaticThread, called AutomaticThreadCondition, is smart enough to restart any threads that have decided to stop due to inactivity. The inactivity threshold is current just 1 second. In this patch I only adopt AutomaticThread for ParallelHelperPool. I plan to adopt it in more places soon. * WTF.xcodeproj/project.pbxproj: * wtf/AutomaticThread.cpp: Added. (WTF::AutomaticThreadCondition::create): (WTF::AutomaticThreadCondition::AutomaticThreadCondition): (WTF::AutomaticThreadCondition::~AutomaticThreadCondition): (WTF::AutomaticThreadCondition::notifyAll): (WTF::AutomaticThreadCondition::add): (WTF::AutomaticThreadCondition::remove): (WTF::AutomaticThreadCondition::contains): (WTF::AutomaticThread::AutomaticThread): (WTF::AutomaticThread::~AutomaticThread): (WTF::AutomaticThread::join): (WTF::AutomaticThread::start): * wtf/AutomaticThread.h: Added. * wtf/CMakeLists.txt: * wtf/ParallelHelperPool.cpp: (WTF::ParallelHelperClient::ParallelHelperClient): (WTF::ParallelHelperClient::~ParallelHelperClient): (WTF::ParallelHelperClient::setTask): (WTF::ParallelHelperClient::finish): (WTF::ParallelHelperClient::doSomeHelping): (WTF::ParallelHelperClient::runTask): (WTF::ParallelHelperPool::ParallelHelperPool): (WTF::ParallelHelperPool::~ParallelHelperPool): (WTF::ParallelHelperPool::ensureThreads): (WTF::ParallelHelperPool::doSomeHelping): (WTF::ParallelHelperPool::Thread::Thread): (WTF::ParallelHelperPool::didMakeWorkAvailable): (WTF::ParallelHelperPool::helperThreadBody): Deleted. (WTF::ParallelHelperPool::waitForClientWithTask): Deleted. * wtf/ParallelHelperPool.h: Canonical link: https://commits.webkit.org/181393@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@207480 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-10-18 20:17:10 +00:00
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
Use pragma once in WTF https://bugs.webkit.org/show_bug.cgi?id=190527 Reviewed by Chris Dumez. Source/WTF: We also need to consistently include wtf headers from within wtf so we can build wtf without symbol redefinition errors from including the copy in Source and the copy in the build directory. * wtf/ASCIICType.h: * wtf/Assertions.cpp: * wtf/Assertions.h: * wtf/Atomics.h: * wtf/AutomaticThread.cpp: * wtf/AutomaticThread.h: * wtf/BackwardsGraph.h: * wtf/Bag.h: * wtf/BagToHashMap.h: * wtf/BitVector.cpp: * wtf/BitVector.h: * wtf/Bitmap.h: * wtf/BloomFilter.h: * wtf/Box.h: * wtf/BubbleSort.h: * wtf/BumpPointerAllocator.h: * wtf/ByteOrder.h: * wtf/CPUTime.cpp: * wtf/CallbackAggregator.h: * wtf/CheckedArithmetic.h: * wtf/CheckedBoolean.h: * wtf/ClockType.cpp: * wtf/ClockType.h: * wtf/CommaPrinter.h: * wtf/CompilationThread.cpp: * wtf/CompilationThread.h: * wtf/Compiler.h: * wtf/ConcurrentPtrHashSet.cpp: * wtf/ConcurrentVector.h: * wtf/Condition.h: * wtf/CountingLock.cpp: * wtf/CrossThreadTaskHandler.cpp: * wtf/CryptographicUtilities.cpp: * wtf/CryptographicUtilities.h: * wtf/CryptographicallyRandomNumber.cpp: * wtf/CryptographicallyRandomNumber.h: * wtf/CurrentTime.cpp: * wtf/DataLog.cpp: * wtf/DataLog.h: * wtf/DateMath.cpp: * wtf/DateMath.h: * wtf/DecimalNumber.cpp: * wtf/DecimalNumber.h: * wtf/Deque.h: * wtf/DisallowCType.h: * wtf/Dominators.h: * wtf/DoublyLinkedList.h: * wtf/FastBitVector.cpp: * wtf/FastMalloc.cpp: * wtf/FastMalloc.h: * wtf/FeatureDefines.h: * wtf/FilePrintStream.cpp: * wtf/FilePrintStream.h: * wtf/FlipBytes.h: * wtf/FunctionDispatcher.cpp: * wtf/FunctionDispatcher.h: * wtf/GetPtr.h: * wtf/Gigacage.cpp: * wtf/GlobalVersion.cpp: * wtf/GraphNodeWorklist.h: * wtf/GregorianDateTime.cpp: * wtf/GregorianDateTime.h: * wtf/HashFunctions.h: * wtf/HashMap.h: * wtf/HashMethod.h: * wtf/HashSet.h: * wtf/HashTable.cpp: * wtf/HashTraits.h: * wtf/Indenter.h: * wtf/IndexSparseSet.h: * wtf/InlineASM.h: * wtf/Insertion.h: * wtf/IteratorAdaptors.h: * wtf/IteratorRange.h: * wtf/JSONValues.cpp: * wtf/JSValueMalloc.cpp: * wtf/LEBDecoder.h: * wtf/Language.cpp: * wtf/ListDump.h: * wtf/Lock.cpp: * wtf/Lock.h: * wtf/LockAlgorithm.h: * wtf/LockedPrintStream.cpp: * wtf/Locker.h: * wtf/MD5.cpp: * wtf/MD5.h: * wtf/MainThread.cpp: * wtf/MainThread.h: * wtf/MallocPtr.h: * wtf/MathExtras.h: * wtf/MediaTime.cpp: * wtf/MediaTime.h: * wtf/MemoryPressureHandler.cpp: * wtf/MessageQueue.h: * wtf/MetaAllocator.cpp: * wtf/MetaAllocator.h: * wtf/MetaAllocatorHandle.h: * wtf/MonotonicTime.cpp: * wtf/MonotonicTime.h: * wtf/NakedPtr.h: * wtf/NoLock.h: * wtf/NoTailCalls.h: * wtf/Noncopyable.h: * wtf/NumberOfCores.cpp: * wtf/NumberOfCores.h: * wtf/OSAllocator.h: * wtf/OSAllocatorPosix.cpp: * wtf/OSRandomSource.cpp: * wtf/OSRandomSource.h: * wtf/ObjcRuntimeExtras.h: * wtf/OrderMaker.h: * wtf/PackedIntVector.h: * wtf/PageAllocation.h: * wtf/PageBlock.cpp: * wtf/PageBlock.h: * wtf/PageReservation.h: * wtf/ParallelHelperPool.cpp: * wtf/ParallelHelperPool.h: * wtf/ParallelJobs.h: * wtf/ParallelJobsLibdispatch.h: * wtf/ParallelVectorIterator.h: * wtf/ParkingLot.cpp: * wtf/ParkingLot.h: * wtf/Platform.h: * wtf/PointerComparison.h: * wtf/Poisoned.cpp: * wtf/PrintStream.cpp: * wtf/PrintStream.h: * wtf/ProcessID.h: * wtf/ProcessPrivilege.cpp: * wtf/RAMSize.cpp: * wtf/RAMSize.h: * wtf/RandomDevice.cpp: * wtf/RandomNumber.cpp: * wtf/RandomNumber.h: * wtf/RandomNumberSeed.h: * wtf/RangeSet.h: * wtf/RawPointer.h: * wtf/ReadWriteLock.cpp: * wtf/RedBlackTree.h: * wtf/Ref.h: * wtf/RefCountedArray.h: * wtf/RefCountedLeakCounter.cpp: * wtf/RefCountedLeakCounter.h: * wtf/RefCounter.h: * wtf/RefPtr.h: * wtf/RetainPtr.h: * wtf/RunLoop.cpp: * wtf/RunLoop.h: * wtf/RunLoopTimer.h: * wtf/RunLoopTimerCF.cpp: * wtf/SHA1.cpp: * wtf/SHA1.h: * wtf/SaturatedArithmetic.h: (saturatedSubtraction): * wtf/SchedulePair.h: * wtf/SchedulePairCF.cpp: * wtf/SchedulePairMac.mm: * wtf/ScopedLambda.h: * wtf/Seconds.cpp: * wtf/Seconds.h: * wtf/SegmentedVector.h: * wtf/SentinelLinkedList.h: * wtf/SharedTask.h: * wtf/SimpleStats.h: * wtf/SingleRootGraph.h: * wtf/SinglyLinkedList.h: * wtf/SixCharacterHash.cpp: * wtf/SixCharacterHash.h: * wtf/SmallPtrSet.h: * wtf/Spectrum.h: * wtf/StackBounds.cpp: * wtf/StackBounds.h: * wtf/StackStats.cpp: * wtf/StackStats.h: * wtf/StackTrace.cpp: * wtf/StdLibExtras.h: * wtf/StreamBuffer.h: * wtf/StringHashDumpContext.h: * wtf/StringPrintStream.cpp: * wtf/StringPrintStream.h: * wtf/ThreadGroup.cpp: * wtf/ThreadMessage.cpp: * wtf/ThreadSpecific.h: * wtf/Threading.cpp: * wtf/Threading.h: * wtf/ThreadingPrimitives.h: * wtf/ThreadingPthreads.cpp: * wtf/TimeWithDynamicClockType.cpp: * wtf/TimeWithDynamicClockType.h: * wtf/TimingScope.cpp: * wtf/TinyLRUCache.h: * wtf/TinyPtrSet.h: * wtf/TriState.h: * wtf/TypeCasts.h: * wtf/UUID.cpp: * wtf/UnionFind.h: * wtf/VMTags.h: * wtf/ValueCheck.h: * wtf/Vector.h: * wtf/VectorTraits.h: * wtf/WallTime.cpp: * wtf/WallTime.h: * wtf/WeakPtr.h: * wtf/WeakRandom.h: * wtf/WordLock.cpp: * wtf/WordLock.h: * wtf/WorkQueue.cpp: * wtf/WorkQueue.h: * wtf/WorkerPool.cpp: * wtf/cf/LanguageCF.cpp: * wtf/cf/RunLoopCF.cpp: * wtf/cocoa/Entitlements.mm: * wtf/cocoa/MachSendRight.cpp: * wtf/cocoa/MainThreadCocoa.mm: * wtf/cocoa/MemoryFootprintCocoa.cpp: * wtf/cocoa/WorkQueueCocoa.cpp: * wtf/dtoa.cpp: * wtf/dtoa.h: * wtf/ios/WebCoreThread.cpp: * wtf/ios/WebCoreThread.h: * wtf/mac/AppKitCompatibilityDeclarations.h: * wtf/mac/DeprecatedSymbolsUsedBySafari.mm: * wtf/mbmalloc.cpp: * wtf/persistence/PersistentCoders.cpp: * wtf/persistence/PersistentDecoder.cpp: * wtf/persistence/PersistentEncoder.cpp: * wtf/spi/cf/CFBundleSPI.h: * wtf/spi/darwin/CommonCryptoSPI.h: * wtf/text/ASCIIFastPath.h: * wtf/text/ASCIILiteral.cpp: * wtf/text/AtomicString.cpp: * wtf/text/AtomicString.h: * wtf/text/AtomicStringHash.h: * wtf/text/AtomicStringImpl.cpp: * wtf/text/AtomicStringImpl.h: * wtf/text/AtomicStringTable.cpp: * wtf/text/AtomicStringTable.h: * wtf/text/Base64.cpp: * wtf/text/CString.cpp: * wtf/text/CString.h: * wtf/text/ConversionMode.h: * wtf/text/ExternalStringImpl.cpp: * wtf/text/IntegerToStringConversion.h: * wtf/text/LChar.h: * wtf/text/LineEnding.cpp: * wtf/text/StringBuffer.h: * wtf/text/StringBuilder.cpp: * wtf/text/StringBuilder.h: * wtf/text/StringBuilderJSON.cpp: * wtf/text/StringCommon.h: * wtf/text/StringConcatenate.h: * wtf/text/StringHash.h: * wtf/text/StringImpl.cpp: * wtf/text/StringImpl.h: * wtf/text/StringOperators.h: * wtf/text/StringView.cpp: * wtf/text/StringView.h: * wtf/text/SymbolImpl.cpp: * wtf/text/SymbolRegistry.cpp: * wtf/text/SymbolRegistry.h: * wtf/text/TextBreakIterator.cpp: * wtf/text/TextBreakIterator.h: * wtf/text/TextBreakIteratorInternalICU.h: * wtf/text/TextPosition.h: * wtf/text/TextStream.cpp: * wtf/text/UniquedStringImpl.h: * wtf/text/WTFString.cpp: * wtf/text/WTFString.h: * wtf/text/cocoa/StringCocoa.mm: * wtf/text/cocoa/StringViewCocoa.mm: * wtf/text/cocoa/TextBreakIteratorInternalICUCocoa.cpp: * wtf/text/icu/UTextProvider.cpp: * wtf/text/icu/UTextProvider.h: * wtf/text/icu/UTextProviderLatin1.cpp: * wtf/text/icu/UTextProviderLatin1.h: * wtf/text/icu/UTextProviderUTF16.cpp: * wtf/text/icu/UTextProviderUTF16.h: * wtf/threads/BinarySemaphore.cpp: * wtf/threads/BinarySemaphore.h: * wtf/threads/Signals.cpp: * wtf/unicode/CharacterNames.h: * wtf/unicode/Collator.h: * wtf/unicode/CollatorDefault.cpp: * wtf/unicode/UTF8.cpp: * wtf/unicode/UTF8.h: Tools: Put WorkQueue in namespace DRT so it does not conflict with WTF::WorkQueue. * DumpRenderTree/TestRunner.cpp: (TestRunner::queueLoadHTMLString): (TestRunner::queueLoadAlternateHTMLString): (TestRunner::queueBackNavigation): (TestRunner::queueForwardNavigation): (TestRunner::queueLoadingScript): (TestRunner::queueNonLoadingScript): (TestRunner::queueReload): * DumpRenderTree/WorkQueue.cpp: (WorkQueue::singleton): Deleted. (WorkQueue::WorkQueue): Deleted. (WorkQueue::queue): Deleted. (WorkQueue::dequeue): Deleted. (WorkQueue::count): Deleted. (WorkQueue::clear): Deleted. (WorkQueue::processWork): Deleted. * DumpRenderTree/WorkQueue.h: (WorkQueue::setFrozen): Deleted. * DumpRenderTree/WorkQueueItem.h: * DumpRenderTree/mac/DumpRenderTree.mm: (runTest): * DumpRenderTree/mac/FrameLoadDelegate.mm: (-[FrameLoadDelegate processWork:]): (-[FrameLoadDelegate webView:locationChangeDone:forDataSource:]): * DumpRenderTree/mac/TestRunnerMac.mm: (TestRunner::notifyDone): (TestRunner::forceImmediateCompletion): (TestRunner::queueLoad): * DumpRenderTree/win/DumpRenderTree.cpp: (runTest): * DumpRenderTree/win/FrameLoadDelegate.cpp: (FrameLoadDelegate::processWork): (FrameLoadDelegate::locationChangeDone): * DumpRenderTree/win/TestRunnerWin.cpp: (TestRunner::notifyDone): (TestRunner::forceImmediateCompletion): (TestRunner::queueLoad): Canonical link: https://commits.webkit.org/205473@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@237099 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-10-15 14:24:49 +00:00
#pragma once
WTF should make it easier to create threads that die automatically after inactivity https://bugs.webkit.org/show_bug.cgi?id=163576 Reviewed by Andreas Kling. Source/JavaScriptCore: Added a sleepSeconds() function, which made it easier for me to test this change. The WTF changes in this patch change how the JSC GC manages threads: the GC threads will now shut down automatically after 1 second of inactivity. Maybe this will save some memory. * jsc.cpp: (GlobalObject::finishCreation): (functionSleepSeconds): Source/WTF: For a long time now, I've been adding threads to WTF/JSC and each time I do this, I feel guilty because those threads don't shut down when they are inactive. For example, in bug 163562, I need to add a new GC thread. There will be one of them per VM. This means that a JSC API client that starts a lot of VMs will have a lot of threads. I don't think that's good. A common pattern for all of these threads is that they have some well-defined trigger that causes them to run. This trigger has a lock, a condition variable, some logic that determines if there is work to do, and then of course the logic for the thread's actual work. The thread bodies usually look like this: void Thingy::runThread() { for (;;) { Work work; { LockHolder locker(m_lock); while (!hasWork()) m_cond.wait(m_lock); work = takeWork(); } doWork(work); } } If you look at ParallelHelperPool (the GC's threads) and DFG::Worklist (some of the JIT's threads), you will see this pattern. This change adds a new kind of thread, called AutomaticThread, that lets you write threads to this pattern while getting automatic thread shutdown for free: instead of just waiting on a condition variable, AutomaticThread will have a timeout that causes the thread to die. The condition variable associated with AutomaticThread, called AutomaticThreadCondition, is smart enough to restart any threads that have decided to stop due to inactivity. The inactivity threshold is current just 1 second. In this patch I only adopt AutomaticThread for ParallelHelperPool. I plan to adopt it in more places soon. * WTF.xcodeproj/project.pbxproj: * wtf/AutomaticThread.cpp: Added. (WTF::AutomaticThreadCondition::create): (WTF::AutomaticThreadCondition::AutomaticThreadCondition): (WTF::AutomaticThreadCondition::~AutomaticThreadCondition): (WTF::AutomaticThreadCondition::notifyAll): (WTF::AutomaticThreadCondition::add): (WTF::AutomaticThreadCondition::remove): (WTF::AutomaticThreadCondition::contains): (WTF::AutomaticThread::AutomaticThread): (WTF::AutomaticThread::~AutomaticThread): (WTF::AutomaticThread::join): (WTF::AutomaticThread::start): * wtf/AutomaticThread.h: Added. * wtf/CMakeLists.txt: * wtf/ParallelHelperPool.cpp: (WTF::ParallelHelperClient::ParallelHelperClient): (WTF::ParallelHelperClient::~ParallelHelperClient): (WTF::ParallelHelperClient::setTask): (WTF::ParallelHelperClient::finish): (WTF::ParallelHelperClient::doSomeHelping): (WTF::ParallelHelperClient::runTask): (WTF::ParallelHelperPool::ParallelHelperPool): (WTF::ParallelHelperPool::~ParallelHelperPool): (WTF::ParallelHelperPool::ensureThreads): (WTF::ParallelHelperPool::doSomeHelping): (WTF::ParallelHelperPool::Thread::Thread): (WTF::ParallelHelperPool::didMakeWorkAvailable): (WTF::ParallelHelperPool::helperThreadBody): Deleted. (WTF::ParallelHelperPool::waitForClientWithTask): Deleted. * wtf/ParallelHelperPool.h: Canonical link: https://commits.webkit.org/181393@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@207480 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-10-18 20:17:10 +00:00
#include <wtf/Box.h>
#include <wtf/Condition.h>
#include <wtf/Lock.h>
#include <wtf/ThreadSafeRefCounted.h>
#include <wtf/Threading.h>
WTF should make it easier to create threads that die automatically after inactivity https://bugs.webkit.org/show_bug.cgi?id=163576 Reviewed by Andreas Kling. Source/JavaScriptCore: Added a sleepSeconds() function, which made it easier for me to test this change. The WTF changes in this patch change how the JSC GC manages threads: the GC threads will now shut down automatically after 1 second of inactivity. Maybe this will save some memory. * jsc.cpp: (GlobalObject::finishCreation): (functionSleepSeconds): Source/WTF: For a long time now, I've been adding threads to WTF/JSC and each time I do this, I feel guilty because those threads don't shut down when they are inactive. For example, in bug 163562, I need to add a new GC thread. There will be one of them per VM. This means that a JSC API client that starts a lot of VMs will have a lot of threads. I don't think that's good. A common pattern for all of these threads is that they have some well-defined trigger that causes them to run. This trigger has a lock, a condition variable, some logic that determines if there is work to do, and then of course the logic for the thread's actual work. The thread bodies usually look like this: void Thingy::runThread() { for (;;) { Work work; { LockHolder locker(m_lock); while (!hasWork()) m_cond.wait(m_lock); work = takeWork(); } doWork(work); } } If you look at ParallelHelperPool (the GC's threads) and DFG::Worklist (some of the JIT's threads), you will see this pattern. This change adds a new kind of thread, called AutomaticThread, that lets you write threads to this pattern while getting automatic thread shutdown for free: instead of just waiting on a condition variable, AutomaticThread will have a timeout that causes the thread to die. The condition variable associated with AutomaticThread, called AutomaticThreadCondition, is smart enough to restart any threads that have decided to stop due to inactivity. The inactivity threshold is current just 1 second. In this patch I only adopt AutomaticThread for ParallelHelperPool. I plan to adopt it in more places soon. * WTF.xcodeproj/project.pbxproj: * wtf/AutomaticThread.cpp: Added. (WTF::AutomaticThreadCondition::create): (WTF::AutomaticThreadCondition::AutomaticThreadCondition): (WTF::AutomaticThreadCondition::~AutomaticThreadCondition): (WTF::AutomaticThreadCondition::notifyAll): (WTF::AutomaticThreadCondition::add): (WTF::AutomaticThreadCondition::remove): (WTF::AutomaticThreadCondition::contains): (WTF::AutomaticThread::AutomaticThread): (WTF::AutomaticThread::~AutomaticThread): (WTF::AutomaticThread::join): (WTF::AutomaticThread::start): * wtf/AutomaticThread.h: Added. * wtf/CMakeLists.txt: * wtf/ParallelHelperPool.cpp: (WTF::ParallelHelperClient::ParallelHelperClient): (WTF::ParallelHelperClient::~ParallelHelperClient): (WTF::ParallelHelperClient::setTask): (WTF::ParallelHelperClient::finish): (WTF::ParallelHelperClient::doSomeHelping): (WTF::ParallelHelperClient::runTask): (WTF::ParallelHelperPool::ParallelHelperPool): (WTF::ParallelHelperPool::~ParallelHelperPool): (WTF::ParallelHelperPool::ensureThreads): (WTF::ParallelHelperPool::doSomeHelping): (WTF::ParallelHelperPool::Thread::Thread): (WTF::ParallelHelperPool::didMakeWorkAvailable): (WTF::ParallelHelperPool::helperThreadBody): Deleted. (WTF::ParallelHelperPool::waitForClientWithTask): Deleted. * wtf/ParallelHelperPool.h: Canonical link: https://commits.webkit.org/181393@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@207480 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-10-18 20:17:10 +00:00
#include <wtf/Vector.h>
namespace WTF {
// Often, we create threads that have this as their body:
//
// for (;;) {
// {
Replace LockHolder with Locker in local variables https://bugs.webkit.org/show_bug.cgi?id=226133 Reviewed by Darin Adler. Replace LockHolder with Locker in local variables. It is shorter and it allows switching the lock type more easily since the compiler with deduce the lock type T for Locker<T>. Source/JavaScriptCore: * API/JSCallbackObject.h: (JSC::JSCallbackObjectData::JSPrivatePropertyMap::setPrivateProperty): (JSC::JSCallbackObjectData::JSPrivatePropertyMap::deletePrivateProperty): (JSC::JSCallbackObjectData::JSPrivatePropertyMap::visitChildren): * API/JSValue.mm: (handerForStructTag): * API/tests/testapi.cpp: (testCAPIViaCpp): * assembler/testmasm.cpp: (JSC::run): * b3/air/testair.cpp: * b3/testb3_1.cpp: (run): * bytecode/DirectEvalCodeCache.cpp: (JSC::DirectEvalCodeCache::setSlow): (JSC::DirectEvalCodeCache::clear): (JSC::DirectEvalCodeCache::visitAggregateImpl): * bytecode/SuperSampler.cpp: (JSC::initializeSuperSampler): (JSC::resetSuperSamplerState): (JSC::printSuperSamplerState): (JSC::enableSuperSampler): (JSC::disableSuperSampler): * dfg/DFGCommonData.cpp: (JSC::DFG::CommonData::invalidate): (JSC::DFG::CommonData::~CommonData): (JSC::DFG::CommonData::installVMTrapBreakpoints): (JSC::DFG::codeBlockForVMTrapPC): * dfg/DFGPlan.cpp: (JSC::DFG::Plan::cleanMustHandleValuesIfNecessary): * dfg/DFGWorklist.cpp: (JSC::DFG::Worklist::~Worklist): (JSC::DFG::Worklist::finishCreation): (JSC::DFG::Worklist::isActiveForVM const): (JSC::DFG::Worklist::enqueue): (JSC::DFG::Worklist::compilationState): (JSC::DFG::Worklist::waitUntilAllPlansForVMAreReady): (JSC::DFG::Worklist::removeAllReadyPlansForVM): (JSC::DFG::Worklist::completeAllReadyPlansForVM): (JSC::DFG::Worklist::visitWeakReferences): (JSC::DFG::Worklist::removeDeadPlans): (JSC::DFG::Worklist::removeNonCompilingPlansForVM): (JSC::DFG::Worklist::queueLength): (JSC::DFG::Worklist::dump const): (JSC::DFG::Worklist::setNumberOfThreads): * dfg/DFGWorklistInlines.h: (JSC::DFG::Worklist::iterateCodeBlocksForGC): * disassembler/Disassembler.cpp: * heap/BlockDirectory.cpp: (JSC::BlockDirectory::addBlock): * heap/CodeBlockSetInlines.h: (JSC::CodeBlockSet::iterateCurrentlyExecuting): * heap/ConservativeRoots.cpp: (JSC::ConservativeRoots::add): * heap/Heap.cpp: (JSC::Heap::Heap): (JSC::Heap::lastChanceToFinalize): (JSC::Heap::collectAsync): (JSC::Heap::runBeginPhase): (JSC::Heap::waitForCollector): (JSC::Heap::requestCollection): (JSC::Heap::notifyIsSafeToCollect): * heap/SlotVisitor.cpp: (JSC::SlotVisitor::didReachTermination): * inspector/agents/InspectorScriptProfilerAgent.cpp: (Inspector::InspectorScriptProfilerAgent::startTracking): (Inspector::InspectorScriptProfilerAgent::trackingComplete): (Inspector::InspectorScriptProfilerAgent::stopSamplingWhenDisconnecting): * inspector/remote/RemoteConnectionToTarget.cpp: (Inspector::RemoteConnectionToTarget::setup): (Inspector::RemoteConnectionToTarget::sendMessageToTarget): (Inspector::RemoteConnectionToTarget::close): (Inspector::RemoteConnectionToTarget::targetClosed): * inspector/remote/RemoteInspector.cpp: (Inspector::RemoteInspector::registerTarget): (Inspector::RemoteInspector::unregisterTarget): (Inspector::RemoteInspector::updateTarget): (Inspector::RemoteInspector::updateClientCapabilities): (Inspector::RemoteInspector::setClient): (Inspector::RemoteInspector::setupFailed): (Inspector::RemoteInspector::setupCompleted): (Inspector::RemoteInspector::stop): * inspector/remote/cocoa/RemoteConnectionToTargetCocoa.mm: (Inspector::RemoteTargetHandleRunSourceGlobal): (Inspector::RemoteTargetQueueTaskOnGlobalQueue): (Inspector::RemoteTargetHandleRunSourceWithInfo): (Inspector::RemoteConnectionToTarget::setup): (Inspector::RemoteConnectionToTarget::targetClosed): (Inspector::RemoteConnectionToTarget::close): (Inspector::RemoteConnectionToTarget::sendMessageToTarget): (Inspector::RemoteConnectionToTarget::queueTaskOnPrivateRunLoop): * inspector/remote/cocoa/RemoteInspectorCocoa.mm: (Inspector::RemoteInspector::updateAutomaticInspectionCandidate): (Inspector::RemoteInspector::sendMessageToRemote): (Inspector::RemoteInspector::start): (Inspector::RemoteInspector::setupXPCConnectionIfNeeded): (Inspector::RemoteInspector::setParentProcessInformation): (Inspector::RemoteInspector::xpcConnectionReceivedMessage): (Inspector::RemoteInspector::xpcConnectionFailed): (Inspector::RemoteInspector::pushListingsSoon): (Inspector::RemoteInspector::receivedIndicateMessage): (Inspector::RemoteInspector::receivedProxyApplicationSetupMessage): * inspector/remote/cocoa/RemoteInspectorXPCConnection.mm: (Inspector::RemoteInspectorXPCConnection::close): (Inspector::RemoteInspectorXPCConnection::closeFromMessage): (Inspector::RemoteInspectorXPCConnection::deserializeMessage): (Inspector::RemoteInspectorXPCConnection::handleEvent): * inspector/remote/glib/RemoteInspectorGlib.cpp: (Inspector::RemoteInspector::start): (Inspector::RemoteInspector::setupConnection): (Inspector::RemoteInspector::pushListingsSoon): (Inspector::RemoteInspector::sendMessageToRemote): (Inspector::RemoteInspector::receivedGetTargetListMessage): (Inspector::RemoteInspector::receivedDataMessage): (Inspector::RemoteInspector::receivedCloseMessage): (Inspector::RemoteInspector::setup): * inspector/remote/socket/RemoteInspectorConnectionClient.cpp: (Inspector::RemoteInspectorConnectionClient::didReceive): * inspector/remote/socket/RemoteInspectorSocket.cpp: (Inspector::RemoteInspector::didClose): (Inspector::RemoteInspector::start): (Inspector::RemoteInspector::pushListingsSoon): (Inspector::RemoteInspector::setup): (Inspector::RemoteInspector::setupInspectorClient): (Inspector::RemoteInspector::frontendDidClose): (Inspector::RemoteInspector::sendMessageToBackend): (Inspector::RemoteInspector::startAutomationSession): * inspector/remote/socket/RemoteInspectorSocketEndpoint.cpp: (Inspector::RemoteInspectorSocketEndpoint::listenInet): (Inspector::RemoteInspectorSocketEndpoint::isListening): (Inspector::RemoteInspectorSocketEndpoint::workerThread): (Inspector::RemoteInspectorSocketEndpoint::createClient): (Inspector::RemoteInspectorSocketEndpoint::disconnect): (Inspector::RemoteInspectorSocketEndpoint::invalidateClient): (Inspector::RemoteInspectorSocketEndpoint::invalidateListener): (Inspector::RemoteInspectorSocketEndpoint::getPort const): (Inspector::RemoteInspectorSocketEndpoint::recvIfEnabled): (Inspector::RemoteInspectorSocketEndpoint::sendIfEnabled): (Inspector::RemoteInspectorSocketEndpoint::send): (Inspector::RemoteInspectorSocketEndpoint::acceptInetSocketIfEnabled): * interpreter/CLoopStack.cpp: (JSC::CLoopStack::addToCommittedByteCount): (JSC::CLoopStack::committedByteCount): * jit/ExecutableAllocator.cpp: (JSC::dumpJITMemory): * jit/ICStats.cpp: (JSC::ICStats::ICStats): (JSC::ICStats::~ICStats): * jit/JITThunks.cpp: (JSC::JITThunks::ctiStub): (JSC::JITThunks::existingCTIStub): (JSC::JITThunks::ctiSlowPathFunctionStub): * jit/JITWorklist.cpp: (JSC::JITWorklist::Plan::compileInThread): (JSC::JITWorklist::Plan::isFinishedCompiling): (JSC::JITWorklist::JITWorklist): (JSC::JITWorklist::completeAllForVM): (JSC::JITWorklist::poll): (JSC::JITWorklist::compileLater): (JSC::JITWorklist::finalizePlans): * parser/SourceProvider.cpp: (JSC::SourceProvider::getID): * profiler/ProfilerDatabase.cpp: (JSC::Profiler::Database::ensureBytecodesFor): (JSC::Profiler::Database::notifyDestruction): (JSC::Profiler::Database::addCompilation): (JSC::Profiler::Database::logEvent): (JSC::Profiler::Database::addDatabaseToAtExit): (JSC::Profiler::Database::removeDatabaseFromAtExit): (JSC::Profiler::Database::removeFirstAtExitDatabase): * profiler/ProfilerUID.cpp: (JSC::Profiler::UID::create): * runtime/DeferredWorkTimer.cpp: (JSC::DeferredWorkTimer::scheduleWorkSoon): (JSC::DeferredWorkTimer::didResumeScriptExecutionOwner): * runtime/SamplingProfiler.cpp: (JSC::SamplingProfiler::timerLoop): (JSC::SamplingProfiler::shutdown): (JSC::SamplingProfiler::start): (JSC::SamplingProfiler::noticeCurrentThreadAsJSCExecutionThread): (JSC::SamplingProfiler::noticeJSLockAcquisition): (JSC::SamplingProfiler::noticeVMEntry): (JSC::SamplingProfiler::registerForReportAtExit): * runtime/Watchdog.cpp: (JSC::Watchdog::startTimer): (JSC::Watchdog::willDestroyVM): * tools/VMInspector.cpp: (JSC::VMInspector::isValidExecutableMemory): * wasm/WasmBBQPlan.cpp: (JSC::Wasm::BBQPlan::work): * wasm/WasmEntryPlan.cpp: (JSC::Wasm::EntryPlan::ThreadCountHolder::ThreadCountHolder): (JSC::Wasm::EntryPlan::ThreadCountHolder::~ThreadCountHolder): * wasm/WasmOMGPlan.cpp: (JSC::Wasm::OMGPlan::work): * wasm/WasmPlan.cpp: (JSC::Wasm::Plan::addCompletionTask): (JSC::Wasm::Plan::waitForCompletion): (JSC::Wasm::Plan::tryRemoveContextAndCancelIfLast): * wasm/WasmSignature.cpp: (JSC::Wasm::SignatureInformation::signatureFor): (JSC::Wasm::SignatureInformation::tryCleanup): * wasm/WasmWorklist.cpp: (JSC::Wasm::Worklist::enqueue): (JSC::Wasm::Worklist::completePlanSynchronously): (JSC::Wasm::Worklist::stopAllPlansForContext): (JSC::Wasm::Worklist::Worklist): (JSC::Wasm::Worklist::~Worklist): Source/WebCore: * Modules/webaudio/AsyncAudioDecoder.cpp: (WebCore::AsyncAudioDecoder::AsyncAudioDecoder): (WebCore::AsyncAudioDecoder::runLoop): * Modules/webdatabase/Database.cpp: (WebCore::Database::performClose): (WebCore::Database::inProgressTransactionCompleted): (WebCore::Database::hasPendingTransaction): (WebCore::Database::runTransaction): * Modules/webdatabase/DatabaseThread.cpp: (WebCore::DatabaseThread::start): (WebCore::DatabaseThread::databaseThread): (WebCore::DatabaseThread::recordDatabaseOpen): (WebCore::DatabaseThread::recordDatabaseClosed): (WebCore::DatabaseThread::hasPendingDatabaseActivity const): * Modules/webdatabase/DatabaseTracker.cpp: (WebCore::DatabaseTracker::canEstablishDatabase): (WebCore::DatabaseTracker::retryCanEstablishDatabase): (WebCore::DatabaseTracker::maximumSize): (WebCore::DatabaseTracker::fullPathForDatabase): (WebCore::DatabaseTracker::origins): (WebCore::DatabaseTracker::databaseNames): (WebCore::DatabaseTracker::detailsForNameAndOrigin): (WebCore::DatabaseTracker::setDatabaseDetails): (WebCore::DatabaseTracker::doneCreatingDatabase): (WebCore::DatabaseTracker::openDatabases): (WebCore::DatabaseTracker::addOpenDatabase): (WebCore::DatabaseTracker::removeOpenDatabase): (WebCore::DatabaseTracker::originLockFor): (WebCore::DatabaseTracker::quota): (WebCore::DatabaseTracker::setQuota): (WebCore::DatabaseTracker::deleteOrigin): (WebCore::DatabaseTracker::deleteDatabase): (WebCore::DatabaseTracker::deleteDatabaseFile): (WebCore::DatabaseTracker::removeDeletedOpenedDatabases): * Modules/webdatabase/SQLCallbackWrapper.h: (WebCore::SQLCallbackWrapper::clear): (WebCore::SQLCallbackWrapper::unwrap): * Modules/webdatabase/SQLTransaction.cpp: (WebCore::SQLTransaction::enqueueStatement): (WebCore::SQLTransaction::checkAndHandleClosedDatabase): (WebCore::SQLTransaction::getNextStatement): * Modules/webdatabase/SQLTransactionBackend.cpp: (WebCore::SQLTransactionBackend::doCleanup): * accessibility/isolatedtree/AXIsolatedTree.cpp: (WebCore::AXIsolatedTree::clear): (WebCore::AXIsolatedTree::generateSubtree): (WebCore::AXIsolatedTree::createSubtree): (WebCore::AXIsolatedTree::updateNode): (WebCore::AXIsolatedTree::updateNodeProperty): (WebCore::AXIsolatedTree::updateChildren): (WebCore::AXIsolatedTree::focusedNode): (WebCore::AXIsolatedTree::rootNode): (WebCore::AXIsolatedTree::setFocusedNodeID): (WebCore::AXIsolatedTree::removeNode): (WebCore::AXIsolatedTree::removeSubtree): (WebCore::AXIsolatedTree::applyPendingChanges): * page/scrolling/mac/ScrollingTreeMac.mm: (ScrollingTreeMac::scrollingNodeForPoint): (ScrollingTreeMac::eventListenerRegionTypesForPoint const): * platform/AbortableTaskQueue.h: * platform/audio/cocoa/CARingBuffer.cpp: (WebCore::CARingBufferStorageVector::flush): (WebCore::CARingBufferStorageVector::setCurrentFrameBounds): * platform/graphics/avfoundation/cf/MediaPlayerPrivateAVFoundationCF.cpp: (WebCore::AVFWrapper::addToMap): (WebCore::AVFWrapper::removeFromMap const): (WebCore::AVFWrapper::periodicTimeObserverCallback): (WebCore::AVFWrapper::processNotification): (WebCore::AVFWrapper::loadPlayableCompletionCallback): (WebCore::AVFWrapper::loadMetadataCompletionCallback): (WebCore::AVFWrapper::seekCompletedCallback): (WebCore::AVFWrapper::processCue): (WebCore::AVFWrapper::legibleOutputCallback): (WebCore::AVFWrapper::processShouldWaitForLoadingOfResource): (WebCore::AVFWrapper::resourceLoaderShouldWaitForLoadingOfRequestedResource): * platform/graphics/avfoundation/objc/ImageDecoderAVFObjC.mm: (-[WebCoreSharedBufferResourceLoaderDelegate setExpectedContentSize:]): (-[WebCoreSharedBufferResourceLoaderDelegate updateData:complete:]): (-[WebCoreSharedBufferResourceLoaderDelegate resourceLoader:shouldWaitForLoadingOfRequestedResource:]): (-[WebCoreSharedBufferResourceLoaderDelegate resourceLoader:didCancelLoadingRequest:]): (WebCore::ImageDecoderAVFObjC::setTrack): (WebCore::ImageDecoderAVFObjC::createFrameImageAtIndex): * platform/graphics/gstreamer/ImageDecoderGStreamer.cpp: (WebCore::ImageDecoderGStreamer::createFrameImageAtIndex): * platform/graphics/gstreamer/InbandTextTrackPrivateGStreamer.cpp: (WebCore::InbandTextTrackPrivateGStreamer::handleSample): (WebCore::InbandTextTrackPrivateGStreamer::notifyTrackOfSample): * platform/graphics/gstreamer/MainThreadNotifier.h: * platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp: (WebCore::MediaPlayerPrivateGStreamer::parseInitDataFromProtectionMessage): (WebCore::MediaPlayerPrivateGStreamer::handleProtectionEvent): * platform/graphics/gstreamer/TrackPrivateBaseGStreamer.cpp: (WebCore::TrackPrivateBaseGStreamer::tagsChanged): (WebCore::TrackPrivateBaseGStreamer::notifyTrackOfTagsChanged): * platform/graphics/gstreamer/VideoSinkGStreamer.cpp: (VideoRenderRequestScheduler::start): (VideoRenderRequestScheduler::stop): (VideoRenderRequestScheduler::drain): (VideoRenderRequestScheduler::requestRender): * platform/graphics/gstreamer/eme/WebKitCommonEncryptionDecryptorGStreamer.cpp: (transformInPlace): (sinkEventHandler): (webKitMediaCommonEncryptionDecryptIsFlushing): (setContext): * platform/graphics/nicosia/NicosiaBuffer.cpp: (Nicosia::Buffer::beginPainting): (Nicosia::Buffer::completePainting): (Nicosia::Buffer::waitUntilPaintingComplete): * platform/graphics/nicosia/NicosiaPlatformLayer.h: (Nicosia::PlatformLayer::setSceneIntegration): (Nicosia::PlatformLayer::createUpdateScope): (Nicosia::CompositionLayer::updateState): (Nicosia::CompositionLayer::flushState): (Nicosia::CompositionLayer::commitState): (Nicosia::CompositionLayer::accessPending): (Nicosia::CompositionLayer::accessCommitted): * platform/graphics/nicosia/NicosiaScene.h: (Nicosia::Scene::accessState): * platform/graphics/nicosia/NicosiaSceneIntegration.cpp: (Nicosia::SceneIntegration::setClient): (Nicosia::SceneIntegration::invalidate): (Nicosia::SceneIntegration::requestUpdate): * platform/graphics/nicosia/texmap/NicosiaBackingStoreTextureMapperImpl.cpp: (Nicosia::BackingStoreTextureMapperImpl::flushUpdate): (Nicosia::BackingStoreTextureMapperImpl::takeUpdate): * platform/graphics/nicosia/texmap/NicosiaContentLayerTextureMapperImpl.cpp: (Nicosia::ContentLayerTextureMapperImpl::~ContentLayerTextureMapperImpl): (Nicosia::ContentLayerTextureMapperImpl::invalidateClient): (Nicosia::ContentLayerTextureMapperImpl::flushUpdate): (Nicosia::ContentLayerTextureMapperImpl::swapBuffersIfNeeded): * platform/graphics/nicosia/texmap/NicosiaImageBackingTextureMapperImpl.cpp: (Nicosia::ImageBackingTextureMapperImpl::flushUpdate): (Nicosia::ImageBackingTextureMapperImpl::takeUpdate): * platform/graphics/texmap/TextureMapperGCGLPlatformLayer.cpp: (WebCore::TextureMapperGCGLPlatformLayer::swapBuffersIfNeeded): * platform/graphics/win/MediaPlayerPrivateMediaFoundation.cpp: (WebCore::MediaPlayerPrivateMediaFoundation::load): (WebCore::MediaPlayerPrivateMediaFoundation::naturalSize const): (WebCore::MediaPlayerPrivateMediaFoundation::addListener): (WebCore::MediaPlayerPrivateMediaFoundation::removeListener): (WebCore::MediaPlayerPrivateMediaFoundation::notifyDeleted): (WebCore::MediaPlayerPrivateMediaFoundation::setNaturalSize): (WebCore::MediaPlayerPrivateMediaFoundation::AsyncCallback::Invoke): (WebCore::MediaPlayerPrivateMediaFoundation::AsyncCallback::onMediaPlayerDeleted): (WebCore::MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::OnClockStart): (WebCore::MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::OnClockStop): (WebCore::MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::OnClockPause): (WebCore::MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::OnClockRestart): (WebCore::MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::OnClockSetRate): (WebCore::MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::ProcessMessage): (WebCore::MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::GetCurrentMediaType): (WebCore::MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::InitServicePointers): (WebCore::MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::ReleaseServicePointers): (WebCore::MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::SetVideoWindow): (WebCore::MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::GetVideoWindow): (WebCore::MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::SetVideoPosition): (WebCore::MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::GetVideoPosition): (WebCore::MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::RepaintVideo): (WebCore::MediaPlayerPrivateMediaFoundation::VideoSamplePool::getSample): (WebCore::MediaPlayerPrivateMediaFoundation::VideoSamplePool::returnSample): (WebCore::MediaPlayerPrivateMediaFoundation::VideoSamplePool::areSamplesPending): (WebCore::MediaPlayerPrivateMediaFoundation::VideoSamplePool::initialize): (WebCore::MediaPlayerPrivateMediaFoundation::VideoSamplePool::clear): (WebCore::MediaPlayerPrivateMediaFoundation::VideoScheduler::stopScheduler): (WebCore::MediaPlayerPrivateMediaFoundation::VideoScheduler::scheduleSample): (WebCore::MediaPlayerPrivateMediaFoundation::VideoScheduler::processSamplesInQueue): (WebCore::MediaPlayerPrivateMediaFoundation::VideoScheduler::processSample): (WebCore::MediaPlayerPrivateMediaFoundation::VideoScheduler::schedulerThreadProcPrivate): (WebCore::MediaPlayerPrivateMediaFoundation::Direct3DPresenter::setVideoWindow): (WebCore::MediaPlayerPrivateMediaFoundation::Direct3DPresenter::setDestinationRect): (WebCore::MediaPlayerPrivateMediaFoundation::Direct3DPresenter::createVideoSamples): (WebCore::MediaPlayerPrivateMediaFoundation::Direct3DPresenter::checkDeviceState): (WebCore::MediaPlayerPrivateMediaFoundation::Direct3DPresenter::presentSample): (WebCore::MediaPlayerPrivateMediaFoundation::Direct3DPresenter::paintCurrentFrame): (WebCore::MediaPlayerPrivateMediaFoundation::Direct3DPresenter::createD3DDevice): * platform/image-decoders/ScalableImageDecoder.cpp: (WebCore::ScalableImageDecoder::frameIsCompleteAtIndex const): (WebCore::ScalableImageDecoder::frameHasAlphaAtIndex const): (WebCore::ScalableImageDecoder::frameBytesAtIndex const): (WebCore::ScalableImageDecoder::frameDurationAtIndex const): (WebCore::ScalableImageDecoder::createFrameImageAtIndex): * platform/image-decoders/ScalableImageDecoder.h: * platform/ios/LegacyTileCache.mm: (WebCore::LegacyTileCache::setTilesOpaque): (WebCore::LegacyTileCache::doLayoutTiles): (WebCore::LegacyTileCache::setCurrentScale): (WebCore::LegacyTileCache::commitScaleChange): (WebCore::LegacyTileCache::layoutTilesNow): (WebCore::LegacyTileCache::layoutTilesNowForRect): (WebCore::LegacyTileCache::removeAllNonVisibleTiles): (WebCore::LegacyTileCache::removeAllTiles): (WebCore::LegacyTileCache::removeForegroundTiles): (WebCore::LegacyTileCache::setContentReplacementImage): (WebCore::LegacyTileCache::contentReplacementImage const): (WebCore::LegacyTileCache::tileCreationTimerFired): (WebCore::LegacyTileCache::setNeedsDisplayInRect): (WebCore::LegacyTileCache::updateTilingMode): (WebCore::LegacyTileCache::setTilingMode): (WebCore::LegacyTileCache::doPendingRepaints): (WebCore::LegacyTileCache::flushSavedDisplayRects): (WebCore::LegacyTileCache::prepareToDraw): * platform/ios/LegacyTileLayerPool.mm: (WebCore::LegacyTileLayerPool::addLayer): (WebCore::LegacyTileLayerPool::takeLayerWithSize): (WebCore::LegacyTileLayerPool::setCapacity): (WebCore::LegacyTileLayerPool::prune): (WebCore::LegacyTileLayerPool::drain): * platform/ios/wak/WAKWindow.mm: (-[WAKWindow setExposedScrollViewRect:]): (-[WAKWindow exposedScrollViewRect]): * platform/ios/wak/WebCoreThread.mm: (RunWebThread): (StartWebThread): * platform/mediastream/gstreamer/RealtimeOutgoingAudioSourceLibWebRTC.cpp: (WebCore::RealtimeOutgoingAudioSourceLibWebRTC::audioSamplesAvailable): (WebCore::RealtimeOutgoingAudioSourceLibWebRTC::pullAudioData): * platform/network/cf/FormDataStreamCFNet.cpp: (WebCore::openNextStream): (WebCore::formFinalize): (WebCore::formClose): * platform/network/curl/CurlRequest.cpp: (WebCore::CurlRequest::setRequestPaused): (WebCore::CurlRequest::setCallbackPaused): (WebCore::CurlRequest::pausedStatusChanged): (WebCore::CurlRequest::enableDownloadToFile): (WebCore::CurlRequest::getDownloadedFilePath): (WebCore::CurlRequest::writeDataToDownloadFileIfEnabled): (WebCore::CurlRequest::closeDownloadFile): (WebCore::CurlRequest::cleanupDownloadFile): * platform/network/curl/CurlSSLHandle.cpp: (WebCore::CurlSSLHandle::allowAnyHTTPSCertificatesForHost): (WebCore::CurlSSLHandle::canIgnoreAnyHTTPSCertificatesForHost const): (WebCore::CurlSSLHandle::setClientCertificateInfo): (WebCore::CurlSSLHandle::getSSLClientCertificate const): * platform/sql/SQLiteDatabase.cpp: (WebCore::SQLiteDatabase::close): (WebCore::SQLiteDatabase::maximumSize): (WebCore::SQLiteDatabase::setMaximumSize): (WebCore::SQLiteDatabase::pageSize): (WebCore::SQLiteDatabase::freeSpaceSize): (WebCore::SQLiteDatabase::totalSize): (WebCore::SQLiteDatabase::runIncrementalVacuumCommand): (WebCore::SQLiteDatabase::interrupt): (WebCore::SQLiteDatabase::setAuthorizer): (WebCore::constructAndPrepareStatement): * platform/sql/SQLiteStatement.cpp: (WebCore::SQLiteStatement::step): Source/WebKit: * NetworkProcess/IndexedDB/WebIDBServer.cpp: (WebKit::m_closeCallback): (WebKit::WebIDBServer::getOrigins): (WebKit::WebIDBServer::closeAndDeleteDatabasesModifiedSince): (WebKit::WebIDBServer::closeAndDeleteDatabasesForOrigins): (WebKit::WebIDBServer::renameOrigin): (WebKit::WebIDBServer::openDatabase): (WebKit::WebIDBServer::deleteDatabase): (WebKit::WebIDBServer::abortTransaction): (WebKit::WebIDBServer::commitTransaction): (WebKit::WebIDBServer::didFinishHandlingVersionChangeTransaction): (WebKit::WebIDBServer::createObjectStore): (WebKit::WebIDBServer::deleteObjectStore): (WebKit::WebIDBServer::renameObjectStore): (WebKit::WebIDBServer::clearObjectStore): (WebKit::WebIDBServer::createIndex): (WebKit::WebIDBServer::deleteIndex): (WebKit::WebIDBServer::renameIndex): (WebKit::WebIDBServer::putOrAdd): (WebKit::WebIDBServer::getRecord): (WebKit::WebIDBServer::getAllRecords): (WebKit::WebIDBServer::getCount): (WebKit::WebIDBServer::deleteRecord): (WebKit::WebIDBServer::openCursor): (WebKit::WebIDBServer::iterateCursor): (WebKit::WebIDBServer::establishTransaction): (WebKit::WebIDBServer::databaseConnectionPendingClose): (WebKit::WebIDBServer::databaseConnectionClosed): (WebKit::WebIDBServer::abortOpenAndUpgradeNeeded): (WebKit::WebIDBServer::didFireVersionChangeEvent): (WebKit::WebIDBServer::openDBRequestCancelled): (WebKit::WebIDBServer::getAllDatabaseNamesAndVersions): (WebKit::WebIDBServer::addConnection): (WebKit::WebIDBServer::removeConnection): (WebKit::WebIDBServer::close): * NetworkProcess/cache/CacheStorageEngine.cpp: (WebKit::CacheStorage::Engine::writeSizeFile): (WebKit::CacheStorage::Engine::readSizeFile): (WebKit::CacheStorage::Engine::clearAllCachesFromDisk): (WebKit::CacheStorage::Engine::deleteNonEmptyDirectoryOnBackgroundThread): * NetworkProcess/glib/DNSCache.cpp: (WebKit::DNSCache::lookup): (WebKit::DNSCache::update): (WebKit::DNSCache::removeExpiredResponsesFired): (WebKit::DNSCache::clear): * Shared/CoordinatedGraphics/threadedcompositor/CompositingRunLoop.cpp: (WebKit::CompositingRunLoop::suspend): (WebKit::CompositingRunLoop::resume): (WebKit::CompositingRunLoop::scheduleUpdate): (WebKit::CompositingRunLoop::stopUpdates): (WebKit::CompositingRunLoop::updateTimerFired): * Shared/CoordinatedGraphics/threadedcompositor/ThreadedCompositor.cpp: (WebKit::m_displayRefreshMonitor): (WebKit::ThreadedCompositor::setScaleFactor): (WebKit::ThreadedCompositor::setScrollPosition): (WebKit::ThreadedCompositor::setViewportSize): (WebKit::ThreadedCompositor::renderLayerTree): (WebKit::ThreadedCompositor::sceneUpdateFinished): (WebKit::ThreadedCompositor::updateSceneState): * UIProcess/API/glib/IconDatabase.cpp: (WebKit::IconDatabase::populatePageURLToIconURLMap): (WebKit::IconDatabase::clearLoadedIconsTimerFired): (WebKit::IconDatabase::checkIconURLAndSetPageURLIfNeeded): (WebKit::IconDatabase::loadIconForPageURL): (WebKit::IconDatabase::iconURLForPageURL): (WebKit::IconDatabase::setIconForPageURL): (WebKit::IconDatabase::clear): Source/WebKitLegacy: * Storage/InProcessIDBServer.cpp: (InProcessIDBServer::InProcessIDBServer): (InProcessIDBServer::deleteDatabase): (InProcessIDBServer::openDatabase): (InProcessIDBServer::abortTransaction): (InProcessIDBServer::commitTransaction): (InProcessIDBServer::didFinishHandlingVersionChangeTransaction): (InProcessIDBServer::createObjectStore): (InProcessIDBServer::deleteObjectStore): (InProcessIDBServer::renameObjectStore): (InProcessIDBServer::clearObjectStore): (InProcessIDBServer::createIndex): (InProcessIDBServer::deleteIndex): (InProcessIDBServer::renameIndex): (InProcessIDBServer::putOrAdd): (InProcessIDBServer::getRecord): (InProcessIDBServer::getAllRecords): (InProcessIDBServer::getCount): (InProcessIDBServer::deleteRecord): (InProcessIDBServer::openCursor): (InProcessIDBServer::iterateCursor): (InProcessIDBServer::establishTransaction): (InProcessIDBServer::databaseConnectionPendingClose): (InProcessIDBServer::databaseConnectionClosed): (InProcessIDBServer::abortOpenAndUpgradeNeeded): (InProcessIDBServer::didFireVersionChangeEvent): (InProcessIDBServer::openDBRequestCancelled): (InProcessIDBServer::getAllDatabaseNamesAndVersions): (InProcessIDBServer::closeAndDeleteDatabasesModifiedSince): * Storage/StorageAreaSync.cpp: (WebKit::StorageAreaSync::syncTimerFired): (WebKit::StorageAreaSync::performSync): * Storage/StorageTracker.cpp: (WebKit::StorageTracker::finishedImportingOriginIdentifiers): (WebKit::StorageTracker::syncImportOriginIdentifiers): (WebKit::StorageTracker::syncFileSystemAndTrackerDatabase): (WebKit::StorageTracker::setOriginDetails): (WebKit::StorageTracker::syncSetOriginDetails): (WebKit::StorageTracker::origins): (WebKit::StorageTracker::deleteAllOrigins): (WebKit::StorageTracker::syncDeleteAllOrigins): (WebKit::StorageTracker::deleteOrigin): (WebKit::StorageTracker::syncDeleteOrigin): (WebKit::StorageTracker::canDeleteOrigin): (WebKit::StorageTracker::cancelDeletingOrigin): (WebKit::StorageTracker::diskUsageForOrigin): Source/WebKitLegacy/mac: * WebView/WebView.mm: (-[WebView _synchronizeCustomFixedPositionLayoutRect]): (-[WebView _setCustomFixedPositionLayoutRectInWebThread:synchronize:]): (-[WebView _setCustomFixedPositionLayoutRect:]): (-[WebView _fetchCustomFixedPositionLayoutRect:]): Source/WebKitLegacy/win: * Plugins/PluginMainThreadScheduler.cpp: (WebCore::PluginMainThreadScheduler::scheduleCall): (WebCore::PluginMainThreadScheduler::registerPlugin): (WebCore::PluginMainThreadScheduler::unregisterPlugin): (WebCore::PluginMainThreadScheduler::dispatchCallsForPlugin): Source/WTF: * benchmarks/LockSpeedTest.cpp: * wtf/AutomaticThread.cpp: (WTF::AutomaticThread::~AutomaticThread): (WTF::AutomaticThread::join): (WTF::AutomaticThread::start): * wtf/AutomaticThread.h: * wtf/MetaAllocator.cpp: (WTF::MetaAllocatorHandle::shrink): (WTF::MetaAllocator::addFreshFreeSpace): (WTF::MetaAllocator::debugFreeSpaceSize): * wtf/ParallelHelperPool.cpp: (WTF::ParallelHelperClient::ParallelHelperClient): (WTF::ParallelHelperClient::~ParallelHelperClient): (WTF::ParallelHelperClient::setTask): (WTF::ParallelHelperClient::finish): (WTF::ParallelHelperClient::doSomeHelping): (WTF::ParallelHelperClient::runTask): (WTF::ParallelHelperPool::~ParallelHelperPool): (WTF::ParallelHelperPool::ensureThreads): (WTF::ParallelHelperPool::doSomeHelping): * wtf/Seconds.cpp: (WTF::sleep): * wtf/TimeWithDynamicClockType.cpp: (WTF::sleep): * wtf/WorkerPool.cpp: (WTF::WorkerPool::WorkerPool): (WTF::WorkerPool::~WorkerPool): (WTF::WorkerPool::postTask): * wtf/posix/ThreadingPOSIX.cpp: (WTF::Thread::suspend): (WTF::Thread::resume): (WTF::Thread::getRegisters): * wtf/win/DbgHelperWin.cpp: (WTF::DbgHelper::SymFromAddress): * wtf/win/ThreadingWin.cpp: (WTF::Thread::suspend): (WTF::Thread::resume): (WTF::Thread::getRegisters): Tools: * TestWebKitAPI/Tests/WTF/WorkQueue.cpp: (TestWebKitAPI::TEST): * TestWebKitAPI/Tests/WTF/glib/WorkQueueGLib.cpp: (TestWebKitAPI::TEST): * TestWebKitAPI/Tests/WebCore/AbortableTaskQueue.cpp: (TestWebKitAPI::DeterministicScheduler::ThreadContext::waitMyTurn): (TestWebKitAPI::DeterministicScheduler::ThreadContext::yieldToThread): Canonical link: https://commits.webkit.org/238053@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@277920 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2021-05-22 16:49:42 +00:00
// Locker locker { m_lock };
WTF should make it easier to create threads that die automatically after inactivity https://bugs.webkit.org/show_bug.cgi?id=163576 Reviewed by Andreas Kling. Source/JavaScriptCore: Added a sleepSeconds() function, which made it easier for me to test this change. The WTF changes in this patch change how the JSC GC manages threads: the GC threads will now shut down automatically after 1 second of inactivity. Maybe this will save some memory. * jsc.cpp: (GlobalObject::finishCreation): (functionSleepSeconds): Source/WTF: For a long time now, I've been adding threads to WTF/JSC and each time I do this, I feel guilty because those threads don't shut down when they are inactive. For example, in bug 163562, I need to add a new GC thread. There will be one of them per VM. This means that a JSC API client that starts a lot of VMs will have a lot of threads. I don't think that's good. A common pattern for all of these threads is that they have some well-defined trigger that causes them to run. This trigger has a lock, a condition variable, some logic that determines if there is work to do, and then of course the logic for the thread's actual work. The thread bodies usually look like this: void Thingy::runThread() { for (;;) { Work work; { LockHolder locker(m_lock); while (!hasWork()) m_cond.wait(m_lock); work = takeWork(); } doWork(work); } } If you look at ParallelHelperPool (the GC's threads) and DFG::Worklist (some of the JIT's threads), you will see this pattern. This change adds a new kind of thread, called AutomaticThread, that lets you write threads to this pattern while getting automatic thread shutdown for free: instead of just waiting on a condition variable, AutomaticThread will have a timeout that causes the thread to die. The condition variable associated with AutomaticThread, called AutomaticThreadCondition, is smart enough to restart any threads that have decided to stop due to inactivity. The inactivity threshold is current just 1 second. In this patch I only adopt AutomaticThread for ParallelHelperPool. I plan to adopt it in more places soon. * WTF.xcodeproj/project.pbxproj: * wtf/AutomaticThread.cpp: Added. (WTF::AutomaticThreadCondition::create): (WTF::AutomaticThreadCondition::AutomaticThreadCondition): (WTF::AutomaticThreadCondition::~AutomaticThreadCondition): (WTF::AutomaticThreadCondition::notifyAll): (WTF::AutomaticThreadCondition::add): (WTF::AutomaticThreadCondition::remove): (WTF::AutomaticThreadCondition::contains): (WTF::AutomaticThread::AutomaticThread): (WTF::AutomaticThread::~AutomaticThread): (WTF::AutomaticThread::join): (WTF::AutomaticThread::start): * wtf/AutomaticThread.h: Added. * wtf/CMakeLists.txt: * wtf/ParallelHelperPool.cpp: (WTF::ParallelHelperClient::ParallelHelperClient): (WTF::ParallelHelperClient::~ParallelHelperClient): (WTF::ParallelHelperClient::setTask): (WTF::ParallelHelperClient::finish): (WTF::ParallelHelperClient::doSomeHelping): (WTF::ParallelHelperClient::runTask): (WTF::ParallelHelperPool::ParallelHelperPool): (WTF::ParallelHelperPool::~ParallelHelperPool): (WTF::ParallelHelperPool::ensureThreads): (WTF::ParallelHelperPool::doSomeHelping): (WTF::ParallelHelperPool::Thread::Thread): (WTF::ParallelHelperPool::didMakeWorkAvailable): (WTF::ParallelHelperPool::helperThreadBody): Deleted. (WTF::ParallelHelperPool::waitForClientWithTask): Deleted. * wtf/ParallelHelperPool.h: Canonical link: https://commits.webkit.org/181393@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@207480 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-10-18 20:17:10 +00:00
// for (;;) {
// [1] stuff that could break, return, or fall through;
// m_condition.wait(m_lock);
// }
// }
//
// [2] do work;
// }
//
// When we do this, we don't always do a good job of managing this thread's lifetime, which may lead
// to this thread sitting around even when it is not needed.
//
// AutomaticThread is here to help you in these situations. It encapsulates a lock, a condition
// variable, and a thread. It will automatically shut the thread down after a timeout of inactivity.
WTF should make it easier to create threads that die automatically after inactivity https://bugs.webkit.org/show_bug.cgi?id=163576 Reviewed by Andreas Kling. Source/JavaScriptCore: Added a sleepSeconds() function, which made it easier for me to test this change. The WTF changes in this patch change how the JSC GC manages threads: the GC threads will now shut down automatically after 1 second of inactivity. Maybe this will save some memory. * jsc.cpp: (GlobalObject::finishCreation): (functionSleepSeconds): Source/WTF: For a long time now, I've been adding threads to WTF/JSC and each time I do this, I feel guilty because those threads don't shut down when they are inactive. For example, in bug 163562, I need to add a new GC thread. There will be one of them per VM. This means that a JSC API client that starts a lot of VMs will have a lot of threads. I don't think that's good. A common pattern for all of these threads is that they have some well-defined trigger that causes them to run. This trigger has a lock, a condition variable, some logic that determines if there is work to do, and then of course the logic for the thread's actual work. The thread bodies usually look like this: void Thingy::runThread() { for (;;) { Work work; { LockHolder locker(m_lock); while (!hasWork()) m_cond.wait(m_lock); work = takeWork(); } doWork(work); } } If you look at ParallelHelperPool (the GC's threads) and DFG::Worklist (some of the JIT's threads), you will see this pattern. This change adds a new kind of thread, called AutomaticThread, that lets you write threads to this pattern while getting automatic thread shutdown for free: instead of just waiting on a condition variable, AutomaticThread will have a timeout that causes the thread to die. The condition variable associated with AutomaticThread, called AutomaticThreadCondition, is smart enough to restart any threads that have decided to stop due to inactivity. The inactivity threshold is current just 1 second. In this patch I only adopt AutomaticThread for ParallelHelperPool. I plan to adopt it in more places soon. * WTF.xcodeproj/project.pbxproj: * wtf/AutomaticThread.cpp: Added. (WTF::AutomaticThreadCondition::create): (WTF::AutomaticThreadCondition::AutomaticThreadCondition): (WTF::AutomaticThreadCondition::~AutomaticThreadCondition): (WTF::AutomaticThreadCondition::notifyAll): (WTF::AutomaticThreadCondition::add): (WTF::AutomaticThreadCondition::remove): (WTF::AutomaticThreadCondition::contains): (WTF::AutomaticThread::AutomaticThread): (WTF::AutomaticThread::~AutomaticThread): (WTF::AutomaticThread::join): (WTF::AutomaticThread::start): * wtf/AutomaticThread.h: Added. * wtf/CMakeLists.txt: * wtf/ParallelHelperPool.cpp: (WTF::ParallelHelperClient::ParallelHelperClient): (WTF::ParallelHelperClient::~ParallelHelperClient): (WTF::ParallelHelperClient::setTask): (WTF::ParallelHelperClient::finish): (WTF::ParallelHelperClient::doSomeHelping): (WTF::ParallelHelperClient::runTask): (WTF::ParallelHelperPool::ParallelHelperPool): (WTF::ParallelHelperPool::~ParallelHelperPool): (WTF::ParallelHelperPool::ensureThreads): (WTF::ParallelHelperPool::doSomeHelping): (WTF::ParallelHelperPool::Thread::Thread): (WTF::ParallelHelperPool::didMakeWorkAvailable): (WTF::ParallelHelperPool::helperThreadBody): Deleted. (WTF::ParallelHelperPool::waitForClientWithTask): Deleted. * wtf/ParallelHelperPool.h: Canonical link: https://commits.webkit.org/181393@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@207480 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-10-18 20:17:10 +00:00
// You use AutomaticThread by subclassing it, and put any state that is needed between [1] and [2]
// in the subclass.
//
// The terminology we use is:
//
// [1] PollResult AutomaticThread::poll()
// [2] WorkResult AutomaticThread::work()
WTF should make it easier to create threads that die automatically after inactivity https://bugs.webkit.org/show_bug.cgi?id=163576 Reviewed by Andreas Kling. Source/JavaScriptCore: Added a sleepSeconds() function, which made it easier for me to test this change. The WTF changes in this patch change how the JSC GC manages threads: the GC threads will now shut down automatically after 1 second of inactivity. Maybe this will save some memory. * jsc.cpp: (GlobalObject::finishCreation): (functionSleepSeconds): Source/WTF: For a long time now, I've been adding threads to WTF/JSC and each time I do this, I feel guilty because those threads don't shut down when they are inactive. For example, in bug 163562, I need to add a new GC thread. There will be one of them per VM. This means that a JSC API client that starts a lot of VMs will have a lot of threads. I don't think that's good. A common pattern for all of these threads is that they have some well-defined trigger that causes them to run. This trigger has a lock, a condition variable, some logic that determines if there is work to do, and then of course the logic for the thread's actual work. The thread bodies usually look like this: void Thingy::runThread() { for (;;) { Work work; { LockHolder locker(m_lock); while (!hasWork()) m_cond.wait(m_lock); work = takeWork(); } doWork(work); } } If you look at ParallelHelperPool (the GC's threads) and DFG::Worklist (some of the JIT's threads), you will see this pattern. This change adds a new kind of thread, called AutomaticThread, that lets you write threads to this pattern while getting automatic thread shutdown for free: instead of just waiting on a condition variable, AutomaticThread will have a timeout that causes the thread to die. The condition variable associated with AutomaticThread, called AutomaticThreadCondition, is smart enough to restart any threads that have decided to stop due to inactivity. The inactivity threshold is current just 1 second. In this patch I only adopt AutomaticThread for ParallelHelperPool. I plan to adopt it in more places soon. * WTF.xcodeproj/project.pbxproj: * wtf/AutomaticThread.cpp: Added. (WTF::AutomaticThreadCondition::create): (WTF::AutomaticThreadCondition::AutomaticThreadCondition): (WTF::AutomaticThreadCondition::~AutomaticThreadCondition): (WTF::AutomaticThreadCondition::notifyAll): (WTF::AutomaticThreadCondition::add): (WTF::AutomaticThreadCondition::remove): (WTF::AutomaticThreadCondition::contains): (WTF::AutomaticThread::AutomaticThread): (WTF::AutomaticThread::~AutomaticThread): (WTF::AutomaticThread::join): (WTF::AutomaticThread::start): * wtf/AutomaticThread.h: Added. * wtf/CMakeLists.txt: * wtf/ParallelHelperPool.cpp: (WTF::ParallelHelperClient::ParallelHelperClient): (WTF::ParallelHelperClient::~ParallelHelperClient): (WTF::ParallelHelperClient::setTask): (WTF::ParallelHelperClient::finish): (WTF::ParallelHelperClient::doSomeHelping): (WTF::ParallelHelperClient::runTask): (WTF::ParallelHelperPool::ParallelHelperPool): (WTF::ParallelHelperPool::~ParallelHelperPool): (WTF::ParallelHelperPool::ensureThreads): (WTF::ParallelHelperPool::doSomeHelping): (WTF::ParallelHelperPool::Thread::Thread): (WTF::ParallelHelperPool::didMakeWorkAvailable): (WTF::ParallelHelperPool::helperThreadBody): Deleted. (WTF::ParallelHelperPool::waitForClientWithTask): Deleted. * wtf/ParallelHelperPool.h: Canonical link: https://commits.webkit.org/181393@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@207480 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-10-18 20:17:10 +00:00
//
// Note that poll() and work() may not be called on the same thread every time, since this will shut
// down the thread as necessary. This is legal since m_condition.wait(m_lock) can drop the lock, and
// so there is no reason to keep the thread around.
class AutomaticThread;
The GC should be in a thread https://bugs.webkit.org/show_bug.cgi?id=163562 Reviewed by Geoffrey Garen and Andreas Kling. Source/JavaScriptCore: In a concurrent GC, the work of collecting happens on a separate thread. This patch implements this, and schedules the thread the way that a concurrent GC thread would be scheduled. But, the GC isn't actually concurrent yet because it calls stopTheWorld() before doing anything and calls resumeTheWorld() after it's done with everything. The next step will be to make it really concurrent by basically calling stopTheWorld()/resumeTheWorld() around bounded snippets of work while making most of the work happen with the world running. Our GC will probably always have stop-the-world phases because the semantics of JSC weak references call for it. This implements concurrent GC scheduling. This means that there is no longer a Heap::collect() API. Instead, you can call collectAsync() which makes sure that a GC is scheduled (it will do nothing if one is scheduled or ongoing) or you can call collectSync() to schedule a GC and wait for it to happen. I made our debugging stuff call collectSync(). It should be a goal to never call collectSync() except for debugging or benchmark harness hacks. The collector thread is an AutomaticThread, so it won't linger when not in use. It works on a ticket-based system, like you would see at the DMV. A ticket is a 64-bit integer. There are two ticket counters: last granted and last served. When you request a collection, last granted is incremented and its new value given to you. When a collection completes, last served is incremented. collectSync() waits until last served catches up to what last granted had been at the time you requested a GC. This means that if you request a sync GC in the middle of an async GC, you will wait for that async GC to finish and then you will request and wait for your sync GC. The synchronization between the collector thread and the main threads is complex. The collector thread needs to be able to ask the main thread to stop. It needs to be able to do some post-GC clean-up, like the synchronous CodeBlock and LargeAllocation sweeps, on the main thread. The collector needs to be able to ask the main thread to execute a cross-modifying code fence before running any JIT code, since the GC might aid the JIT worklist and run JIT finalization. It's possible for the GC to want the main thread to run something at the same time that the main thread wants to wait for the GC. The main thread needs to be able to run non-JSC stuff without causing the GC to completely stall. The main thread needs to be able to query its own state (is there a request to stop?) and change it (running JSC versus not) quickly, since this may happen on hot paths. This kind of intertwined system of requests, notifications, and state changes requires a combination of lock-free algorithms and waiting. So, this is all implemented using a Atomic<unsigned> Heap::m_worldState, which has bits to represent things being requested by the collector and the heap access state of the mutator. I am borrowing a lot of terms that I've seen in other VMs that I've worked on. Here's what they mean: - Stop the world: make sure that either the mutator is not running, or that it's not running code that could mess with the heap. - Heap access: the mutator is said to have heap access if it could mess with the heap. If you stop the world and the mutator doesn't have heap access, all you're doing is making sure that it will block when it tries to acquire heap access. This means that our GC is already fully concurrent in cases where the GC is requested while the mutator has no heap access. This probably won't happen, but if it did then it should just work. Usually, stopping the world means that we state our shouldStop request with m_worldState, and a future call to Heap::stopIfNecessary() will go to slow path and stop. The act of stopping or waiting to acquire heap access is managed by using ParkingLot API directly on m_worldState. This works out great because it would be very awkward to get the same functionality using locks and condition variables, since we want stopIfNecessary/acquireAccess/requestAccess fast paths that are single atomic instructions (load/CAS/CAS, respectively). The mutator will call these things frequently. Currently we have Heap::stopIfNecessary() polling on every allocator slow path, but we may want to make it even more frequent than that. Currently only JSC API clients benefit from the heap access optimization. The DOM forces us to assume that heap access is permanently on, since DOM manipulation doesn't always hold the JSLock. We could still allow the GC to proceed when the runloop is idle by having the GC put a task on the runloop that just calls stopIfNecessary(). This is perf neutral. The only behavior change that clients ought to observe is that marking and the weak fixpoint happen on a separate thread. Marking was already parallel so it already handled multiple threads, but now it _never_ runs on the main thread. The weak fixpoint needed some help to be able to run on another thread - mostly because there was some code in IndexedDB that was using thread specifics in the weak fixpoint. * API/JSBase.cpp: (JSSynchronousEdenCollectForDebugging): * API/JSManagedValue.mm: (-[JSManagedValue initWithValue:]): * heap/EdenGCActivityCallback.cpp: (JSC::EdenGCActivityCallback::doCollection): * heap/FullGCActivityCallback.cpp: (JSC::FullGCActivityCallback::doCollection): * heap/Heap.cpp: (JSC::Heap::Thread::Thread): (JSC::Heap::Heap): (JSC::Heap::lastChanceToFinalize): (JSC::Heap::markRoots): (JSC::Heap::gatherStackRoots): (JSC::Heap::deleteUnmarkedCompiledCode): (JSC::Heap::collectAllGarbage): (JSC::Heap::collectAsync): (JSC::Heap::collectSync): (JSC::Heap::shouldCollectInThread): (JSC::Heap::collectInThread): (JSC::Heap::stopTheWorld): (JSC::Heap::resumeTheWorld): (JSC::Heap::stopIfNecessarySlow): (JSC::Heap::acquireAccessSlow): (JSC::Heap::releaseAccessSlow): (JSC::Heap::handleDidJIT): (JSC::Heap::handleNeedFinalize): (JSC::Heap::setDidJIT): (JSC::Heap::setNeedFinalize): (JSC::Heap::waitWhileNeedFinalize): (JSC::Heap::finalize): (JSC::Heap::requestCollection): (JSC::Heap::waitForCollection): (JSC::Heap::didFinishCollection): (JSC::Heap::canCollect): (JSC::Heap::shouldCollectHeuristic): (JSC::Heap::shouldCollect): (JSC::Heap::collectIfNecessaryOrDefer): (JSC::Heap::collectAccordingToDeferGCProbability): (JSC::Heap::collect): Deleted. (JSC::Heap::collectWithoutAnySweep): Deleted. (JSC::Heap::collectImpl): Deleted. * heap/Heap.h: (JSC::Heap::ReleaseAccessScope::ReleaseAccessScope): (JSC::Heap::ReleaseAccessScope::~ReleaseAccessScope): * heap/HeapInlines.h: (JSC::Heap::acquireAccess): (JSC::Heap::releaseAccess): (JSC::Heap::stopIfNecessary): * heap/MachineStackMarker.cpp: (JSC::MachineThreads::gatherConservativeRoots): (JSC::MachineThreads::gatherFromCurrentThread): Deleted. * heap/MachineStackMarker.h: * jit/JITWorklist.cpp: (JSC::JITWorklist::completeAllForVM): * jit/JITWorklist.h: * jsc.cpp: (functionFullGC): (functionEdenGC): * runtime/InitializeThreading.cpp: (JSC::initializeThreading): * runtime/JSLock.cpp: (JSC::JSLock::didAcquireLock): (JSC::JSLock::unlock): (JSC::JSLock::willReleaseLock): * tools/JSDollarVMPrototype.cpp: (JSC::JSDollarVMPrototype::edenGC): Source/WebCore: No new tests because existing tests cover this. We now need to be more careful about using JSLock. This fixes some places that were not holding it. New assertions in the GC are more likely to catch this than before. * bindings/js/WorkerScriptController.cpp: (WebCore::WorkerScriptController::WorkerScriptController): Source/WTF: This fixes some bugs and adds a few features. * wtf/Atomics.h: The GC may do work on behalf of the JIT. If it does, the main thread needs to execute a cross-modifying code fence. This is cpuid on x86 and I believe it's isb on ARM. It would have been an isync on PPC and I think that isb is the ARM equivalent. (WTF::arm_isb): (WTF::crossModifyingCodeFence): (WTF::x86_ortop): (WTF::x86_cpuid): * wtf/AutomaticThread.cpp: I accidentally had AutomaticThreadCondition inherit from ThreadSafeRefCounted<AutomaticThread> [sic]. This never crashed before because all of our prior AutomaticThreadConditions were immortal. (WTF::AutomaticThread::AutomaticThread): (WTF::AutomaticThread::~AutomaticThread): (WTF::AutomaticThread::start): * wtf/AutomaticThread.h: * wtf/MainThread.cpp: Need to allow initializeGCThreads() to be called separately because it's now more than just a debugging thing. (WTF::initializeGCThreads): Canonical link: https://commits.webkit.org/182065@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@208306 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-11-02 22:01:04 +00:00
class AutomaticThreadCondition : public ThreadSafeRefCounted<AutomaticThreadCondition> {
WTF should make it easier to create threads that die automatically after inactivity https://bugs.webkit.org/show_bug.cgi?id=163576 Reviewed by Andreas Kling. Source/JavaScriptCore: Added a sleepSeconds() function, which made it easier for me to test this change. The WTF changes in this patch change how the JSC GC manages threads: the GC threads will now shut down automatically after 1 second of inactivity. Maybe this will save some memory. * jsc.cpp: (GlobalObject::finishCreation): (functionSleepSeconds): Source/WTF: For a long time now, I've been adding threads to WTF/JSC and each time I do this, I feel guilty because those threads don't shut down when they are inactive. For example, in bug 163562, I need to add a new GC thread. There will be one of them per VM. This means that a JSC API client that starts a lot of VMs will have a lot of threads. I don't think that's good. A common pattern for all of these threads is that they have some well-defined trigger that causes them to run. This trigger has a lock, a condition variable, some logic that determines if there is work to do, and then of course the logic for the thread's actual work. The thread bodies usually look like this: void Thingy::runThread() { for (;;) { Work work; { LockHolder locker(m_lock); while (!hasWork()) m_cond.wait(m_lock); work = takeWork(); } doWork(work); } } If you look at ParallelHelperPool (the GC's threads) and DFG::Worklist (some of the JIT's threads), you will see this pattern. This change adds a new kind of thread, called AutomaticThread, that lets you write threads to this pattern while getting automatic thread shutdown for free: instead of just waiting on a condition variable, AutomaticThread will have a timeout that causes the thread to die. The condition variable associated with AutomaticThread, called AutomaticThreadCondition, is smart enough to restart any threads that have decided to stop due to inactivity. The inactivity threshold is current just 1 second. In this patch I only adopt AutomaticThread for ParallelHelperPool. I plan to adopt it in more places soon. * WTF.xcodeproj/project.pbxproj: * wtf/AutomaticThread.cpp: Added. (WTF::AutomaticThreadCondition::create): (WTF::AutomaticThreadCondition::AutomaticThreadCondition): (WTF::AutomaticThreadCondition::~AutomaticThreadCondition): (WTF::AutomaticThreadCondition::notifyAll): (WTF::AutomaticThreadCondition::add): (WTF::AutomaticThreadCondition::remove): (WTF::AutomaticThreadCondition::contains): (WTF::AutomaticThread::AutomaticThread): (WTF::AutomaticThread::~AutomaticThread): (WTF::AutomaticThread::join): (WTF::AutomaticThread::start): * wtf/AutomaticThread.h: Added. * wtf/CMakeLists.txt: * wtf/ParallelHelperPool.cpp: (WTF::ParallelHelperClient::ParallelHelperClient): (WTF::ParallelHelperClient::~ParallelHelperClient): (WTF::ParallelHelperClient::setTask): (WTF::ParallelHelperClient::finish): (WTF::ParallelHelperClient::doSomeHelping): (WTF::ParallelHelperClient::runTask): (WTF::ParallelHelperPool::ParallelHelperPool): (WTF::ParallelHelperPool::~ParallelHelperPool): (WTF::ParallelHelperPool::ensureThreads): (WTF::ParallelHelperPool::doSomeHelping): (WTF::ParallelHelperPool::Thread::Thread): (WTF::ParallelHelperPool::didMakeWorkAvailable): (WTF::ParallelHelperPool::helperThreadBody): Deleted. (WTF::ParallelHelperPool::waitForClientWithTask): Deleted. * wtf/ParallelHelperPool.h: Canonical link: https://commits.webkit.org/181393@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@207480 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-10-18 20:17:10 +00:00
public:
static WTF_EXPORT_PRIVATE Ref<AutomaticThreadCondition> create();
WTF should make it easier to create threads that die automatically after inactivity https://bugs.webkit.org/show_bug.cgi?id=163576 Reviewed by Andreas Kling. Source/JavaScriptCore: Added a sleepSeconds() function, which made it easier for me to test this change. The WTF changes in this patch change how the JSC GC manages threads: the GC threads will now shut down automatically after 1 second of inactivity. Maybe this will save some memory. * jsc.cpp: (GlobalObject::finishCreation): (functionSleepSeconds): Source/WTF: For a long time now, I've been adding threads to WTF/JSC and each time I do this, I feel guilty because those threads don't shut down when they are inactive. For example, in bug 163562, I need to add a new GC thread. There will be one of them per VM. This means that a JSC API client that starts a lot of VMs will have a lot of threads. I don't think that's good. A common pattern for all of these threads is that they have some well-defined trigger that causes them to run. This trigger has a lock, a condition variable, some logic that determines if there is work to do, and then of course the logic for the thread's actual work. The thread bodies usually look like this: void Thingy::runThread() { for (;;) { Work work; { LockHolder locker(m_lock); while (!hasWork()) m_cond.wait(m_lock); work = takeWork(); } doWork(work); } } If you look at ParallelHelperPool (the GC's threads) and DFG::Worklist (some of the JIT's threads), you will see this pattern. This change adds a new kind of thread, called AutomaticThread, that lets you write threads to this pattern while getting automatic thread shutdown for free: instead of just waiting on a condition variable, AutomaticThread will have a timeout that causes the thread to die. The condition variable associated with AutomaticThread, called AutomaticThreadCondition, is smart enough to restart any threads that have decided to stop due to inactivity. The inactivity threshold is current just 1 second. In this patch I only adopt AutomaticThread for ParallelHelperPool. I plan to adopt it in more places soon. * WTF.xcodeproj/project.pbxproj: * wtf/AutomaticThread.cpp: Added. (WTF::AutomaticThreadCondition::create): (WTF::AutomaticThreadCondition::AutomaticThreadCondition): (WTF::AutomaticThreadCondition::~AutomaticThreadCondition): (WTF::AutomaticThreadCondition::notifyAll): (WTF::AutomaticThreadCondition::add): (WTF::AutomaticThreadCondition::remove): (WTF::AutomaticThreadCondition::contains): (WTF::AutomaticThread::AutomaticThread): (WTF::AutomaticThread::~AutomaticThread): (WTF::AutomaticThread::join): (WTF::AutomaticThread::start): * wtf/AutomaticThread.h: Added. * wtf/CMakeLists.txt: * wtf/ParallelHelperPool.cpp: (WTF::ParallelHelperClient::ParallelHelperClient): (WTF::ParallelHelperClient::~ParallelHelperClient): (WTF::ParallelHelperClient::setTask): (WTF::ParallelHelperClient::finish): (WTF::ParallelHelperClient::doSomeHelping): (WTF::ParallelHelperClient::runTask): (WTF::ParallelHelperPool::ParallelHelperPool): (WTF::ParallelHelperPool::~ParallelHelperPool): (WTF::ParallelHelperPool::ensureThreads): (WTF::ParallelHelperPool::doSomeHelping): (WTF::ParallelHelperPool::Thread::Thread): (WTF::ParallelHelperPool::didMakeWorkAvailable): (WTF::ParallelHelperPool::helperThreadBody): Deleted. (WTF::ParallelHelperPool::waitForClientWithTask): Deleted. * wtf/ParallelHelperPool.h: Canonical link: https://commits.webkit.org/181393@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@207480 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-10-18 20:17:10 +00:00
WTF_EXPORT_PRIVATE ~AutomaticThreadCondition();
The collector thread should only start when the mutator doesn't have heap access https://bugs.webkit.org/show_bug.cgi?id=167737 Reviewed by Keith Miller. JSTests: Add versions of splay that flash heap access, to simulate what might happen if a third-party app was running concurrent GC. In this case, we might actually start the collector thread. * stress/splay-flash-access-1ms.js: Added. (performance.now): (this.Setup.setup.setup): (this.TearDown.tearDown.tearDown): (Benchmark): (BenchmarkResult): (BenchmarkResult.prototype.valueOf): (BenchmarkSuite): (alert): (Math.random): (BenchmarkSuite.ResetRNG): (RunStep): (BenchmarkSuite.RunSuites): (BenchmarkSuite.CountBenchmarks): (BenchmarkSuite.GeometricMean): (BenchmarkSuite.GeometricMeanTime): (BenchmarkSuite.AverageAbovePercentile): (BenchmarkSuite.GeometricMeanLatency): (BenchmarkSuite.FormatScore): (BenchmarkSuite.prototype.NotifyStep): (BenchmarkSuite.prototype.NotifyResult): (BenchmarkSuite.prototype.NotifyError): (BenchmarkSuite.prototype.RunSingleBenchmark): (RunNextSetup): (RunNextBenchmark): (RunNextTearDown): (BenchmarkSuite.prototype.RunStep): (GeneratePayloadTree): (GenerateKey): (SplayUpdateStats): (InsertNewNode): (SplaySetup): (SplayTearDown): (SplayRun): (SplayTree): (SplayTree.prototype.isEmpty): (SplayTree.prototype.insert): (SplayTree.prototype.remove): (SplayTree.prototype.find): (SplayTree.prototype.findMax): (SplayTree.prototype.findGreatestLessThan): (SplayTree.prototype.exportKeys): (SplayTree.prototype.splay_): (SplayTree.Node): (SplayTree.Node.prototype.traverse_): (jscSetUp): (jscTearDown): (jscRun): (averageAbovePercentile): (printPercentile): * stress/splay-flash-access.js: Added. (performance.now): (this.Setup.setup.setup): (this.TearDown.tearDown.tearDown): (Benchmark): (BenchmarkResult): (BenchmarkResult.prototype.valueOf): (BenchmarkSuite): (alert): (Math.random): (BenchmarkSuite.ResetRNG): (RunStep): (BenchmarkSuite.RunSuites): (BenchmarkSuite.CountBenchmarks): (BenchmarkSuite.GeometricMean): (BenchmarkSuite.GeometricMeanTime): (BenchmarkSuite.AverageAbovePercentile): (BenchmarkSuite.GeometricMeanLatency): (BenchmarkSuite.FormatScore): (BenchmarkSuite.prototype.NotifyStep): (BenchmarkSuite.prototype.NotifyResult): (BenchmarkSuite.prototype.NotifyError): (BenchmarkSuite.prototype.RunSingleBenchmark): (RunNextSetup): (RunNextBenchmark): (RunNextTearDown): (BenchmarkSuite.prototype.RunStep): (GeneratePayloadTree): (GenerateKey): (SplayUpdateStats): (InsertNewNode): (SplaySetup): (SplayTearDown): (SplayRun): (SplayTree): (SplayTree.prototype.isEmpty): (SplayTree.prototype.insert): (SplayTree.prototype.remove): (SplayTree.prototype.find): (SplayTree.prototype.findMax): (SplayTree.prototype.findGreatestLessThan): (SplayTree.prototype.exportKeys): (SplayTree.prototype.splay_): (SplayTree.Node): (SplayTree.Node.prototype.traverse_): (jscSetUp): (jscTearDown): (jscRun): (averageAbovePercentile): (printPercentile): Source/JavaScriptCore: This turns the collector thread's workflow into a state machine, so that the mutator thread can run it directly. This reduces the amount of synchronization we do with the collector thread, and means that most apps will never start the collector thread. The collector thread will still start when we need to finish collecting and we don't have heap access. In this new world, "stopping the world" means relinquishing control of collection to the mutator. This means tracking who is conducting collection. I use the GCConductor enum to say who is conducting. It's either GCConductor::Mutator or GCConductor::Collector. I use the term "conn" to refer to the concept of conducting (having the conn, relinquishing the conn, taking the conn). So, stopping the world means giving the mutator the conn. Releasing heap access means giving the collector the conn. This meant bringing back the conservative scan of the calling thread. It turns out that this scan was too slow to be called on each GC increment because apparently setjmp() now does system calls. So, I wrote our own callee save register saving for the GC. Then I had doubts about whether or not it was correct, so I also made it so that the GC only rarely asks for the register state. I think we still want to use my register saving code instead of setjmp because setjmp seems to save things we don't need, and that could make us overly conservative. It turns out that this new scheduling discipline makes the old space-time scheduler perform better than the new stochastic space-time scheduler on systems with fewer than 4 cores. This is because the mutator having the conn enables us to time the mutator<->collector context switches by polling. The OS is never involved. So, we can use super precise timing. This allows the old space-time schduler to shine like it hadn't before. The splay results imply that this is all a good thing. On 2-core systems, this reduces pause times by 40% and it increases throughput about 5%. On 1-core systems, this reduces pause times by half and reduces throughput by 8%. On 4-or-more-core systems, this doesn't seem to have much effect. * CMakeLists.txt: * JavaScriptCore.xcodeproj/project.pbxproj: * bytecode/CodeBlock.cpp: (JSC::CodeBlock::visitChildren): * dfg/DFGWorklist.cpp: (JSC::DFG::Worklist::ThreadBody::ThreadBody): (JSC::DFG::Worklist::dump): (JSC::DFG::numberOfWorklists): (JSC::DFG::ensureWorklistForIndex): (JSC::DFG::existingWorklistForIndexOrNull): (JSC::DFG::existingWorklistForIndex): * dfg/DFGWorklist.h: (JSC::DFG::numberOfWorklists): Deleted. (JSC::DFG::ensureWorklistForIndex): Deleted. (JSC::DFG::existingWorklistForIndexOrNull): Deleted. (JSC::DFG::existingWorklistForIndex): Deleted. * heap/CollectingScope.h: Added. (JSC::CollectingScope::CollectingScope): (JSC::CollectingScope::~CollectingScope): * heap/CollectorPhase.cpp: Added. (JSC::worldShouldBeSuspended): (WTF::printInternal): * heap/CollectorPhase.h: Added. * heap/EdenGCActivityCallback.cpp: (JSC::EdenGCActivityCallback::lastGCLength): * heap/FullGCActivityCallback.cpp: (JSC::FullGCActivityCallback::doCollection): (JSC::FullGCActivityCallback::lastGCLength): * heap/GCConductor.cpp: Added. (JSC::gcConductorShortName): (WTF::printInternal): * heap/GCConductor.h: Added. * heap/GCFinalizationCallback.cpp: Added. (JSC::GCFinalizationCallback::GCFinalizationCallback): (JSC::GCFinalizationCallback::~GCFinalizationCallback): * heap/GCFinalizationCallback.h: Added. (JSC::GCFinalizationCallbackFuncAdaptor::GCFinalizationCallbackFuncAdaptor): (JSC::createGCFinalizationCallback): * heap/Heap.cpp: (JSC::Heap::Thread::Thread): (JSC::Heap::Heap): (JSC::Heap::lastChanceToFinalize): (JSC::Heap::gatherStackRoots): (JSC::Heap::updateObjectCounts): (JSC::Heap::sweepSynchronously): (JSC::Heap::collectAllGarbage): (JSC::Heap::collectAsync): (JSC::Heap::collectSync): (JSC::Heap::shouldCollectInCollectorThread): (JSC::Heap::collectInCollectorThread): (JSC::Heap::checkConn): (JSC::Heap::runNotRunningPhase): (JSC::Heap::runBeginPhase): (JSC::Heap::runFixpointPhase): (JSC::Heap::runConcurrentPhase): (JSC::Heap::runReloopPhase): (JSC::Heap::runEndPhase): (JSC::Heap::changePhase): (JSC::Heap::finishChangingPhase): (JSC::Heap::stopThePeriphery): (JSC::Heap::resumeThePeriphery): (JSC::Heap::stopTheMutator): (JSC::Heap::resumeTheMutator): (JSC::Heap::stopIfNecessarySlow): (JSC::Heap::collectInMutatorThread): (JSC::Heap::waitForCollector): (JSC::Heap::acquireAccessSlow): (JSC::Heap::releaseAccessSlow): (JSC::Heap::relinquishConn): (JSC::Heap::finishRelinquishingConn): (JSC::Heap::handleNeedFinalize): (JSC::Heap::notifyThreadStopping): (JSC::Heap::finalize): (JSC::Heap::addFinalizationCallback): (JSC::Heap::requestCollection): (JSC::Heap::waitForCollection): (JSC::Heap::updateAllocationLimits): (JSC::Heap::didFinishCollection): (JSC::Heap::collectIfNecessaryOrDefer): (JSC::Heap::notifyIsSafeToCollect): (JSC::Heap::preventCollection): (JSC::Heap::performIncrement): (JSC::Heap::markToFixpoint): Deleted. (JSC::Heap::shouldCollectInThread): Deleted. (JSC::Heap::collectInThread): Deleted. (JSC::Heap::stopTheWorld): Deleted. (JSC::Heap::resumeTheWorld): Deleted. * heap/Heap.h: (JSC::Heap::machineThreads): (JSC::Heap::lastFullGCLength): (JSC::Heap::lastEdenGCLength): (JSC::Heap::increaseLastFullGCLength): * heap/HeapInlines.h: (JSC::Heap::mutatorIsStopped): Deleted. * heap/HeapStatistics.cpp: Removed. * heap/HeapStatistics.h: Removed. * heap/HelpingGCScope.h: Removed. * heap/IncrementalSweeper.cpp: (JSC::IncrementalSweeper::stopSweeping): (JSC::IncrementalSweeper::willFinishSweeping): Deleted. * heap/IncrementalSweeper.h: * heap/MachineStackMarker.cpp: (JSC::MachineThreads::gatherFromCurrentThread): (JSC::MachineThreads::gatherConservativeRoots): (JSC::callWithCurrentThreadState): * heap/MachineStackMarker.h: * heap/MarkedAllocator.cpp: (JSC::MarkedAllocator::allocateSlowCaseImpl): * heap/MarkedBlock.cpp: (JSC::MarkedBlock::Handle::sweep): * heap/MarkedSpace.cpp: (JSC::MarkedSpace::sweep): * heap/MutatorState.cpp: (WTF::printInternal): * heap/MutatorState.h: * heap/RegisterState.h: Added. * heap/RunningScope.h: Added. (JSC::RunningScope::RunningScope): (JSC::RunningScope::~RunningScope): * heap/SlotVisitor.cpp: (JSC::SlotVisitor::SlotVisitor): (JSC::SlotVisitor::drain): (JSC::SlotVisitor::drainFromShared): (JSC::SlotVisitor::drainInParallelPassively): (JSC::SlotVisitor::donateAll): (JSC::SlotVisitor::donate): * heap/SlotVisitor.h: (JSC::SlotVisitor::codeName): * heap/StochasticSpaceTimeMutatorScheduler.cpp: (JSC::StochasticSpaceTimeMutatorScheduler::beginCollection): (JSC::StochasticSpaceTimeMutatorScheduler::synchronousDrainingDidStall): (JSC::StochasticSpaceTimeMutatorScheduler::timeToStop): * heap/SweepingScope.h: Added. (JSC::SweepingScope::SweepingScope): (JSC::SweepingScope::~SweepingScope): * jit/JITWorklist.cpp: (JSC::JITWorklist::Thread::Thread): * jsc.cpp: (GlobalObject::finishCreation): (functionFlashHeapAccess): * runtime/InitializeThreading.cpp: (JSC::initializeThreading): * runtime/JSCellInlines.h: (JSC::JSCell::classInfo): * runtime/Options.cpp: (JSC::overrideDefaults): * runtime/Options.h: * runtime/TestRunnerUtils.cpp: (JSC::finalizeStatsAtEndOfTesting): Source/WebCore: Added new tests in JSTests. The WebCore changes involve: - Refactoring around new header discipline. - Adding crazy GC APIs to window.internals to enable us to test the GC's runloop discipline. * ForwardingHeaders/heap/GCFinalizationCallback.h: Added. * ForwardingHeaders/heap/IncrementalSweeper.h: Added. * ForwardingHeaders/heap/MachineStackMarker.h: Added. * ForwardingHeaders/heap/RunningScope.h: Added. * bindings/js/CommonVM.cpp: * testing/Internals.cpp: (WebCore::Internals::parserMetaData): (WebCore::Internals::isReadableStreamDisturbed): (WebCore::Internals::isGCRunning): (WebCore::Internals::addGCFinalizationCallback): (WebCore::Internals::stopSweeping): (WebCore::Internals::startSweeping): * testing/Internals.h: * testing/Internals.idl: Source/WTF: Extend the use of AbstractLocker so that we can use more locking idioms. * wtf/AutomaticThread.cpp: (WTF::AutomaticThreadCondition::notifyOne): (WTF::AutomaticThreadCondition::notifyAll): (WTF::AutomaticThreadCondition::add): (WTF::AutomaticThreadCondition::remove): (WTF::AutomaticThreadCondition::contains): (WTF::AutomaticThread::AutomaticThread): (WTF::AutomaticThread::tryStop): (WTF::AutomaticThread::isWaiting): (WTF::AutomaticThread::notify): (WTF::AutomaticThread::start): (WTF::AutomaticThread::threadIsStopping): * wtf/AutomaticThread.h: * wtf/NumberOfCores.cpp: (WTF::numberOfProcessorCores): * wtf/ParallelHelperPool.cpp: (WTF::ParallelHelperClient::finish): (WTF::ParallelHelperClient::claimTask): (WTF::ParallelHelperPool::Thread::Thread): (WTF::ParallelHelperPool::didMakeWorkAvailable): (WTF::ParallelHelperPool::hasClientWithTask): (WTF::ParallelHelperPool::getClientWithTask): * wtf/ParallelHelperPool.h: Tools: Make more tests collect continuously. * Scripts/run-jsc-stress-tests: Canonical link: https://commits.webkit.org/185692@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@212778 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-02-22 00:58:15 +00:00
WTF_EXPORT_PRIVATE void notifyOne(const AbstractLocker&);
WTF_EXPORT_PRIVATE void notifyAll(const AbstractLocker&);
WTF should make it easier to create threads that die automatically after inactivity https://bugs.webkit.org/show_bug.cgi?id=163576 Reviewed by Andreas Kling. Source/JavaScriptCore: Added a sleepSeconds() function, which made it easier for me to test this change. The WTF changes in this patch change how the JSC GC manages threads: the GC threads will now shut down automatically after 1 second of inactivity. Maybe this will save some memory. * jsc.cpp: (GlobalObject::finishCreation): (functionSleepSeconds): Source/WTF: For a long time now, I've been adding threads to WTF/JSC and each time I do this, I feel guilty because those threads don't shut down when they are inactive. For example, in bug 163562, I need to add a new GC thread. There will be one of them per VM. This means that a JSC API client that starts a lot of VMs will have a lot of threads. I don't think that's good. A common pattern for all of these threads is that they have some well-defined trigger that causes them to run. This trigger has a lock, a condition variable, some logic that determines if there is work to do, and then of course the logic for the thread's actual work. The thread bodies usually look like this: void Thingy::runThread() { for (;;) { Work work; { LockHolder locker(m_lock); while (!hasWork()) m_cond.wait(m_lock); work = takeWork(); } doWork(work); } } If you look at ParallelHelperPool (the GC's threads) and DFG::Worklist (some of the JIT's threads), you will see this pattern. This change adds a new kind of thread, called AutomaticThread, that lets you write threads to this pattern while getting automatic thread shutdown for free: instead of just waiting on a condition variable, AutomaticThread will have a timeout that causes the thread to die. The condition variable associated with AutomaticThread, called AutomaticThreadCondition, is smart enough to restart any threads that have decided to stop due to inactivity. The inactivity threshold is current just 1 second. In this patch I only adopt AutomaticThread for ParallelHelperPool. I plan to adopt it in more places soon. * WTF.xcodeproj/project.pbxproj: * wtf/AutomaticThread.cpp: Added. (WTF::AutomaticThreadCondition::create): (WTF::AutomaticThreadCondition::AutomaticThreadCondition): (WTF::AutomaticThreadCondition::~AutomaticThreadCondition): (WTF::AutomaticThreadCondition::notifyAll): (WTF::AutomaticThreadCondition::add): (WTF::AutomaticThreadCondition::remove): (WTF::AutomaticThreadCondition::contains): (WTF::AutomaticThread::AutomaticThread): (WTF::AutomaticThread::~AutomaticThread): (WTF::AutomaticThread::join): (WTF::AutomaticThread::start): * wtf/AutomaticThread.h: Added. * wtf/CMakeLists.txt: * wtf/ParallelHelperPool.cpp: (WTF::ParallelHelperClient::ParallelHelperClient): (WTF::ParallelHelperClient::~ParallelHelperClient): (WTF::ParallelHelperClient::setTask): (WTF::ParallelHelperClient::finish): (WTF::ParallelHelperClient::doSomeHelping): (WTF::ParallelHelperClient::runTask): (WTF::ParallelHelperPool::ParallelHelperPool): (WTF::ParallelHelperPool::~ParallelHelperPool): (WTF::ParallelHelperPool::ensureThreads): (WTF::ParallelHelperPool::doSomeHelping): (WTF::ParallelHelperPool::Thread::Thread): (WTF::ParallelHelperPool::didMakeWorkAvailable): (WTF::ParallelHelperPool::helperThreadBody): Deleted. (WTF::ParallelHelperPool::waitForClientWithTask): Deleted. * wtf/ParallelHelperPool.h: Canonical link: https://commits.webkit.org/181393@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@207480 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-10-18 20:17:10 +00:00
Baseline JIT should use AutomaticThread https://bugs.webkit.org/show_bug.cgi?id=163686 Reviewed by Geoffrey Garen. Source/JavaScriptCore: Change the JITWorklist to use AutomaticThread, so that the Baseline JIT's concurrent compiler thread shuts down automatically after inactivity. With this change, all of JSC's threads shut down automatically. If you run splay for a few seconds (which fires up all threads - compiler and GC) and then go to sleep for a second, you'll see that the only threads left are the main thread and the bmalloc thread. * jit/JITWorklist.cpp: (JSC::JITWorklist::Thread::Thread): (JSC::JITWorklist::JITWorklist): (JSC::JITWorklist::completeAllForVM): (JSC::JITWorklist::poll): (JSC::JITWorklist::compileLater): (JSC::JITWorklist::compileNow): (JSC::JITWorklist::finalizePlans): (JSC::JITWorklist::runThread): Deleted. * jit/JITWorklist.h: Source/WTF: Added a AutomaticThreadCondition::wait() method, so that if you really want to use one common condition for your thread and something else, you can do it. This trivially works if you only use notifyAll(), and behaves as you'd expect for notifyOne() (i.e. it's dangerous, since you don't know who will wake up). The Baseline JIT used the one-true-Condition idiom because it used notifyAll() in an optimal way: there are just two threads talking to each other, so it wakes up at most one thread and that thread is exactly the one you want woken up. Adding wait() means that I did not have to change that code. * wtf/AutomaticThread.cpp: (WTF::AutomaticThreadCondition::wait): * wtf/AutomaticThread.h: Canonical link: https://commits.webkit.org/181474@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@207566 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-10-19 20:37:20 +00:00
// You can reuse this condition for other things, just as you would any other condition.
// However, since conflating conditions could lead to thundering herd, it's best to avoid it.
// One known-good case for one-true-condition is when the communication involves just two
// threads. In such cases, the thread doing the notifyAll() can wake up at most one thread -
// its partner.
WTF_EXPORT_PRIVATE void wait(Lock& lock) WTF_REQUIRES_LOCK(lock);
WTF_EXPORT_PRIVATE bool waitFor(Lock& lock, Seconds) WTF_REQUIRES_LOCK(lock);
Baseline JIT should use AutomaticThread https://bugs.webkit.org/show_bug.cgi?id=163686 Reviewed by Geoffrey Garen. Source/JavaScriptCore: Change the JITWorklist to use AutomaticThread, so that the Baseline JIT's concurrent compiler thread shuts down automatically after inactivity. With this change, all of JSC's threads shut down automatically. If you run splay for a few seconds (which fires up all threads - compiler and GC) and then go to sleep for a second, you'll see that the only threads left are the main thread and the bmalloc thread. * jit/JITWorklist.cpp: (JSC::JITWorklist::Thread::Thread): (JSC::JITWorklist::JITWorklist): (JSC::JITWorklist::completeAllForVM): (JSC::JITWorklist::poll): (JSC::JITWorklist::compileLater): (JSC::JITWorklist::compileNow): (JSC::JITWorklist::finalizePlans): (JSC::JITWorklist::runThread): Deleted. * jit/JITWorklist.h: Source/WTF: Added a AutomaticThreadCondition::wait() method, so that if you really want to use one common condition for your thread and something else, you can do it. This trivially works if you only use notifyAll(), and behaves as you'd expect for notifyOne() (i.e. it's dangerous, since you don't know who will wake up). The Baseline JIT used the one-true-Condition idiom because it used notifyAll() in an optimal way: there are just two threads talking to each other, so it wakes up at most one thread and that thread is exactly the one you want woken up. Adding wait() means that I did not have to change that code. * wtf/AutomaticThread.cpp: (WTF::AutomaticThreadCondition::wait): * wtf/AutomaticThread.h: Canonical link: https://commits.webkit.org/181474@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@207566 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-10-19 20:37:20 +00:00
WTF should make it easier to create threads that die automatically after inactivity https://bugs.webkit.org/show_bug.cgi?id=163576 Reviewed by Andreas Kling. Source/JavaScriptCore: Added a sleepSeconds() function, which made it easier for me to test this change. The WTF changes in this patch change how the JSC GC manages threads: the GC threads will now shut down automatically after 1 second of inactivity. Maybe this will save some memory. * jsc.cpp: (GlobalObject::finishCreation): (functionSleepSeconds): Source/WTF: For a long time now, I've been adding threads to WTF/JSC and each time I do this, I feel guilty because those threads don't shut down when they are inactive. For example, in bug 163562, I need to add a new GC thread. There will be one of them per VM. This means that a JSC API client that starts a lot of VMs will have a lot of threads. I don't think that's good. A common pattern for all of these threads is that they have some well-defined trigger that causes them to run. This trigger has a lock, a condition variable, some logic that determines if there is work to do, and then of course the logic for the thread's actual work. The thread bodies usually look like this: void Thingy::runThread() { for (;;) { Work work; { LockHolder locker(m_lock); while (!hasWork()) m_cond.wait(m_lock); work = takeWork(); } doWork(work); } } If you look at ParallelHelperPool (the GC's threads) and DFG::Worklist (some of the JIT's threads), you will see this pattern. This change adds a new kind of thread, called AutomaticThread, that lets you write threads to this pattern while getting automatic thread shutdown for free: instead of just waiting on a condition variable, AutomaticThread will have a timeout that causes the thread to die. The condition variable associated with AutomaticThread, called AutomaticThreadCondition, is smart enough to restart any threads that have decided to stop due to inactivity. The inactivity threshold is current just 1 second. In this patch I only adopt AutomaticThread for ParallelHelperPool. I plan to adopt it in more places soon. * WTF.xcodeproj/project.pbxproj: * wtf/AutomaticThread.cpp: Added. (WTF::AutomaticThreadCondition::create): (WTF::AutomaticThreadCondition::AutomaticThreadCondition): (WTF::AutomaticThreadCondition::~AutomaticThreadCondition): (WTF::AutomaticThreadCondition::notifyAll): (WTF::AutomaticThreadCondition::add): (WTF::AutomaticThreadCondition::remove): (WTF::AutomaticThreadCondition::contains): (WTF::AutomaticThread::AutomaticThread): (WTF::AutomaticThread::~AutomaticThread): (WTF::AutomaticThread::join): (WTF::AutomaticThread::start): * wtf/AutomaticThread.h: Added. * wtf/CMakeLists.txt: * wtf/ParallelHelperPool.cpp: (WTF::ParallelHelperClient::ParallelHelperClient): (WTF::ParallelHelperClient::~ParallelHelperClient): (WTF::ParallelHelperClient::setTask): (WTF::ParallelHelperClient::finish): (WTF::ParallelHelperClient::doSomeHelping): (WTF::ParallelHelperClient::runTask): (WTF::ParallelHelperPool::ParallelHelperPool): (WTF::ParallelHelperPool::~ParallelHelperPool): (WTF::ParallelHelperPool::ensureThreads): (WTF::ParallelHelperPool::doSomeHelping): (WTF::ParallelHelperPool::Thread::Thread): (WTF::ParallelHelperPool::didMakeWorkAvailable): (WTF::ParallelHelperPool::helperThreadBody): Deleted. (WTF::ParallelHelperPool::waitForClientWithTask): Deleted. * wtf/ParallelHelperPool.h: Canonical link: https://commits.webkit.org/181393@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@207480 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-10-18 20:17:10 +00:00
private:
friend class AutomaticThread;
WTF_EXPORT_PRIVATE AutomaticThreadCondition();
The collector thread should only start when the mutator doesn't have heap access https://bugs.webkit.org/show_bug.cgi?id=167737 Reviewed by Keith Miller. JSTests: Add versions of splay that flash heap access, to simulate what might happen if a third-party app was running concurrent GC. In this case, we might actually start the collector thread. * stress/splay-flash-access-1ms.js: Added. (performance.now): (this.Setup.setup.setup): (this.TearDown.tearDown.tearDown): (Benchmark): (BenchmarkResult): (BenchmarkResult.prototype.valueOf): (BenchmarkSuite): (alert): (Math.random): (BenchmarkSuite.ResetRNG): (RunStep): (BenchmarkSuite.RunSuites): (BenchmarkSuite.CountBenchmarks): (BenchmarkSuite.GeometricMean): (BenchmarkSuite.GeometricMeanTime): (BenchmarkSuite.AverageAbovePercentile): (BenchmarkSuite.GeometricMeanLatency): (BenchmarkSuite.FormatScore): (BenchmarkSuite.prototype.NotifyStep): (BenchmarkSuite.prototype.NotifyResult): (BenchmarkSuite.prototype.NotifyError): (BenchmarkSuite.prototype.RunSingleBenchmark): (RunNextSetup): (RunNextBenchmark): (RunNextTearDown): (BenchmarkSuite.prototype.RunStep): (GeneratePayloadTree): (GenerateKey): (SplayUpdateStats): (InsertNewNode): (SplaySetup): (SplayTearDown): (SplayRun): (SplayTree): (SplayTree.prototype.isEmpty): (SplayTree.prototype.insert): (SplayTree.prototype.remove): (SplayTree.prototype.find): (SplayTree.prototype.findMax): (SplayTree.prototype.findGreatestLessThan): (SplayTree.prototype.exportKeys): (SplayTree.prototype.splay_): (SplayTree.Node): (SplayTree.Node.prototype.traverse_): (jscSetUp): (jscTearDown): (jscRun): (averageAbovePercentile): (printPercentile): * stress/splay-flash-access.js: Added. (performance.now): (this.Setup.setup.setup): (this.TearDown.tearDown.tearDown): (Benchmark): (BenchmarkResult): (BenchmarkResult.prototype.valueOf): (BenchmarkSuite): (alert): (Math.random): (BenchmarkSuite.ResetRNG): (RunStep): (BenchmarkSuite.RunSuites): (BenchmarkSuite.CountBenchmarks): (BenchmarkSuite.GeometricMean): (BenchmarkSuite.GeometricMeanTime): (BenchmarkSuite.AverageAbovePercentile): (BenchmarkSuite.GeometricMeanLatency): (BenchmarkSuite.FormatScore): (BenchmarkSuite.prototype.NotifyStep): (BenchmarkSuite.prototype.NotifyResult): (BenchmarkSuite.prototype.NotifyError): (BenchmarkSuite.prototype.RunSingleBenchmark): (RunNextSetup): (RunNextBenchmark): (RunNextTearDown): (BenchmarkSuite.prototype.RunStep): (GeneratePayloadTree): (GenerateKey): (SplayUpdateStats): (InsertNewNode): (SplaySetup): (SplayTearDown): (SplayRun): (SplayTree): (SplayTree.prototype.isEmpty): (SplayTree.prototype.insert): (SplayTree.prototype.remove): (SplayTree.prototype.find): (SplayTree.prototype.findMax): (SplayTree.prototype.findGreatestLessThan): (SplayTree.prototype.exportKeys): (SplayTree.prototype.splay_): (SplayTree.Node): (SplayTree.Node.prototype.traverse_): (jscSetUp): (jscTearDown): (jscRun): (averageAbovePercentile): (printPercentile): Source/JavaScriptCore: This turns the collector thread's workflow into a state machine, so that the mutator thread can run it directly. This reduces the amount of synchronization we do with the collector thread, and means that most apps will never start the collector thread. The collector thread will still start when we need to finish collecting and we don't have heap access. In this new world, "stopping the world" means relinquishing control of collection to the mutator. This means tracking who is conducting collection. I use the GCConductor enum to say who is conducting. It's either GCConductor::Mutator or GCConductor::Collector. I use the term "conn" to refer to the concept of conducting (having the conn, relinquishing the conn, taking the conn). So, stopping the world means giving the mutator the conn. Releasing heap access means giving the collector the conn. This meant bringing back the conservative scan of the calling thread. It turns out that this scan was too slow to be called on each GC increment because apparently setjmp() now does system calls. So, I wrote our own callee save register saving for the GC. Then I had doubts about whether or not it was correct, so I also made it so that the GC only rarely asks for the register state. I think we still want to use my register saving code instead of setjmp because setjmp seems to save things we don't need, and that could make us overly conservative. It turns out that this new scheduling discipline makes the old space-time scheduler perform better than the new stochastic space-time scheduler on systems with fewer than 4 cores. This is because the mutator having the conn enables us to time the mutator<->collector context switches by polling. The OS is never involved. So, we can use super precise timing. This allows the old space-time schduler to shine like it hadn't before. The splay results imply that this is all a good thing. On 2-core systems, this reduces pause times by 40% and it increases throughput about 5%. On 1-core systems, this reduces pause times by half and reduces throughput by 8%. On 4-or-more-core systems, this doesn't seem to have much effect. * CMakeLists.txt: * JavaScriptCore.xcodeproj/project.pbxproj: * bytecode/CodeBlock.cpp: (JSC::CodeBlock::visitChildren): * dfg/DFGWorklist.cpp: (JSC::DFG::Worklist::ThreadBody::ThreadBody): (JSC::DFG::Worklist::dump): (JSC::DFG::numberOfWorklists): (JSC::DFG::ensureWorklistForIndex): (JSC::DFG::existingWorklistForIndexOrNull): (JSC::DFG::existingWorklistForIndex): * dfg/DFGWorklist.h: (JSC::DFG::numberOfWorklists): Deleted. (JSC::DFG::ensureWorklistForIndex): Deleted. (JSC::DFG::existingWorklistForIndexOrNull): Deleted. (JSC::DFG::existingWorklistForIndex): Deleted. * heap/CollectingScope.h: Added. (JSC::CollectingScope::CollectingScope): (JSC::CollectingScope::~CollectingScope): * heap/CollectorPhase.cpp: Added. (JSC::worldShouldBeSuspended): (WTF::printInternal): * heap/CollectorPhase.h: Added. * heap/EdenGCActivityCallback.cpp: (JSC::EdenGCActivityCallback::lastGCLength): * heap/FullGCActivityCallback.cpp: (JSC::FullGCActivityCallback::doCollection): (JSC::FullGCActivityCallback::lastGCLength): * heap/GCConductor.cpp: Added. (JSC::gcConductorShortName): (WTF::printInternal): * heap/GCConductor.h: Added. * heap/GCFinalizationCallback.cpp: Added. (JSC::GCFinalizationCallback::GCFinalizationCallback): (JSC::GCFinalizationCallback::~GCFinalizationCallback): * heap/GCFinalizationCallback.h: Added. (JSC::GCFinalizationCallbackFuncAdaptor::GCFinalizationCallbackFuncAdaptor): (JSC::createGCFinalizationCallback): * heap/Heap.cpp: (JSC::Heap::Thread::Thread): (JSC::Heap::Heap): (JSC::Heap::lastChanceToFinalize): (JSC::Heap::gatherStackRoots): (JSC::Heap::updateObjectCounts): (JSC::Heap::sweepSynchronously): (JSC::Heap::collectAllGarbage): (JSC::Heap::collectAsync): (JSC::Heap::collectSync): (JSC::Heap::shouldCollectInCollectorThread): (JSC::Heap::collectInCollectorThread): (JSC::Heap::checkConn): (JSC::Heap::runNotRunningPhase): (JSC::Heap::runBeginPhase): (JSC::Heap::runFixpointPhase): (JSC::Heap::runConcurrentPhase): (JSC::Heap::runReloopPhase): (JSC::Heap::runEndPhase): (JSC::Heap::changePhase): (JSC::Heap::finishChangingPhase): (JSC::Heap::stopThePeriphery): (JSC::Heap::resumeThePeriphery): (JSC::Heap::stopTheMutator): (JSC::Heap::resumeTheMutator): (JSC::Heap::stopIfNecessarySlow): (JSC::Heap::collectInMutatorThread): (JSC::Heap::waitForCollector): (JSC::Heap::acquireAccessSlow): (JSC::Heap::releaseAccessSlow): (JSC::Heap::relinquishConn): (JSC::Heap::finishRelinquishingConn): (JSC::Heap::handleNeedFinalize): (JSC::Heap::notifyThreadStopping): (JSC::Heap::finalize): (JSC::Heap::addFinalizationCallback): (JSC::Heap::requestCollection): (JSC::Heap::waitForCollection): (JSC::Heap::updateAllocationLimits): (JSC::Heap::didFinishCollection): (JSC::Heap::collectIfNecessaryOrDefer): (JSC::Heap::notifyIsSafeToCollect): (JSC::Heap::preventCollection): (JSC::Heap::performIncrement): (JSC::Heap::markToFixpoint): Deleted. (JSC::Heap::shouldCollectInThread): Deleted. (JSC::Heap::collectInThread): Deleted. (JSC::Heap::stopTheWorld): Deleted. (JSC::Heap::resumeTheWorld): Deleted. * heap/Heap.h: (JSC::Heap::machineThreads): (JSC::Heap::lastFullGCLength): (JSC::Heap::lastEdenGCLength): (JSC::Heap::increaseLastFullGCLength): * heap/HeapInlines.h: (JSC::Heap::mutatorIsStopped): Deleted. * heap/HeapStatistics.cpp: Removed. * heap/HeapStatistics.h: Removed. * heap/HelpingGCScope.h: Removed. * heap/IncrementalSweeper.cpp: (JSC::IncrementalSweeper::stopSweeping): (JSC::IncrementalSweeper::willFinishSweeping): Deleted. * heap/IncrementalSweeper.h: * heap/MachineStackMarker.cpp: (JSC::MachineThreads::gatherFromCurrentThread): (JSC::MachineThreads::gatherConservativeRoots): (JSC::callWithCurrentThreadState): * heap/MachineStackMarker.h: * heap/MarkedAllocator.cpp: (JSC::MarkedAllocator::allocateSlowCaseImpl): * heap/MarkedBlock.cpp: (JSC::MarkedBlock::Handle::sweep): * heap/MarkedSpace.cpp: (JSC::MarkedSpace::sweep): * heap/MutatorState.cpp: (WTF::printInternal): * heap/MutatorState.h: * heap/RegisterState.h: Added. * heap/RunningScope.h: Added. (JSC::RunningScope::RunningScope): (JSC::RunningScope::~RunningScope): * heap/SlotVisitor.cpp: (JSC::SlotVisitor::SlotVisitor): (JSC::SlotVisitor::drain): (JSC::SlotVisitor::drainFromShared): (JSC::SlotVisitor::drainInParallelPassively): (JSC::SlotVisitor::donateAll): (JSC::SlotVisitor::donate): * heap/SlotVisitor.h: (JSC::SlotVisitor::codeName): * heap/StochasticSpaceTimeMutatorScheduler.cpp: (JSC::StochasticSpaceTimeMutatorScheduler::beginCollection): (JSC::StochasticSpaceTimeMutatorScheduler::synchronousDrainingDidStall): (JSC::StochasticSpaceTimeMutatorScheduler::timeToStop): * heap/SweepingScope.h: Added. (JSC::SweepingScope::SweepingScope): (JSC::SweepingScope::~SweepingScope): * jit/JITWorklist.cpp: (JSC::JITWorklist::Thread::Thread): * jsc.cpp: (GlobalObject::finishCreation): (functionFlashHeapAccess): * runtime/InitializeThreading.cpp: (JSC::initializeThreading): * runtime/JSCellInlines.h: (JSC::JSCell::classInfo): * runtime/Options.cpp: (JSC::overrideDefaults): * runtime/Options.h: * runtime/TestRunnerUtils.cpp: (JSC::finalizeStatsAtEndOfTesting): Source/WebCore: Added new tests in JSTests. The WebCore changes involve: - Refactoring around new header discipline. - Adding crazy GC APIs to window.internals to enable us to test the GC's runloop discipline. * ForwardingHeaders/heap/GCFinalizationCallback.h: Added. * ForwardingHeaders/heap/IncrementalSweeper.h: Added. * ForwardingHeaders/heap/MachineStackMarker.h: Added. * ForwardingHeaders/heap/RunningScope.h: Added. * bindings/js/CommonVM.cpp: * testing/Internals.cpp: (WebCore::Internals::parserMetaData): (WebCore::Internals::isReadableStreamDisturbed): (WebCore::Internals::isGCRunning): (WebCore::Internals::addGCFinalizationCallback): (WebCore::Internals::stopSweeping): (WebCore::Internals::startSweeping): * testing/Internals.h: * testing/Internals.idl: Source/WTF: Extend the use of AbstractLocker so that we can use more locking idioms. * wtf/AutomaticThread.cpp: (WTF::AutomaticThreadCondition::notifyOne): (WTF::AutomaticThreadCondition::notifyAll): (WTF::AutomaticThreadCondition::add): (WTF::AutomaticThreadCondition::remove): (WTF::AutomaticThreadCondition::contains): (WTF::AutomaticThread::AutomaticThread): (WTF::AutomaticThread::tryStop): (WTF::AutomaticThread::isWaiting): (WTF::AutomaticThread::notify): (WTF::AutomaticThread::start): (WTF::AutomaticThread::threadIsStopping): * wtf/AutomaticThread.h: * wtf/NumberOfCores.cpp: (WTF::numberOfProcessorCores): * wtf/ParallelHelperPool.cpp: (WTF::ParallelHelperClient::finish): (WTF::ParallelHelperClient::claimTask): (WTF::ParallelHelperPool::Thread::Thread): (WTF::ParallelHelperPool::didMakeWorkAvailable): (WTF::ParallelHelperPool::hasClientWithTask): (WTF::ParallelHelperPool::getClientWithTask): * wtf/ParallelHelperPool.h: Tools: Make more tests collect continuously. * Scripts/run-jsc-stress-tests: Canonical link: https://commits.webkit.org/185692@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@212778 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-02-22 00:58:15 +00:00
void add(const AbstractLocker&, AutomaticThread*);
void remove(const AbstractLocker&, AutomaticThread*);
bool contains(const AbstractLocker&, AutomaticThread*);
WTF should make it easier to create threads that die automatically after inactivity https://bugs.webkit.org/show_bug.cgi?id=163576 Reviewed by Andreas Kling. Source/JavaScriptCore: Added a sleepSeconds() function, which made it easier for me to test this change. The WTF changes in this patch change how the JSC GC manages threads: the GC threads will now shut down automatically after 1 second of inactivity. Maybe this will save some memory. * jsc.cpp: (GlobalObject::finishCreation): (functionSleepSeconds): Source/WTF: For a long time now, I've been adding threads to WTF/JSC and each time I do this, I feel guilty because those threads don't shut down when they are inactive. For example, in bug 163562, I need to add a new GC thread. There will be one of them per VM. This means that a JSC API client that starts a lot of VMs will have a lot of threads. I don't think that's good. A common pattern for all of these threads is that they have some well-defined trigger that causes them to run. This trigger has a lock, a condition variable, some logic that determines if there is work to do, and then of course the logic for the thread's actual work. The thread bodies usually look like this: void Thingy::runThread() { for (;;) { Work work; { LockHolder locker(m_lock); while (!hasWork()) m_cond.wait(m_lock); work = takeWork(); } doWork(work); } } If you look at ParallelHelperPool (the GC's threads) and DFG::Worklist (some of the JIT's threads), you will see this pattern. This change adds a new kind of thread, called AutomaticThread, that lets you write threads to this pattern while getting automatic thread shutdown for free: instead of just waiting on a condition variable, AutomaticThread will have a timeout that causes the thread to die. The condition variable associated with AutomaticThread, called AutomaticThreadCondition, is smart enough to restart any threads that have decided to stop due to inactivity. The inactivity threshold is current just 1 second. In this patch I only adopt AutomaticThread for ParallelHelperPool. I plan to adopt it in more places soon. * WTF.xcodeproj/project.pbxproj: * wtf/AutomaticThread.cpp: Added. (WTF::AutomaticThreadCondition::create): (WTF::AutomaticThreadCondition::AutomaticThreadCondition): (WTF::AutomaticThreadCondition::~AutomaticThreadCondition): (WTF::AutomaticThreadCondition::notifyAll): (WTF::AutomaticThreadCondition::add): (WTF::AutomaticThreadCondition::remove): (WTF::AutomaticThreadCondition::contains): (WTF::AutomaticThread::AutomaticThread): (WTF::AutomaticThread::~AutomaticThread): (WTF::AutomaticThread::join): (WTF::AutomaticThread::start): * wtf/AutomaticThread.h: Added. * wtf/CMakeLists.txt: * wtf/ParallelHelperPool.cpp: (WTF::ParallelHelperClient::ParallelHelperClient): (WTF::ParallelHelperClient::~ParallelHelperClient): (WTF::ParallelHelperClient::setTask): (WTF::ParallelHelperClient::finish): (WTF::ParallelHelperClient::doSomeHelping): (WTF::ParallelHelperClient::runTask): (WTF::ParallelHelperPool::ParallelHelperPool): (WTF::ParallelHelperPool::~ParallelHelperPool): (WTF::ParallelHelperPool::ensureThreads): (WTF::ParallelHelperPool::doSomeHelping): (WTF::ParallelHelperPool::Thread::Thread): (WTF::ParallelHelperPool::didMakeWorkAvailable): (WTF::ParallelHelperPool::helperThreadBody): Deleted. (WTF::ParallelHelperPool::waitForClientWithTask): Deleted. * wtf/ParallelHelperPool.h: Canonical link: https://commits.webkit.org/181393@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@207480 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-10-18 20:17:10 +00:00
Condition m_condition;
WTF should make it easier to create threads that die automatically after inactivity https://bugs.webkit.org/show_bug.cgi?id=163576 Reviewed by Andreas Kling. Source/JavaScriptCore: Added a sleepSeconds() function, which made it easier for me to test this change. The WTF changes in this patch change how the JSC GC manages threads: the GC threads will now shut down automatically after 1 second of inactivity. Maybe this will save some memory. * jsc.cpp: (GlobalObject::finishCreation): (functionSleepSeconds): Source/WTF: For a long time now, I've been adding threads to WTF/JSC and each time I do this, I feel guilty because those threads don't shut down when they are inactive. For example, in bug 163562, I need to add a new GC thread. There will be one of them per VM. This means that a JSC API client that starts a lot of VMs will have a lot of threads. I don't think that's good. A common pattern for all of these threads is that they have some well-defined trigger that causes them to run. This trigger has a lock, a condition variable, some logic that determines if there is work to do, and then of course the logic for the thread's actual work. The thread bodies usually look like this: void Thingy::runThread() { for (;;) { Work work; { LockHolder locker(m_lock); while (!hasWork()) m_cond.wait(m_lock); work = takeWork(); } doWork(work); } } If you look at ParallelHelperPool (the GC's threads) and DFG::Worklist (some of the JIT's threads), you will see this pattern. This change adds a new kind of thread, called AutomaticThread, that lets you write threads to this pattern while getting automatic thread shutdown for free: instead of just waiting on a condition variable, AutomaticThread will have a timeout that causes the thread to die. The condition variable associated with AutomaticThread, called AutomaticThreadCondition, is smart enough to restart any threads that have decided to stop due to inactivity. The inactivity threshold is current just 1 second. In this patch I only adopt AutomaticThread for ParallelHelperPool. I plan to adopt it in more places soon. * WTF.xcodeproj/project.pbxproj: * wtf/AutomaticThread.cpp: Added. (WTF::AutomaticThreadCondition::create): (WTF::AutomaticThreadCondition::AutomaticThreadCondition): (WTF::AutomaticThreadCondition::~AutomaticThreadCondition): (WTF::AutomaticThreadCondition::notifyAll): (WTF::AutomaticThreadCondition::add): (WTF::AutomaticThreadCondition::remove): (WTF::AutomaticThreadCondition::contains): (WTF::AutomaticThread::AutomaticThread): (WTF::AutomaticThread::~AutomaticThread): (WTF::AutomaticThread::join): (WTF::AutomaticThread::start): * wtf/AutomaticThread.h: Added. * wtf/CMakeLists.txt: * wtf/ParallelHelperPool.cpp: (WTF::ParallelHelperClient::ParallelHelperClient): (WTF::ParallelHelperClient::~ParallelHelperClient): (WTF::ParallelHelperClient::setTask): (WTF::ParallelHelperClient::finish): (WTF::ParallelHelperClient::doSomeHelping): (WTF::ParallelHelperClient::runTask): (WTF::ParallelHelperPool::ParallelHelperPool): (WTF::ParallelHelperPool::~ParallelHelperPool): (WTF::ParallelHelperPool::ensureThreads): (WTF::ParallelHelperPool::doSomeHelping): (WTF::ParallelHelperPool::Thread::Thread): (WTF::ParallelHelperPool::didMakeWorkAvailable): (WTF::ParallelHelperPool::helperThreadBody): Deleted. (WTF::ParallelHelperPool::waitForClientWithTask): Deleted. * wtf/ParallelHelperPool.h: Canonical link: https://commits.webkit.org/181393@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@207480 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-10-18 20:17:10 +00:00
Vector<AutomaticThread*> m_threads;
};
class WTF_EXPORT_PRIVATE AutomaticThread : public ThreadSafeRefCounted<AutomaticThread> {
public:
// Note that if you drop all of your references to an AutomaticThread then as soon as there is a
// timeout during which it doesn't get woken up, it will simply die on its own. This is a
WTF should make it easier to create threads that die automatically after inactivity https://bugs.webkit.org/show_bug.cgi?id=163576 Reviewed by Andreas Kling. Source/JavaScriptCore: Added a sleepSeconds() function, which made it easier for me to test this change. The WTF changes in this patch change how the JSC GC manages threads: the GC threads will now shut down automatically after 1 second of inactivity. Maybe this will save some memory. * jsc.cpp: (GlobalObject::finishCreation): (functionSleepSeconds): Source/WTF: For a long time now, I've been adding threads to WTF/JSC and each time I do this, I feel guilty because those threads don't shut down when they are inactive. For example, in bug 163562, I need to add a new GC thread. There will be one of them per VM. This means that a JSC API client that starts a lot of VMs will have a lot of threads. I don't think that's good. A common pattern for all of these threads is that they have some well-defined trigger that causes them to run. This trigger has a lock, a condition variable, some logic that determines if there is work to do, and then of course the logic for the thread's actual work. The thread bodies usually look like this: void Thingy::runThread() { for (;;) { Work work; { LockHolder locker(m_lock); while (!hasWork()) m_cond.wait(m_lock); work = takeWork(); } doWork(work); } } If you look at ParallelHelperPool (the GC's threads) and DFG::Worklist (some of the JIT's threads), you will see this pattern. This change adds a new kind of thread, called AutomaticThread, that lets you write threads to this pattern while getting automatic thread shutdown for free: instead of just waiting on a condition variable, AutomaticThread will have a timeout that causes the thread to die. The condition variable associated with AutomaticThread, called AutomaticThreadCondition, is smart enough to restart any threads that have decided to stop due to inactivity. The inactivity threshold is current just 1 second. In this patch I only adopt AutomaticThread for ParallelHelperPool. I plan to adopt it in more places soon. * WTF.xcodeproj/project.pbxproj: * wtf/AutomaticThread.cpp: Added. (WTF::AutomaticThreadCondition::create): (WTF::AutomaticThreadCondition::AutomaticThreadCondition): (WTF::AutomaticThreadCondition::~AutomaticThreadCondition): (WTF::AutomaticThreadCondition::notifyAll): (WTF::AutomaticThreadCondition::add): (WTF::AutomaticThreadCondition::remove): (WTF::AutomaticThreadCondition::contains): (WTF::AutomaticThread::AutomaticThread): (WTF::AutomaticThread::~AutomaticThread): (WTF::AutomaticThread::join): (WTF::AutomaticThread::start): * wtf/AutomaticThread.h: Added. * wtf/CMakeLists.txt: * wtf/ParallelHelperPool.cpp: (WTF::ParallelHelperClient::ParallelHelperClient): (WTF::ParallelHelperClient::~ParallelHelperClient): (WTF::ParallelHelperClient::setTask): (WTF::ParallelHelperClient::finish): (WTF::ParallelHelperClient::doSomeHelping): (WTF::ParallelHelperClient::runTask): (WTF::ParallelHelperPool::ParallelHelperPool): (WTF::ParallelHelperPool::~ParallelHelperPool): (WTF::ParallelHelperPool::ensureThreads): (WTF::ParallelHelperPool::doSomeHelping): (WTF::ParallelHelperPool::Thread::Thread): (WTF::ParallelHelperPool::didMakeWorkAvailable): (WTF::ParallelHelperPool::helperThreadBody): Deleted. (WTF::ParallelHelperPool::waitForClientWithTask): Deleted. * wtf/ParallelHelperPool.h: Canonical link: https://commits.webkit.org/181393@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@207480 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-10-18 20:17:10 +00:00
// permanent kind of death where the AutomaticThread object goes away, rather than the temporary
// kind of death where AutomaticThread lives but its underlying thread dies. All you have to do
// to prevent permanent death is keep a ref to AutomaticThread. At time of writing, every user of
// AutomaticThread keeps a ref to it and does join() as part of the shutdown process, so only the
// temporary kind of automatic death happens in practice. We keep the permanent death feature
// because it leads to an easy-to-understand reference counting discipline (AutomaticThread holds
// strong ref to AutomaticThreadCondition and the underlying thread holds a strong ref to
// AutomaticThread).
virtual ~AutomaticThread();
The GC should be in a thread https://bugs.webkit.org/show_bug.cgi?id=163562 Reviewed by Geoffrey Garen and Andreas Kling. Source/JavaScriptCore: In a concurrent GC, the work of collecting happens on a separate thread. This patch implements this, and schedules the thread the way that a concurrent GC thread would be scheduled. But, the GC isn't actually concurrent yet because it calls stopTheWorld() before doing anything and calls resumeTheWorld() after it's done with everything. The next step will be to make it really concurrent by basically calling stopTheWorld()/resumeTheWorld() around bounded snippets of work while making most of the work happen with the world running. Our GC will probably always have stop-the-world phases because the semantics of JSC weak references call for it. This implements concurrent GC scheduling. This means that there is no longer a Heap::collect() API. Instead, you can call collectAsync() which makes sure that a GC is scheduled (it will do nothing if one is scheduled or ongoing) or you can call collectSync() to schedule a GC and wait for it to happen. I made our debugging stuff call collectSync(). It should be a goal to never call collectSync() except for debugging or benchmark harness hacks. The collector thread is an AutomaticThread, so it won't linger when not in use. It works on a ticket-based system, like you would see at the DMV. A ticket is a 64-bit integer. There are two ticket counters: last granted and last served. When you request a collection, last granted is incremented and its new value given to you. When a collection completes, last served is incremented. collectSync() waits until last served catches up to what last granted had been at the time you requested a GC. This means that if you request a sync GC in the middle of an async GC, you will wait for that async GC to finish and then you will request and wait for your sync GC. The synchronization between the collector thread and the main threads is complex. The collector thread needs to be able to ask the main thread to stop. It needs to be able to do some post-GC clean-up, like the synchronous CodeBlock and LargeAllocation sweeps, on the main thread. The collector needs to be able to ask the main thread to execute a cross-modifying code fence before running any JIT code, since the GC might aid the JIT worklist and run JIT finalization. It's possible for the GC to want the main thread to run something at the same time that the main thread wants to wait for the GC. The main thread needs to be able to run non-JSC stuff without causing the GC to completely stall. The main thread needs to be able to query its own state (is there a request to stop?) and change it (running JSC versus not) quickly, since this may happen on hot paths. This kind of intertwined system of requests, notifications, and state changes requires a combination of lock-free algorithms and waiting. So, this is all implemented using a Atomic<unsigned> Heap::m_worldState, which has bits to represent things being requested by the collector and the heap access state of the mutator. I am borrowing a lot of terms that I've seen in other VMs that I've worked on. Here's what they mean: - Stop the world: make sure that either the mutator is not running, or that it's not running code that could mess with the heap. - Heap access: the mutator is said to have heap access if it could mess with the heap. If you stop the world and the mutator doesn't have heap access, all you're doing is making sure that it will block when it tries to acquire heap access. This means that our GC is already fully concurrent in cases where the GC is requested while the mutator has no heap access. This probably won't happen, but if it did then it should just work. Usually, stopping the world means that we state our shouldStop request with m_worldState, and a future call to Heap::stopIfNecessary() will go to slow path and stop. The act of stopping or waiting to acquire heap access is managed by using ParkingLot API directly on m_worldState. This works out great because it would be very awkward to get the same functionality using locks and condition variables, since we want stopIfNecessary/acquireAccess/requestAccess fast paths that are single atomic instructions (load/CAS/CAS, respectively). The mutator will call these things frequently. Currently we have Heap::stopIfNecessary() polling on every allocator slow path, but we may want to make it even more frequent than that. Currently only JSC API clients benefit from the heap access optimization. The DOM forces us to assume that heap access is permanently on, since DOM manipulation doesn't always hold the JSLock. We could still allow the GC to proceed when the runloop is idle by having the GC put a task on the runloop that just calls stopIfNecessary(). This is perf neutral. The only behavior change that clients ought to observe is that marking and the weak fixpoint happen on a separate thread. Marking was already parallel so it already handled multiple threads, but now it _never_ runs on the main thread. The weak fixpoint needed some help to be able to run on another thread - mostly because there was some code in IndexedDB that was using thread specifics in the weak fixpoint. * API/JSBase.cpp: (JSSynchronousEdenCollectForDebugging): * API/JSManagedValue.mm: (-[JSManagedValue initWithValue:]): * heap/EdenGCActivityCallback.cpp: (JSC::EdenGCActivityCallback::doCollection): * heap/FullGCActivityCallback.cpp: (JSC::FullGCActivityCallback::doCollection): * heap/Heap.cpp: (JSC::Heap::Thread::Thread): (JSC::Heap::Heap): (JSC::Heap::lastChanceToFinalize): (JSC::Heap::markRoots): (JSC::Heap::gatherStackRoots): (JSC::Heap::deleteUnmarkedCompiledCode): (JSC::Heap::collectAllGarbage): (JSC::Heap::collectAsync): (JSC::Heap::collectSync): (JSC::Heap::shouldCollectInThread): (JSC::Heap::collectInThread): (JSC::Heap::stopTheWorld): (JSC::Heap::resumeTheWorld): (JSC::Heap::stopIfNecessarySlow): (JSC::Heap::acquireAccessSlow): (JSC::Heap::releaseAccessSlow): (JSC::Heap::handleDidJIT): (JSC::Heap::handleNeedFinalize): (JSC::Heap::setDidJIT): (JSC::Heap::setNeedFinalize): (JSC::Heap::waitWhileNeedFinalize): (JSC::Heap::finalize): (JSC::Heap::requestCollection): (JSC::Heap::waitForCollection): (JSC::Heap::didFinishCollection): (JSC::Heap::canCollect): (JSC::Heap::shouldCollectHeuristic): (JSC::Heap::shouldCollect): (JSC::Heap::collectIfNecessaryOrDefer): (JSC::Heap::collectAccordingToDeferGCProbability): (JSC::Heap::collect): Deleted. (JSC::Heap::collectWithoutAnySweep): Deleted. (JSC::Heap::collectImpl): Deleted. * heap/Heap.h: (JSC::Heap::ReleaseAccessScope::ReleaseAccessScope): (JSC::Heap::ReleaseAccessScope::~ReleaseAccessScope): * heap/HeapInlines.h: (JSC::Heap::acquireAccess): (JSC::Heap::releaseAccess): (JSC::Heap::stopIfNecessary): * heap/MachineStackMarker.cpp: (JSC::MachineThreads::gatherConservativeRoots): (JSC::MachineThreads::gatherFromCurrentThread): Deleted. * heap/MachineStackMarker.h: * jit/JITWorklist.cpp: (JSC::JITWorklist::completeAllForVM): * jit/JITWorklist.h: * jsc.cpp: (functionFullGC): (functionEdenGC): * runtime/InitializeThreading.cpp: (JSC::initializeThreading): * runtime/JSLock.cpp: (JSC::JSLock::didAcquireLock): (JSC::JSLock::unlock): (JSC::JSLock::willReleaseLock): * tools/JSDollarVMPrototype.cpp: (JSC::JSDollarVMPrototype::edenGC): Source/WebCore: No new tests because existing tests cover this. We now need to be more careful about using JSLock. This fixes some places that were not holding it. New assertions in the GC are more likely to catch this than before. * bindings/js/WorkerScriptController.cpp: (WebCore::WorkerScriptController::WorkerScriptController): Source/WTF: This fixes some bugs and adds a few features. * wtf/Atomics.h: The GC may do work on behalf of the JIT. If it does, the main thread needs to execute a cross-modifying code fence. This is cpuid on x86 and I believe it's isb on ARM. It would have been an isync on PPC and I think that isb is the ARM equivalent. (WTF::arm_isb): (WTF::crossModifyingCodeFence): (WTF::x86_ortop): (WTF::x86_cpuid): * wtf/AutomaticThread.cpp: I accidentally had AutomaticThreadCondition inherit from ThreadSafeRefCounted<AutomaticThread> [sic]. This never crashed before because all of our prior AutomaticThreadConditions were immortal. (WTF::AutomaticThread::AutomaticThread): (WTF::AutomaticThread::~AutomaticThread): (WTF::AutomaticThread::start): * wtf/AutomaticThread.h: * wtf/MainThread.cpp: Need to allow initializeGCThreads() to be called separately because it's now more than just a debugging thing. (WTF::initializeGCThreads): Canonical link: https://commits.webkit.org/182065@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@208306 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-11-02 22:01:04 +00:00
// Sometimes it's possible to optimize for the case that there is no underlying thread.
The collector thread should only start when the mutator doesn't have heap access https://bugs.webkit.org/show_bug.cgi?id=167737 Reviewed by Keith Miller. JSTests: Add versions of splay that flash heap access, to simulate what might happen if a third-party app was running concurrent GC. In this case, we might actually start the collector thread. * stress/splay-flash-access-1ms.js: Added. (performance.now): (this.Setup.setup.setup): (this.TearDown.tearDown.tearDown): (Benchmark): (BenchmarkResult): (BenchmarkResult.prototype.valueOf): (BenchmarkSuite): (alert): (Math.random): (BenchmarkSuite.ResetRNG): (RunStep): (BenchmarkSuite.RunSuites): (BenchmarkSuite.CountBenchmarks): (BenchmarkSuite.GeometricMean): (BenchmarkSuite.GeometricMeanTime): (BenchmarkSuite.AverageAbovePercentile): (BenchmarkSuite.GeometricMeanLatency): (BenchmarkSuite.FormatScore): (BenchmarkSuite.prototype.NotifyStep): (BenchmarkSuite.prototype.NotifyResult): (BenchmarkSuite.prototype.NotifyError): (BenchmarkSuite.prototype.RunSingleBenchmark): (RunNextSetup): (RunNextBenchmark): (RunNextTearDown): (BenchmarkSuite.prototype.RunStep): (GeneratePayloadTree): (GenerateKey): (SplayUpdateStats): (InsertNewNode): (SplaySetup): (SplayTearDown): (SplayRun): (SplayTree): (SplayTree.prototype.isEmpty): (SplayTree.prototype.insert): (SplayTree.prototype.remove): (SplayTree.prototype.find): (SplayTree.prototype.findMax): (SplayTree.prototype.findGreatestLessThan): (SplayTree.prototype.exportKeys): (SplayTree.prototype.splay_): (SplayTree.Node): (SplayTree.Node.prototype.traverse_): (jscSetUp): (jscTearDown): (jscRun): (averageAbovePercentile): (printPercentile): * stress/splay-flash-access.js: Added. (performance.now): (this.Setup.setup.setup): (this.TearDown.tearDown.tearDown): (Benchmark): (BenchmarkResult): (BenchmarkResult.prototype.valueOf): (BenchmarkSuite): (alert): (Math.random): (BenchmarkSuite.ResetRNG): (RunStep): (BenchmarkSuite.RunSuites): (BenchmarkSuite.CountBenchmarks): (BenchmarkSuite.GeometricMean): (BenchmarkSuite.GeometricMeanTime): (BenchmarkSuite.AverageAbovePercentile): (BenchmarkSuite.GeometricMeanLatency): (BenchmarkSuite.FormatScore): (BenchmarkSuite.prototype.NotifyStep): (BenchmarkSuite.prototype.NotifyResult): (BenchmarkSuite.prototype.NotifyError): (BenchmarkSuite.prototype.RunSingleBenchmark): (RunNextSetup): (RunNextBenchmark): (RunNextTearDown): (BenchmarkSuite.prototype.RunStep): (GeneratePayloadTree): (GenerateKey): (SplayUpdateStats): (InsertNewNode): (SplaySetup): (SplayTearDown): (SplayRun): (SplayTree): (SplayTree.prototype.isEmpty): (SplayTree.prototype.insert): (SplayTree.prototype.remove): (SplayTree.prototype.find): (SplayTree.prototype.findMax): (SplayTree.prototype.findGreatestLessThan): (SplayTree.prototype.exportKeys): (SplayTree.prototype.splay_): (SplayTree.Node): (SplayTree.Node.prototype.traverse_): (jscSetUp): (jscTearDown): (jscRun): (averageAbovePercentile): (printPercentile): Source/JavaScriptCore: This turns the collector thread's workflow into a state machine, so that the mutator thread can run it directly. This reduces the amount of synchronization we do with the collector thread, and means that most apps will never start the collector thread. The collector thread will still start when we need to finish collecting and we don't have heap access. In this new world, "stopping the world" means relinquishing control of collection to the mutator. This means tracking who is conducting collection. I use the GCConductor enum to say who is conducting. It's either GCConductor::Mutator or GCConductor::Collector. I use the term "conn" to refer to the concept of conducting (having the conn, relinquishing the conn, taking the conn). So, stopping the world means giving the mutator the conn. Releasing heap access means giving the collector the conn. This meant bringing back the conservative scan of the calling thread. It turns out that this scan was too slow to be called on each GC increment because apparently setjmp() now does system calls. So, I wrote our own callee save register saving for the GC. Then I had doubts about whether or not it was correct, so I also made it so that the GC only rarely asks for the register state. I think we still want to use my register saving code instead of setjmp because setjmp seems to save things we don't need, and that could make us overly conservative. It turns out that this new scheduling discipline makes the old space-time scheduler perform better than the new stochastic space-time scheduler on systems with fewer than 4 cores. This is because the mutator having the conn enables us to time the mutator<->collector context switches by polling. The OS is never involved. So, we can use super precise timing. This allows the old space-time schduler to shine like it hadn't before. The splay results imply that this is all a good thing. On 2-core systems, this reduces pause times by 40% and it increases throughput about 5%. On 1-core systems, this reduces pause times by half and reduces throughput by 8%. On 4-or-more-core systems, this doesn't seem to have much effect. * CMakeLists.txt: * JavaScriptCore.xcodeproj/project.pbxproj: * bytecode/CodeBlock.cpp: (JSC::CodeBlock::visitChildren): * dfg/DFGWorklist.cpp: (JSC::DFG::Worklist::ThreadBody::ThreadBody): (JSC::DFG::Worklist::dump): (JSC::DFG::numberOfWorklists): (JSC::DFG::ensureWorklistForIndex): (JSC::DFG::existingWorklistForIndexOrNull): (JSC::DFG::existingWorklistForIndex): * dfg/DFGWorklist.h: (JSC::DFG::numberOfWorklists): Deleted. (JSC::DFG::ensureWorklistForIndex): Deleted. (JSC::DFG::existingWorklistForIndexOrNull): Deleted. (JSC::DFG::existingWorklistForIndex): Deleted. * heap/CollectingScope.h: Added. (JSC::CollectingScope::CollectingScope): (JSC::CollectingScope::~CollectingScope): * heap/CollectorPhase.cpp: Added. (JSC::worldShouldBeSuspended): (WTF::printInternal): * heap/CollectorPhase.h: Added. * heap/EdenGCActivityCallback.cpp: (JSC::EdenGCActivityCallback::lastGCLength): * heap/FullGCActivityCallback.cpp: (JSC::FullGCActivityCallback::doCollection): (JSC::FullGCActivityCallback::lastGCLength): * heap/GCConductor.cpp: Added. (JSC::gcConductorShortName): (WTF::printInternal): * heap/GCConductor.h: Added. * heap/GCFinalizationCallback.cpp: Added. (JSC::GCFinalizationCallback::GCFinalizationCallback): (JSC::GCFinalizationCallback::~GCFinalizationCallback): * heap/GCFinalizationCallback.h: Added. (JSC::GCFinalizationCallbackFuncAdaptor::GCFinalizationCallbackFuncAdaptor): (JSC::createGCFinalizationCallback): * heap/Heap.cpp: (JSC::Heap::Thread::Thread): (JSC::Heap::Heap): (JSC::Heap::lastChanceToFinalize): (JSC::Heap::gatherStackRoots): (JSC::Heap::updateObjectCounts): (JSC::Heap::sweepSynchronously): (JSC::Heap::collectAllGarbage): (JSC::Heap::collectAsync): (JSC::Heap::collectSync): (JSC::Heap::shouldCollectInCollectorThread): (JSC::Heap::collectInCollectorThread): (JSC::Heap::checkConn): (JSC::Heap::runNotRunningPhase): (JSC::Heap::runBeginPhase): (JSC::Heap::runFixpointPhase): (JSC::Heap::runConcurrentPhase): (JSC::Heap::runReloopPhase): (JSC::Heap::runEndPhase): (JSC::Heap::changePhase): (JSC::Heap::finishChangingPhase): (JSC::Heap::stopThePeriphery): (JSC::Heap::resumeThePeriphery): (JSC::Heap::stopTheMutator): (JSC::Heap::resumeTheMutator): (JSC::Heap::stopIfNecessarySlow): (JSC::Heap::collectInMutatorThread): (JSC::Heap::waitForCollector): (JSC::Heap::acquireAccessSlow): (JSC::Heap::releaseAccessSlow): (JSC::Heap::relinquishConn): (JSC::Heap::finishRelinquishingConn): (JSC::Heap::handleNeedFinalize): (JSC::Heap::notifyThreadStopping): (JSC::Heap::finalize): (JSC::Heap::addFinalizationCallback): (JSC::Heap::requestCollection): (JSC::Heap::waitForCollection): (JSC::Heap::updateAllocationLimits): (JSC::Heap::didFinishCollection): (JSC::Heap::collectIfNecessaryOrDefer): (JSC::Heap::notifyIsSafeToCollect): (JSC::Heap::preventCollection): (JSC::Heap::performIncrement): (JSC::Heap::markToFixpoint): Deleted. (JSC::Heap::shouldCollectInThread): Deleted. (JSC::Heap::collectInThread): Deleted. (JSC::Heap::stopTheWorld): Deleted. (JSC::Heap::resumeTheWorld): Deleted. * heap/Heap.h: (JSC::Heap::machineThreads): (JSC::Heap::lastFullGCLength): (JSC::Heap::lastEdenGCLength): (JSC::Heap::increaseLastFullGCLength): * heap/HeapInlines.h: (JSC::Heap::mutatorIsStopped): Deleted. * heap/HeapStatistics.cpp: Removed. * heap/HeapStatistics.h: Removed. * heap/HelpingGCScope.h: Removed. * heap/IncrementalSweeper.cpp: (JSC::IncrementalSweeper::stopSweeping): (JSC::IncrementalSweeper::willFinishSweeping): Deleted. * heap/IncrementalSweeper.h: * heap/MachineStackMarker.cpp: (JSC::MachineThreads::gatherFromCurrentThread): (JSC::MachineThreads::gatherConservativeRoots): (JSC::callWithCurrentThreadState): * heap/MachineStackMarker.h: * heap/MarkedAllocator.cpp: (JSC::MarkedAllocator::allocateSlowCaseImpl): * heap/MarkedBlock.cpp: (JSC::MarkedBlock::Handle::sweep): * heap/MarkedSpace.cpp: (JSC::MarkedSpace::sweep): * heap/MutatorState.cpp: (WTF::printInternal): * heap/MutatorState.h: * heap/RegisterState.h: Added. * heap/RunningScope.h: Added. (JSC::RunningScope::RunningScope): (JSC::RunningScope::~RunningScope): * heap/SlotVisitor.cpp: (JSC::SlotVisitor::SlotVisitor): (JSC::SlotVisitor::drain): (JSC::SlotVisitor::drainFromShared): (JSC::SlotVisitor::drainInParallelPassively): (JSC::SlotVisitor::donateAll): (JSC::SlotVisitor::donate): * heap/SlotVisitor.h: (JSC::SlotVisitor::codeName): * heap/StochasticSpaceTimeMutatorScheduler.cpp: (JSC::StochasticSpaceTimeMutatorScheduler::beginCollection): (JSC::StochasticSpaceTimeMutatorScheduler::synchronousDrainingDidStall): (JSC::StochasticSpaceTimeMutatorScheduler::timeToStop): * heap/SweepingScope.h: Added. (JSC::SweepingScope::SweepingScope): (JSC::SweepingScope::~SweepingScope): * jit/JITWorklist.cpp: (JSC::JITWorklist::Thread::Thread): * jsc.cpp: (GlobalObject::finishCreation): (functionFlashHeapAccess): * runtime/InitializeThreading.cpp: (JSC::initializeThreading): * runtime/JSCellInlines.h: (JSC::JSCell::classInfo): * runtime/Options.cpp: (JSC::overrideDefaults): * runtime/Options.h: * runtime/TestRunnerUtils.cpp: (JSC::finalizeStatsAtEndOfTesting): Source/WebCore: Added new tests in JSTests. The WebCore changes involve: - Refactoring around new header discipline. - Adding crazy GC APIs to window.internals to enable us to test the GC's runloop discipline. * ForwardingHeaders/heap/GCFinalizationCallback.h: Added. * ForwardingHeaders/heap/IncrementalSweeper.h: Added. * ForwardingHeaders/heap/MachineStackMarker.h: Added. * ForwardingHeaders/heap/RunningScope.h: Added. * bindings/js/CommonVM.cpp: * testing/Internals.cpp: (WebCore::Internals::parserMetaData): (WebCore::Internals::isReadableStreamDisturbed): (WebCore::Internals::isGCRunning): (WebCore::Internals::addGCFinalizationCallback): (WebCore::Internals::stopSweeping): (WebCore::Internals::startSweeping): * testing/Internals.h: * testing/Internals.idl: Source/WTF: Extend the use of AbstractLocker so that we can use more locking idioms. * wtf/AutomaticThread.cpp: (WTF::AutomaticThreadCondition::notifyOne): (WTF::AutomaticThreadCondition::notifyAll): (WTF::AutomaticThreadCondition::add): (WTF::AutomaticThreadCondition::remove): (WTF::AutomaticThreadCondition::contains): (WTF::AutomaticThread::AutomaticThread): (WTF::AutomaticThread::tryStop): (WTF::AutomaticThread::isWaiting): (WTF::AutomaticThread::notify): (WTF::AutomaticThread::start): (WTF::AutomaticThread::threadIsStopping): * wtf/AutomaticThread.h: * wtf/NumberOfCores.cpp: (WTF::numberOfProcessorCores): * wtf/ParallelHelperPool.cpp: (WTF::ParallelHelperClient::finish): (WTF::ParallelHelperClient::claimTask): (WTF::ParallelHelperPool::Thread::Thread): (WTF::ParallelHelperPool::didMakeWorkAvailable): (WTF::ParallelHelperPool::hasClientWithTask): (WTF::ParallelHelperPool::getClientWithTask): * wtf/ParallelHelperPool.h: Tools: Make more tests collect continuously. * Scripts/run-jsc-stress-tests: Canonical link: https://commits.webkit.org/185692@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@212778 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-02-22 00:58:15 +00:00
bool hasUnderlyingThread(const AbstractLocker&) const { return m_hasUnderlyingThread; }
The GC should be in a thread https://bugs.webkit.org/show_bug.cgi?id=163562 Reviewed by Geoffrey Garen and Andreas Kling. Source/JavaScriptCore: In a concurrent GC, the work of collecting happens on a separate thread. This patch implements this, and schedules the thread the way that a concurrent GC thread would be scheduled. But, the GC isn't actually concurrent yet because it calls stopTheWorld() before doing anything and calls resumeTheWorld() after it's done with everything. The next step will be to make it really concurrent by basically calling stopTheWorld()/resumeTheWorld() around bounded snippets of work while making most of the work happen with the world running. Our GC will probably always have stop-the-world phases because the semantics of JSC weak references call for it. This implements concurrent GC scheduling. This means that there is no longer a Heap::collect() API. Instead, you can call collectAsync() which makes sure that a GC is scheduled (it will do nothing if one is scheduled or ongoing) or you can call collectSync() to schedule a GC and wait for it to happen. I made our debugging stuff call collectSync(). It should be a goal to never call collectSync() except for debugging or benchmark harness hacks. The collector thread is an AutomaticThread, so it won't linger when not in use. It works on a ticket-based system, like you would see at the DMV. A ticket is a 64-bit integer. There are two ticket counters: last granted and last served. When you request a collection, last granted is incremented and its new value given to you. When a collection completes, last served is incremented. collectSync() waits until last served catches up to what last granted had been at the time you requested a GC. This means that if you request a sync GC in the middle of an async GC, you will wait for that async GC to finish and then you will request and wait for your sync GC. The synchronization between the collector thread and the main threads is complex. The collector thread needs to be able to ask the main thread to stop. It needs to be able to do some post-GC clean-up, like the synchronous CodeBlock and LargeAllocation sweeps, on the main thread. The collector needs to be able to ask the main thread to execute a cross-modifying code fence before running any JIT code, since the GC might aid the JIT worklist and run JIT finalization. It's possible for the GC to want the main thread to run something at the same time that the main thread wants to wait for the GC. The main thread needs to be able to run non-JSC stuff without causing the GC to completely stall. The main thread needs to be able to query its own state (is there a request to stop?) and change it (running JSC versus not) quickly, since this may happen on hot paths. This kind of intertwined system of requests, notifications, and state changes requires a combination of lock-free algorithms and waiting. So, this is all implemented using a Atomic<unsigned> Heap::m_worldState, which has bits to represent things being requested by the collector and the heap access state of the mutator. I am borrowing a lot of terms that I've seen in other VMs that I've worked on. Here's what they mean: - Stop the world: make sure that either the mutator is not running, or that it's not running code that could mess with the heap. - Heap access: the mutator is said to have heap access if it could mess with the heap. If you stop the world and the mutator doesn't have heap access, all you're doing is making sure that it will block when it tries to acquire heap access. This means that our GC is already fully concurrent in cases where the GC is requested while the mutator has no heap access. This probably won't happen, but if it did then it should just work. Usually, stopping the world means that we state our shouldStop request with m_worldState, and a future call to Heap::stopIfNecessary() will go to slow path and stop. The act of stopping or waiting to acquire heap access is managed by using ParkingLot API directly on m_worldState. This works out great because it would be very awkward to get the same functionality using locks and condition variables, since we want stopIfNecessary/acquireAccess/requestAccess fast paths that are single atomic instructions (load/CAS/CAS, respectively). The mutator will call these things frequently. Currently we have Heap::stopIfNecessary() polling on every allocator slow path, but we may want to make it even more frequent than that. Currently only JSC API clients benefit from the heap access optimization. The DOM forces us to assume that heap access is permanently on, since DOM manipulation doesn't always hold the JSLock. We could still allow the GC to proceed when the runloop is idle by having the GC put a task on the runloop that just calls stopIfNecessary(). This is perf neutral. The only behavior change that clients ought to observe is that marking and the weak fixpoint happen on a separate thread. Marking was already parallel so it already handled multiple threads, but now it _never_ runs on the main thread. The weak fixpoint needed some help to be able to run on another thread - mostly because there was some code in IndexedDB that was using thread specifics in the weak fixpoint. * API/JSBase.cpp: (JSSynchronousEdenCollectForDebugging): * API/JSManagedValue.mm: (-[JSManagedValue initWithValue:]): * heap/EdenGCActivityCallback.cpp: (JSC::EdenGCActivityCallback::doCollection): * heap/FullGCActivityCallback.cpp: (JSC::FullGCActivityCallback::doCollection): * heap/Heap.cpp: (JSC::Heap::Thread::Thread): (JSC::Heap::Heap): (JSC::Heap::lastChanceToFinalize): (JSC::Heap::markRoots): (JSC::Heap::gatherStackRoots): (JSC::Heap::deleteUnmarkedCompiledCode): (JSC::Heap::collectAllGarbage): (JSC::Heap::collectAsync): (JSC::Heap::collectSync): (JSC::Heap::shouldCollectInThread): (JSC::Heap::collectInThread): (JSC::Heap::stopTheWorld): (JSC::Heap::resumeTheWorld): (JSC::Heap::stopIfNecessarySlow): (JSC::Heap::acquireAccessSlow): (JSC::Heap::releaseAccessSlow): (JSC::Heap::handleDidJIT): (JSC::Heap::handleNeedFinalize): (JSC::Heap::setDidJIT): (JSC::Heap::setNeedFinalize): (JSC::Heap::waitWhileNeedFinalize): (JSC::Heap::finalize): (JSC::Heap::requestCollection): (JSC::Heap::waitForCollection): (JSC::Heap::didFinishCollection): (JSC::Heap::canCollect): (JSC::Heap::shouldCollectHeuristic): (JSC::Heap::shouldCollect): (JSC::Heap::collectIfNecessaryOrDefer): (JSC::Heap::collectAccordingToDeferGCProbability): (JSC::Heap::collect): Deleted. (JSC::Heap::collectWithoutAnySweep): Deleted. (JSC::Heap::collectImpl): Deleted. * heap/Heap.h: (JSC::Heap::ReleaseAccessScope::ReleaseAccessScope): (JSC::Heap::ReleaseAccessScope::~ReleaseAccessScope): * heap/HeapInlines.h: (JSC::Heap::acquireAccess): (JSC::Heap::releaseAccess): (JSC::Heap::stopIfNecessary): * heap/MachineStackMarker.cpp: (JSC::MachineThreads::gatherConservativeRoots): (JSC::MachineThreads::gatherFromCurrentThread): Deleted. * heap/MachineStackMarker.h: * jit/JITWorklist.cpp: (JSC::JITWorklist::completeAllForVM): * jit/JITWorklist.h: * jsc.cpp: (functionFullGC): (functionEdenGC): * runtime/InitializeThreading.cpp: (JSC::initializeThreading): * runtime/JSLock.cpp: (JSC::JSLock::didAcquireLock): (JSC::JSLock::unlock): (JSC::JSLock::willReleaseLock): * tools/JSDollarVMPrototype.cpp: (JSC::JSDollarVMPrototype::edenGC): Source/WebCore: No new tests because existing tests cover this. We now need to be more careful about using JSLock. This fixes some places that were not holding it. New assertions in the GC are more likely to catch this than before. * bindings/js/WorkerScriptController.cpp: (WebCore::WorkerScriptController::WorkerScriptController): Source/WTF: This fixes some bugs and adds a few features. * wtf/Atomics.h: The GC may do work on behalf of the JIT. If it does, the main thread needs to execute a cross-modifying code fence. This is cpuid on x86 and I believe it's isb on ARM. It would have been an isync on PPC and I think that isb is the ARM equivalent. (WTF::arm_isb): (WTF::crossModifyingCodeFence): (WTF::x86_ortop): (WTF::x86_cpuid): * wtf/AutomaticThread.cpp: I accidentally had AutomaticThreadCondition inherit from ThreadSafeRefCounted<AutomaticThread> [sic]. This never crashed before because all of our prior AutomaticThreadConditions were immortal. (WTF::AutomaticThread::AutomaticThread): (WTF::AutomaticThread::~AutomaticThread): (WTF::AutomaticThread::start): * wtf/AutomaticThread.h: * wtf/MainThread.cpp: Need to allow initializeGCThreads() to be called separately because it's now more than just a debugging thing. (WTF::initializeGCThreads): Canonical link: https://commits.webkit.org/182065@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@208306 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-11-02 22:01:04 +00:00
// This attempts to quickly stop the thread. This will succeed if the thread happens to not be
// running. Returns true if the thread has been stopped. A good idiom for stopping your automatic
// thread is to first try this, and if that doesn't work, to tell the thread using your own
// mechanism (set some flag and then notify the condition).
The collector thread should only start when the mutator doesn't have heap access https://bugs.webkit.org/show_bug.cgi?id=167737 Reviewed by Keith Miller. JSTests: Add versions of splay that flash heap access, to simulate what might happen if a third-party app was running concurrent GC. In this case, we might actually start the collector thread. * stress/splay-flash-access-1ms.js: Added. (performance.now): (this.Setup.setup.setup): (this.TearDown.tearDown.tearDown): (Benchmark): (BenchmarkResult): (BenchmarkResult.prototype.valueOf): (BenchmarkSuite): (alert): (Math.random): (BenchmarkSuite.ResetRNG): (RunStep): (BenchmarkSuite.RunSuites): (BenchmarkSuite.CountBenchmarks): (BenchmarkSuite.GeometricMean): (BenchmarkSuite.GeometricMeanTime): (BenchmarkSuite.AverageAbovePercentile): (BenchmarkSuite.GeometricMeanLatency): (BenchmarkSuite.FormatScore): (BenchmarkSuite.prototype.NotifyStep): (BenchmarkSuite.prototype.NotifyResult): (BenchmarkSuite.prototype.NotifyError): (BenchmarkSuite.prototype.RunSingleBenchmark): (RunNextSetup): (RunNextBenchmark): (RunNextTearDown): (BenchmarkSuite.prototype.RunStep): (GeneratePayloadTree): (GenerateKey): (SplayUpdateStats): (InsertNewNode): (SplaySetup): (SplayTearDown): (SplayRun): (SplayTree): (SplayTree.prototype.isEmpty): (SplayTree.prototype.insert): (SplayTree.prototype.remove): (SplayTree.prototype.find): (SplayTree.prototype.findMax): (SplayTree.prototype.findGreatestLessThan): (SplayTree.prototype.exportKeys): (SplayTree.prototype.splay_): (SplayTree.Node): (SplayTree.Node.prototype.traverse_): (jscSetUp): (jscTearDown): (jscRun): (averageAbovePercentile): (printPercentile): * stress/splay-flash-access.js: Added. (performance.now): (this.Setup.setup.setup): (this.TearDown.tearDown.tearDown): (Benchmark): (BenchmarkResult): (BenchmarkResult.prototype.valueOf): (BenchmarkSuite): (alert): (Math.random): (BenchmarkSuite.ResetRNG): (RunStep): (BenchmarkSuite.RunSuites): (BenchmarkSuite.CountBenchmarks): (BenchmarkSuite.GeometricMean): (BenchmarkSuite.GeometricMeanTime): (BenchmarkSuite.AverageAbovePercentile): (BenchmarkSuite.GeometricMeanLatency): (BenchmarkSuite.FormatScore): (BenchmarkSuite.prototype.NotifyStep): (BenchmarkSuite.prototype.NotifyResult): (BenchmarkSuite.prototype.NotifyError): (BenchmarkSuite.prototype.RunSingleBenchmark): (RunNextSetup): (RunNextBenchmark): (RunNextTearDown): (BenchmarkSuite.prototype.RunStep): (GeneratePayloadTree): (GenerateKey): (SplayUpdateStats): (InsertNewNode): (SplaySetup): (SplayTearDown): (SplayRun): (SplayTree): (SplayTree.prototype.isEmpty): (SplayTree.prototype.insert): (SplayTree.prototype.remove): (SplayTree.prototype.find): (SplayTree.prototype.findMax): (SplayTree.prototype.findGreatestLessThan): (SplayTree.prototype.exportKeys): (SplayTree.prototype.splay_): (SplayTree.Node): (SplayTree.Node.prototype.traverse_): (jscSetUp): (jscTearDown): (jscRun): (averageAbovePercentile): (printPercentile): Source/JavaScriptCore: This turns the collector thread's workflow into a state machine, so that the mutator thread can run it directly. This reduces the amount of synchronization we do with the collector thread, and means that most apps will never start the collector thread. The collector thread will still start when we need to finish collecting and we don't have heap access. In this new world, "stopping the world" means relinquishing control of collection to the mutator. This means tracking who is conducting collection. I use the GCConductor enum to say who is conducting. It's either GCConductor::Mutator or GCConductor::Collector. I use the term "conn" to refer to the concept of conducting (having the conn, relinquishing the conn, taking the conn). So, stopping the world means giving the mutator the conn. Releasing heap access means giving the collector the conn. This meant bringing back the conservative scan of the calling thread. It turns out that this scan was too slow to be called on each GC increment because apparently setjmp() now does system calls. So, I wrote our own callee save register saving for the GC. Then I had doubts about whether or not it was correct, so I also made it so that the GC only rarely asks for the register state. I think we still want to use my register saving code instead of setjmp because setjmp seems to save things we don't need, and that could make us overly conservative. It turns out that this new scheduling discipline makes the old space-time scheduler perform better than the new stochastic space-time scheduler on systems with fewer than 4 cores. This is because the mutator having the conn enables us to time the mutator<->collector context switches by polling. The OS is never involved. So, we can use super precise timing. This allows the old space-time schduler to shine like it hadn't before. The splay results imply that this is all a good thing. On 2-core systems, this reduces pause times by 40% and it increases throughput about 5%. On 1-core systems, this reduces pause times by half and reduces throughput by 8%. On 4-or-more-core systems, this doesn't seem to have much effect. * CMakeLists.txt: * JavaScriptCore.xcodeproj/project.pbxproj: * bytecode/CodeBlock.cpp: (JSC::CodeBlock::visitChildren): * dfg/DFGWorklist.cpp: (JSC::DFG::Worklist::ThreadBody::ThreadBody): (JSC::DFG::Worklist::dump): (JSC::DFG::numberOfWorklists): (JSC::DFG::ensureWorklistForIndex): (JSC::DFG::existingWorklistForIndexOrNull): (JSC::DFG::existingWorklistForIndex): * dfg/DFGWorklist.h: (JSC::DFG::numberOfWorklists): Deleted. (JSC::DFG::ensureWorklistForIndex): Deleted. (JSC::DFG::existingWorklistForIndexOrNull): Deleted. (JSC::DFG::existingWorklistForIndex): Deleted. * heap/CollectingScope.h: Added. (JSC::CollectingScope::CollectingScope): (JSC::CollectingScope::~CollectingScope): * heap/CollectorPhase.cpp: Added. (JSC::worldShouldBeSuspended): (WTF::printInternal): * heap/CollectorPhase.h: Added. * heap/EdenGCActivityCallback.cpp: (JSC::EdenGCActivityCallback::lastGCLength): * heap/FullGCActivityCallback.cpp: (JSC::FullGCActivityCallback::doCollection): (JSC::FullGCActivityCallback::lastGCLength): * heap/GCConductor.cpp: Added. (JSC::gcConductorShortName): (WTF::printInternal): * heap/GCConductor.h: Added. * heap/GCFinalizationCallback.cpp: Added. (JSC::GCFinalizationCallback::GCFinalizationCallback): (JSC::GCFinalizationCallback::~GCFinalizationCallback): * heap/GCFinalizationCallback.h: Added. (JSC::GCFinalizationCallbackFuncAdaptor::GCFinalizationCallbackFuncAdaptor): (JSC::createGCFinalizationCallback): * heap/Heap.cpp: (JSC::Heap::Thread::Thread): (JSC::Heap::Heap): (JSC::Heap::lastChanceToFinalize): (JSC::Heap::gatherStackRoots): (JSC::Heap::updateObjectCounts): (JSC::Heap::sweepSynchronously): (JSC::Heap::collectAllGarbage): (JSC::Heap::collectAsync): (JSC::Heap::collectSync): (JSC::Heap::shouldCollectInCollectorThread): (JSC::Heap::collectInCollectorThread): (JSC::Heap::checkConn): (JSC::Heap::runNotRunningPhase): (JSC::Heap::runBeginPhase): (JSC::Heap::runFixpointPhase): (JSC::Heap::runConcurrentPhase): (JSC::Heap::runReloopPhase): (JSC::Heap::runEndPhase): (JSC::Heap::changePhase): (JSC::Heap::finishChangingPhase): (JSC::Heap::stopThePeriphery): (JSC::Heap::resumeThePeriphery): (JSC::Heap::stopTheMutator): (JSC::Heap::resumeTheMutator): (JSC::Heap::stopIfNecessarySlow): (JSC::Heap::collectInMutatorThread): (JSC::Heap::waitForCollector): (JSC::Heap::acquireAccessSlow): (JSC::Heap::releaseAccessSlow): (JSC::Heap::relinquishConn): (JSC::Heap::finishRelinquishingConn): (JSC::Heap::handleNeedFinalize): (JSC::Heap::notifyThreadStopping): (JSC::Heap::finalize): (JSC::Heap::addFinalizationCallback): (JSC::Heap::requestCollection): (JSC::Heap::waitForCollection): (JSC::Heap::updateAllocationLimits): (JSC::Heap::didFinishCollection): (JSC::Heap::collectIfNecessaryOrDefer): (JSC::Heap::notifyIsSafeToCollect): (JSC::Heap::preventCollection): (JSC::Heap::performIncrement): (JSC::Heap::markToFixpoint): Deleted. (JSC::Heap::shouldCollectInThread): Deleted. (JSC::Heap::collectInThread): Deleted. (JSC::Heap::stopTheWorld): Deleted. (JSC::Heap::resumeTheWorld): Deleted. * heap/Heap.h: (JSC::Heap::machineThreads): (JSC::Heap::lastFullGCLength): (JSC::Heap::lastEdenGCLength): (JSC::Heap::increaseLastFullGCLength): * heap/HeapInlines.h: (JSC::Heap::mutatorIsStopped): Deleted. * heap/HeapStatistics.cpp: Removed. * heap/HeapStatistics.h: Removed. * heap/HelpingGCScope.h: Removed. * heap/IncrementalSweeper.cpp: (JSC::IncrementalSweeper::stopSweeping): (JSC::IncrementalSweeper::willFinishSweeping): Deleted. * heap/IncrementalSweeper.h: * heap/MachineStackMarker.cpp: (JSC::MachineThreads::gatherFromCurrentThread): (JSC::MachineThreads::gatherConservativeRoots): (JSC::callWithCurrentThreadState): * heap/MachineStackMarker.h: * heap/MarkedAllocator.cpp: (JSC::MarkedAllocator::allocateSlowCaseImpl): * heap/MarkedBlock.cpp: (JSC::MarkedBlock::Handle::sweep): * heap/MarkedSpace.cpp: (JSC::MarkedSpace::sweep): * heap/MutatorState.cpp: (WTF::printInternal): * heap/MutatorState.h: * heap/RegisterState.h: Added. * heap/RunningScope.h: Added. (JSC::RunningScope::RunningScope): (JSC::RunningScope::~RunningScope): * heap/SlotVisitor.cpp: (JSC::SlotVisitor::SlotVisitor): (JSC::SlotVisitor::drain): (JSC::SlotVisitor::drainFromShared): (JSC::SlotVisitor::drainInParallelPassively): (JSC::SlotVisitor::donateAll): (JSC::SlotVisitor::donate): * heap/SlotVisitor.h: (JSC::SlotVisitor::codeName): * heap/StochasticSpaceTimeMutatorScheduler.cpp: (JSC::StochasticSpaceTimeMutatorScheduler::beginCollection): (JSC::StochasticSpaceTimeMutatorScheduler::synchronousDrainingDidStall): (JSC::StochasticSpaceTimeMutatorScheduler::timeToStop): * heap/SweepingScope.h: Added. (JSC::SweepingScope::SweepingScope): (JSC::SweepingScope::~SweepingScope): * jit/JITWorklist.cpp: (JSC::JITWorklist::Thread::Thread): * jsc.cpp: (GlobalObject::finishCreation): (functionFlashHeapAccess): * runtime/InitializeThreading.cpp: (JSC::initializeThreading): * runtime/JSCellInlines.h: (JSC::JSCell::classInfo): * runtime/Options.cpp: (JSC::overrideDefaults): * runtime/Options.h: * runtime/TestRunnerUtils.cpp: (JSC::finalizeStatsAtEndOfTesting): Source/WebCore: Added new tests in JSTests. The WebCore changes involve: - Refactoring around new header discipline. - Adding crazy GC APIs to window.internals to enable us to test the GC's runloop discipline. * ForwardingHeaders/heap/GCFinalizationCallback.h: Added. * ForwardingHeaders/heap/IncrementalSweeper.h: Added. * ForwardingHeaders/heap/MachineStackMarker.h: Added. * ForwardingHeaders/heap/RunningScope.h: Added. * bindings/js/CommonVM.cpp: * testing/Internals.cpp: (WebCore::Internals::parserMetaData): (WebCore::Internals::isReadableStreamDisturbed): (WebCore::Internals::isGCRunning): (WebCore::Internals::addGCFinalizationCallback): (WebCore::Internals::stopSweeping): (WebCore::Internals::startSweeping): * testing/Internals.h: * testing/Internals.idl: Source/WTF: Extend the use of AbstractLocker so that we can use more locking idioms. * wtf/AutomaticThread.cpp: (WTF::AutomaticThreadCondition::notifyOne): (WTF::AutomaticThreadCondition::notifyAll): (WTF::AutomaticThreadCondition::add): (WTF::AutomaticThreadCondition::remove): (WTF::AutomaticThreadCondition::contains): (WTF::AutomaticThread::AutomaticThread): (WTF::AutomaticThread::tryStop): (WTF::AutomaticThread::isWaiting): (WTF::AutomaticThread::notify): (WTF::AutomaticThread::start): (WTF::AutomaticThread::threadIsStopping): * wtf/AutomaticThread.h: * wtf/NumberOfCores.cpp: (WTF::numberOfProcessorCores): * wtf/ParallelHelperPool.cpp: (WTF::ParallelHelperClient::finish): (WTF::ParallelHelperClient::claimTask): (WTF::ParallelHelperPool::Thread::Thread): (WTF::ParallelHelperPool::didMakeWorkAvailable): (WTF::ParallelHelperPool::hasClientWithTask): (WTF::ParallelHelperPool::getClientWithTask): * wtf/ParallelHelperPool.h: Tools: Make more tests collect continuously. * Scripts/run-jsc-stress-tests: Canonical link: https://commits.webkit.org/185692@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@212778 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-02-22 00:58:15 +00:00
bool tryStop(const AbstractLocker&);
REGRESSION: HipChat and Mail sometimes hang beneath JSC::Heap::lastChanceToFinalize() https://bugs.webkit.org/show_bug.cgi?id=165962 Reviewed by Filip Pizlo. There is an inherent race in Condition::waitFor() where the timeout can happen just before a notify from another thread. Fixed this by adding a condition variable and flag to each AutomaticThread. The flag is used to signify to a notifying thread that the thread is waiting. That flag is set in the waiting thread before calling waitFor() and cleared by another thread when it notifies the thread. The access to that flag happens when the lock is held. Now the waiting thread checks if the flag after a timeout to see that it in fact should proceed like a normal notification. The added condition variable allows us to target a specific thread. We used to keep a list of waiting threads, now we keep a list of all threads. To notify one thread, we look for a waiting thread and notify it directly. If we can't find a waiting thread, we start a sleeping thread. We notify all threads by waking all waiting threads and starting all sleeping threads. * wtf/AutomaticThread.cpp: (WTF::AutomaticThreadCondition::notifyOne): (WTF::AutomaticThreadCondition::notifyAll): (WTF::AutomaticThread::isWaiting): (WTF::AutomaticThread::notify): (WTF::AutomaticThread::start): * wtf/AutomaticThread.h: Canonical link: https://commits.webkit.org/183569@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@209938 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-12-16 22:26:09 +00:00
The collector thread should only start when the mutator doesn't have heap access https://bugs.webkit.org/show_bug.cgi?id=167737 Reviewed by Keith Miller. JSTests: Add versions of splay that flash heap access, to simulate what might happen if a third-party app was running concurrent GC. In this case, we might actually start the collector thread. * stress/splay-flash-access-1ms.js: Added. (performance.now): (this.Setup.setup.setup): (this.TearDown.tearDown.tearDown): (Benchmark): (BenchmarkResult): (BenchmarkResult.prototype.valueOf): (BenchmarkSuite): (alert): (Math.random): (BenchmarkSuite.ResetRNG): (RunStep): (BenchmarkSuite.RunSuites): (BenchmarkSuite.CountBenchmarks): (BenchmarkSuite.GeometricMean): (BenchmarkSuite.GeometricMeanTime): (BenchmarkSuite.AverageAbovePercentile): (BenchmarkSuite.GeometricMeanLatency): (BenchmarkSuite.FormatScore): (BenchmarkSuite.prototype.NotifyStep): (BenchmarkSuite.prototype.NotifyResult): (BenchmarkSuite.prototype.NotifyError): (BenchmarkSuite.prototype.RunSingleBenchmark): (RunNextSetup): (RunNextBenchmark): (RunNextTearDown): (BenchmarkSuite.prototype.RunStep): (GeneratePayloadTree): (GenerateKey): (SplayUpdateStats): (InsertNewNode): (SplaySetup): (SplayTearDown): (SplayRun): (SplayTree): (SplayTree.prototype.isEmpty): (SplayTree.prototype.insert): (SplayTree.prototype.remove): (SplayTree.prototype.find): (SplayTree.prototype.findMax): (SplayTree.prototype.findGreatestLessThan): (SplayTree.prototype.exportKeys): (SplayTree.prototype.splay_): (SplayTree.Node): (SplayTree.Node.prototype.traverse_): (jscSetUp): (jscTearDown): (jscRun): (averageAbovePercentile): (printPercentile): * stress/splay-flash-access.js: Added. (performance.now): (this.Setup.setup.setup): (this.TearDown.tearDown.tearDown): (Benchmark): (BenchmarkResult): (BenchmarkResult.prototype.valueOf): (BenchmarkSuite): (alert): (Math.random): (BenchmarkSuite.ResetRNG): (RunStep): (BenchmarkSuite.RunSuites): (BenchmarkSuite.CountBenchmarks): (BenchmarkSuite.GeometricMean): (BenchmarkSuite.GeometricMeanTime): (BenchmarkSuite.AverageAbovePercentile): (BenchmarkSuite.GeometricMeanLatency): (BenchmarkSuite.FormatScore): (BenchmarkSuite.prototype.NotifyStep): (BenchmarkSuite.prototype.NotifyResult): (BenchmarkSuite.prototype.NotifyError): (BenchmarkSuite.prototype.RunSingleBenchmark): (RunNextSetup): (RunNextBenchmark): (RunNextTearDown): (BenchmarkSuite.prototype.RunStep): (GeneratePayloadTree): (GenerateKey): (SplayUpdateStats): (InsertNewNode): (SplaySetup): (SplayTearDown): (SplayRun): (SplayTree): (SplayTree.prototype.isEmpty): (SplayTree.prototype.insert): (SplayTree.prototype.remove): (SplayTree.prototype.find): (SplayTree.prototype.findMax): (SplayTree.prototype.findGreatestLessThan): (SplayTree.prototype.exportKeys): (SplayTree.prototype.splay_): (SplayTree.Node): (SplayTree.Node.prototype.traverse_): (jscSetUp): (jscTearDown): (jscRun): (averageAbovePercentile): (printPercentile): Source/JavaScriptCore: This turns the collector thread's workflow into a state machine, so that the mutator thread can run it directly. This reduces the amount of synchronization we do with the collector thread, and means that most apps will never start the collector thread. The collector thread will still start when we need to finish collecting and we don't have heap access. In this new world, "stopping the world" means relinquishing control of collection to the mutator. This means tracking who is conducting collection. I use the GCConductor enum to say who is conducting. It's either GCConductor::Mutator or GCConductor::Collector. I use the term "conn" to refer to the concept of conducting (having the conn, relinquishing the conn, taking the conn). So, stopping the world means giving the mutator the conn. Releasing heap access means giving the collector the conn. This meant bringing back the conservative scan of the calling thread. It turns out that this scan was too slow to be called on each GC increment because apparently setjmp() now does system calls. So, I wrote our own callee save register saving for the GC. Then I had doubts about whether or not it was correct, so I also made it so that the GC only rarely asks for the register state. I think we still want to use my register saving code instead of setjmp because setjmp seems to save things we don't need, and that could make us overly conservative. It turns out that this new scheduling discipline makes the old space-time scheduler perform better than the new stochastic space-time scheduler on systems with fewer than 4 cores. This is because the mutator having the conn enables us to time the mutator<->collector context switches by polling. The OS is never involved. So, we can use super precise timing. This allows the old space-time schduler to shine like it hadn't before. The splay results imply that this is all a good thing. On 2-core systems, this reduces pause times by 40% and it increases throughput about 5%. On 1-core systems, this reduces pause times by half and reduces throughput by 8%. On 4-or-more-core systems, this doesn't seem to have much effect. * CMakeLists.txt: * JavaScriptCore.xcodeproj/project.pbxproj: * bytecode/CodeBlock.cpp: (JSC::CodeBlock::visitChildren): * dfg/DFGWorklist.cpp: (JSC::DFG::Worklist::ThreadBody::ThreadBody): (JSC::DFG::Worklist::dump): (JSC::DFG::numberOfWorklists): (JSC::DFG::ensureWorklistForIndex): (JSC::DFG::existingWorklistForIndexOrNull): (JSC::DFG::existingWorklistForIndex): * dfg/DFGWorklist.h: (JSC::DFG::numberOfWorklists): Deleted. (JSC::DFG::ensureWorklistForIndex): Deleted. (JSC::DFG::existingWorklistForIndexOrNull): Deleted. (JSC::DFG::existingWorklistForIndex): Deleted. * heap/CollectingScope.h: Added. (JSC::CollectingScope::CollectingScope): (JSC::CollectingScope::~CollectingScope): * heap/CollectorPhase.cpp: Added. (JSC::worldShouldBeSuspended): (WTF::printInternal): * heap/CollectorPhase.h: Added. * heap/EdenGCActivityCallback.cpp: (JSC::EdenGCActivityCallback::lastGCLength): * heap/FullGCActivityCallback.cpp: (JSC::FullGCActivityCallback::doCollection): (JSC::FullGCActivityCallback::lastGCLength): * heap/GCConductor.cpp: Added. (JSC::gcConductorShortName): (WTF::printInternal): * heap/GCConductor.h: Added. * heap/GCFinalizationCallback.cpp: Added. (JSC::GCFinalizationCallback::GCFinalizationCallback): (JSC::GCFinalizationCallback::~GCFinalizationCallback): * heap/GCFinalizationCallback.h: Added. (JSC::GCFinalizationCallbackFuncAdaptor::GCFinalizationCallbackFuncAdaptor): (JSC::createGCFinalizationCallback): * heap/Heap.cpp: (JSC::Heap::Thread::Thread): (JSC::Heap::Heap): (JSC::Heap::lastChanceToFinalize): (JSC::Heap::gatherStackRoots): (JSC::Heap::updateObjectCounts): (JSC::Heap::sweepSynchronously): (JSC::Heap::collectAllGarbage): (JSC::Heap::collectAsync): (JSC::Heap::collectSync): (JSC::Heap::shouldCollectInCollectorThread): (JSC::Heap::collectInCollectorThread): (JSC::Heap::checkConn): (JSC::Heap::runNotRunningPhase): (JSC::Heap::runBeginPhase): (JSC::Heap::runFixpointPhase): (JSC::Heap::runConcurrentPhase): (JSC::Heap::runReloopPhase): (JSC::Heap::runEndPhase): (JSC::Heap::changePhase): (JSC::Heap::finishChangingPhase): (JSC::Heap::stopThePeriphery): (JSC::Heap::resumeThePeriphery): (JSC::Heap::stopTheMutator): (JSC::Heap::resumeTheMutator): (JSC::Heap::stopIfNecessarySlow): (JSC::Heap::collectInMutatorThread): (JSC::Heap::waitForCollector): (JSC::Heap::acquireAccessSlow): (JSC::Heap::releaseAccessSlow): (JSC::Heap::relinquishConn): (JSC::Heap::finishRelinquishingConn): (JSC::Heap::handleNeedFinalize): (JSC::Heap::notifyThreadStopping): (JSC::Heap::finalize): (JSC::Heap::addFinalizationCallback): (JSC::Heap::requestCollection): (JSC::Heap::waitForCollection): (JSC::Heap::updateAllocationLimits): (JSC::Heap::didFinishCollection): (JSC::Heap::collectIfNecessaryOrDefer): (JSC::Heap::notifyIsSafeToCollect): (JSC::Heap::preventCollection): (JSC::Heap::performIncrement): (JSC::Heap::markToFixpoint): Deleted. (JSC::Heap::shouldCollectInThread): Deleted. (JSC::Heap::collectInThread): Deleted. (JSC::Heap::stopTheWorld): Deleted. (JSC::Heap::resumeTheWorld): Deleted. * heap/Heap.h: (JSC::Heap::machineThreads): (JSC::Heap::lastFullGCLength): (JSC::Heap::lastEdenGCLength): (JSC::Heap::increaseLastFullGCLength): * heap/HeapInlines.h: (JSC::Heap::mutatorIsStopped): Deleted. * heap/HeapStatistics.cpp: Removed. * heap/HeapStatistics.h: Removed. * heap/HelpingGCScope.h: Removed. * heap/IncrementalSweeper.cpp: (JSC::IncrementalSweeper::stopSweeping): (JSC::IncrementalSweeper::willFinishSweeping): Deleted. * heap/IncrementalSweeper.h: * heap/MachineStackMarker.cpp: (JSC::MachineThreads::gatherFromCurrentThread): (JSC::MachineThreads::gatherConservativeRoots): (JSC::callWithCurrentThreadState): * heap/MachineStackMarker.h: * heap/MarkedAllocator.cpp: (JSC::MarkedAllocator::allocateSlowCaseImpl): * heap/MarkedBlock.cpp: (JSC::MarkedBlock::Handle::sweep): * heap/MarkedSpace.cpp: (JSC::MarkedSpace::sweep): * heap/MutatorState.cpp: (WTF::printInternal): * heap/MutatorState.h: * heap/RegisterState.h: Added. * heap/RunningScope.h: Added. (JSC::RunningScope::RunningScope): (JSC::RunningScope::~RunningScope): * heap/SlotVisitor.cpp: (JSC::SlotVisitor::SlotVisitor): (JSC::SlotVisitor::drain): (JSC::SlotVisitor::drainFromShared): (JSC::SlotVisitor::drainInParallelPassively): (JSC::SlotVisitor::donateAll): (JSC::SlotVisitor::donate): * heap/SlotVisitor.h: (JSC::SlotVisitor::codeName): * heap/StochasticSpaceTimeMutatorScheduler.cpp: (JSC::StochasticSpaceTimeMutatorScheduler::beginCollection): (JSC::StochasticSpaceTimeMutatorScheduler::synchronousDrainingDidStall): (JSC::StochasticSpaceTimeMutatorScheduler::timeToStop): * heap/SweepingScope.h: Added. (JSC::SweepingScope::SweepingScope): (JSC::SweepingScope::~SweepingScope): * jit/JITWorklist.cpp: (JSC::JITWorklist::Thread::Thread): * jsc.cpp: (GlobalObject::finishCreation): (functionFlashHeapAccess): * runtime/InitializeThreading.cpp: (JSC::initializeThreading): * runtime/JSCellInlines.h: (JSC::JSCell::classInfo): * runtime/Options.cpp: (JSC::overrideDefaults): * runtime/Options.h: * runtime/TestRunnerUtils.cpp: (JSC::finalizeStatsAtEndOfTesting): Source/WebCore: Added new tests in JSTests. The WebCore changes involve: - Refactoring around new header discipline. - Adding crazy GC APIs to window.internals to enable us to test the GC's runloop discipline. * ForwardingHeaders/heap/GCFinalizationCallback.h: Added. * ForwardingHeaders/heap/IncrementalSweeper.h: Added. * ForwardingHeaders/heap/MachineStackMarker.h: Added. * ForwardingHeaders/heap/RunningScope.h: Added. * bindings/js/CommonVM.cpp: * testing/Internals.cpp: (WebCore::Internals::parserMetaData): (WebCore::Internals::isReadableStreamDisturbed): (WebCore::Internals::isGCRunning): (WebCore::Internals::addGCFinalizationCallback): (WebCore::Internals::stopSweeping): (WebCore::Internals::startSweeping): * testing/Internals.h: * testing/Internals.idl: Source/WTF: Extend the use of AbstractLocker so that we can use more locking idioms. * wtf/AutomaticThread.cpp: (WTF::AutomaticThreadCondition::notifyOne): (WTF::AutomaticThreadCondition::notifyAll): (WTF::AutomaticThreadCondition::add): (WTF::AutomaticThreadCondition::remove): (WTF::AutomaticThreadCondition::contains): (WTF::AutomaticThread::AutomaticThread): (WTF::AutomaticThread::tryStop): (WTF::AutomaticThread::isWaiting): (WTF::AutomaticThread::notify): (WTF::AutomaticThread::start): (WTF::AutomaticThread::threadIsStopping): * wtf/AutomaticThread.h: * wtf/NumberOfCores.cpp: (WTF::numberOfProcessorCores): * wtf/ParallelHelperPool.cpp: (WTF::ParallelHelperClient::finish): (WTF::ParallelHelperClient::claimTask): (WTF::ParallelHelperPool::Thread::Thread): (WTF::ParallelHelperPool::didMakeWorkAvailable): (WTF::ParallelHelperPool::hasClientWithTask): (WTF::ParallelHelperPool::getClientWithTask): * wtf/ParallelHelperPool.h: Tools: Make more tests collect continuously. * Scripts/run-jsc-stress-tests: Canonical link: https://commits.webkit.org/185692@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@212778 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-02-22 00:58:15 +00:00
bool isWaiting(const AbstractLocker&);
REGRESSION: HipChat and Mail sometimes hang beneath JSC::Heap::lastChanceToFinalize() https://bugs.webkit.org/show_bug.cgi?id=165962 Reviewed by Filip Pizlo. There is an inherent race in Condition::waitFor() where the timeout can happen just before a notify from another thread. Fixed this by adding a condition variable and flag to each AutomaticThread. The flag is used to signify to a notifying thread that the thread is waiting. That flag is set in the waiting thread before calling waitFor() and cleared by another thread when it notifies the thread. The access to that flag happens when the lock is held. Now the waiting thread checks if the flag after a timeout to see that it in fact should proceed like a normal notification. The added condition variable allows us to target a specific thread. We used to keep a list of waiting threads, now we keep a list of all threads. To notify one thread, we look for a waiting thread and notify it directly. If we can't find a waiting thread, we start a sleeping thread. We notify all threads by waking all waiting threads and starting all sleeping threads. * wtf/AutomaticThread.cpp: (WTF::AutomaticThreadCondition::notifyOne): (WTF::AutomaticThreadCondition::notifyAll): (WTF::AutomaticThread::isWaiting): (WTF::AutomaticThread::notify): (WTF::AutomaticThread::start): * wtf/AutomaticThread.h: Canonical link: https://commits.webkit.org/183569@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@209938 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-12-16 22:26:09 +00:00
The collector thread should only start when the mutator doesn't have heap access https://bugs.webkit.org/show_bug.cgi?id=167737 Reviewed by Keith Miller. JSTests: Add versions of splay that flash heap access, to simulate what might happen if a third-party app was running concurrent GC. In this case, we might actually start the collector thread. * stress/splay-flash-access-1ms.js: Added. (performance.now): (this.Setup.setup.setup): (this.TearDown.tearDown.tearDown): (Benchmark): (BenchmarkResult): (BenchmarkResult.prototype.valueOf): (BenchmarkSuite): (alert): (Math.random): (BenchmarkSuite.ResetRNG): (RunStep): (BenchmarkSuite.RunSuites): (BenchmarkSuite.CountBenchmarks): (BenchmarkSuite.GeometricMean): (BenchmarkSuite.GeometricMeanTime): (BenchmarkSuite.AverageAbovePercentile): (BenchmarkSuite.GeometricMeanLatency): (BenchmarkSuite.FormatScore): (BenchmarkSuite.prototype.NotifyStep): (BenchmarkSuite.prototype.NotifyResult): (BenchmarkSuite.prototype.NotifyError): (BenchmarkSuite.prototype.RunSingleBenchmark): (RunNextSetup): (RunNextBenchmark): (RunNextTearDown): (BenchmarkSuite.prototype.RunStep): (GeneratePayloadTree): (GenerateKey): (SplayUpdateStats): (InsertNewNode): (SplaySetup): (SplayTearDown): (SplayRun): (SplayTree): (SplayTree.prototype.isEmpty): (SplayTree.prototype.insert): (SplayTree.prototype.remove): (SplayTree.prototype.find): (SplayTree.prototype.findMax): (SplayTree.prototype.findGreatestLessThan): (SplayTree.prototype.exportKeys): (SplayTree.prototype.splay_): (SplayTree.Node): (SplayTree.Node.prototype.traverse_): (jscSetUp): (jscTearDown): (jscRun): (averageAbovePercentile): (printPercentile): * stress/splay-flash-access.js: Added. (performance.now): (this.Setup.setup.setup): (this.TearDown.tearDown.tearDown): (Benchmark): (BenchmarkResult): (BenchmarkResult.prototype.valueOf): (BenchmarkSuite): (alert): (Math.random): (BenchmarkSuite.ResetRNG): (RunStep): (BenchmarkSuite.RunSuites): (BenchmarkSuite.CountBenchmarks): (BenchmarkSuite.GeometricMean): (BenchmarkSuite.GeometricMeanTime): (BenchmarkSuite.AverageAbovePercentile): (BenchmarkSuite.GeometricMeanLatency): (BenchmarkSuite.FormatScore): (BenchmarkSuite.prototype.NotifyStep): (BenchmarkSuite.prototype.NotifyResult): (BenchmarkSuite.prototype.NotifyError): (BenchmarkSuite.prototype.RunSingleBenchmark): (RunNextSetup): (RunNextBenchmark): (RunNextTearDown): (BenchmarkSuite.prototype.RunStep): (GeneratePayloadTree): (GenerateKey): (SplayUpdateStats): (InsertNewNode): (SplaySetup): (SplayTearDown): (SplayRun): (SplayTree): (SplayTree.prototype.isEmpty): (SplayTree.prototype.insert): (SplayTree.prototype.remove): (SplayTree.prototype.find): (SplayTree.prototype.findMax): (SplayTree.prototype.findGreatestLessThan): (SplayTree.prototype.exportKeys): (SplayTree.prototype.splay_): (SplayTree.Node): (SplayTree.Node.prototype.traverse_): (jscSetUp): (jscTearDown): (jscRun): (averageAbovePercentile): (printPercentile): Source/JavaScriptCore: This turns the collector thread's workflow into a state machine, so that the mutator thread can run it directly. This reduces the amount of synchronization we do with the collector thread, and means that most apps will never start the collector thread. The collector thread will still start when we need to finish collecting and we don't have heap access. In this new world, "stopping the world" means relinquishing control of collection to the mutator. This means tracking who is conducting collection. I use the GCConductor enum to say who is conducting. It's either GCConductor::Mutator or GCConductor::Collector. I use the term "conn" to refer to the concept of conducting (having the conn, relinquishing the conn, taking the conn). So, stopping the world means giving the mutator the conn. Releasing heap access means giving the collector the conn. This meant bringing back the conservative scan of the calling thread. It turns out that this scan was too slow to be called on each GC increment because apparently setjmp() now does system calls. So, I wrote our own callee save register saving for the GC. Then I had doubts about whether or not it was correct, so I also made it so that the GC only rarely asks for the register state. I think we still want to use my register saving code instead of setjmp because setjmp seems to save things we don't need, and that could make us overly conservative. It turns out that this new scheduling discipline makes the old space-time scheduler perform better than the new stochastic space-time scheduler on systems with fewer than 4 cores. This is because the mutator having the conn enables us to time the mutator<->collector context switches by polling. The OS is never involved. So, we can use super precise timing. This allows the old space-time schduler to shine like it hadn't before. The splay results imply that this is all a good thing. On 2-core systems, this reduces pause times by 40% and it increases throughput about 5%. On 1-core systems, this reduces pause times by half and reduces throughput by 8%. On 4-or-more-core systems, this doesn't seem to have much effect. * CMakeLists.txt: * JavaScriptCore.xcodeproj/project.pbxproj: * bytecode/CodeBlock.cpp: (JSC::CodeBlock::visitChildren): * dfg/DFGWorklist.cpp: (JSC::DFG::Worklist::ThreadBody::ThreadBody): (JSC::DFG::Worklist::dump): (JSC::DFG::numberOfWorklists): (JSC::DFG::ensureWorklistForIndex): (JSC::DFG::existingWorklistForIndexOrNull): (JSC::DFG::existingWorklistForIndex): * dfg/DFGWorklist.h: (JSC::DFG::numberOfWorklists): Deleted. (JSC::DFG::ensureWorklistForIndex): Deleted. (JSC::DFG::existingWorklistForIndexOrNull): Deleted. (JSC::DFG::existingWorklistForIndex): Deleted. * heap/CollectingScope.h: Added. (JSC::CollectingScope::CollectingScope): (JSC::CollectingScope::~CollectingScope): * heap/CollectorPhase.cpp: Added. (JSC::worldShouldBeSuspended): (WTF::printInternal): * heap/CollectorPhase.h: Added. * heap/EdenGCActivityCallback.cpp: (JSC::EdenGCActivityCallback::lastGCLength): * heap/FullGCActivityCallback.cpp: (JSC::FullGCActivityCallback::doCollection): (JSC::FullGCActivityCallback::lastGCLength): * heap/GCConductor.cpp: Added. (JSC::gcConductorShortName): (WTF::printInternal): * heap/GCConductor.h: Added. * heap/GCFinalizationCallback.cpp: Added. (JSC::GCFinalizationCallback::GCFinalizationCallback): (JSC::GCFinalizationCallback::~GCFinalizationCallback): * heap/GCFinalizationCallback.h: Added. (JSC::GCFinalizationCallbackFuncAdaptor::GCFinalizationCallbackFuncAdaptor): (JSC::createGCFinalizationCallback): * heap/Heap.cpp: (JSC::Heap::Thread::Thread): (JSC::Heap::Heap): (JSC::Heap::lastChanceToFinalize): (JSC::Heap::gatherStackRoots): (JSC::Heap::updateObjectCounts): (JSC::Heap::sweepSynchronously): (JSC::Heap::collectAllGarbage): (JSC::Heap::collectAsync): (JSC::Heap::collectSync): (JSC::Heap::shouldCollectInCollectorThread): (JSC::Heap::collectInCollectorThread): (JSC::Heap::checkConn): (JSC::Heap::runNotRunningPhase): (JSC::Heap::runBeginPhase): (JSC::Heap::runFixpointPhase): (JSC::Heap::runConcurrentPhase): (JSC::Heap::runReloopPhase): (JSC::Heap::runEndPhase): (JSC::Heap::changePhase): (JSC::Heap::finishChangingPhase): (JSC::Heap::stopThePeriphery): (JSC::Heap::resumeThePeriphery): (JSC::Heap::stopTheMutator): (JSC::Heap::resumeTheMutator): (JSC::Heap::stopIfNecessarySlow): (JSC::Heap::collectInMutatorThread): (JSC::Heap::waitForCollector): (JSC::Heap::acquireAccessSlow): (JSC::Heap::releaseAccessSlow): (JSC::Heap::relinquishConn): (JSC::Heap::finishRelinquishingConn): (JSC::Heap::handleNeedFinalize): (JSC::Heap::notifyThreadStopping): (JSC::Heap::finalize): (JSC::Heap::addFinalizationCallback): (JSC::Heap::requestCollection): (JSC::Heap::waitForCollection): (JSC::Heap::updateAllocationLimits): (JSC::Heap::didFinishCollection): (JSC::Heap::collectIfNecessaryOrDefer): (JSC::Heap::notifyIsSafeToCollect): (JSC::Heap::preventCollection): (JSC::Heap::performIncrement): (JSC::Heap::markToFixpoint): Deleted. (JSC::Heap::shouldCollectInThread): Deleted. (JSC::Heap::collectInThread): Deleted. (JSC::Heap::stopTheWorld): Deleted. (JSC::Heap::resumeTheWorld): Deleted. * heap/Heap.h: (JSC::Heap::machineThreads): (JSC::Heap::lastFullGCLength): (JSC::Heap::lastEdenGCLength): (JSC::Heap::increaseLastFullGCLength): * heap/HeapInlines.h: (JSC::Heap::mutatorIsStopped): Deleted. * heap/HeapStatistics.cpp: Removed. * heap/HeapStatistics.h: Removed. * heap/HelpingGCScope.h: Removed. * heap/IncrementalSweeper.cpp: (JSC::IncrementalSweeper::stopSweeping): (JSC::IncrementalSweeper::willFinishSweeping): Deleted. * heap/IncrementalSweeper.h: * heap/MachineStackMarker.cpp: (JSC::MachineThreads::gatherFromCurrentThread): (JSC::MachineThreads::gatherConservativeRoots): (JSC::callWithCurrentThreadState): * heap/MachineStackMarker.h: * heap/MarkedAllocator.cpp: (JSC::MarkedAllocator::allocateSlowCaseImpl): * heap/MarkedBlock.cpp: (JSC::MarkedBlock::Handle::sweep): * heap/MarkedSpace.cpp: (JSC::MarkedSpace::sweep): * heap/MutatorState.cpp: (WTF::printInternal): * heap/MutatorState.h: * heap/RegisterState.h: Added. * heap/RunningScope.h: Added. (JSC::RunningScope::RunningScope): (JSC::RunningScope::~RunningScope): * heap/SlotVisitor.cpp: (JSC::SlotVisitor::SlotVisitor): (JSC::SlotVisitor::drain): (JSC::SlotVisitor::drainFromShared): (JSC::SlotVisitor::drainInParallelPassively): (JSC::SlotVisitor::donateAll): (JSC::SlotVisitor::donate): * heap/SlotVisitor.h: (JSC::SlotVisitor::codeName): * heap/StochasticSpaceTimeMutatorScheduler.cpp: (JSC::StochasticSpaceTimeMutatorScheduler::beginCollection): (JSC::StochasticSpaceTimeMutatorScheduler::synchronousDrainingDidStall): (JSC::StochasticSpaceTimeMutatorScheduler::timeToStop): * heap/SweepingScope.h: Added. (JSC::SweepingScope::SweepingScope): (JSC::SweepingScope::~SweepingScope): * jit/JITWorklist.cpp: (JSC::JITWorklist::Thread::Thread): * jsc.cpp: (GlobalObject::finishCreation): (functionFlashHeapAccess): * runtime/InitializeThreading.cpp: (JSC::initializeThreading): * runtime/JSCellInlines.h: (JSC::JSCell::classInfo): * runtime/Options.cpp: (JSC::overrideDefaults): * runtime/Options.h: * runtime/TestRunnerUtils.cpp: (JSC::finalizeStatsAtEndOfTesting): Source/WebCore: Added new tests in JSTests. The WebCore changes involve: - Refactoring around new header discipline. - Adding crazy GC APIs to window.internals to enable us to test the GC's runloop discipline. * ForwardingHeaders/heap/GCFinalizationCallback.h: Added. * ForwardingHeaders/heap/IncrementalSweeper.h: Added. * ForwardingHeaders/heap/MachineStackMarker.h: Added. * ForwardingHeaders/heap/RunningScope.h: Added. * bindings/js/CommonVM.cpp: * testing/Internals.cpp: (WebCore::Internals::parserMetaData): (WebCore::Internals::isReadableStreamDisturbed): (WebCore::Internals::isGCRunning): (WebCore::Internals::addGCFinalizationCallback): (WebCore::Internals::stopSweeping): (WebCore::Internals::startSweeping): * testing/Internals.h: * testing/Internals.idl: Source/WTF: Extend the use of AbstractLocker so that we can use more locking idioms. * wtf/AutomaticThread.cpp: (WTF::AutomaticThreadCondition::notifyOne): (WTF::AutomaticThreadCondition::notifyAll): (WTF::AutomaticThreadCondition::add): (WTF::AutomaticThreadCondition::remove): (WTF::AutomaticThreadCondition::contains): (WTF::AutomaticThread::AutomaticThread): (WTF::AutomaticThread::tryStop): (WTF::AutomaticThread::isWaiting): (WTF::AutomaticThread::notify): (WTF::AutomaticThread::start): (WTF::AutomaticThread::threadIsStopping): * wtf/AutomaticThread.h: * wtf/NumberOfCores.cpp: (WTF::numberOfProcessorCores): * wtf/ParallelHelperPool.cpp: (WTF::ParallelHelperClient::finish): (WTF::ParallelHelperClient::claimTask): (WTF::ParallelHelperPool::Thread::Thread): (WTF::ParallelHelperPool::didMakeWorkAvailable): (WTF::ParallelHelperPool::hasClientWithTask): (WTF::ParallelHelperPool::getClientWithTask): * wtf/ParallelHelperPool.h: Tools: Make more tests collect continuously. * Scripts/run-jsc-stress-tests: Canonical link: https://commits.webkit.org/185692@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@212778 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-02-22 00:58:15 +00:00
bool notify(const AbstractLocker&);
REGRESSION: HipChat and Mail sometimes hang beneath JSC::Heap::lastChanceToFinalize() https://bugs.webkit.org/show_bug.cgi?id=165962 Reviewed by Filip Pizlo. There is an inherent race in Condition::waitFor() where the timeout can happen just before a notify from another thread. Fixed this by adding a condition variable and flag to each AutomaticThread. The flag is used to signify to a notifying thread that the thread is waiting. That flag is set in the waiting thread before calling waitFor() and cleared by another thread when it notifies the thread. The access to that flag happens when the lock is held. Now the waiting thread checks if the flag after a timeout to see that it in fact should proceed like a normal notification. The added condition variable allows us to target a specific thread. We used to keep a list of waiting threads, now we keep a list of all threads. To notify one thread, we look for a waiting thread and notify it directly. If we can't find a waiting thread, we start a sleeping thread. We notify all threads by waking all waiting threads and starting all sleeping threads. * wtf/AutomaticThread.cpp: (WTF::AutomaticThreadCondition::notifyOne): (WTF::AutomaticThreadCondition::notifyAll): (WTF::AutomaticThread::isWaiting): (WTF::AutomaticThread::notify): (WTF::AutomaticThread::start): * wtf/AutomaticThread.h: Canonical link: https://commits.webkit.org/183569@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@209938 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-12-16 22:26:09 +00:00
WTF should make it easier to create threads that die automatically after inactivity https://bugs.webkit.org/show_bug.cgi?id=163576 Reviewed by Andreas Kling. Source/JavaScriptCore: Added a sleepSeconds() function, which made it easier for me to test this change. The WTF changes in this patch change how the JSC GC manages threads: the GC threads will now shut down automatically after 1 second of inactivity. Maybe this will save some memory. * jsc.cpp: (GlobalObject::finishCreation): (functionSleepSeconds): Source/WTF: For a long time now, I've been adding threads to WTF/JSC and each time I do this, I feel guilty because those threads don't shut down when they are inactive. For example, in bug 163562, I need to add a new GC thread. There will be one of them per VM. This means that a JSC API client that starts a lot of VMs will have a lot of threads. I don't think that's good. A common pattern for all of these threads is that they have some well-defined trigger that causes them to run. This trigger has a lock, a condition variable, some logic that determines if there is work to do, and then of course the logic for the thread's actual work. The thread bodies usually look like this: void Thingy::runThread() { for (;;) { Work work; { LockHolder locker(m_lock); while (!hasWork()) m_cond.wait(m_lock); work = takeWork(); } doWork(work); } } If you look at ParallelHelperPool (the GC's threads) and DFG::Worklist (some of the JIT's threads), you will see this pattern. This change adds a new kind of thread, called AutomaticThread, that lets you write threads to this pattern while getting automatic thread shutdown for free: instead of just waiting on a condition variable, AutomaticThread will have a timeout that causes the thread to die. The condition variable associated with AutomaticThread, called AutomaticThreadCondition, is smart enough to restart any threads that have decided to stop due to inactivity. The inactivity threshold is current just 1 second. In this patch I only adopt AutomaticThread for ParallelHelperPool. I plan to adopt it in more places soon. * WTF.xcodeproj/project.pbxproj: * wtf/AutomaticThread.cpp: Added. (WTF::AutomaticThreadCondition::create): (WTF::AutomaticThreadCondition::AutomaticThreadCondition): (WTF::AutomaticThreadCondition::~AutomaticThreadCondition): (WTF::AutomaticThreadCondition::notifyAll): (WTF::AutomaticThreadCondition::add): (WTF::AutomaticThreadCondition::remove): (WTF::AutomaticThreadCondition::contains): (WTF::AutomaticThread::AutomaticThread): (WTF::AutomaticThread::~AutomaticThread): (WTF::AutomaticThread::join): (WTF::AutomaticThread::start): * wtf/AutomaticThread.h: Added. * wtf/CMakeLists.txt: * wtf/ParallelHelperPool.cpp: (WTF::ParallelHelperClient::ParallelHelperClient): (WTF::ParallelHelperClient::~ParallelHelperClient): (WTF::ParallelHelperClient::setTask): (WTF::ParallelHelperClient::finish): (WTF::ParallelHelperClient::doSomeHelping): (WTF::ParallelHelperClient::runTask): (WTF::ParallelHelperPool::ParallelHelperPool): (WTF::ParallelHelperPool::~ParallelHelperPool): (WTF::ParallelHelperPool::ensureThreads): (WTF::ParallelHelperPool::doSomeHelping): (WTF::ParallelHelperPool::Thread::Thread): (WTF::ParallelHelperPool::didMakeWorkAvailable): (WTF::ParallelHelperPool::helperThreadBody): Deleted. (WTF::ParallelHelperPool::waitForClientWithTask): Deleted. * wtf/ParallelHelperPool.h: Canonical link: https://commits.webkit.org/181393@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@207480 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-10-18 20:17:10 +00:00
void join();
virtual const char* name() const { return "WTF::AutomaticThread"; }
WTF should make it easier to create threads that die automatically after inactivity https://bugs.webkit.org/show_bug.cgi?id=163576 Reviewed by Andreas Kling. Source/JavaScriptCore: Added a sleepSeconds() function, which made it easier for me to test this change. The WTF changes in this patch change how the JSC GC manages threads: the GC threads will now shut down automatically after 1 second of inactivity. Maybe this will save some memory. * jsc.cpp: (GlobalObject::finishCreation): (functionSleepSeconds): Source/WTF: For a long time now, I've been adding threads to WTF/JSC and each time I do this, I feel guilty because those threads don't shut down when they are inactive. For example, in bug 163562, I need to add a new GC thread. There will be one of them per VM. This means that a JSC API client that starts a lot of VMs will have a lot of threads. I don't think that's good. A common pattern for all of these threads is that they have some well-defined trigger that causes them to run. This trigger has a lock, a condition variable, some logic that determines if there is work to do, and then of course the logic for the thread's actual work. The thread bodies usually look like this: void Thingy::runThread() { for (;;) { Work work; { LockHolder locker(m_lock); while (!hasWork()) m_cond.wait(m_lock); work = takeWork(); } doWork(work); } } If you look at ParallelHelperPool (the GC's threads) and DFG::Worklist (some of the JIT's threads), you will see this pattern. This change adds a new kind of thread, called AutomaticThread, that lets you write threads to this pattern while getting automatic thread shutdown for free: instead of just waiting on a condition variable, AutomaticThread will have a timeout that causes the thread to die. The condition variable associated with AutomaticThread, called AutomaticThreadCondition, is smart enough to restart any threads that have decided to stop due to inactivity. The inactivity threshold is current just 1 second. In this patch I only adopt AutomaticThread for ParallelHelperPool. I plan to adopt it in more places soon. * WTF.xcodeproj/project.pbxproj: * wtf/AutomaticThread.cpp: Added. (WTF::AutomaticThreadCondition::create): (WTF::AutomaticThreadCondition::AutomaticThreadCondition): (WTF::AutomaticThreadCondition::~AutomaticThreadCondition): (WTF::AutomaticThreadCondition::notifyAll): (WTF::AutomaticThreadCondition::add): (WTF::AutomaticThreadCondition::remove): (WTF::AutomaticThreadCondition::contains): (WTF::AutomaticThread::AutomaticThread): (WTF::AutomaticThread::~AutomaticThread): (WTF::AutomaticThread::join): (WTF::AutomaticThread::start): * wtf/AutomaticThread.h: Added. * wtf/CMakeLists.txt: * wtf/ParallelHelperPool.cpp: (WTF::ParallelHelperClient::ParallelHelperClient): (WTF::ParallelHelperClient::~ParallelHelperClient): (WTF::ParallelHelperClient::setTask): (WTF::ParallelHelperClient::finish): (WTF::ParallelHelperClient::doSomeHelping): (WTF::ParallelHelperClient::runTask): (WTF::ParallelHelperPool::ParallelHelperPool): (WTF::ParallelHelperPool::~ParallelHelperPool): (WTF::ParallelHelperPool::ensureThreads): (WTF::ParallelHelperPool::doSomeHelping): (WTF::ParallelHelperPool::Thread::Thread): (WTF::ParallelHelperPool::didMakeWorkAvailable): (WTF::ParallelHelperPool::helperThreadBody): Deleted. (WTF::ParallelHelperPool::waitForClientWithTask): Deleted. * wtf/ParallelHelperPool.h: Canonical link: https://commits.webkit.org/181393@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@207480 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-10-18 20:17:10 +00:00
protected:
// This logically creates the thread, but in reality the thread won't be created until someone
DFG worklist should use AutomaticThread https://bugs.webkit.org/show_bug.cgi?id=163615 Reviewed by Mark Lam. Source/JavaScriptCore: AutomaticThread is a new feature in WTF that allows you to easily create worker threads that shut down automatically. This changes DFG::Worklist to use AutomaticThread, so that its threads shut down automatically, too. This has the potential to save a lot of memory. This required some improvements to AutomaticThread: Worklist likes to be able to keep state around for the whole lifetime of a thread, and so it likes knowing when threads are born and when they die. I added virtual methods for that. Also, Worklist uses notifyOne() so I added that, too. This looks to be perf-neutral. * dfg/DFGThreadData.cpp: (JSC::DFG::ThreadData::ThreadData): * dfg/DFGThreadData.h: * dfg/DFGWorklist.cpp: (JSC::DFG::Worklist::ThreadBody::ThreadBody): (JSC::DFG::Worklist::Worklist): (JSC::DFG::Worklist::~Worklist): (JSC::DFG::Worklist::finishCreation): (JSC::DFG::Worklist::isActiveForVM): (JSC::DFG::Worklist::enqueue): (JSC::DFG::Worklist::compilationState): (JSC::DFG::Worklist::waitUntilAllPlansForVMAreReady): (JSC::DFG::Worklist::removeAllReadyPlansForVM): (JSC::DFG::Worklist::completeAllReadyPlansForVM): (JSC::DFG::Worklist::rememberCodeBlocks): (JSC::DFG::Worklist::visitWeakReferences): (JSC::DFG::Worklist::removeDeadPlans): (JSC::DFG::Worklist::removeNonCompilingPlansForVM): (JSC::DFG::Worklist::queueLength): (JSC::DFG::Worklist::dump): (JSC::DFG::Worklist::runThread): Deleted. (JSC::DFG::Worklist::threadFunction): Deleted. * dfg/DFGWorklist.h: Source/WTF: This adds new functionality to AutomaticThread to support DFG::Worklist: - AutomaticThread::threadDidStart/threadWillStop virtual methods called at the start and end of a thread's lifetime. This allows Worklist to tie some resources to the life of the thread, and also means that now those resources will naturally free up when the Worklist is not in use. - AutomaticThreadCondition::notifyOne(). This required changes to Condition::notifyOne(). We need to know if the Condition woke up anyone. If it didn't, then we need to launch one of our threads. * wtf/AutomaticThread.cpp: (WTF::AutomaticThreadCondition::notifyOne): (WTF::AutomaticThread::ThreadScope::ThreadScope): (WTF::AutomaticThread::ThreadScope::~ThreadScope): (WTF::AutomaticThread::start): (WTF::AutomaticThread::threadDidStart): (WTF::AutomaticThread::threadWillStop): * wtf/AutomaticThread.h: * wtf/Condition.h: (WTF::ConditionBase::notifyOne): Canonical link: https://commits.webkit.org/181455@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@207545 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-10-19 17:47:30 +00:00
// calls AutomaticThreadCondition::notifyOne() or notifyAll().
AutomaticThread(const AbstractLocker&, Box<Lock>, Ref<AutomaticThreadCondition>&&, Seconds timeout = 10_s);
AutomaticThread(const AbstractLocker&, Box<Lock>, Ref<AutomaticThreadCondition>&&, ThreadType, Seconds timeout = 10_s);
WTF should make it easier to create threads that die automatically after inactivity https://bugs.webkit.org/show_bug.cgi?id=163576 Reviewed by Andreas Kling. Source/JavaScriptCore: Added a sleepSeconds() function, which made it easier for me to test this change. The WTF changes in this patch change how the JSC GC manages threads: the GC threads will now shut down automatically after 1 second of inactivity. Maybe this will save some memory. * jsc.cpp: (GlobalObject::finishCreation): (functionSleepSeconds): Source/WTF: For a long time now, I've been adding threads to WTF/JSC and each time I do this, I feel guilty because those threads don't shut down when they are inactive. For example, in bug 163562, I need to add a new GC thread. There will be one of them per VM. This means that a JSC API client that starts a lot of VMs will have a lot of threads. I don't think that's good. A common pattern for all of these threads is that they have some well-defined trigger that causes them to run. This trigger has a lock, a condition variable, some logic that determines if there is work to do, and then of course the logic for the thread's actual work. The thread bodies usually look like this: void Thingy::runThread() { for (;;) { Work work; { LockHolder locker(m_lock); while (!hasWork()) m_cond.wait(m_lock); work = takeWork(); } doWork(work); } } If you look at ParallelHelperPool (the GC's threads) and DFG::Worklist (some of the JIT's threads), you will see this pattern. This change adds a new kind of thread, called AutomaticThread, that lets you write threads to this pattern while getting automatic thread shutdown for free: instead of just waiting on a condition variable, AutomaticThread will have a timeout that causes the thread to die. The condition variable associated with AutomaticThread, called AutomaticThreadCondition, is smart enough to restart any threads that have decided to stop due to inactivity. The inactivity threshold is current just 1 second. In this patch I only adopt AutomaticThread for ParallelHelperPool. I plan to adopt it in more places soon. * WTF.xcodeproj/project.pbxproj: * wtf/AutomaticThread.cpp: Added. (WTF::AutomaticThreadCondition::create): (WTF::AutomaticThreadCondition::AutomaticThreadCondition): (WTF::AutomaticThreadCondition::~AutomaticThreadCondition): (WTF::AutomaticThreadCondition::notifyAll): (WTF::AutomaticThreadCondition::add): (WTF::AutomaticThreadCondition::remove): (WTF::AutomaticThreadCondition::contains): (WTF::AutomaticThread::AutomaticThread): (WTF::AutomaticThread::~AutomaticThread): (WTF::AutomaticThread::join): (WTF::AutomaticThread::start): * wtf/AutomaticThread.h: Added. * wtf/CMakeLists.txt: * wtf/ParallelHelperPool.cpp: (WTF::ParallelHelperClient::ParallelHelperClient): (WTF::ParallelHelperClient::~ParallelHelperClient): (WTF::ParallelHelperClient::setTask): (WTF::ParallelHelperClient::finish): (WTF::ParallelHelperClient::doSomeHelping): (WTF::ParallelHelperClient::runTask): (WTF::ParallelHelperPool::ParallelHelperPool): (WTF::ParallelHelperPool::~ParallelHelperPool): (WTF::ParallelHelperPool::ensureThreads): (WTF::ParallelHelperPool::doSomeHelping): (WTF::ParallelHelperPool::Thread::Thread): (WTF::ParallelHelperPool::didMakeWorkAvailable): (WTF::ParallelHelperPool::helperThreadBody): Deleted. (WTF::ParallelHelperPool::waitForClientWithTask): Deleted. * wtf/ParallelHelperPool.h: Canonical link: https://commits.webkit.org/181393@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@207480 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-10-18 20:17:10 +00:00
// To understand PollResult and WorkResult, imagine that poll() and work() are being called like
// so:
//
// void AutomaticThread::runThread()
// {
// for (;;) {
// {
Replace LockHolder with Locker in local variables https://bugs.webkit.org/show_bug.cgi?id=226133 Reviewed by Darin Adler. Replace LockHolder with Locker in local variables. It is shorter and it allows switching the lock type more easily since the compiler with deduce the lock type T for Locker<T>. Source/JavaScriptCore: * API/JSCallbackObject.h: (JSC::JSCallbackObjectData::JSPrivatePropertyMap::setPrivateProperty): (JSC::JSCallbackObjectData::JSPrivatePropertyMap::deletePrivateProperty): (JSC::JSCallbackObjectData::JSPrivatePropertyMap::visitChildren): * API/JSValue.mm: (handerForStructTag): * API/tests/testapi.cpp: (testCAPIViaCpp): * assembler/testmasm.cpp: (JSC::run): * b3/air/testair.cpp: * b3/testb3_1.cpp: (run): * bytecode/DirectEvalCodeCache.cpp: (JSC::DirectEvalCodeCache::setSlow): (JSC::DirectEvalCodeCache::clear): (JSC::DirectEvalCodeCache::visitAggregateImpl): * bytecode/SuperSampler.cpp: (JSC::initializeSuperSampler): (JSC::resetSuperSamplerState): (JSC::printSuperSamplerState): (JSC::enableSuperSampler): (JSC::disableSuperSampler): * dfg/DFGCommonData.cpp: (JSC::DFG::CommonData::invalidate): (JSC::DFG::CommonData::~CommonData): (JSC::DFG::CommonData::installVMTrapBreakpoints): (JSC::DFG::codeBlockForVMTrapPC): * dfg/DFGPlan.cpp: (JSC::DFG::Plan::cleanMustHandleValuesIfNecessary): * dfg/DFGWorklist.cpp: (JSC::DFG::Worklist::~Worklist): (JSC::DFG::Worklist::finishCreation): (JSC::DFG::Worklist::isActiveForVM const): (JSC::DFG::Worklist::enqueue): (JSC::DFG::Worklist::compilationState): (JSC::DFG::Worklist::waitUntilAllPlansForVMAreReady): (JSC::DFG::Worklist::removeAllReadyPlansForVM): (JSC::DFG::Worklist::completeAllReadyPlansForVM): (JSC::DFG::Worklist::visitWeakReferences): (JSC::DFG::Worklist::removeDeadPlans): (JSC::DFG::Worklist::removeNonCompilingPlansForVM): (JSC::DFG::Worklist::queueLength): (JSC::DFG::Worklist::dump const): (JSC::DFG::Worklist::setNumberOfThreads): * dfg/DFGWorklistInlines.h: (JSC::DFG::Worklist::iterateCodeBlocksForGC): * disassembler/Disassembler.cpp: * heap/BlockDirectory.cpp: (JSC::BlockDirectory::addBlock): * heap/CodeBlockSetInlines.h: (JSC::CodeBlockSet::iterateCurrentlyExecuting): * heap/ConservativeRoots.cpp: (JSC::ConservativeRoots::add): * heap/Heap.cpp: (JSC::Heap::Heap): (JSC::Heap::lastChanceToFinalize): (JSC::Heap::collectAsync): (JSC::Heap::runBeginPhase): (JSC::Heap::waitForCollector): (JSC::Heap::requestCollection): (JSC::Heap::notifyIsSafeToCollect): * heap/SlotVisitor.cpp: (JSC::SlotVisitor::didReachTermination): * inspector/agents/InspectorScriptProfilerAgent.cpp: (Inspector::InspectorScriptProfilerAgent::startTracking): (Inspector::InspectorScriptProfilerAgent::trackingComplete): (Inspector::InspectorScriptProfilerAgent::stopSamplingWhenDisconnecting): * inspector/remote/RemoteConnectionToTarget.cpp: (Inspector::RemoteConnectionToTarget::setup): (Inspector::RemoteConnectionToTarget::sendMessageToTarget): (Inspector::RemoteConnectionToTarget::close): (Inspector::RemoteConnectionToTarget::targetClosed): * inspector/remote/RemoteInspector.cpp: (Inspector::RemoteInspector::registerTarget): (Inspector::RemoteInspector::unregisterTarget): (Inspector::RemoteInspector::updateTarget): (Inspector::RemoteInspector::updateClientCapabilities): (Inspector::RemoteInspector::setClient): (Inspector::RemoteInspector::setupFailed): (Inspector::RemoteInspector::setupCompleted): (Inspector::RemoteInspector::stop): * inspector/remote/cocoa/RemoteConnectionToTargetCocoa.mm: (Inspector::RemoteTargetHandleRunSourceGlobal): (Inspector::RemoteTargetQueueTaskOnGlobalQueue): (Inspector::RemoteTargetHandleRunSourceWithInfo): (Inspector::RemoteConnectionToTarget::setup): (Inspector::RemoteConnectionToTarget::targetClosed): (Inspector::RemoteConnectionToTarget::close): (Inspector::RemoteConnectionToTarget::sendMessageToTarget): (Inspector::RemoteConnectionToTarget::queueTaskOnPrivateRunLoop): * inspector/remote/cocoa/RemoteInspectorCocoa.mm: (Inspector::RemoteInspector::updateAutomaticInspectionCandidate): (Inspector::RemoteInspector::sendMessageToRemote): (Inspector::RemoteInspector::start): (Inspector::RemoteInspector::setupXPCConnectionIfNeeded): (Inspector::RemoteInspector::setParentProcessInformation): (Inspector::RemoteInspector::xpcConnectionReceivedMessage): (Inspector::RemoteInspector::xpcConnectionFailed): (Inspector::RemoteInspector::pushListingsSoon): (Inspector::RemoteInspector::receivedIndicateMessage): (Inspector::RemoteInspector::receivedProxyApplicationSetupMessage): * inspector/remote/cocoa/RemoteInspectorXPCConnection.mm: (Inspector::RemoteInspectorXPCConnection::close): (Inspector::RemoteInspectorXPCConnection::closeFromMessage): (Inspector::RemoteInspectorXPCConnection::deserializeMessage): (Inspector::RemoteInspectorXPCConnection::handleEvent): * inspector/remote/glib/RemoteInspectorGlib.cpp: (Inspector::RemoteInspector::start): (Inspector::RemoteInspector::setupConnection): (Inspector::RemoteInspector::pushListingsSoon): (Inspector::RemoteInspector::sendMessageToRemote): (Inspector::RemoteInspector::receivedGetTargetListMessage): (Inspector::RemoteInspector::receivedDataMessage): (Inspector::RemoteInspector::receivedCloseMessage): (Inspector::RemoteInspector::setup): * inspector/remote/socket/RemoteInspectorConnectionClient.cpp: (Inspector::RemoteInspectorConnectionClient::didReceive): * inspector/remote/socket/RemoteInspectorSocket.cpp: (Inspector::RemoteInspector::didClose): (Inspector::RemoteInspector::start): (Inspector::RemoteInspector::pushListingsSoon): (Inspector::RemoteInspector::setup): (Inspector::RemoteInspector::setupInspectorClient): (Inspector::RemoteInspector::frontendDidClose): (Inspector::RemoteInspector::sendMessageToBackend): (Inspector::RemoteInspector::startAutomationSession): * inspector/remote/socket/RemoteInspectorSocketEndpoint.cpp: (Inspector::RemoteInspectorSocketEndpoint::listenInet): (Inspector::RemoteInspectorSocketEndpoint::isListening): (Inspector::RemoteInspectorSocketEndpoint::workerThread): (Inspector::RemoteInspectorSocketEndpoint::createClient): (Inspector::RemoteInspectorSocketEndpoint::disconnect): (Inspector::RemoteInspectorSocketEndpoint::invalidateClient): (Inspector::RemoteInspectorSocketEndpoint::invalidateListener): (Inspector::RemoteInspectorSocketEndpoint::getPort const): (Inspector::RemoteInspectorSocketEndpoint::recvIfEnabled): (Inspector::RemoteInspectorSocketEndpoint::sendIfEnabled): (Inspector::RemoteInspectorSocketEndpoint::send): (Inspector::RemoteInspectorSocketEndpoint::acceptInetSocketIfEnabled): * interpreter/CLoopStack.cpp: (JSC::CLoopStack::addToCommittedByteCount): (JSC::CLoopStack::committedByteCount): * jit/ExecutableAllocator.cpp: (JSC::dumpJITMemory): * jit/ICStats.cpp: (JSC::ICStats::ICStats): (JSC::ICStats::~ICStats): * jit/JITThunks.cpp: (JSC::JITThunks::ctiStub): (JSC::JITThunks::existingCTIStub): (JSC::JITThunks::ctiSlowPathFunctionStub): * jit/JITWorklist.cpp: (JSC::JITWorklist::Plan::compileInThread): (JSC::JITWorklist::Plan::isFinishedCompiling): (JSC::JITWorklist::JITWorklist): (JSC::JITWorklist::completeAllForVM): (JSC::JITWorklist::poll): (JSC::JITWorklist::compileLater): (JSC::JITWorklist::finalizePlans): * parser/SourceProvider.cpp: (JSC::SourceProvider::getID): * profiler/ProfilerDatabase.cpp: (JSC::Profiler::Database::ensureBytecodesFor): (JSC::Profiler::Database::notifyDestruction): (JSC::Profiler::Database::addCompilation): (JSC::Profiler::Database::logEvent): (JSC::Profiler::Database::addDatabaseToAtExit): (JSC::Profiler::Database::removeDatabaseFromAtExit): (JSC::Profiler::Database::removeFirstAtExitDatabase): * profiler/ProfilerUID.cpp: (JSC::Profiler::UID::create): * runtime/DeferredWorkTimer.cpp: (JSC::DeferredWorkTimer::scheduleWorkSoon): (JSC::DeferredWorkTimer::didResumeScriptExecutionOwner): * runtime/SamplingProfiler.cpp: (JSC::SamplingProfiler::timerLoop): (JSC::SamplingProfiler::shutdown): (JSC::SamplingProfiler::start): (JSC::SamplingProfiler::noticeCurrentThreadAsJSCExecutionThread): (JSC::SamplingProfiler::noticeJSLockAcquisition): (JSC::SamplingProfiler::noticeVMEntry): (JSC::SamplingProfiler::registerForReportAtExit): * runtime/Watchdog.cpp: (JSC::Watchdog::startTimer): (JSC::Watchdog::willDestroyVM): * tools/VMInspector.cpp: (JSC::VMInspector::isValidExecutableMemory): * wasm/WasmBBQPlan.cpp: (JSC::Wasm::BBQPlan::work): * wasm/WasmEntryPlan.cpp: (JSC::Wasm::EntryPlan::ThreadCountHolder::ThreadCountHolder): (JSC::Wasm::EntryPlan::ThreadCountHolder::~ThreadCountHolder): * wasm/WasmOMGPlan.cpp: (JSC::Wasm::OMGPlan::work): * wasm/WasmPlan.cpp: (JSC::Wasm::Plan::addCompletionTask): (JSC::Wasm::Plan::waitForCompletion): (JSC::Wasm::Plan::tryRemoveContextAndCancelIfLast): * wasm/WasmSignature.cpp: (JSC::Wasm::SignatureInformation::signatureFor): (JSC::Wasm::SignatureInformation::tryCleanup): * wasm/WasmWorklist.cpp: (JSC::Wasm::Worklist::enqueue): (JSC::Wasm::Worklist::completePlanSynchronously): (JSC::Wasm::Worklist::stopAllPlansForContext): (JSC::Wasm::Worklist::Worklist): (JSC::Wasm::Worklist::~Worklist): Source/WebCore: * Modules/webaudio/AsyncAudioDecoder.cpp: (WebCore::AsyncAudioDecoder::AsyncAudioDecoder): (WebCore::AsyncAudioDecoder::runLoop): * Modules/webdatabase/Database.cpp: (WebCore::Database::performClose): (WebCore::Database::inProgressTransactionCompleted): (WebCore::Database::hasPendingTransaction): (WebCore::Database::runTransaction): * Modules/webdatabase/DatabaseThread.cpp: (WebCore::DatabaseThread::start): (WebCore::DatabaseThread::databaseThread): (WebCore::DatabaseThread::recordDatabaseOpen): (WebCore::DatabaseThread::recordDatabaseClosed): (WebCore::DatabaseThread::hasPendingDatabaseActivity const): * Modules/webdatabase/DatabaseTracker.cpp: (WebCore::DatabaseTracker::canEstablishDatabase): (WebCore::DatabaseTracker::retryCanEstablishDatabase): (WebCore::DatabaseTracker::maximumSize): (WebCore::DatabaseTracker::fullPathForDatabase): (WebCore::DatabaseTracker::origins): (WebCore::DatabaseTracker::databaseNames): (WebCore::DatabaseTracker::detailsForNameAndOrigin): (WebCore::DatabaseTracker::setDatabaseDetails): (WebCore::DatabaseTracker::doneCreatingDatabase): (WebCore::DatabaseTracker::openDatabases): (WebCore::DatabaseTracker::addOpenDatabase): (WebCore::DatabaseTracker::removeOpenDatabase): (WebCore::DatabaseTracker::originLockFor): (WebCore::DatabaseTracker::quota): (WebCore::DatabaseTracker::setQuota): (WebCore::DatabaseTracker::deleteOrigin): (WebCore::DatabaseTracker::deleteDatabase): (WebCore::DatabaseTracker::deleteDatabaseFile): (WebCore::DatabaseTracker::removeDeletedOpenedDatabases): * Modules/webdatabase/SQLCallbackWrapper.h: (WebCore::SQLCallbackWrapper::clear): (WebCore::SQLCallbackWrapper::unwrap): * Modules/webdatabase/SQLTransaction.cpp: (WebCore::SQLTransaction::enqueueStatement): (WebCore::SQLTransaction::checkAndHandleClosedDatabase): (WebCore::SQLTransaction::getNextStatement): * Modules/webdatabase/SQLTransactionBackend.cpp: (WebCore::SQLTransactionBackend::doCleanup): * accessibility/isolatedtree/AXIsolatedTree.cpp: (WebCore::AXIsolatedTree::clear): (WebCore::AXIsolatedTree::generateSubtree): (WebCore::AXIsolatedTree::createSubtree): (WebCore::AXIsolatedTree::updateNode): (WebCore::AXIsolatedTree::updateNodeProperty): (WebCore::AXIsolatedTree::updateChildren): (WebCore::AXIsolatedTree::focusedNode): (WebCore::AXIsolatedTree::rootNode): (WebCore::AXIsolatedTree::setFocusedNodeID): (WebCore::AXIsolatedTree::removeNode): (WebCore::AXIsolatedTree::removeSubtree): (WebCore::AXIsolatedTree::applyPendingChanges): * page/scrolling/mac/ScrollingTreeMac.mm: (ScrollingTreeMac::scrollingNodeForPoint): (ScrollingTreeMac::eventListenerRegionTypesForPoint const): * platform/AbortableTaskQueue.h: * platform/audio/cocoa/CARingBuffer.cpp: (WebCore::CARingBufferStorageVector::flush): (WebCore::CARingBufferStorageVector::setCurrentFrameBounds): * platform/graphics/avfoundation/cf/MediaPlayerPrivateAVFoundationCF.cpp: (WebCore::AVFWrapper::addToMap): (WebCore::AVFWrapper::removeFromMap const): (WebCore::AVFWrapper::periodicTimeObserverCallback): (WebCore::AVFWrapper::processNotification): (WebCore::AVFWrapper::loadPlayableCompletionCallback): (WebCore::AVFWrapper::loadMetadataCompletionCallback): (WebCore::AVFWrapper::seekCompletedCallback): (WebCore::AVFWrapper::processCue): (WebCore::AVFWrapper::legibleOutputCallback): (WebCore::AVFWrapper::processShouldWaitForLoadingOfResource): (WebCore::AVFWrapper::resourceLoaderShouldWaitForLoadingOfRequestedResource): * platform/graphics/avfoundation/objc/ImageDecoderAVFObjC.mm: (-[WebCoreSharedBufferResourceLoaderDelegate setExpectedContentSize:]): (-[WebCoreSharedBufferResourceLoaderDelegate updateData:complete:]): (-[WebCoreSharedBufferResourceLoaderDelegate resourceLoader:shouldWaitForLoadingOfRequestedResource:]): (-[WebCoreSharedBufferResourceLoaderDelegate resourceLoader:didCancelLoadingRequest:]): (WebCore::ImageDecoderAVFObjC::setTrack): (WebCore::ImageDecoderAVFObjC::createFrameImageAtIndex): * platform/graphics/gstreamer/ImageDecoderGStreamer.cpp: (WebCore::ImageDecoderGStreamer::createFrameImageAtIndex): * platform/graphics/gstreamer/InbandTextTrackPrivateGStreamer.cpp: (WebCore::InbandTextTrackPrivateGStreamer::handleSample): (WebCore::InbandTextTrackPrivateGStreamer::notifyTrackOfSample): * platform/graphics/gstreamer/MainThreadNotifier.h: * platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp: (WebCore::MediaPlayerPrivateGStreamer::parseInitDataFromProtectionMessage): (WebCore::MediaPlayerPrivateGStreamer::handleProtectionEvent): * platform/graphics/gstreamer/TrackPrivateBaseGStreamer.cpp: (WebCore::TrackPrivateBaseGStreamer::tagsChanged): (WebCore::TrackPrivateBaseGStreamer::notifyTrackOfTagsChanged): * platform/graphics/gstreamer/VideoSinkGStreamer.cpp: (VideoRenderRequestScheduler::start): (VideoRenderRequestScheduler::stop): (VideoRenderRequestScheduler::drain): (VideoRenderRequestScheduler::requestRender): * platform/graphics/gstreamer/eme/WebKitCommonEncryptionDecryptorGStreamer.cpp: (transformInPlace): (sinkEventHandler): (webKitMediaCommonEncryptionDecryptIsFlushing): (setContext): * platform/graphics/nicosia/NicosiaBuffer.cpp: (Nicosia::Buffer::beginPainting): (Nicosia::Buffer::completePainting): (Nicosia::Buffer::waitUntilPaintingComplete): * platform/graphics/nicosia/NicosiaPlatformLayer.h: (Nicosia::PlatformLayer::setSceneIntegration): (Nicosia::PlatformLayer::createUpdateScope): (Nicosia::CompositionLayer::updateState): (Nicosia::CompositionLayer::flushState): (Nicosia::CompositionLayer::commitState): (Nicosia::CompositionLayer::accessPending): (Nicosia::CompositionLayer::accessCommitted): * platform/graphics/nicosia/NicosiaScene.h: (Nicosia::Scene::accessState): * platform/graphics/nicosia/NicosiaSceneIntegration.cpp: (Nicosia::SceneIntegration::setClient): (Nicosia::SceneIntegration::invalidate): (Nicosia::SceneIntegration::requestUpdate): * platform/graphics/nicosia/texmap/NicosiaBackingStoreTextureMapperImpl.cpp: (Nicosia::BackingStoreTextureMapperImpl::flushUpdate): (Nicosia::BackingStoreTextureMapperImpl::takeUpdate): * platform/graphics/nicosia/texmap/NicosiaContentLayerTextureMapperImpl.cpp: (Nicosia::ContentLayerTextureMapperImpl::~ContentLayerTextureMapperImpl): (Nicosia::ContentLayerTextureMapperImpl::invalidateClient): (Nicosia::ContentLayerTextureMapperImpl::flushUpdate): (Nicosia::ContentLayerTextureMapperImpl::swapBuffersIfNeeded): * platform/graphics/nicosia/texmap/NicosiaImageBackingTextureMapperImpl.cpp: (Nicosia::ImageBackingTextureMapperImpl::flushUpdate): (Nicosia::ImageBackingTextureMapperImpl::takeUpdate): * platform/graphics/texmap/TextureMapperGCGLPlatformLayer.cpp: (WebCore::TextureMapperGCGLPlatformLayer::swapBuffersIfNeeded): * platform/graphics/win/MediaPlayerPrivateMediaFoundation.cpp: (WebCore::MediaPlayerPrivateMediaFoundation::load): (WebCore::MediaPlayerPrivateMediaFoundation::naturalSize const): (WebCore::MediaPlayerPrivateMediaFoundation::addListener): (WebCore::MediaPlayerPrivateMediaFoundation::removeListener): (WebCore::MediaPlayerPrivateMediaFoundation::notifyDeleted): (WebCore::MediaPlayerPrivateMediaFoundation::setNaturalSize): (WebCore::MediaPlayerPrivateMediaFoundation::AsyncCallback::Invoke): (WebCore::MediaPlayerPrivateMediaFoundation::AsyncCallback::onMediaPlayerDeleted): (WebCore::MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::OnClockStart): (WebCore::MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::OnClockStop): (WebCore::MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::OnClockPause): (WebCore::MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::OnClockRestart): (WebCore::MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::OnClockSetRate): (WebCore::MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::ProcessMessage): (WebCore::MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::GetCurrentMediaType): (WebCore::MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::InitServicePointers): (WebCore::MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::ReleaseServicePointers): (WebCore::MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::SetVideoWindow): (WebCore::MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::GetVideoWindow): (WebCore::MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::SetVideoPosition): (WebCore::MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::GetVideoPosition): (WebCore::MediaPlayerPrivateMediaFoundation::CustomVideoPresenter::RepaintVideo): (WebCore::MediaPlayerPrivateMediaFoundation::VideoSamplePool::getSample): (WebCore::MediaPlayerPrivateMediaFoundation::VideoSamplePool::returnSample): (WebCore::MediaPlayerPrivateMediaFoundation::VideoSamplePool::areSamplesPending): (WebCore::MediaPlayerPrivateMediaFoundation::VideoSamplePool::initialize): (WebCore::MediaPlayerPrivateMediaFoundation::VideoSamplePool::clear): (WebCore::MediaPlayerPrivateMediaFoundation::VideoScheduler::stopScheduler): (WebCore::MediaPlayerPrivateMediaFoundation::VideoScheduler::scheduleSample): (WebCore::MediaPlayerPrivateMediaFoundation::VideoScheduler::processSamplesInQueue): (WebCore::MediaPlayerPrivateMediaFoundation::VideoScheduler::processSample): (WebCore::MediaPlayerPrivateMediaFoundation::VideoScheduler::schedulerThreadProcPrivate): (WebCore::MediaPlayerPrivateMediaFoundation::Direct3DPresenter::setVideoWindow): (WebCore::MediaPlayerPrivateMediaFoundation::Direct3DPresenter::setDestinationRect): (WebCore::MediaPlayerPrivateMediaFoundation::Direct3DPresenter::createVideoSamples): (WebCore::MediaPlayerPrivateMediaFoundation::Direct3DPresenter::checkDeviceState): (WebCore::MediaPlayerPrivateMediaFoundation::Direct3DPresenter::presentSample): (WebCore::MediaPlayerPrivateMediaFoundation::Direct3DPresenter::paintCurrentFrame): (WebCore::MediaPlayerPrivateMediaFoundation::Direct3DPresenter::createD3DDevice): * platform/image-decoders/ScalableImageDecoder.cpp: (WebCore::ScalableImageDecoder::frameIsCompleteAtIndex const): (WebCore::ScalableImageDecoder::frameHasAlphaAtIndex const): (WebCore::ScalableImageDecoder::frameBytesAtIndex const): (WebCore::ScalableImageDecoder::frameDurationAtIndex const): (WebCore::ScalableImageDecoder::createFrameImageAtIndex): * platform/image-decoders/ScalableImageDecoder.h: * platform/ios/LegacyTileCache.mm: (WebCore::LegacyTileCache::setTilesOpaque): (WebCore::LegacyTileCache::doLayoutTiles): (WebCore::LegacyTileCache::setCurrentScale): (WebCore::LegacyTileCache::commitScaleChange): (WebCore::LegacyTileCache::layoutTilesNow): (WebCore::LegacyTileCache::layoutTilesNowForRect): (WebCore::LegacyTileCache::removeAllNonVisibleTiles): (WebCore::LegacyTileCache::removeAllTiles): (WebCore::LegacyTileCache::removeForegroundTiles): (WebCore::LegacyTileCache::setContentReplacementImage): (WebCore::LegacyTileCache::contentReplacementImage const): (WebCore::LegacyTileCache::tileCreationTimerFired): (WebCore::LegacyTileCache::setNeedsDisplayInRect): (WebCore::LegacyTileCache::updateTilingMode): (WebCore::LegacyTileCache::setTilingMode): (WebCore::LegacyTileCache::doPendingRepaints): (WebCore::LegacyTileCache::flushSavedDisplayRects): (WebCore::LegacyTileCache::prepareToDraw): * platform/ios/LegacyTileLayerPool.mm: (WebCore::LegacyTileLayerPool::addLayer): (WebCore::LegacyTileLayerPool::takeLayerWithSize): (WebCore::LegacyTileLayerPool::setCapacity): (WebCore::LegacyTileLayerPool::prune): (WebCore::LegacyTileLayerPool::drain): * platform/ios/wak/WAKWindow.mm: (-[WAKWindow setExposedScrollViewRect:]): (-[WAKWindow exposedScrollViewRect]): * platform/ios/wak/WebCoreThread.mm: (RunWebThread): (StartWebThread): * platform/mediastream/gstreamer/RealtimeOutgoingAudioSourceLibWebRTC.cpp: (WebCore::RealtimeOutgoingAudioSourceLibWebRTC::audioSamplesAvailable): (WebCore::RealtimeOutgoingAudioSourceLibWebRTC::pullAudioData): * platform/network/cf/FormDataStreamCFNet.cpp: (WebCore::openNextStream): (WebCore::formFinalize): (WebCore::formClose): * platform/network/curl/CurlRequest.cpp: (WebCore::CurlRequest::setRequestPaused): (WebCore::CurlRequest::setCallbackPaused): (WebCore::CurlRequest::pausedStatusChanged): (WebCore::CurlRequest::enableDownloadToFile): (WebCore::CurlRequest::getDownloadedFilePath): (WebCore::CurlRequest::writeDataToDownloadFileIfEnabled): (WebCore::CurlRequest::closeDownloadFile): (WebCore::CurlRequest::cleanupDownloadFile): * platform/network/curl/CurlSSLHandle.cpp: (WebCore::CurlSSLHandle::allowAnyHTTPSCertificatesForHost): (WebCore::CurlSSLHandle::canIgnoreAnyHTTPSCertificatesForHost const): (WebCore::CurlSSLHandle::setClientCertificateInfo): (WebCore::CurlSSLHandle::getSSLClientCertificate const): * platform/sql/SQLiteDatabase.cpp: (WebCore::SQLiteDatabase::close): (WebCore::SQLiteDatabase::maximumSize): (WebCore::SQLiteDatabase::setMaximumSize): (WebCore::SQLiteDatabase::pageSize): (WebCore::SQLiteDatabase::freeSpaceSize): (WebCore::SQLiteDatabase::totalSize): (WebCore::SQLiteDatabase::runIncrementalVacuumCommand): (WebCore::SQLiteDatabase::interrupt): (WebCore::SQLiteDatabase::setAuthorizer): (WebCore::constructAndPrepareStatement): * platform/sql/SQLiteStatement.cpp: (WebCore::SQLiteStatement::step): Source/WebKit: * NetworkProcess/IndexedDB/WebIDBServer.cpp: (WebKit::m_closeCallback): (WebKit::WebIDBServer::getOrigins): (WebKit::WebIDBServer::closeAndDeleteDatabasesModifiedSince): (WebKit::WebIDBServer::closeAndDeleteDatabasesForOrigins): (WebKit::WebIDBServer::renameOrigin): (WebKit::WebIDBServer::openDatabase): (WebKit::WebIDBServer::deleteDatabase): (WebKit::WebIDBServer::abortTransaction): (WebKit::WebIDBServer::commitTransaction): (WebKit::WebIDBServer::didFinishHandlingVersionChangeTransaction): (WebKit::WebIDBServer::createObjectStore): (WebKit::WebIDBServer::deleteObjectStore): (WebKit::WebIDBServer::renameObjectStore): (WebKit::WebIDBServer::clearObjectStore): (WebKit::WebIDBServer::createIndex): (WebKit::WebIDBServer::deleteIndex): (WebKit::WebIDBServer::renameIndex): (WebKit::WebIDBServer::putOrAdd): (WebKit::WebIDBServer::getRecord): (WebKit::WebIDBServer::getAllRecords): (WebKit::WebIDBServer::getCount): (WebKit::WebIDBServer::deleteRecord): (WebKit::WebIDBServer::openCursor): (WebKit::WebIDBServer::iterateCursor): (WebKit::WebIDBServer::establishTransaction): (WebKit::WebIDBServer::databaseConnectionPendingClose): (WebKit::WebIDBServer::databaseConnectionClosed): (WebKit::WebIDBServer::abortOpenAndUpgradeNeeded): (WebKit::WebIDBServer::didFireVersionChangeEvent): (WebKit::WebIDBServer::openDBRequestCancelled): (WebKit::WebIDBServer::getAllDatabaseNamesAndVersions): (WebKit::WebIDBServer::addConnection): (WebKit::WebIDBServer::removeConnection): (WebKit::WebIDBServer::close): * NetworkProcess/cache/CacheStorageEngine.cpp: (WebKit::CacheStorage::Engine::writeSizeFile): (WebKit::CacheStorage::Engine::readSizeFile): (WebKit::CacheStorage::Engine::clearAllCachesFromDisk): (WebKit::CacheStorage::Engine::deleteNonEmptyDirectoryOnBackgroundThread): * NetworkProcess/glib/DNSCache.cpp: (WebKit::DNSCache::lookup): (WebKit::DNSCache::update): (WebKit::DNSCache::removeExpiredResponsesFired): (WebKit::DNSCache::clear): * Shared/CoordinatedGraphics/threadedcompositor/CompositingRunLoop.cpp: (WebKit::CompositingRunLoop::suspend): (WebKit::CompositingRunLoop::resume): (WebKit::CompositingRunLoop::scheduleUpdate): (WebKit::CompositingRunLoop::stopUpdates): (WebKit::CompositingRunLoop::updateTimerFired): * Shared/CoordinatedGraphics/threadedcompositor/ThreadedCompositor.cpp: (WebKit::m_displayRefreshMonitor): (WebKit::ThreadedCompositor::setScaleFactor): (WebKit::ThreadedCompositor::setScrollPosition): (WebKit::ThreadedCompositor::setViewportSize): (WebKit::ThreadedCompositor::renderLayerTree): (WebKit::ThreadedCompositor::sceneUpdateFinished): (WebKit::ThreadedCompositor::updateSceneState): * UIProcess/API/glib/IconDatabase.cpp: (WebKit::IconDatabase::populatePageURLToIconURLMap): (WebKit::IconDatabase::clearLoadedIconsTimerFired): (WebKit::IconDatabase::checkIconURLAndSetPageURLIfNeeded): (WebKit::IconDatabase::loadIconForPageURL): (WebKit::IconDatabase::iconURLForPageURL): (WebKit::IconDatabase::setIconForPageURL): (WebKit::IconDatabase::clear): Source/WebKitLegacy: * Storage/InProcessIDBServer.cpp: (InProcessIDBServer::InProcessIDBServer): (InProcessIDBServer::deleteDatabase): (InProcessIDBServer::openDatabase): (InProcessIDBServer::abortTransaction): (InProcessIDBServer::commitTransaction): (InProcessIDBServer::didFinishHandlingVersionChangeTransaction): (InProcessIDBServer::createObjectStore): (InProcessIDBServer::deleteObjectStore): (InProcessIDBServer::renameObjectStore): (InProcessIDBServer::clearObjectStore): (InProcessIDBServer::createIndex): (InProcessIDBServer::deleteIndex): (InProcessIDBServer::renameIndex): (InProcessIDBServer::putOrAdd): (InProcessIDBServer::getRecord): (InProcessIDBServer::getAllRecords): (InProcessIDBServer::getCount): (InProcessIDBServer::deleteRecord): (InProcessIDBServer::openCursor): (InProcessIDBServer::iterateCursor): (InProcessIDBServer::establishTransaction): (InProcessIDBServer::databaseConnectionPendingClose): (InProcessIDBServer::databaseConnectionClosed): (InProcessIDBServer::abortOpenAndUpgradeNeeded): (InProcessIDBServer::didFireVersionChangeEvent): (InProcessIDBServer::openDBRequestCancelled): (InProcessIDBServer::getAllDatabaseNamesAndVersions): (InProcessIDBServer::closeAndDeleteDatabasesModifiedSince): * Storage/StorageAreaSync.cpp: (WebKit::StorageAreaSync::syncTimerFired): (WebKit::StorageAreaSync::performSync): * Storage/StorageTracker.cpp: (WebKit::StorageTracker::finishedImportingOriginIdentifiers): (WebKit::StorageTracker::syncImportOriginIdentifiers): (WebKit::StorageTracker::syncFileSystemAndTrackerDatabase): (WebKit::StorageTracker::setOriginDetails): (WebKit::StorageTracker::syncSetOriginDetails): (WebKit::StorageTracker::origins): (WebKit::StorageTracker::deleteAllOrigins): (WebKit::StorageTracker::syncDeleteAllOrigins): (WebKit::StorageTracker::deleteOrigin): (WebKit::StorageTracker::syncDeleteOrigin): (WebKit::StorageTracker::canDeleteOrigin): (WebKit::StorageTracker::cancelDeletingOrigin): (WebKit::StorageTracker::diskUsageForOrigin): Source/WebKitLegacy/mac: * WebView/WebView.mm: (-[WebView _synchronizeCustomFixedPositionLayoutRect]): (-[WebView _setCustomFixedPositionLayoutRectInWebThread:synchronize:]): (-[WebView _setCustomFixedPositionLayoutRect:]): (-[WebView _fetchCustomFixedPositionLayoutRect:]): Source/WebKitLegacy/win: * Plugins/PluginMainThreadScheduler.cpp: (WebCore::PluginMainThreadScheduler::scheduleCall): (WebCore::PluginMainThreadScheduler::registerPlugin): (WebCore::PluginMainThreadScheduler::unregisterPlugin): (WebCore::PluginMainThreadScheduler::dispatchCallsForPlugin): Source/WTF: * benchmarks/LockSpeedTest.cpp: * wtf/AutomaticThread.cpp: (WTF::AutomaticThread::~AutomaticThread): (WTF::AutomaticThread::join): (WTF::AutomaticThread::start): * wtf/AutomaticThread.h: * wtf/MetaAllocator.cpp: (WTF::MetaAllocatorHandle::shrink): (WTF::MetaAllocator::addFreshFreeSpace): (WTF::MetaAllocator::debugFreeSpaceSize): * wtf/ParallelHelperPool.cpp: (WTF::ParallelHelperClient::ParallelHelperClient): (WTF::ParallelHelperClient::~ParallelHelperClient): (WTF::ParallelHelperClient::setTask): (WTF::ParallelHelperClient::finish): (WTF::ParallelHelperClient::doSomeHelping): (WTF::ParallelHelperClient::runTask): (WTF::ParallelHelperPool::~ParallelHelperPool): (WTF::ParallelHelperPool::ensureThreads): (WTF::ParallelHelperPool::doSomeHelping): * wtf/Seconds.cpp: (WTF::sleep): * wtf/TimeWithDynamicClockType.cpp: (WTF::sleep): * wtf/WorkerPool.cpp: (WTF::WorkerPool::WorkerPool): (WTF::WorkerPool::~WorkerPool): (WTF::WorkerPool::postTask): * wtf/posix/ThreadingPOSIX.cpp: (WTF::Thread::suspend): (WTF::Thread::resume): (WTF::Thread::getRegisters): * wtf/win/DbgHelperWin.cpp: (WTF::DbgHelper::SymFromAddress): * wtf/win/ThreadingWin.cpp: (WTF::Thread::suspend): (WTF::Thread::resume): (WTF::Thread::getRegisters): Tools: * TestWebKitAPI/Tests/WTF/WorkQueue.cpp: (TestWebKitAPI::TEST): * TestWebKitAPI/Tests/WTF/glib/WorkQueueGLib.cpp: (TestWebKitAPI::TEST): * TestWebKitAPI/Tests/WebCore/AbortableTaskQueue.cpp: (TestWebKitAPI::DeterministicScheduler::ThreadContext::waitMyTurn): (TestWebKitAPI::DeterministicScheduler::ThreadContext::yieldToThread): Canonical link: https://commits.webkit.org/238053@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@277920 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2021-05-22 16:49:42 +00:00
// Locker locker { m_lock };
WTF should make it easier to create threads that die automatically after inactivity https://bugs.webkit.org/show_bug.cgi?id=163576 Reviewed by Andreas Kling. Source/JavaScriptCore: Added a sleepSeconds() function, which made it easier for me to test this change. The WTF changes in this patch change how the JSC GC manages threads: the GC threads will now shut down automatically after 1 second of inactivity. Maybe this will save some memory. * jsc.cpp: (GlobalObject::finishCreation): (functionSleepSeconds): Source/WTF: For a long time now, I've been adding threads to WTF/JSC and each time I do this, I feel guilty because those threads don't shut down when they are inactive. For example, in bug 163562, I need to add a new GC thread. There will be one of them per VM. This means that a JSC API client that starts a lot of VMs will have a lot of threads. I don't think that's good. A common pattern for all of these threads is that they have some well-defined trigger that causes them to run. This trigger has a lock, a condition variable, some logic that determines if there is work to do, and then of course the logic for the thread's actual work. The thread bodies usually look like this: void Thingy::runThread() { for (;;) { Work work; { LockHolder locker(m_lock); while (!hasWork()) m_cond.wait(m_lock); work = takeWork(); } doWork(work); } } If you look at ParallelHelperPool (the GC's threads) and DFG::Worklist (some of the JIT's threads), you will see this pattern. This change adds a new kind of thread, called AutomaticThread, that lets you write threads to this pattern while getting automatic thread shutdown for free: instead of just waiting on a condition variable, AutomaticThread will have a timeout that causes the thread to die. The condition variable associated with AutomaticThread, called AutomaticThreadCondition, is smart enough to restart any threads that have decided to stop due to inactivity. The inactivity threshold is current just 1 second. In this patch I only adopt AutomaticThread for ParallelHelperPool. I plan to adopt it in more places soon. * WTF.xcodeproj/project.pbxproj: * wtf/AutomaticThread.cpp: Added. (WTF::AutomaticThreadCondition::create): (WTF::AutomaticThreadCondition::AutomaticThreadCondition): (WTF::AutomaticThreadCondition::~AutomaticThreadCondition): (WTF::AutomaticThreadCondition::notifyAll): (WTF::AutomaticThreadCondition::add): (WTF::AutomaticThreadCondition::remove): (WTF::AutomaticThreadCondition::contains): (WTF::AutomaticThread::AutomaticThread): (WTF::AutomaticThread::~AutomaticThread): (WTF::AutomaticThread::join): (WTF::AutomaticThread::start): * wtf/AutomaticThread.h: Added. * wtf/CMakeLists.txt: * wtf/ParallelHelperPool.cpp: (WTF::ParallelHelperClient::ParallelHelperClient): (WTF::ParallelHelperClient::~ParallelHelperClient): (WTF::ParallelHelperClient::setTask): (WTF::ParallelHelperClient::finish): (WTF::ParallelHelperClient::doSomeHelping): (WTF::ParallelHelperClient::runTask): (WTF::ParallelHelperPool::ParallelHelperPool): (WTF::ParallelHelperPool::~ParallelHelperPool): (WTF::ParallelHelperPool::ensureThreads): (WTF::ParallelHelperPool::doSomeHelping): (WTF::ParallelHelperPool::Thread::Thread): (WTF::ParallelHelperPool::didMakeWorkAvailable): (WTF::ParallelHelperPool::helperThreadBody): Deleted. (WTF::ParallelHelperPool::waitForClientWithTask): Deleted. * wtf/ParallelHelperPool.h: Canonical link: https://commits.webkit.org/181393@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@207480 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-10-18 20:17:10 +00:00
// for (;;) {
// PollResult result = poll();
// if (result == PollResult::Work)
// break;
// if (result == PollResult::Stop)
// return;
// RELEASE_ASSERT(result == PollResult::Wait);
// m_condition.wait(m_lock);
// }
// }
//
// WorkResult result = work();
// if (result == WorkResult::Stop)
// return;
// RELEASE_ASSERT(result == WorkResult::Continue);
// }
// }
enum class PollResult { Work, Stop, Wait };
The collector thread should only start when the mutator doesn't have heap access https://bugs.webkit.org/show_bug.cgi?id=167737 Reviewed by Keith Miller. JSTests: Add versions of splay that flash heap access, to simulate what might happen if a third-party app was running concurrent GC. In this case, we might actually start the collector thread. * stress/splay-flash-access-1ms.js: Added. (performance.now): (this.Setup.setup.setup): (this.TearDown.tearDown.tearDown): (Benchmark): (BenchmarkResult): (BenchmarkResult.prototype.valueOf): (BenchmarkSuite): (alert): (Math.random): (BenchmarkSuite.ResetRNG): (RunStep): (BenchmarkSuite.RunSuites): (BenchmarkSuite.CountBenchmarks): (BenchmarkSuite.GeometricMean): (BenchmarkSuite.GeometricMeanTime): (BenchmarkSuite.AverageAbovePercentile): (BenchmarkSuite.GeometricMeanLatency): (BenchmarkSuite.FormatScore): (BenchmarkSuite.prototype.NotifyStep): (BenchmarkSuite.prototype.NotifyResult): (BenchmarkSuite.prototype.NotifyError): (BenchmarkSuite.prototype.RunSingleBenchmark): (RunNextSetup): (RunNextBenchmark): (RunNextTearDown): (BenchmarkSuite.prototype.RunStep): (GeneratePayloadTree): (GenerateKey): (SplayUpdateStats): (InsertNewNode): (SplaySetup): (SplayTearDown): (SplayRun): (SplayTree): (SplayTree.prototype.isEmpty): (SplayTree.prototype.insert): (SplayTree.prototype.remove): (SplayTree.prototype.find): (SplayTree.prototype.findMax): (SplayTree.prototype.findGreatestLessThan): (SplayTree.prototype.exportKeys): (SplayTree.prototype.splay_): (SplayTree.Node): (SplayTree.Node.prototype.traverse_): (jscSetUp): (jscTearDown): (jscRun): (averageAbovePercentile): (printPercentile): * stress/splay-flash-access.js: Added. (performance.now): (this.Setup.setup.setup): (this.TearDown.tearDown.tearDown): (Benchmark): (BenchmarkResult): (BenchmarkResult.prototype.valueOf): (BenchmarkSuite): (alert): (Math.random): (BenchmarkSuite.ResetRNG): (RunStep): (BenchmarkSuite.RunSuites): (BenchmarkSuite.CountBenchmarks): (BenchmarkSuite.GeometricMean): (BenchmarkSuite.GeometricMeanTime): (BenchmarkSuite.AverageAbovePercentile): (BenchmarkSuite.GeometricMeanLatency): (BenchmarkSuite.FormatScore): (BenchmarkSuite.prototype.NotifyStep): (BenchmarkSuite.prototype.NotifyResult): (BenchmarkSuite.prototype.NotifyError): (BenchmarkSuite.prototype.RunSingleBenchmark): (RunNextSetup): (RunNextBenchmark): (RunNextTearDown): (BenchmarkSuite.prototype.RunStep): (GeneratePayloadTree): (GenerateKey): (SplayUpdateStats): (InsertNewNode): (SplaySetup): (SplayTearDown): (SplayRun): (SplayTree): (SplayTree.prototype.isEmpty): (SplayTree.prototype.insert): (SplayTree.prototype.remove): (SplayTree.prototype.find): (SplayTree.prototype.findMax): (SplayTree.prototype.findGreatestLessThan): (SplayTree.prototype.exportKeys): (SplayTree.prototype.splay_): (SplayTree.Node): (SplayTree.Node.prototype.traverse_): (jscSetUp): (jscTearDown): (jscRun): (averageAbovePercentile): (printPercentile): Source/JavaScriptCore: This turns the collector thread's workflow into a state machine, so that the mutator thread can run it directly. This reduces the amount of synchronization we do with the collector thread, and means that most apps will never start the collector thread. The collector thread will still start when we need to finish collecting and we don't have heap access. In this new world, "stopping the world" means relinquishing control of collection to the mutator. This means tracking who is conducting collection. I use the GCConductor enum to say who is conducting. It's either GCConductor::Mutator or GCConductor::Collector. I use the term "conn" to refer to the concept of conducting (having the conn, relinquishing the conn, taking the conn). So, stopping the world means giving the mutator the conn. Releasing heap access means giving the collector the conn. This meant bringing back the conservative scan of the calling thread. It turns out that this scan was too slow to be called on each GC increment because apparently setjmp() now does system calls. So, I wrote our own callee save register saving for the GC. Then I had doubts about whether or not it was correct, so I also made it so that the GC only rarely asks for the register state. I think we still want to use my register saving code instead of setjmp because setjmp seems to save things we don't need, and that could make us overly conservative. It turns out that this new scheduling discipline makes the old space-time scheduler perform better than the new stochastic space-time scheduler on systems with fewer than 4 cores. This is because the mutator having the conn enables us to time the mutator<->collector context switches by polling. The OS is never involved. So, we can use super precise timing. This allows the old space-time schduler to shine like it hadn't before. The splay results imply that this is all a good thing. On 2-core systems, this reduces pause times by 40% and it increases throughput about 5%. On 1-core systems, this reduces pause times by half and reduces throughput by 8%. On 4-or-more-core systems, this doesn't seem to have much effect. * CMakeLists.txt: * JavaScriptCore.xcodeproj/project.pbxproj: * bytecode/CodeBlock.cpp: (JSC::CodeBlock::visitChildren): * dfg/DFGWorklist.cpp: (JSC::DFG::Worklist::ThreadBody::ThreadBody): (JSC::DFG::Worklist::dump): (JSC::DFG::numberOfWorklists): (JSC::DFG::ensureWorklistForIndex): (JSC::DFG::existingWorklistForIndexOrNull): (JSC::DFG::existingWorklistForIndex): * dfg/DFGWorklist.h: (JSC::DFG::numberOfWorklists): Deleted. (JSC::DFG::ensureWorklistForIndex): Deleted. (JSC::DFG::existingWorklistForIndexOrNull): Deleted. (JSC::DFG::existingWorklistForIndex): Deleted. * heap/CollectingScope.h: Added. (JSC::CollectingScope::CollectingScope): (JSC::CollectingScope::~CollectingScope): * heap/CollectorPhase.cpp: Added. (JSC::worldShouldBeSuspended): (WTF::printInternal): * heap/CollectorPhase.h: Added. * heap/EdenGCActivityCallback.cpp: (JSC::EdenGCActivityCallback::lastGCLength): * heap/FullGCActivityCallback.cpp: (JSC::FullGCActivityCallback::doCollection): (JSC::FullGCActivityCallback::lastGCLength): * heap/GCConductor.cpp: Added. (JSC::gcConductorShortName): (WTF::printInternal): * heap/GCConductor.h: Added. * heap/GCFinalizationCallback.cpp: Added. (JSC::GCFinalizationCallback::GCFinalizationCallback): (JSC::GCFinalizationCallback::~GCFinalizationCallback): * heap/GCFinalizationCallback.h: Added. (JSC::GCFinalizationCallbackFuncAdaptor::GCFinalizationCallbackFuncAdaptor): (JSC::createGCFinalizationCallback): * heap/Heap.cpp: (JSC::Heap::Thread::Thread): (JSC::Heap::Heap): (JSC::Heap::lastChanceToFinalize): (JSC::Heap::gatherStackRoots): (JSC::Heap::updateObjectCounts): (JSC::Heap::sweepSynchronously): (JSC::Heap::collectAllGarbage): (JSC::Heap::collectAsync): (JSC::Heap::collectSync): (JSC::Heap::shouldCollectInCollectorThread): (JSC::Heap::collectInCollectorThread): (JSC::Heap::checkConn): (JSC::Heap::runNotRunningPhase): (JSC::Heap::runBeginPhase): (JSC::Heap::runFixpointPhase): (JSC::Heap::runConcurrentPhase): (JSC::Heap::runReloopPhase): (JSC::Heap::runEndPhase): (JSC::Heap::changePhase): (JSC::Heap::finishChangingPhase): (JSC::Heap::stopThePeriphery): (JSC::Heap::resumeThePeriphery): (JSC::Heap::stopTheMutator): (JSC::Heap::resumeTheMutator): (JSC::Heap::stopIfNecessarySlow): (JSC::Heap::collectInMutatorThread): (JSC::Heap::waitForCollector): (JSC::Heap::acquireAccessSlow): (JSC::Heap::releaseAccessSlow): (JSC::Heap::relinquishConn): (JSC::Heap::finishRelinquishingConn): (JSC::Heap::handleNeedFinalize): (JSC::Heap::notifyThreadStopping): (JSC::Heap::finalize): (JSC::Heap::addFinalizationCallback): (JSC::Heap::requestCollection): (JSC::Heap::waitForCollection): (JSC::Heap::updateAllocationLimits): (JSC::Heap::didFinishCollection): (JSC::Heap::collectIfNecessaryOrDefer): (JSC::Heap::notifyIsSafeToCollect): (JSC::Heap::preventCollection): (JSC::Heap::performIncrement): (JSC::Heap::markToFixpoint): Deleted. (JSC::Heap::shouldCollectInThread): Deleted. (JSC::Heap::collectInThread): Deleted. (JSC::Heap::stopTheWorld): Deleted. (JSC::Heap::resumeTheWorld): Deleted. * heap/Heap.h: (JSC::Heap::machineThreads): (JSC::Heap::lastFullGCLength): (JSC::Heap::lastEdenGCLength): (JSC::Heap::increaseLastFullGCLength): * heap/HeapInlines.h: (JSC::Heap::mutatorIsStopped): Deleted. * heap/HeapStatistics.cpp: Removed. * heap/HeapStatistics.h: Removed. * heap/HelpingGCScope.h: Removed. * heap/IncrementalSweeper.cpp: (JSC::IncrementalSweeper::stopSweeping): (JSC::IncrementalSweeper::willFinishSweeping): Deleted. * heap/IncrementalSweeper.h: * heap/MachineStackMarker.cpp: (JSC::MachineThreads::gatherFromCurrentThread): (JSC::MachineThreads::gatherConservativeRoots): (JSC::callWithCurrentThreadState): * heap/MachineStackMarker.h: * heap/MarkedAllocator.cpp: (JSC::MarkedAllocator::allocateSlowCaseImpl): * heap/MarkedBlock.cpp: (JSC::MarkedBlock::Handle::sweep): * heap/MarkedSpace.cpp: (JSC::MarkedSpace::sweep): * heap/MutatorState.cpp: (WTF::printInternal): * heap/MutatorState.h: * heap/RegisterState.h: Added. * heap/RunningScope.h: Added. (JSC::RunningScope::RunningScope): (JSC::RunningScope::~RunningScope): * heap/SlotVisitor.cpp: (JSC::SlotVisitor::SlotVisitor): (JSC::SlotVisitor::drain): (JSC::SlotVisitor::drainFromShared): (JSC::SlotVisitor::drainInParallelPassively): (JSC::SlotVisitor::donateAll): (JSC::SlotVisitor::donate): * heap/SlotVisitor.h: (JSC::SlotVisitor::codeName): * heap/StochasticSpaceTimeMutatorScheduler.cpp: (JSC::StochasticSpaceTimeMutatorScheduler::beginCollection): (JSC::StochasticSpaceTimeMutatorScheduler::synchronousDrainingDidStall): (JSC::StochasticSpaceTimeMutatorScheduler::timeToStop): * heap/SweepingScope.h: Added. (JSC::SweepingScope::SweepingScope): (JSC::SweepingScope::~SweepingScope): * jit/JITWorklist.cpp: (JSC::JITWorklist::Thread::Thread): * jsc.cpp: (GlobalObject::finishCreation): (functionFlashHeapAccess): * runtime/InitializeThreading.cpp: (JSC::initializeThreading): * runtime/JSCellInlines.h: (JSC::JSCell::classInfo): * runtime/Options.cpp: (JSC::overrideDefaults): * runtime/Options.h: * runtime/TestRunnerUtils.cpp: (JSC::finalizeStatsAtEndOfTesting): Source/WebCore: Added new tests in JSTests. The WebCore changes involve: - Refactoring around new header discipline. - Adding crazy GC APIs to window.internals to enable us to test the GC's runloop discipline. * ForwardingHeaders/heap/GCFinalizationCallback.h: Added. * ForwardingHeaders/heap/IncrementalSweeper.h: Added. * ForwardingHeaders/heap/MachineStackMarker.h: Added. * ForwardingHeaders/heap/RunningScope.h: Added. * bindings/js/CommonVM.cpp: * testing/Internals.cpp: (WebCore::Internals::parserMetaData): (WebCore::Internals::isReadableStreamDisturbed): (WebCore::Internals::isGCRunning): (WebCore::Internals::addGCFinalizationCallback): (WebCore::Internals::stopSweeping): (WebCore::Internals::startSweeping): * testing/Internals.h: * testing/Internals.idl: Source/WTF: Extend the use of AbstractLocker so that we can use more locking idioms. * wtf/AutomaticThread.cpp: (WTF::AutomaticThreadCondition::notifyOne): (WTF::AutomaticThreadCondition::notifyAll): (WTF::AutomaticThreadCondition::add): (WTF::AutomaticThreadCondition::remove): (WTF::AutomaticThreadCondition::contains): (WTF::AutomaticThread::AutomaticThread): (WTF::AutomaticThread::tryStop): (WTF::AutomaticThread::isWaiting): (WTF::AutomaticThread::notify): (WTF::AutomaticThread::start): (WTF::AutomaticThread::threadIsStopping): * wtf/AutomaticThread.h: * wtf/NumberOfCores.cpp: (WTF::numberOfProcessorCores): * wtf/ParallelHelperPool.cpp: (WTF::ParallelHelperClient::finish): (WTF::ParallelHelperClient::claimTask): (WTF::ParallelHelperPool::Thread::Thread): (WTF::ParallelHelperPool::didMakeWorkAvailable): (WTF::ParallelHelperPool::hasClientWithTask): (WTF::ParallelHelperPool::getClientWithTask): * wtf/ParallelHelperPool.h: Tools: Make more tests collect continuously. * Scripts/run-jsc-stress-tests: Canonical link: https://commits.webkit.org/185692@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@212778 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-02-22 00:58:15 +00:00
virtual PollResult poll(const AbstractLocker&) = 0;
WTF should make it easier to create threads that die automatically after inactivity https://bugs.webkit.org/show_bug.cgi?id=163576 Reviewed by Andreas Kling. Source/JavaScriptCore: Added a sleepSeconds() function, which made it easier for me to test this change. The WTF changes in this patch change how the JSC GC manages threads: the GC threads will now shut down automatically after 1 second of inactivity. Maybe this will save some memory. * jsc.cpp: (GlobalObject::finishCreation): (functionSleepSeconds): Source/WTF: For a long time now, I've been adding threads to WTF/JSC and each time I do this, I feel guilty because those threads don't shut down when they are inactive. For example, in bug 163562, I need to add a new GC thread. There will be one of them per VM. This means that a JSC API client that starts a lot of VMs will have a lot of threads. I don't think that's good. A common pattern for all of these threads is that they have some well-defined trigger that causes them to run. This trigger has a lock, a condition variable, some logic that determines if there is work to do, and then of course the logic for the thread's actual work. The thread bodies usually look like this: void Thingy::runThread() { for (;;) { Work work; { LockHolder locker(m_lock); while (!hasWork()) m_cond.wait(m_lock); work = takeWork(); } doWork(work); } } If you look at ParallelHelperPool (the GC's threads) and DFG::Worklist (some of the JIT's threads), you will see this pattern. This change adds a new kind of thread, called AutomaticThread, that lets you write threads to this pattern while getting automatic thread shutdown for free: instead of just waiting on a condition variable, AutomaticThread will have a timeout that causes the thread to die. The condition variable associated with AutomaticThread, called AutomaticThreadCondition, is smart enough to restart any threads that have decided to stop due to inactivity. The inactivity threshold is current just 1 second. In this patch I only adopt AutomaticThread for ParallelHelperPool. I plan to adopt it in more places soon. * WTF.xcodeproj/project.pbxproj: * wtf/AutomaticThread.cpp: Added. (WTF::AutomaticThreadCondition::create): (WTF::AutomaticThreadCondition::AutomaticThreadCondition): (WTF::AutomaticThreadCondition::~AutomaticThreadCondition): (WTF::AutomaticThreadCondition::notifyAll): (WTF::AutomaticThreadCondition::add): (WTF::AutomaticThreadCondition::remove): (WTF::AutomaticThreadCondition::contains): (WTF::AutomaticThread::AutomaticThread): (WTF::AutomaticThread::~AutomaticThread): (WTF::AutomaticThread::join): (WTF::AutomaticThread::start): * wtf/AutomaticThread.h: Added. * wtf/CMakeLists.txt: * wtf/ParallelHelperPool.cpp: (WTF::ParallelHelperClient::ParallelHelperClient): (WTF::ParallelHelperClient::~ParallelHelperClient): (WTF::ParallelHelperClient::setTask): (WTF::ParallelHelperClient::finish): (WTF::ParallelHelperClient::doSomeHelping): (WTF::ParallelHelperClient::runTask): (WTF::ParallelHelperPool::ParallelHelperPool): (WTF::ParallelHelperPool::~ParallelHelperPool): (WTF::ParallelHelperPool::ensureThreads): (WTF::ParallelHelperPool::doSomeHelping): (WTF::ParallelHelperPool::Thread::Thread): (WTF::ParallelHelperPool::didMakeWorkAvailable): (WTF::ParallelHelperPool::helperThreadBody): Deleted. (WTF::ParallelHelperPool::waitForClientWithTask): Deleted. * wtf/ParallelHelperPool.h: Canonical link: https://commits.webkit.org/181393@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@207480 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-10-18 20:17:10 +00:00
enum class WorkResult { Continue, Stop };
virtual WorkResult work() = 0;
DFG worklist should use AutomaticThread https://bugs.webkit.org/show_bug.cgi?id=163615 Reviewed by Mark Lam. Source/JavaScriptCore: AutomaticThread is a new feature in WTF that allows you to easily create worker threads that shut down automatically. This changes DFG::Worklist to use AutomaticThread, so that its threads shut down automatically, too. This has the potential to save a lot of memory. This required some improvements to AutomaticThread: Worklist likes to be able to keep state around for the whole lifetime of a thread, and so it likes knowing when threads are born and when they die. I added virtual methods for that. Also, Worklist uses notifyOne() so I added that, too. This looks to be perf-neutral. * dfg/DFGThreadData.cpp: (JSC::DFG::ThreadData::ThreadData): * dfg/DFGThreadData.h: * dfg/DFGWorklist.cpp: (JSC::DFG::Worklist::ThreadBody::ThreadBody): (JSC::DFG::Worklist::Worklist): (JSC::DFG::Worklist::~Worklist): (JSC::DFG::Worklist::finishCreation): (JSC::DFG::Worklist::isActiveForVM): (JSC::DFG::Worklist::enqueue): (JSC::DFG::Worklist::compilationState): (JSC::DFG::Worklist::waitUntilAllPlansForVMAreReady): (JSC::DFG::Worklist::removeAllReadyPlansForVM): (JSC::DFG::Worklist::completeAllReadyPlansForVM): (JSC::DFG::Worklist::rememberCodeBlocks): (JSC::DFG::Worklist::visitWeakReferences): (JSC::DFG::Worklist::removeDeadPlans): (JSC::DFG::Worklist::removeNonCompilingPlansForVM): (JSC::DFG::Worklist::queueLength): (JSC::DFG::Worklist::dump): (JSC::DFG::Worklist::runThread): Deleted. (JSC::DFG::Worklist::threadFunction): Deleted. * dfg/DFGWorklist.h: Source/WTF: This adds new functionality to AutomaticThread to support DFG::Worklist: - AutomaticThread::threadDidStart/threadWillStop virtual methods called at the start and end of a thread's lifetime. This allows Worklist to tie some resources to the life of the thread, and also means that now those resources will naturally free up when the Worklist is not in use. - AutomaticThreadCondition::notifyOne(). This required changes to Condition::notifyOne(). We need to know if the Condition woke up anyone. If it didn't, then we need to launch one of our threads. * wtf/AutomaticThread.cpp: (WTF::AutomaticThreadCondition::notifyOne): (WTF::AutomaticThread::ThreadScope::ThreadScope): (WTF::AutomaticThread::ThreadScope::~ThreadScope): (WTF::AutomaticThread::start): (WTF::AutomaticThread::threadDidStart): (WTF::AutomaticThread::threadWillStop): * wtf/AutomaticThread.h: * wtf/Condition.h: (WTF::ConditionBase::notifyOne): Canonical link: https://commits.webkit.org/181455@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@207545 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-10-19 17:47:30 +00:00
// It's sometimes useful to allocate resources while the thread is running, and to destroy them
// when the thread dies. These methods let you do this. You can override these methods, and you
// can be sure that the default ones don't do anything (so you don't need a super call).
virtual void threadDidStart();
The collector thread should only start when the mutator doesn't have heap access https://bugs.webkit.org/show_bug.cgi?id=167737 Reviewed by Keith Miller. JSTests: Add versions of splay that flash heap access, to simulate what might happen if a third-party app was running concurrent GC. In this case, we might actually start the collector thread. * stress/splay-flash-access-1ms.js: Added. (performance.now): (this.Setup.setup.setup): (this.TearDown.tearDown.tearDown): (Benchmark): (BenchmarkResult): (BenchmarkResult.prototype.valueOf): (BenchmarkSuite): (alert): (Math.random): (BenchmarkSuite.ResetRNG): (RunStep): (BenchmarkSuite.RunSuites): (BenchmarkSuite.CountBenchmarks): (BenchmarkSuite.GeometricMean): (BenchmarkSuite.GeometricMeanTime): (BenchmarkSuite.AverageAbovePercentile): (BenchmarkSuite.GeometricMeanLatency): (BenchmarkSuite.FormatScore): (BenchmarkSuite.prototype.NotifyStep): (BenchmarkSuite.prototype.NotifyResult): (BenchmarkSuite.prototype.NotifyError): (BenchmarkSuite.prototype.RunSingleBenchmark): (RunNextSetup): (RunNextBenchmark): (RunNextTearDown): (BenchmarkSuite.prototype.RunStep): (GeneratePayloadTree): (GenerateKey): (SplayUpdateStats): (InsertNewNode): (SplaySetup): (SplayTearDown): (SplayRun): (SplayTree): (SplayTree.prototype.isEmpty): (SplayTree.prototype.insert): (SplayTree.prototype.remove): (SplayTree.prototype.find): (SplayTree.prototype.findMax): (SplayTree.prototype.findGreatestLessThan): (SplayTree.prototype.exportKeys): (SplayTree.prototype.splay_): (SplayTree.Node): (SplayTree.Node.prototype.traverse_): (jscSetUp): (jscTearDown): (jscRun): (averageAbovePercentile): (printPercentile): * stress/splay-flash-access.js: Added. (performance.now): (this.Setup.setup.setup): (this.TearDown.tearDown.tearDown): (Benchmark): (BenchmarkResult): (BenchmarkResult.prototype.valueOf): (BenchmarkSuite): (alert): (Math.random): (BenchmarkSuite.ResetRNG): (RunStep): (BenchmarkSuite.RunSuites): (BenchmarkSuite.CountBenchmarks): (BenchmarkSuite.GeometricMean): (BenchmarkSuite.GeometricMeanTime): (BenchmarkSuite.AverageAbovePercentile): (BenchmarkSuite.GeometricMeanLatency): (BenchmarkSuite.FormatScore): (BenchmarkSuite.prototype.NotifyStep): (BenchmarkSuite.prototype.NotifyResult): (BenchmarkSuite.prototype.NotifyError): (BenchmarkSuite.prototype.RunSingleBenchmark): (RunNextSetup): (RunNextBenchmark): (RunNextTearDown): (BenchmarkSuite.prototype.RunStep): (GeneratePayloadTree): (GenerateKey): (SplayUpdateStats): (InsertNewNode): (SplaySetup): (SplayTearDown): (SplayRun): (SplayTree): (SplayTree.prototype.isEmpty): (SplayTree.prototype.insert): (SplayTree.prototype.remove): (SplayTree.prototype.find): (SplayTree.prototype.findMax): (SplayTree.prototype.findGreatestLessThan): (SplayTree.prototype.exportKeys): (SplayTree.prototype.splay_): (SplayTree.Node): (SplayTree.Node.prototype.traverse_): (jscSetUp): (jscTearDown): (jscRun): (averageAbovePercentile): (printPercentile): Source/JavaScriptCore: This turns the collector thread's workflow into a state machine, so that the mutator thread can run it directly. This reduces the amount of synchronization we do with the collector thread, and means that most apps will never start the collector thread. The collector thread will still start when we need to finish collecting and we don't have heap access. In this new world, "stopping the world" means relinquishing control of collection to the mutator. This means tracking who is conducting collection. I use the GCConductor enum to say who is conducting. It's either GCConductor::Mutator or GCConductor::Collector. I use the term "conn" to refer to the concept of conducting (having the conn, relinquishing the conn, taking the conn). So, stopping the world means giving the mutator the conn. Releasing heap access means giving the collector the conn. This meant bringing back the conservative scan of the calling thread. It turns out that this scan was too slow to be called on each GC increment because apparently setjmp() now does system calls. So, I wrote our own callee save register saving for the GC. Then I had doubts about whether or not it was correct, so I also made it so that the GC only rarely asks for the register state. I think we still want to use my register saving code instead of setjmp because setjmp seems to save things we don't need, and that could make us overly conservative. It turns out that this new scheduling discipline makes the old space-time scheduler perform better than the new stochastic space-time scheduler on systems with fewer than 4 cores. This is because the mutator having the conn enables us to time the mutator<->collector context switches by polling. The OS is never involved. So, we can use super precise timing. This allows the old space-time schduler to shine like it hadn't before. The splay results imply that this is all a good thing. On 2-core systems, this reduces pause times by 40% and it increases throughput about 5%. On 1-core systems, this reduces pause times by half and reduces throughput by 8%. On 4-or-more-core systems, this doesn't seem to have much effect. * CMakeLists.txt: * JavaScriptCore.xcodeproj/project.pbxproj: * bytecode/CodeBlock.cpp: (JSC::CodeBlock::visitChildren): * dfg/DFGWorklist.cpp: (JSC::DFG::Worklist::ThreadBody::ThreadBody): (JSC::DFG::Worklist::dump): (JSC::DFG::numberOfWorklists): (JSC::DFG::ensureWorklistForIndex): (JSC::DFG::existingWorklistForIndexOrNull): (JSC::DFG::existingWorklistForIndex): * dfg/DFGWorklist.h: (JSC::DFG::numberOfWorklists): Deleted. (JSC::DFG::ensureWorklistForIndex): Deleted. (JSC::DFG::existingWorklistForIndexOrNull): Deleted. (JSC::DFG::existingWorklistForIndex): Deleted. * heap/CollectingScope.h: Added. (JSC::CollectingScope::CollectingScope): (JSC::CollectingScope::~CollectingScope): * heap/CollectorPhase.cpp: Added. (JSC::worldShouldBeSuspended): (WTF::printInternal): * heap/CollectorPhase.h: Added. * heap/EdenGCActivityCallback.cpp: (JSC::EdenGCActivityCallback::lastGCLength): * heap/FullGCActivityCallback.cpp: (JSC::FullGCActivityCallback::doCollection): (JSC::FullGCActivityCallback::lastGCLength): * heap/GCConductor.cpp: Added. (JSC::gcConductorShortName): (WTF::printInternal): * heap/GCConductor.h: Added. * heap/GCFinalizationCallback.cpp: Added. (JSC::GCFinalizationCallback::GCFinalizationCallback): (JSC::GCFinalizationCallback::~GCFinalizationCallback): * heap/GCFinalizationCallback.h: Added. (JSC::GCFinalizationCallbackFuncAdaptor::GCFinalizationCallbackFuncAdaptor): (JSC::createGCFinalizationCallback): * heap/Heap.cpp: (JSC::Heap::Thread::Thread): (JSC::Heap::Heap): (JSC::Heap::lastChanceToFinalize): (JSC::Heap::gatherStackRoots): (JSC::Heap::updateObjectCounts): (JSC::Heap::sweepSynchronously): (JSC::Heap::collectAllGarbage): (JSC::Heap::collectAsync): (JSC::Heap::collectSync): (JSC::Heap::shouldCollectInCollectorThread): (JSC::Heap::collectInCollectorThread): (JSC::Heap::checkConn): (JSC::Heap::runNotRunningPhase): (JSC::Heap::runBeginPhase): (JSC::Heap::runFixpointPhase): (JSC::Heap::runConcurrentPhase): (JSC::Heap::runReloopPhase): (JSC::Heap::runEndPhase): (JSC::Heap::changePhase): (JSC::Heap::finishChangingPhase): (JSC::Heap::stopThePeriphery): (JSC::Heap::resumeThePeriphery): (JSC::Heap::stopTheMutator): (JSC::Heap::resumeTheMutator): (JSC::Heap::stopIfNecessarySlow): (JSC::Heap::collectInMutatorThread): (JSC::Heap::waitForCollector): (JSC::Heap::acquireAccessSlow): (JSC::Heap::releaseAccessSlow): (JSC::Heap::relinquishConn): (JSC::Heap::finishRelinquishingConn): (JSC::Heap::handleNeedFinalize): (JSC::Heap::notifyThreadStopping): (JSC::Heap::finalize): (JSC::Heap::addFinalizationCallback): (JSC::Heap::requestCollection): (JSC::Heap::waitForCollection): (JSC::Heap::updateAllocationLimits): (JSC::Heap::didFinishCollection): (JSC::Heap::collectIfNecessaryOrDefer): (JSC::Heap::notifyIsSafeToCollect): (JSC::Heap::preventCollection): (JSC::Heap::performIncrement): (JSC::Heap::markToFixpoint): Deleted. (JSC::Heap::shouldCollectInThread): Deleted. (JSC::Heap::collectInThread): Deleted. (JSC::Heap::stopTheWorld): Deleted. (JSC::Heap::resumeTheWorld): Deleted. * heap/Heap.h: (JSC::Heap::machineThreads): (JSC::Heap::lastFullGCLength): (JSC::Heap::lastEdenGCLength): (JSC::Heap::increaseLastFullGCLength): * heap/HeapInlines.h: (JSC::Heap::mutatorIsStopped): Deleted. * heap/HeapStatistics.cpp: Removed. * heap/HeapStatistics.h: Removed. * heap/HelpingGCScope.h: Removed. * heap/IncrementalSweeper.cpp: (JSC::IncrementalSweeper::stopSweeping): (JSC::IncrementalSweeper::willFinishSweeping): Deleted. * heap/IncrementalSweeper.h: * heap/MachineStackMarker.cpp: (JSC::MachineThreads::gatherFromCurrentThread): (JSC::MachineThreads::gatherConservativeRoots): (JSC::callWithCurrentThreadState): * heap/MachineStackMarker.h: * heap/MarkedAllocator.cpp: (JSC::MarkedAllocator::allocateSlowCaseImpl): * heap/MarkedBlock.cpp: (JSC::MarkedBlock::Handle::sweep): * heap/MarkedSpace.cpp: (JSC::MarkedSpace::sweep): * heap/MutatorState.cpp: (WTF::printInternal): * heap/MutatorState.h: * heap/RegisterState.h: Added. * heap/RunningScope.h: Added. (JSC::RunningScope::RunningScope): (JSC::RunningScope::~RunningScope): * heap/SlotVisitor.cpp: (JSC::SlotVisitor::SlotVisitor): (JSC::SlotVisitor::drain): (JSC::SlotVisitor::drainFromShared): (JSC::SlotVisitor::drainInParallelPassively): (JSC::SlotVisitor::donateAll): (JSC::SlotVisitor::donate): * heap/SlotVisitor.h: (JSC::SlotVisitor::codeName): * heap/StochasticSpaceTimeMutatorScheduler.cpp: (JSC::StochasticSpaceTimeMutatorScheduler::beginCollection): (JSC::StochasticSpaceTimeMutatorScheduler::synchronousDrainingDidStall): (JSC::StochasticSpaceTimeMutatorScheduler::timeToStop): * heap/SweepingScope.h: Added. (JSC::SweepingScope::SweepingScope): (JSC::SweepingScope::~SweepingScope): * jit/JITWorklist.cpp: (JSC::JITWorklist::Thread::Thread): * jsc.cpp: (GlobalObject::finishCreation): (functionFlashHeapAccess): * runtime/InitializeThreading.cpp: (JSC::initializeThreading): * runtime/JSCellInlines.h: (JSC::JSCell::classInfo): * runtime/Options.cpp: (JSC::overrideDefaults): * runtime/Options.h: * runtime/TestRunnerUtils.cpp: (JSC::finalizeStatsAtEndOfTesting): Source/WebCore: Added new tests in JSTests. The WebCore changes involve: - Refactoring around new header discipline. - Adding crazy GC APIs to window.internals to enable us to test the GC's runloop discipline. * ForwardingHeaders/heap/GCFinalizationCallback.h: Added. * ForwardingHeaders/heap/IncrementalSweeper.h: Added. * ForwardingHeaders/heap/MachineStackMarker.h: Added. * ForwardingHeaders/heap/RunningScope.h: Added. * bindings/js/CommonVM.cpp: * testing/Internals.cpp: (WebCore::Internals::parserMetaData): (WebCore::Internals::isReadableStreamDisturbed): (WebCore::Internals::isGCRunning): (WebCore::Internals::addGCFinalizationCallback): (WebCore::Internals::stopSweeping): (WebCore::Internals::startSweeping): * testing/Internals.h: * testing/Internals.idl: Source/WTF: Extend the use of AbstractLocker so that we can use more locking idioms. * wtf/AutomaticThread.cpp: (WTF::AutomaticThreadCondition::notifyOne): (WTF::AutomaticThreadCondition::notifyAll): (WTF::AutomaticThreadCondition::add): (WTF::AutomaticThreadCondition::remove): (WTF::AutomaticThreadCondition::contains): (WTF::AutomaticThread::AutomaticThread): (WTF::AutomaticThread::tryStop): (WTF::AutomaticThread::isWaiting): (WTF::AutomaticThread::notify): (WTF::AutomaticThread::start): (WTF::AutomaticThread::threadIsStopping): * wtf/AutomaticThread.h: * wtf/NumberOfCores.cpp: (WTF::numberOfProcessorCores): * wtf/ParallelHelperPool.cpp: (WTF::ParallelHelperClient::finish): (WTF::ParallelHelperClient::claimTask): (WTF::ParallelHelperPool::Thread::Thread): (WTF::ParallelHelperPool::didMakeWorkAvailable): (WTF::ParallelHelperPool::hasClientWithTask): (WTF::ParallelHelperPool::getClientWithTask): * wtf/ParallelHelperPool.h: Tools: Make more tests collect continuously. * Scripts/run-jsc-stress-tests: Canonical link: https://commits.webkit.org/185692@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@212778 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-02-22 00:58:15 +00:00
virtual void threadIsStopping(const AbstractLocker&);
[WTF] Add WorkerPool https://bugs.webkit.org/show_bug.cgi?id=174569 Reviewed by Carlos Garcia Campos. Source/WebCore: We start using WorkerPool for NicosiaPaintingEngineThreaded instead of glib thread pool. This makes NicosiaPaintingEngineThreaded platform-independent and usable for WinCairo. * platform/graphics/nicosia/NicosiaPaintingEngineThreaded.cpp: (Nicosia::PaintingEngineThreaded::PaintingEngineThreaded): (Nicosia::PaintingEngineThreaded::~PaintingEngineThreaded): (Nicosia::PaintingEngineThreaded::paint): (Nicosia::s_threadFunc): Deleted. * platform/graphics/nicosia/NicosiaPaintingEngineThreaded.h: Source/WTF: This patch adds WorkerPool, which is a thread pool that consists of AutomaticThread. Since it is based on AutomaticThread, this WorkerPool can take `timeout`: once `timeout` passes without any tasks, threads in WorkerPool will be destroyed. We add shouldSleep handler to AutomaticThread to make destruction of threads in WorkerPool moderate. Without this, all threads are destroyed at once after `timeout` passes. * WTF.xcodeproj/project.pbxproj: * wtf/AutomaticThread.cpp: (WTF::AutomaticThread::AutomaticThread): (WTF::AutomaticThread::start): * wtf/AutomaticThread.h: * wtf/CMakeLists.txt: * wtf/WorkerPool.cpp: Added. (WTF::WorkerPool::WorkerPool): (WTF::WorkerPool::~WorkerPool): (WTF::WorkerPool::shouldSleep): (WTF::WorkerPool::postTask): * wtf/WorkerPool.h: Added. (WTF::WorkerPool::create): Tools: * TestWebKitAPI/CMakeLists.txt: * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj: * TestWebKitAPI/Tests/WTF/WorkerPool.cpp: Added. (TestWebKitAPI::TEST): Canonical link: https://commits.webkit.org/201790@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@232619 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-06-08 08:47:06 +00:00
// Control whether this automatic thread should sleep when timeout happens.
// By overriding this function, we can customize how automatic threads will sleep.
// For example, when you have thread pool, you can decrease active threads moderately.
virtual bool shouldSleep(const AbstractLocker&) { return true; }
DFG worklist should use AutomaticThread https://bugs.webkit.org/show_bug.cgi?id=163615 Reviewed by Mark Lam. Source/JavaScriptCore: AutomaticThread is a new feature in WTF that allows you to easily create worker threads that shut down automatically. This changes DFG::Worklist to use AutomaticThread, so that its threads shut down automatically, too. This has the potential to save a lot of memory. This required some improvements to AutomaticThread: Worklist likes to be able to keep state around for the whole lifetime of a thread, and so it likes knowing when threads are born and when they die. I added virtual methods for that. Also, Worklist uses notifyOne() so I added that, too. This looks to be perf-neutral. * dfg/DFGThreadData.cpp: (JSC::DFG::ThreadData::ThreadData): * dfg/DFGThreadData.h: * dfg/DFGWorklist.cpp: (JSC::DFG::Worklist::ThreadBody::ThreadBody): (JSC::DFG::Worklist::Worklist): (JSC::DFG::Worklist::~Worklist): (JSC::DFG::Worklist::finishCreation): (JSC::DFG::Worklist::isActiveForVM): (JSC::DFG::Worklist::enqueue): (JSC::DFG::Worklist::compilationState): (JSC::DFG::Worklist::waitUntilAllPlansForVMAreReady): (JSC::DFG::Worklist::removeAllReadyPlansForVM): (JSC::DFG::Worklist::completeAllReadyPlansForVM): (JSC::DFG::Worklist::rememberCodeBlocks): (JSC::DFG::Worklist::visitWeakReferences): (JSC::DFG::Worklist::removeDeadPlans): (JSC::DFG::Worklist::removeNonCompilingPlansForVM): (JSC::DFG::Worklist::queueLength): (JSC::DFG::Worklist::dump): (JSC::DFG::Worklist::runThread): Deleted. (JSC::DFG::Worklist::threadFunction): Deleted. * dfg/DFGWorklist.h: Source/WTF: This adds new functionality to AutomaticThread to support DFG::Worklist: - AutomaticThread::threadDidStart/threadWillStop virtual methods called at the start and end of a thread's lifetime. This allows Worklist to tie some resources to the life of the thread, and also means that now those resources will naturally free up when the Worklist is not in use. - AutomaticThreadCondition::notifyOne(). This required changes to Condition::notifyOne(). We need to know if the Condition woke up anyone. If it didn't, then we need to launch one of our threads. * wtf/AutomaticThread.cpp: (WTF::AutomaticThreadCondition::notifyOne): (WTF::AutomaticThread::ThreadScope::ThreadScope): (WTF::AutomaticThread::ThreadScope::~ThreadScope): (WTF::AutomaticThread::start): (WTF::AutomaticThread::threadDidStart): (WTF::AutomaticThread::threadWillStop): * wtf/AutomaticThread.h: * wtf/Condition.h: (WTF::ConditionBase::notifyOne): Canonical link: https://commits.webkit.org/181455@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@207545 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-10-19 17:47:30 +00:00
WTF should make it easier to create threads that die automatically after inactivity https://bugs.webkit.org/show_bug.cgi?id=163576 Reviewed by Andreas Kling. Source/JavaScriptCore: Added a sleepSeconds() function, which made it easier for me to test this change. The WTF changes in this patch change how the JSC GC manages threads: the GC threads will now shut down automatically after 1 second of inactivity. Maybe this will save some memory. * jsc.cpp: (GlobalObject::finishCreation): (functionSleepSeconds): Source/WTF: For a long time now, I've been adding threads to WTF/JSC and each time I do this, I feel guilty because those threads don't shut down when they are inactive. For example, in bug 163562, I need to add a new GC thread. There will be one of them per VM. This means that a JSC API client that starts a lot of VMs will have a lot of threads. I don't think that's good. A common pattern for all of these threads is that they have some well-defined trigger that causes them to run. This trigger has a lock, a condition variable, some logic that determines if there is work to do, and then of course the logic for the thread's actual work. The thread bodies usually look like this: void Thingy::runThread() { for (;;) { Work work; { LockHolder locker(m_lock); while (!hasWork()) m_cond.wait(m_lock); work = takeWork(); } doWork(work); } } If you look at ParallelHelperPool (the GC's threads) and DFG::Worklist (some of the JIT's threads), you will see this pattern. This change adds a new kind of thread, called AutomaticThread, that lets you write threads to this pattern while getting automatic thread shutdown for free: instead of just waiting on a condition variable, AutomaticThread will have a timeout that causes the thread to die. The condition variable associated with AutomaticThread, called AutomaticThreadCondition, is smart enough to restart any threads that have decided to stop due to inactivity. The inactivity threshold is current just 1 second. In this patch I only adopt AutomaticThread for ParallelHelperPool. I plan to adopt it in more places soon. * WTF.xcodeproj/project.pbxproj: * wtf/AutomaticThread.cpp: Added. (WTF::AutomaticThreadCondition::create): (WTF::AutomaticThreadCondition::AutomaticThreadCondition): (WTF::AutomaticThreadCondition::~AutomaticThreadCondition): (WTF::AutomaticThreadCondition::notifyAll): (WTF::AutomaticThreadCondition::add): (WTF::AutomaticThreadCondition::remove): (WTF::AutomaticThreadCondition::contains): (WTF::AutomaticThread::AutomaticThread): (WTF::AutomaticThread::~AutomaticThread): (WTF::AutomaticThread::join): (WTF::AutomaticThread::start): * wtf/AutomaticThread.h: Added. * wtf/CMakeLists.txt: * wtf/ParallelHelperPool.cpp: (WTF::ParallelHelperClient::ParallelHelperClient): (WTF::ParallelHelperClient::~ParallelHelperClient): (WTF::ParallelHelperClient::setTask): (WTF::ParallelHelperClient::finish): (WTF::ParallelHelperClient::doSomeHelping): (WTF::ParallelHelperClient::runTask): (WTF::ParallelHelperPool::ParallelHelperPool): (WTF::ParallelHelperPool::~ParallelHelperPool): (WTF::ParallelHelperPool::ensureThreads): (WTF::ParallelHelperPool::doSomeHelping): (WTF::ParallelHelperPool::Thread::Thread): (WTF::ParallelHelperPool::didMakeWorkAvailable): (WTF::ParallelHelperPool::helperThreadBody): Deleted. (WTF::ParallelHelperPool::waitForClientWithTask): Deleted. * wtf/ParallelHelperPool.h: Canonical link: https://commits.webkit.org/181393@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@207480 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-10-18 20:17:10 +00:00
private:
friend class AutomaticThreadCondition;
The collector thread should only start when the mutator doesn't have heap access https://bugs.webkit.org/show_bug.cgi?id=167737 Reviewed by Keith Miller. JSTests: Add versions of splay that flash heap access, to simulate what might happen if a third-party app was running concurrent GC. In this case, we might actually start the collector thread. * stress/splay-flash-access-1ms.js: Added. (performance.now): (this.Setup.setup.setup): (this.TearDown.tearDown.tearDown): (Benchmark): (BenchmarkResult): (BenchmarkResult.prototype.valueOf): (BenchmarkSuite): (alert): (Math.random): (BenchmarkSuite.ResetRNG): (RunStep): (BenchmarkSuite.RunSuites): (BenchmarkSuite.CountBenchmarks): (BenchmarkSuite.GeometricMean): (BenchmarkSuite.GeometricMeanTime): (BenchmarkSuite.AverageAbovePercentile): (BenchmarkSuite.GeometricMeanLatency): (BenchmarkSuite.FormatScore): (BenchmarkSuite.prototype.NotifyStep): (BenchmarkSuite.prototype.NotifyResult): (BenchmarkSuite.prototype.NotifyError): (BenchmarkSuite.prototype.RunSingleBenchmark): (RunNextSetup): (RunNextBenchmark): (RunNextTearDown): (BenchmarkSuite.prototype.RunStep): (GeneratePayloadTree): (GenerateKey): (SplayUpdateStats): (InsertNewNode): (SplaySetup): (SplayTearDown): (SplayRun): (SplayTree): (SplayTree.prototype.isEmpty): (SplayTree.prototype.insert): (SplayTree.prototype.remove): (SplayTree.prototype.find): (SplayTree.prototype.findMax): (SplayTree.prototype.findGreatestLessThan): (SplayTree.prototype.exportKeys): (SplayTree.prototype.splay_): (SplayTree.Node): (SplayTree.Node.prototype.traverse_): (jscSetUp): (jscTearDown): (jscRun): (averageAbovePercentile): (printPercentile): * stress/splay-flash-access.js: Added. (performance.now): (this.Setup.setup.setup): (this.TearDown.tearDown.tearDown): (Benchmark): (BenchmarkResult): (BenchmarkResult.prototype.valueOf): (BenchmarkSuite): (alert): (Math.random): (BenchmarkSuite.ResetRNG): (RunStep): (BenchmarkSuite.RunSuites): (BenchmarkSuite.CountBenchmarks): (BenchmarkSuite.GeometricMean): (BenchmarkSuite.GeometricMeanTime): (BenchmarkSuite.AverageAbovePercentile): (BenchmarkSuite.GeometricMeanLatency): (BenchmarkSuite.FormatScore): (BenchmarkSuite.prototype.NotifyStep): (BenchmarkSuite.prototype.NotifyResult): (BenchmarkSuite.prototype.NotifyError): (BenchmarkSuite.prototype.RunSingleBenchmark): (RunNextSetup): (RunNextBenchmark): (RunNextTearDown): (BenchmarkSuite.prototype.RunStep): (GeneratePayloadTree): (GenerateKey): (SplayUpdateStats): (InsertNewNode): (SplaySetup): (SplayTearDown): (SplayRun): (SplayTree): (SplayTree.prototype.isEmpty): (SplayTree.prototype.insert): (SplayTree.prototype.remove): (SplayTree.prototype.find): (SplayTree.prototype.findMax): (SplayTree.prototype.findGreatestLessThan): (SplayTree.prototype.exportKeys): (SplayTree.prototype.splay_): (SplayTree.Node): (SplayTree.Node.prototype.traverse_): (jscSetUp): (jscTearDown): (jscRun): (averageAbovePercentile): (printPercentile): Source/JavaScriptCore: This turns the collector thread's workflow into a state machine, so that the mutator thread can run it directly. This reduces the amount of synchronization we do with the collector thread, and means that most apps will never start the collector thread. The collector thread will still start when we need to finish collecting and we don't have heap access. In this new world, "stopping the world" means relinquishing control of collection to the mutator. This means tracking who is conducting collection. I use the GCConductor enum to say who is conducting. It's either GCConductor::Mutator or GCConductor::Collector. I use the term "conn" to refer to the concept of conducting (having the conn, relinquishing the conn, taking the conn). So, stopping the world means giving the mutator the conn. Releasing heap access means giving the collector the conn. This meant bringing back the conservative scan of the calling thread. It turns out that this scan was too slow to be called on each GC increment because apparently setjmp() now does system calls. So, I wrote our own callee save register saving for the GC. Then I had doubts about whether or not it was correct, so I also made it so that the GC only rarely asks for the register state. I think we still want to use my register saving code instead of setjmp because setjmp seems to save things we don't need, and that could make us overly conservative. It turns out that this new scheduling discipline makes the old space-time scheduler perform better than the new stochastic space-time scheduler on systems with fewer than 4 cores. This is because the mutator having the conn enables us to time the mutator<->collector context switches by polling. The OS is never involved. So, we can use super precise timing. This allows the old space-time schduler to shine like it hadn't before. The splay results imply that this is all a good thing. On 2-core systems, this reduces pause times by 40% and it increases throughput about 5%. On 1-core systems, this reduces pause times by half and reduces throughput by 8%. On 4-or-more-core systems, this doesn't seem to have much effect. * CMakeLists.txt: * JavaScriptCore.xcodeproj/project.pbxproj: * bytecode/CodeBlock.cpp: (JSC::CodeBlock::visitChildren): * dfg/DFGWorklist.cpp: (JSC::DFG::Worklist::ThreadBody::ThreadBody): (JSC::DFG::Worklist::dump): (JSC::DFG::numberOfWorklists): (JSC::DFG::ensureWorklistForIndex): (JSC::DFG::existingWorklistForIndexOrNull): (JSC::DFG::existingWorklistForIndex): * dfg/DFGWorklist.h: (JSC::DFG::numberOfWorklists): Deleted. (JSC::DFG::ensureWorklistForIndex): Deleted. (JSC::DFG::existingWorklistForIndexOrNull): Deleted. (JSC::DFG::existingWorklistForIndex): Deleted. * heap/CollectingScope.h: Added. (JSC::CollectingScope::CollectingScope): (JSC::CollectingScope::~CollectingScope): * heap/CollectorPhase.cpp: Added. (JSC::worldShouldBeSuspended): (WTF::printInternal): * heap/CollectorPhase.h: Added. * heap/EdenGCActivityCallback.cpp: (JSC::EdenGCActivityCallback::lastGCLength): * heap/FullGCActivityCallback.cpp: (JSC::FullGCActivityCallback::doCollection): (JSC::FullGCActivityCallback::lastGCLength): * heap/GCConductor.cpp: Added. (JSC::gcConductorShortName): (WTF::printInternal): * heap/GCConductor.h: Added. * heap/GCFinalizationCallback.cpp: Added. (JSC::GCFinalizationCallback::GCFinalizationCallback): (JSC::GCFinalizationCallback::~GCFinalizationCallback): * heap/GCFinalizationCallback.h: Added. (JSC::GCFinalizationCallbackFuncAdaptor::GCFinalizationCallbackFuncAdaptor): (JSC::createGCFinalizationCallback): * heap/Heap.cpp: (JSC::Heap::Thread::Thread): (JSC::Heap::Heap): (JSC::Heap::lastChanceToFinalize): (JSC::Heap::gatherStackRoots): (JSC::Heap::updateObjectCounts): (JSC::Heap::sweepSynchronously): (JSC::Heap::collectAllGarbage): (JSC::Heap::collectAsync): (JSC::Heap::collectSync): (JSC::Heap::shouldCollectInCollectorThread): (JSC::Heap::collectInCollectorThread): (JSC::Heap::checkConn): (JSC::Heap::runNotRunningPhase): (JSC::Heap::runBeginPhase): (JSC::Heap::runFixpointPhase): (JSC::Heap::runConcurrentPhase): (JSC::Heap::runReloopPhase): (JSC::Heap::runEndPhase): (JSC::Heap::changePhase): (JSC::Heap::finishChangingPhase): (JSC::Heap::stopThePeriphery): (JSC::Heap::resumeThePeriphery): (JSC::Heap::stopTheMutator): (JSC::Heap::resumeTheMutator): (JSC::Heap::stopIfNecessarySlow): (JSC::Heap::collectInMutatorThread): (JSC::Heap::waitForCollector): (JSC::Heap::acquireAccessSlow): (JSC::Heap::releaseAccessSlow): (JSC::Heap::relinquishConn): (JSC::Heap::finishRelinquishingConn): (JSC::Heap::handleNeedFinalize): (JSC::Heap::notifyThreadStopping): (JSC::Heap::finalize): (JSC::Heap::addFinalizationCallback): (JSC::Heap::requestCollection): (JSC::Heap::waitForCollection): (JSC::Heap::updateAllocationLimits): (JSC::Heap::didFinishCollection): (JSC::Heap::collectIfNecessaryOrDefer): (JSC::Heap::notifyIsSafeToCollect): (JSC::Heap::preventCollection): (JSC::Heap::performIncrement): (JSC::Heap::markToFixpoint): Deleted. (JSC::Heap::shouldCollectInThread): Deleted. (JSC::Heap::collectInThread): Deleted. (JSC::Heap::stopTheWorld): Deleted. (JSC::Heap::resumeTheWorld): Deleted. * heap/Heap.h: (JSC::Heap::machineThreads): (JSC::Heap::lastFullGCLength): (JSC::Heap::lastEdenGCLength): (JSC::Heap::increaseLastFullGCLength): * heap/HeapInlines.h: (JSC::Heap::mutatorIsStopped): Deleted. * heap/HeapStatistics.cpp: Removed. * heap/HeapStatistics.h: Removed. * heap/HelpingGCScope.h: Removed. * heap/IncrementalSweeper.cpp: (JSC::IncrementalSweeper::stopSweeping): (JSC::IncrementalSweeper::willFinishSweeping): Deleted. * heap/IncrementalSweeper.h: * heap/MachineStackMarker.cpp: (JSC::MachineThreads::gatherFromCurrentThread): (JSC::MachineThreads::gatherConservativeRoots): (JSC::callWithCurrentThreadState): * heap/MachineStackMarker.h: * heap/MarkedAllocator.cpp: (JSC::MarkedAllocator::allocateSlowCaseImpl): * heap/MarkedBlock.cpp: (JSC::MarkedBlock::Handle::sweep): * heap/MarkedSpace.cpp: (JSC::MarkedSpace::sweep): * heap/MutatorState.cpp: (WTF::printInternal): * heap/MutatorState.h: * heap/RegisterState.h: Added. * heap/RunningScope.h: Added. (JSC::RunningScope::RunningScope): (JSC::RunningScope::~RunningScope): * heap/SlotVisitor.cpp: (JSC::SlotVisitor::SlotVisitor): (JSC::SlotVisitor::drain): (JSC::SlotVisitor::drainFromShared): (JSC::SlotVisitor::drainInParallelPassively): (JSC::SlotVisitor::donateAll): (JSC::SlotVisitor::donate): * heap/SlotVisitor.h: (JSC::SlotVisitor::codeName): * heap/StochasticSpaceTimeMutatorScheduler.cpp: (JSC::StochasticSpaceTimeMutatorScheduler::beginCollection): (JSC::StochasticSpaceTimeMutatorScheduler::synchronousDrainingDidStall): (JSC::StochasticSpaceTimeMutatorScheduler::timeToStop): * heap/SweepingScope.h: Added. (JSC::SweepingScope::SweepingScope): (JSC::SweepingScope::~SweepingScope): * jit/JITWorklist.cpp: (JSC::JITWorklist::Thread::Thread): * jsc.cpp: (GlobalObject::finishCreation): (functionFlashHeapAccess): * runtime/InitializeThreading.cpp: (JSC::initializeThreading): * runtime/JSCellInlines.h: (JSC::JSCell::classInfo): * runtime/Options.cpp: (JSC::overrideDefaults): * runtime/Options.h: * runtime/TestRunnerUtils.cpp: (JSC::finalizeStatsAtEndOfTesting): Source/WebCore: Added new tests in JSTests. The WebCore changes involve: - Refactoring around new header discipline. - Adding crazy GC APIs to window.internals to enable us to test the GC's runloop discipline. * ForwardingHeaders/heap/GCFinalizationCallback.h: Added. * ForwardingHeaders/heap/IncrementalSweeper.h: Added. * ForwardingHeaders/heap/MachineStackMarker.h: Added. * ForwardingHeaders/heap/RunningScope.h: Added. * bindings/js/CommonVM.cpp: * testing/Internals.cpp: (WebCore::Internals::parserMetaData): (WebCore::Internals::isReadableStreamDisturbed): (WebCore::Internals::isGCRunning): (WebCore::Internals::addGCFinalizationCallback): (WebCore::Internals::stopSweeping): (WebCore::Internals::startSweeping): * testing/Internals.h: * testing/Internals.idl: Source/WTF: Extend the use of AbstractLocker so that we can use more locking idioms. * wtf/AutomaticThread.cpp: (WTF::AutomaticThreadCondition::notifyOne): (WTF::AutomaticThreadCondition::notifyAll): (WTF::AutomaticThreadCondition::add): (WTF::AutomaticThreadCondition::remove): (WTF::AutomaticThreadCondition::contains): (WTF::AutomaticThread::AutomaticThread): (WTF::AutomaticThread::tryStop): (WTF::AutomaticThread::isWaiting): (WTF::AutomaticThread::notify): (WTF::AutomaticThread::start): (WTF::AutomaticThread::threadIsStopping): * wtf/AutomaticThread.h: * wtf/NumberOfCores.cpp: (WTF::numberOfProcessorCores): * wtf/ParallelHelperPool.cpp: (WTF::ParallelHelperClient::finish): (WTF::ParallelHelperClient::claimTask): (WTF::ParallelHelperPool::Thread::Thread): (WTF::ParallelHelperPool::didMakeWorkAvailable): (WTF::ParallelHelperPool::hasClientWithTask): (WTF::ParallelHelperPool::getClientWithTask): * wtf/ParallelHelperPool.h: Tools: Make more tests collect continuously. * Scripts/run-jsc-stress-tests: Canonical link: https://commits.webkit.org/185692@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@212778 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2017-02-22 00:58:15 +00:00
void start(const AbstractLocker&);
WTF should make it easier to create threads that die automatically after inactivity https://bugs.webkit.org/show_bug.cgi?id=163576 Reviewed by Andreas Kling. Source/JavaScriptCore: Added a sleepSeconds() function, which made it easier for me to test this change. The WTF changes in this patch change how the JSC GC manages threads: the GC threads will now shut down automatically after 1 second of inactivity. Maybe this will save some memory. * jsc.cpp: (GlobalObject::finishCreation): (functionSleepSeconds): Source/WTF: For a long time now, I've been adding threads to WTF/JSC and each time I do this, I feel guilty because those threads don't shut down when they are inactive. For example, in bug 163562, I need to add a new GC thread. There will be one of them per VM. This means that a JSC API client that starts a lot of VMs will have a lot of threads. I don't think that's good. A common pattern for all of these threads is that they have some well-defined trigger that causes them to run. This trigger has a lock, a condition variable, some logic that determines if there is work to do, and then of course the logic for the thread's actual work. The thread bodies usually look like this: void Thingy::runThread() { for (;;) { Work work; { LockHolder locker(m_lock); while (!hasWork()) m_cond.wait(m_lock); work = takeWork(); } doWork(work); } } If you look at ParallelHelperPool (the GC's threads) and DFG::Worklist (some of the JIT's threads), you will see this pattern. This change adds a new kind of thread, called AutomaticThread, that lets you write threads to this pattern while getting automatic thread shutdown for free: instead of just waiting on a condition variable, AutomaticThread will have a timeout that causes the thread to die. The condition variable associated with AutomaticThread, called AutomaticThreadCondition, is smart enough to restart any threads that have decided to stop due to inactivity. The inactivity threshold is current just 1 second. In this patch I only adopt AutomaticThread for ParallelHelperPool. I plan to adopt it in more places soon. * WTF.xcodeproj/project.pbxproj: * wtf/AutomaticThread.cpp: Added. (WTF::AutomaticThreadCondition::create): (WTF::AutomaticThreadCondition::AutomaticThreadCondition): (WTF::AutomaticThreadCondition::~AutomaticThreadCondition): (WTF::AutomaticThreadCondition::notifyAll): (WTF::AutomaticThreadCondition::add): (WTF::AutomaticThreadCondition::remove): (WTF::AutomaticThreadCondition::contains): (WTF::AutomaticThread::AutomaticThread): (WTF::AutomaticThread::~AutomaticThread): (WTF::AutomaticThread::join): (WTF::AutomaticThread::start): * wtf/AutomaticThread.h: Added. * wtf/CMakeLists.txt: * wtf/ParallelHelperPool.cpp: (WTF::ParallelHelperClient::ParallelHelperClient): (WTF::ParallelHelperClient::~ParallelHelperClient): (WTF::ParallelHelperClient::setTask): (WTF::ParallelHelperClient::finish): (WTF::ParallelHelperClient::doSomeHelping): (WTF::ParallelHelperClient::runTask): (WTF::ParallelHelperPool::ParallelHelperPool): (WTF::ParallelHelperPool::~ParallelHelperPool): (WTF::ParallelHelperPool::ensureThreads): (WTF::ParallelHelperPool::doSomeHelping): (WTF::ParallelHelperPool::Thread::Thread): (WTF::ParallelHelperPool::didMakeWorkAvailable): (WTF::ParallelHelperPool::helperThreadBody): Deleted. (WTF::ParallelHelperPool::waitForClientWithTask): Deleted. * wtf/ParallelHelperPool.h: Canonical link: https://commits.webkit.org/181393@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@207480 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-10-18 20:17:10 +00:00
Box<Lock> m_lock;
Ref<AutomaticThreadCondition> m_condition;
[WTF] Add WorkerPool https://bugs.webkit.org/show_bug.cgi?id=174569 Reviewed by Carlos Garcia Campos. Source/WebCore: We start using WorkerPool for NicosiaPaintingEngineThreaded instead of glib thread pool. This makes NicosiaPaintingEngineThreaded platform-independent and usable for WinCairo. * platform/graphics/nicosia/NicosiaPaintingEngineThreaded.cpp: (Nicosia::PaintingEngineThreaded::PaintingEngineThreaded): (Nicosia::PaintingEngineThreaded::~PaintingEngineThreaded): (Nicosia::PaintingEngineThreaded::paint): (Nicosia::s_threadFunc): Deleted. * platform/graphics/nicosia/NicosiaPaintingEngineThreaded.h: Source/WTF: This patch adds WorkerPool, which is a thread pool that consists of AutomaticThread. Since it is based on AutomaticThread, this WorkerPool can take `timeout`: once `timeout` passes without any tasks, threads in WorkerPool will be destroyed. We add shouldSleep handler to AutomaticThread to make destruction of threads in WorkerPool moderate. Without this, all threads are destroyed at once after `timeout` passes. * WTF.xcodeproj/project.pbxproj: * wtf/AutomaticThread.cpp: (WTF::AutomaticThread::AutomaticThread): (WTF::AutomaticThread::start): * wtf/AutomaticThread.h: * wtf/CMakeLists.txt: * wtf/WorkerPool.cpp: Added. (WTF::WorkerPool::WorkerPool): (WTF::WorkerPool::~WorkerPool): (WTF::WorkerPool::shouldSleep): (WTF::WorkerPool::postTask): * wtf/WorkerPool.h: Added. (WTF::WorkerPool::create): Tools: * TestWebKitAPI/CMakeLists.txt: * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj: * TestWebKitAPI/Tests/WTF/WorkerPool.cpp: Added. (TestWebKitAPI::TEST): Canonical link: https://commits.webkit.org/201790@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@232619 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-06-08 08:47:06 +00:00
Seconds m_timeout;
ThreadType m_threadType { ThreadType::Unknown };
WTF should make it easier to create threads that die automatically after inactivity https://bugs.webkit.org/show_bug.cgi?id=163576 Reviewed by Andreas Kling. Source/JavaScriptCore: Added a sleepSeconds() function, which made it easier for me to test this change. The WTF changes in this patch change how the JSC GC manages threads: the GC threads will now shut down automatically after 1 second of inactivity. Maybe this will save some memory. * jsc.cpp: (GlobalObject::finishCreation): (functionSleepSeconds): Source/WTF: For a long time now, I've been adding threads to WTF/JSC and each time I do this, I feel guilty because those threads don't shut down when they are inactive. For example, in bug 163562, I need to add a new GC thread. There will be one of them per VM. This means that a JSC API client that starts a lot of VMs will have a lot of threads. I don't think that's good. A common pattern for all of these threads is that they have some well-defined trigger that causes them to run. This trigger has a lock, a condition variable, some logic that determines if there is work to do, and then of course the logic for the thread's actual work. The thread bodies usually look like this: void Thingy::runThread() { for (;;) { Work work; { LockHolder locker(m_lock); while (!hasWork()) m_cond.wait(m_lock); work = takeWork(); } doWork(work); } } If you look at ParallelHelperPool (the GC's threads) and DFG::Worklist (some of the JIT's threads), you will see this pattern. This change adds a new kind of thread, called AutomaticThread, that lets you write threads to this pattern while getting automatic thread shutdown for free: instead of just waiting on a condition variable, AutomaticThread will have a timeout that causes the thread to die. The condition variable associated with AutomaticThread, called AutomaticThreadCondition, is smart enough to restart any threads that have decided to stop due to inactivity. The inactivity threshold is current just 1 second. In this patch I only adopt AutomaticThread for ParallelHelperPool. I plan to adopt it in more places soon. * WTF.xcodeproj/project.pbxproj: * wtf/AutomaticThread.cpp: Added. (WTF::AutomaticThreadCondition::create): (WTF::AutomaticThreadCondition::AutomaticThreadCondition): (WTF::AutomaticThreadCondition::~AutomaticThreadCondition): (WTF::AutomaticThreadCondition::notifyAll): (WTF::AutomaticThreadCondition::add): (WTF::AutomaticThreadCondition::remove): (WTF::AutomaticThreadCondition::contains): (WTF::AutomaticThread::AutomaticThread): (WTF::AutomaticThread::~AutomaticThread): (WTF::AutomaticThread::join): (WTF::AutomaticThread::start): * wtf/AutomaticThread.h: Added. * wtf/CMakeLists.txt: * wtf/ParallelHelperPool.cpp: (WTF::ParallelHelperClient::ParallelHelperClient): (WTF::ParallelHelperClient::~ParallelHelperClient): (WTF::ParallelHelperClient::setTask): (WTF::ParallelHelperClient::finish): (WTF::ParallelHelperClient::doSomeHelping): (WTF::ParallelHelperClient::runTask): (WTF::ParallelHelperPool::ParallelHelperPool): (WTF::ParallelHelperPool::~ParallelHelperPool): (WTF::ParallelHelperPool::ensureThreads): (WTF::ParallelHelperPool::doSomeHelping): (WTF::ParallelHelperPool::Thread::Thread): (WTF::ParallelHelperPool::didMakeWorkAvailable): (WTF::ParallelHelperPool::helperThreadBody): Deleted. (WTF::ParallelHelperPool::waitForClientWithTask): Deleted. * wtf/ParallelHelperPool.h: Canonical link: https://commits.webkit.org/181393@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@207480 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-10-18 20:17:10 +00:00
bool m_isRunning { true };
REGRESSION: HipChat and Mail sometimes hang beneath JSC::Heap::lastChanceToFinalize() https://bugs.webkit.org/show_bug.cgi?id=165962 Reviewed by Filip Pizlo. There is an inherent race in Condition::waitFor() where the timeout can happen just before a notify from another thread. Fixed this by adding a condition variable and flag to each AutomaticThread. The flag is used to signify to a notifying thread that the thread is waiting. That flag is set in the waiting thread before calling waitFor() and cleared by another thread when it notifies the thread. The access to that flag happens when the lock is held. Now the waiting thread checks if the flag after a timeout to see that it in fact should proceed like a normal notification. The added condition variable allows us to target a specific thread. We used to keep a list of waiting threads, now we keep a list of all threads. To notify one thread, we look for a waiting thread and notify it directly. If we can't find a waiting thread, we start a sleeping thread. We notify all threads by waking all waiting threads and starting all sleeping threads. * wtf/AutomaticThread.cpp: (WTF::AutomaticThreadCondition::notifyOne): (WTF::AutomaticThreadCondition::notifyAll): (WTF::AutomaticThread::isWaiting): (WTF::AutomaticThread::notify): (WTF::AutomaticThread::start): * wtf/AutomaticThread.h: Canonical link: https://commits.webkit.org/183569@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@209938 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-12-16 22:26:09 +00:00
bool m_isWaiting { false };
The GC should be in a thread https://bugs.webkit.org/show_bug.cgi?id=163562 Reviewed by Geoffrey Garen and Andreas Kling. Source/JavaScriptCore: In a concurrent GC, the work of collecting happens on a separate thread. This patch implements this, and schedules the thread the way that a concurrent GC thread would be scheduled. But, the GC isn't actually concurrent yet because it calls stopTheWorld() before doing anything and calls resumeTheWorld() after it's done with everything. The next step will be to make it really concurrent by basically calling stopTheWorld()/resumeTheWorld() around bounded snippets of work while making most of the work happen with the world running. Our GC will probably always have stop-the-world phases because the semantics of JSC weak references call for it. This implements concurrent GC scheduling. This means that there is no longer a Heap::collect() API. Instead, you can call collectAsync() which makes sure that a GC is scheduled (it will do nothing if one is scheduled or ongoing) or you can call collectSync() to schedule a GC and wait for it to happen. I made our debugging stuff call collectSync(). It should be a goal to never call collectSync() except for debugging or benchmark harness hacks. The collector thread is an AutomaticThread, so it won't linger when not in use. It works on a ticket-based system, like you would see at the DMV. A ticket is a 64-bit integer. There are two ticket counters: last granted and last served. When you request a collection, last granted is incremented and its new value given to you. When a collection completes, last served is incremented. collectSync() waits until last served catches up to what last granted had been at the time you requested a GC. This means that if you request a sync GC in the middle of an async GC, you will wait for that async GC to finish and then you will request and wait for your sync GC. The synchronization between the collector thread and the main threads is complex. The collector thread needs to be able to ask the main thread to stop. It needs to be able to do some post-GC clean-up, like the synchronous CodeBlock and LargeAllocation sweeps, on the main thread. The collector needs to be able to ask the main thread to execute a cross-modifying code fence before running any JIT code, since the GC might aid the JIT worklist and run JIT finalization. It's possible for the GC to want the main thread to run something at the same time that the main thread wants to wait for the GC. The main thread needs to be able to run non-JSC stuff without causing the GC to completely stall. The main thread needs to be able to query its own state (is there a request to stop?) and change it (running JSC versus not) quickly, since this may happen on hot paths. This kind of intertwined system of requests, notifications, and state changes requires a combination of lock-free algorithms and waiting. So, this is all implemented using a Atomic<unsigned> Heap::m_worldState, which has bits to represent things being requested by the collector and the heap access state of the mutator. I am borrowing a lot of terms that I've seen in other VMs that I've worked on. Here's what they mean: - Stop the world: make sure that either the mutator is not running, or that it's not running code that could mess with the heap. - Heap access: the mutator is said to have heap access if it could mess with the heap. If you stop the world and the mutator doesn't have heap access, all you're doing is making sure that it will block when it tries to acquire heap access. This means that our GC is already fully concurrent in cases where the GC is requested while the mutator has no heap access. This probably won't happen, but if it did then it should just work. Usually, stopping the world means that we state our shouldStop request with m_worldState, and a future call to Heap::stopIfNecessary() will go to slow path and stop. The act of stopping or waiting to acquire heap access is managed by using ParkingLot API directly on m_worldState. This works out great because it would be very awkward to get the same functionality using locks and condition variables, since we want stopIfNecessary/acquireAccess/requestAccess fast paths that are single atomic instructions (load/CAS/CAS, respectively). The mutator will call these things frequently. Currently we have Heap::stopIfNecessary() polling on every allocator slow path, but we may want to make it even more frequent than that. Currently only JSC API clients benefit from the heap access optimization. The DOM forces us to assume that heap access is permanently on, since DOM manipulation doesn't always hold the JSLock. We could still allow the GC to proceed when the runloop is idle by having the GC put a task on the runloop that just calls stopIfNecessary(). This is perf neutral. The only behavior change that clients ought to observe is that marking and the weak fixpoint happen on a separate thread. Marking was already parallel so it already handled multiple threads, but now it _never_ runs on the main thread. The weak fixpoint needed some help to be able to run on another thread - mostly because there was some code in IndexedDB that was using thread specifics in the weak fixpoint. * API/JSBase.cpp: (JSSynchronousEdenCollectForDebugging): * API/JSManagedValue.mm: (-[JSManagedValue initWithValue:]): * heap/EdenGCActivityCallback.cpp: (JSC::EdenGCActivityCallback::doCollection): * heap/FullGCActivityCallback.cpp: (JSC::FullGCActivityCallback::doCollection): * heap/Heap.cpp: (JSC::Heap::Thread::Thread): (JSC::Heap::Heap): (JSC::Heap::lastChanceToFinalize): (JSC::Heap::markRoots): (JSC::Heap::gatherStackRoots): (JSC::Heap::deleteUnmarkedCompiledCode): (JSC::Heap::collectAllGarbage): (JSC::Heap::collectAsync): (JSC::Heap::collectSync): (JSC::Heap::shouldCollectInThread): (JSC::Heap::collectInThread): (JSC::Heap::stopTheWorld): (JSC::Heap::resumeTheWorld): (JSC::Heap::stopIfNecessarySlow): (JSC::Heap::acquireAccessSlow): (JSC::Heap::releaseAccessSlow): (JSC::Heap::handleDidJIT): (JSC::Heap::handleNeedFinalize): (JSC::Heap::setDidJIT): (JSC::Heap::setNeedFinalize): (JSC::Heap::waitWhileNeedFinalize): (JSC::Heap::finalize): (JSC::Heap::requestCollection): (JSC::Heap::waitForCollection): (JSC::Heap::didFinishCollection): (JSC::Heap::canCollect): (JSC::Heap::shouldCollectHeuristic): (JSC::Heap::shouldCollect): (JSC::Heap::collectIfNecessaryOrDefer): (JSC::Heap::collectAccordingToDeferGCProbability): (JSC::Heap::collect): Deleted. (JSC::Heap::collectWithoutAnySweep): Deleted. (JSC::Heap::collectImpl): Deleted. * heap/Heap.h: (JSC::Heap::ReleaseAccessScope::ReleaseAccessScope): (JSC::Heap::ReleaseAccessScope::~ReleaseAccessScope): * heap/HeapInlines.h: (JSC::Heap::acquireAccess): (JSC::Heap::releaseAccess): (JSC::Heap::stopIfNecessary): * heap/MachineStackMarker.cpp: (JSC::MachineThreads::gatherConservativeRoots): (JSC::MachineThreads::gatherFromCurrentThread): Deleted. * heap/MachineStackMarker.h: * jit/JITWorklist.cpp: (JSC::JITWorklist::completeAllForVM): * jit/JITWorklist.h: * jsc.cpp: (functionFullGC): (functionEdenGC): * runtime/InitializeThreading.cpp: (JSC::initializeThreading): * runtime/JSLock.cpp: (JSC::JSLock::didAcquireLock): (JSC::JSLock::unlock): (JSC::JSLock::willReleaseLock): * tools/JSDollarVMPrototype.cpp: (JSC::JSDollarVMPrototype::edenGC): Source/WebCore: No new tests because existing tests cover this. We now need to be more careful about using JSLock. This fixes some places that were not holding it. New assertions in the GC are more likely to catch this than before. * bindings/js/WorkerScriptController.cpp: (WebCore::WorkerScriptController::WorkerScriptController): Source/WTF: This fixes some bugs and adds a few features. * wtf/Atomics.h: The GC may do work on behalf of the JIT. If it does, the main thread needs to execute a cross-modifying code fence. This is cpuid on x86 and I believe it's isb on ARM. It would have been an isync on PPC and I think that isb is the ARM equivalent. (WTF::arm_isb): (WTF::crossModifyingCodeFence): (WTF::x86_ortop): (WTF::x86_cpuid): * wtf/AutomaticThread.cpp: I accidentally had AutomaticThreadCondition inherit from ThreadSafeRefCounted<AutomaticThread> [sic]. This never crashed before because all of our prior AutomaticThreadConditions were immortal. (WTF::AutomaticThread::AutomaticThread): (WTF::AutomaticThread::~AutomaticThread): (WTF::AutomaticThread::start): * wtf/AutomaticThread.h: * wtf/MainThread.cpp: Need to allow initializeGCThreads() to be called separately because it's now more than just a debugging thing. (WTF::initializeGCThreads): Canonical link: https://commits.webkit.org/182065@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@208306 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-11-02 22:01:04 +00:00
bool m_hasUnderlyingThread { false };
Condition m_waitCondition;
Condition m_isRunningCondition;
WTF should make it easier to create threads that die automatically after inactivity https://bugs.webkit.org/show_bug.cgi?id=163576 Reviewed by Andreas Kling. Source/JavaScriptCore: Added a sleepSeconds() function, which made it easier for me to test this change. The WTF changes in this patch change how the JSC GC manages threads: the GC threads will now shut down automatically after 1 second of inactivity. Maybe this will save some memory. * jsc.cpp: (GlobalObject::finishCreation): (functionSleepSeconds): Source/WTF: For a long time now, I've been adding threads to WTF/JSC and each time I do this, I feel guilty because those threads don't shut down when they are inactive. For example, in bug 163562, I need to add a new GC thread. There will be one of them per VM. This means that a JSC API client that starts a lot of VMs will have a lot of threads. I don't think that's good. A common pattern for all of these threads is that they have some well-defined trigger that causes them to run. This trigger has a lock, a condition variable, some logic that determines if there is work to do, and then of course the logic for the thread's actual work. The thread bodies usually look like this: void Thingy::runThread() { for (;;) { Work work; { LockHolder locker(m_lock); while (!hasWork()) m_cond.wait(m_lock); work = takeWork(); } doWork(work); } } If you look at ParallelHelperPool (the GC's threads) and DFG::Worklist (some of the JIT's threads), you will see this pattern. This change adds a new kind of thread, called AutomaticThread, that lets you write threads to this pattern while getting automatic thread shutdown for free: instead of just waiting on a condition variable, AutomaticThread will have a timeout that causes the thread to die. The condition variable associated with AutomaticThread, called AutomaticThreadCondition, is smart enough to restart any threads that have decided to stop due to inactivity. The inactivity threshold is current just 1 second. In this patch I only adopt AutomaticThread for ParallelHelperPool. I plan to adopt it in more places soon. * WTF.xcodeproj/project.pbxproj: * wtf/AutomaticThread.cpp: Added. (WTF::AutomaticThreadCondition::create): (WTF::AutomaticThreadCondition::AutomaticThreadCondition): (WTF::AutomaticThreadCondition::~AutomaticThreadCondition): (WTF::AutomaticThreadCondition::notifyAll): (WTF::AutomaticThreadCondition::add): (WTF::AutomaticThreadCondition::remove): (WTF::AutomaticThreadCondition::contains): (WTF::AutomaticThread::AutomaticThread): (WTF::AutomaticThread::~AutomaticThread): (WTF::AutomaticThread::join): (WTF::AutomaticThread::start): * wtf/AutomaticThread.h: Added. * wtf/CMakeLists.txt: * wtf/ParallelHelperPool.cpp: (WTF::ParallelHelperClient::ParallelHelperClient): (WTF::ParallelHelperClient::~ParallelHelperClient): (WTF::ParallelHelperClient::setTask): (WTF::ParallelHelperClient::finish): (WTF::ParallelHelperClient::doSomeHelping): (WTF::ParallelHelperClient::runTask): (WTF::ParallelHelperPool::ParallelHelperPool): (WTF::ParallelHelperPool::~ParallelHelperPool): (WTF::ParallelHelperPool::ensureThreads): (WTF::ParallelHelperPool::doSomeHelping): (WTF::ParallelHelperPool::Thread::Thread): (WTF::ParallelHelperPool::didMakeWorkAvailable): (WTF::ParallelHelperPool::helperThreadBody): Deleted. (WTF::ParallelHelperPool::waitForClientWithTask): Deleted. * wtf/ParallelHelperPool.h: Canonical link: https://commits.webkit.org/181393@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@207480 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-10-18 20:17:10 +00:00
};
} // namespace WTF
using WTF::AutomaticThread;
DFG worklist should use AutomaticThread https://bugs.webkit.org/show_bug.cgi?id=163615 Reviewed by Mark Lam. Source/JavaScriptCore: AutomaticThread is a new feature in WTF that allows you to easily create worker threads that shut down automatically. This changes DFG::Worklist to use AutomaticThread, so that its threads shut down automatically, too. This has the potential to save a lot of memory. This required some improvements to AutomaticThread: Worklist likes to be able to keep state around for the whole lifetime of a thread, and so it likes knowing when threads are born and when they die. I added virtual methods for that. Also, Worklist uses notifyOne() so I added that, too. This looks to be perf-neutral. * dfg/DFGThreadData.cpp: (JSC::DFG::ThreadData::ThreadData): * dfg/DFGThreadData.h: * dfg/DFGWorklist.cpp: (JSC::DFG::Worklist::ThreadBody::ThreadBody): (JSC::DFG::Worklist::Worklist): (JSC::DFG::Worklist::~Worklist): (JSC::DFG::Worklist::finishCreation): (JSC::DFG::Worklist::isActiveForVM): (JSC::DFG::Worklist::enqueue): (JSC::DFG::Worklist::compilationState): (JSC::DFG::Worklist::waitUntilAllPlansForVMAreReady): (JSC::DFG::Worklist::removeAllReadyPlansForVM): (JSC::DFG::Worklist::completeAllReadyPlansForVM): (JSC::DFG::Worklist::rememberCodeBlocks): (JSC::DFG::Worklist::visitWeakReferences): (JSC::DFG::Worklist::removeDeadPlans): (JSC::DFG::Worklist::removeNonCompilingPlansForVM): (JSC::DFG::Worklist::queueLength): (JSC::DFG::Worklist::dump): (JSC::DFG::Worklist::runThread): Deleted. (JSC::DFG::Worklist::threadFunction): Deleted. * dfg/DFGWorklist.h: Source/WTF: This adds new functionality to AutomaticThread to support DFG::Worklist: - AutomaticThread::threadDidStart/threadWillStop virtual methods called at the start and end of a thread's lifetime. This allows Worklist to tie some resources to the life of the thread, and also means that now those resources will naturally free up when the Worklist is not in use. - AutomaticThreadCondition::notifyOne(). This required changes to Condition::notifyOne(). We need to know if the Condition woke up anyone. If it didn't, then we need to launch one of our threads. * wtf/AutomaticThread.cpp: (WTF::AutomaticThreadCondition::notifyOne): (WTF::AutomaticThread::ThreadScope::ThreadScope): (WTF::AutomaticThread::ThreadScope::~ThreadScope): (WTF::AutomaticThread::start): (WTF::AutomaticThread::threadDidStart): (WTF::AutomaticThread::threadWillStop): * wtf/AutomaticThread.h: * wtf/Condition.h: (WTF::ConditionBase::notifyOne): Canonical link: https://commits.webkit.org/181455@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@207545 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-10-19 17:47:30 +00:00
using WTF::AutomaticThreadCondition;