Changeset 215265 in webkit for trunk/Source/JavaScriptCore


Ignore:
Timestamp:
Apr 12, 2017, 5:08:29 AM (8 years ago)
Author:
Yusuke Suzuki
Message:

[WTF] Introduce Thread class and use RefPtr<Thread> and align Windows Threading implementation semantics to Pthread one
https://bugs.webkit.org/show_bug.cgi?id=170502

Reviewed by Mark Lam.

Source/JavaScriptCore:

  • API/tests/CompareAndSwapTest.cpp:

(testCompareAndSwap):

  • JavaScriptCore.xcodeproj/project.pbxproj:
  • b3/air/testair.cpp:
  • b3/testb3.cpp:

(JSC::B3::run):

  • bytecode/SuperSampler.cpp:

(JSC::initializeSuperSampler):

  • dfg/DFGWorklist.cpp:
  • disassembler/Disassembler.cpp:
  • heap/Heap.cpp:

(JSC::Heap::lastChanceToFinalize):
(JSC::Heap::notifyIsSafeToCollect):

  • heap/Heap.h:
  • heap/MachineStackMarker.cpp:

(JSC::MachineThreads::~MachineThreads):
(JSC::MachineThreads::addCurrentThread):
(JSC::MachineThreads::removeThread):
(JSC::MachineThreads::removeThreadIfFound):
(JSC::MachineThreads::MachineThread::MachineThread):
(JSC::MachineThreads::MachineThread::getRegisters):
(JSC::MachineThreads::MachineThread::Registers::stackPointer):
(JSC::MachineThreads::MachineThread::Registers::framePointer):
(JSC::MachineThreads::MachineThread::Registers::instructionPointer):
(JSC::MachineThreads::MachineThread::Registers::llintPC):
(JSC::MachineThreads::MachineThread::captureStack):
(JSC::MachineThreads::tryCopyOtherThreadStack):
(JSC::MachineThreads::tryCopyOtherThreadStacks):
(pthreadSignalHandlerSuspendResume): Deleted.
(JSC::threadData): Deleted.
(JSC::MachineThreads::Thread::Thread): Deleted.
(JSC::MachineThreads::Thread::createForCurrentThread): Deleted.
(JSC::MachineThreads::Thread::operator==): Deleted.
(JSC::MachineThreads::machineThreadForCurrentThread): Deleted.
(JSC::MachineThreads::ThreadData::ThreadData): Deleted.
(JSC::MachineThreads::ThreadData::~ThreadData): Deleted.
(JSC::MachineThreads::ThreadData::suspend): Deleted.
(JSC::MachineThreads::ThreadData::resume): Deleted.
(JSC::MachineThreads::ThreadData::getRegisters): Deleted.
(JSC::MachineThreads::ThreadData::Registers::stackPointer): Deleted.
(JSC::MachineThreads::ThreadData::Registers::framePointer): Deleted.
(JSC::MachineThreads::ThreadData::Registers::instructionPointer): Deleted.
(JSC::MachineThreads::ThreadData::Registers::llintPC): Deleted.
(JSC::MachineThreads::ThreadData::freeRegisters): Deleted.
(JSC::MachineThreads::ThreadData::captureStack): Deleted.

  • heap/MachineStackMarker.h:

(JSC::MachineThreads::MachineThread::suspend):
(JSC::MachineThreads::MachineThread::resume):
(JSC::MachineThreads::MachineThread::threadID):
(JSC::MachineThreads::MachineThread::stackBase):
(JSC::MachineThreads::MachineThread::stackEnd):
(JSC::MachineThreads::threadsListHead):
(JSC::MachineThreads::Thread::operator!=): Deleted.
(JSC::MachineThreads::Thread::suspend): Deleted.
(JSC::MachineThreads::Thread::resume): Deleted.
(JSC::MachineThreads::Thread::getRegisters): Deleted.
(JSC::MachineThreads::Thread::freeRegisters): Deleted.
(JSC::MachineThreads::Thread::captureStack): Deleted.
(JSC::MachineThreads::Thread::platformThread): Deleted.
(JSC::MachineThreads::Thread::stackBase): Deleted.
(JSC::MachineThreads::Thread::stackEnd): Deleted.

  • jit/ICStats.cpp:

(JSC::ICStats::ICStats):
(JSC::ICStats::~ICStats):

  • jit/ICStats.h:
  • jsc.cpp:

(functionDollarAgentStart):
(startTimeoutThreadIfNeeded):

  • runtime/JSLock.cpp:

(JSC::JSLock::lock):

  • runtime/JSLock.h:

(JSC::JSLock::ownerThread):
(JSC::JSLock::currentThreadIsHoldingLock):

  • runtime/SamplingProfiler.cpp:

(JSC::FrameWalker::isValidFramePointer):
(JSC::SamplingProfiler::SamplingProfiler):
(JSC::SamplingProfiler::createThreadIfNecessary):
(JSC::SamplingProfiler::takeSample):

  • runtime/SamplingProfiler.h:
  • runtime/VM.h:

(JSC::VM::ownerThread):

  • runtime/VMTraps.cpp:

(JSC::findActiveVMAndStackBounds):
(JSC::VMTraps::SignalSender::send):
(JSC::VMTraps::fireTrap):

Source/WebCore:

Mechanical change. Use Thread:: APIs.

  • Modules/indexeddb/server/IDBServer.cpp:

(WebCore::IDBServer::IDBServer::IDBServer):

  • Modules/indexeddb/server/IDBServer.h:
  • Modules/webaudio/AsyncAudioDecoder.cpp:

(WebCore::AsyncAudioDecoder::AsyncAudioDecoder):
(WebCore::AsyncAudioDecoder::~AsyncAudioDecoder):
(WebCore::AsyncAudioDecoder::runLoop):

  • Modules/webaudio/AsyncAudioDecoder.h:
  • Modules/webaudio/OfflineAudioDestinationNode.cpp:

(WebCore::OfflineAudioDestinationNode::OfflineAudioDestinationNode):
(WebCore::OfflineAudioDestinationNode::uninitialize):
(WebCore::OfflineAudioDestinationNode::startRendering):

  • Modules/webaudio/OfflineAudioDestinationNode.h:
  • Modules/webdatabase/Database.cpp:

(WebCore::Database::securityOrigin):

  • Modules/webdatabase/DatabaseThread.cpp:

(WebCore::DatabaseThread::start):
(WebCore::DatabaseThread::databaseThread):
(WebCore::DatabaseThread::recordDatabaseOpen):
(WebCore::DatabaseThread::recordDatabaseClosed):

  • Modules/webdatabase/DatabaseThread.h:

(WebCore::DatabaseThread::getThreadID):

  • bindings/js/GCController.cpp:

(WebCore::GCController::garbageCollectOnAlternateThreadForDebugging):

  • fileapi/AsyncFileStream.cpp:

(WebCore::callOnFileThread):

  • loader/icon/IconDatabase.cpp:

(WebCore::IconDatabase::open):
(WebCore::IconDatabase::close):

  • loader/icon/IconDatabase.h:
  • page/ResourceUsageThread.cpp:

(WebCore::ResourceUsageThread::createThreadIfNeeded):

  • page/ResourceUsageThread.h:
  • page/scrolling/ScrollingThread.cpp:

(WebCore::ScrollingThread::ScrollingThread):
(WebCore::ScrollingThread::isCurrentThread):
(WebCore::ScrollingThread::createThreadIfNeeded):
(WebCore::ScrollingThread::threadCallback):

  • page/scrolling/ScrollingThread.h:
  • platform/audio/HRTFDatabaseLoader.cpp:

(WebCore::HRTFDatabaseLoader::HRTFDatabaseLoader):
(WebCore::HRTFDatabaseLoader::loadAsynchronously):
(WebCore::HRTFDatabaseLoader::waitForLoaderThreadCompletion):

  • platform/audio/HRTFDatabaseLoader.h:
  • platform/audio/ReverbConvolver.cpp:

(WebCore::ReverbConvolver::ReverbConvolver):
(WebCore::ReverbConvolver::~ReverbConvolver):

  • platform/audio/ReverbConvolver.h:
  • platform/audio/gstreamer/AudioFileReaderGStreamer.cpp:

(WebCore::createBusFromAudioFile):
(WebCore::createBusFromInMemoryAudioFile):

  • platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp:

(ResourceHandleStreamingClient::ResourceHandleStreamingClient):
(ResourceHandleStreamingClient::~ResourceHandleStreamingClient):

  • platform/network/cf/LoaderRunLoopCF.cpp:

(WebCore::loaderRunLoop):

  • platform/network/curl/CurlDownload.cpp:

(WebCore::CurlDownloadManager::startThreadIfNeeded):
(WebCore::CurlDownloadManager::stopThread):

  • platform/network/curl/CurlDownload.h:
  • platform/network/curl/SocketStreamHandleImpl.h:
  • platform/network/curl/SocketStreamHandleImplCurl.cpp:

(WebCore::SocketStreamHandleImpl::startThread):
(WebCore::SocketStreamHandleImpl::stopThread):

  • workers/WorkerThread.cpp:

(WebCore::WorkerThread::WorkerThread):
(WebCore::WorkerThread::start):
(WebCore::WorkerThread::workerThread):

  • workers/WorkerThread.h:

(WebCore::WorkerThread::threadID):

Source/WebKit:

Mechanical change. Use Thread:: APIs.

  • Storage/StorageThread.cpp:

(WebCore::StorageThread::StorageThread):
(WebCore::StorageThread::~StorageThread):
(WebCore::StorageThread::start):
(WebCore::StorageThread::dispatch):
(WebCore::StorageThread::terminate):

  • Storage/StorageThread.h:

Source/WebKit2:

Mechanical change. Use Thread:: APIs.

  • NetworkProcess/NetworkProcess.cpp:

(WebKit::NetworkProcess::initializeNetworkProcess):

  • NetworkProcess/cache/NetworkCacheIOChannelSoup.cpp:

(WebKit::NetworkCache::IOChannel::readSyncInThread):

  • Platform/IPC/Connection.cpp:

(IPC::Connection::processIncomingMessage):

  • Shared/EntryPointUtilities/mac/XPCService/XPCServiceEntryPoint.h:

(WebKit::XPCServiceInitializer):

  • UIProcess/linux/MemoryPressureMonitor.cpp:

(WebKit::MemoryPressureMonitor::MemoryPressureMonitor):

  • WebProcess/WebProcess.cpp:

(WebKit::WebProcess::initializeWebProcess):

Source/WTF:

This patch is refactoring of WTF Threading mechanism to merge JavaScriptCore's threading extension to WTF Threading.
Previously, JavaScriptCore requires richer threading features (such as suspending and resuming threads), and they
are implemented for PlatformThread in JavaScriptCore. But these features should be implemented in WTF Threading side
instead of maintaining JSC's own threading features too. This patch removes these features from JSC and move it to
WTF Threading.

However, current WTF Threading has one problem: Windows version of WTF Threading has different semantics from Pthreads
one. In Windows WTF Threading, we cannot perform any operation after the target thread is detached: WTF Threading stop
tracking the state of the thread once the thread is detached. But this is not the same to Pthreads one. In Pthreads,
pthread_detach just means that the resource of the thread will be destroyed automatically. While some operations like
pthread_join will be rejected, some operations like pthread_kill will be accepted.

The problem is that detached thread can be suspended and resumed in JSC. For example, in jsc.cpp, we start the worker
thread and detach it immediately. In worker thread, we will create VM and thus concurrent GC will suspend and resume
the detached thread. However, in Windows WTF Threading, we have no reference to the detached thread. Thus we cannot
perform suspend and resume operations onto the detached thread.

To solve the problem, we change Windows Threading mechanism drastically to align it to the Pthread semantics. In the
new Threading, we have RefPtr<Thread> class. It holds a handle to a platform thread. We can perform threading operations
with this class. For example, Thread::suspend is offered. And we use destructor of the thread local variable to release
the resources held by RefPtr<Thread>. In Windows, Thread::detach does nothing because the resource will be destroyed
automatically by RefPtr<Thread>.

To do so, we introduce ThreadHolder for Windows. This is similar to the previous ThreadIdentifierData for Pthreads.
It holds RefPtr<Thread> in the thread local storage (technically, it is Fiber Local Storage in Windows). Thread::current()
will return this reference.

The problematic situation is that the order of the deallocation of the thread local storage is not defined. So we should
not touch thread local storage in the destructor of the thread local storage. To avoid such edge cases, we have
currentThread() / Thread::currentID() APIs. They are safe to be called even in the destructor of the other thread local
storage. And in Windows, in the FLS destructor, we will create the thread_local variable to defer the destruction of
the ThreadHolder. We ensure that this destructor is called after the other FLS destructors are called in Windows 10.

This patch is performance neutral.

  • WTF.xcodeproj/project.pbxproj:
  • benchmarks/ConditionSpeedTest.cpp:
  • benchmarks/LockFairnessTest.cpp:
  • benchmarks/LockSpeedTest.cpp:
  • wtf/AutomaticThread.cpp:

(WTF::AutomaticThread::start):

  • wtf/CMakeLists.txt:
  • wtf/MainThread.h:
  • wtf/MemoryPressureHandler.h:
  • wtf/ParallelJobsGeneric.cpp:

(WTF::ParallelEnvironment::ThreadPrivate::tryLockFor):
(WTF::ParallelEnvironment::ThreadPrivate::workerThread):

  • wtf/ParallelJobsGeneric.h:

(WTF::ParallelEnvironment::ThreadPrivate::ThreadPrivate): Deleted.

  • wtf/ParkingLot.cpp:

(WTF::ParkingLot::forEachImpl):

  • wtf/ParkingLot.h:

(WTF::ParkingLot::forEach):

  • wtf/PlatformRegisters.h: Renamed from Source/JavaScriptCore/runtime/PlatformThread.h.
  • wtf/RefPtr.h:

(WTF::RefPtr::RefPtr):

  • wtf/ThreadFunctionInvocation.h:

(WTF::ThreadFunctionInvocation::ThreadFunctionInvocation):

  • wtf/ThreadHolder.cpp: Added.

(WTF::ThreadHolder::~ThreadHolder):
(WTF::ThreadHolder::initialize):

  • wtf/ThreadHolder.h: Renamed from Source/WTF/wtf/ThreadIdentifierDataPthreads.h.

(WTF::ThreadHolder::thread):
(WTF::ThreadHolder::ThreadHolder):

  • wtf/ThreadHolderPthreads.cpp: Renamed from Source/WTF/wtf/ThreadIdentifierDataPthreads.cpp.

(WTF::ThreadHolder::initializeOnce):
(WTF::ThreadHolder::current):
(WTF::ThreadHolder::destruct):

  • wtf/ThreadHolderWin.cpp: Added.

(WTF::threadMapMutex):
(WTF::threadMap):
(WTF::ThreadHolder::initializeOnce):
(WTF::ThreadHolder::current):
(WTF::ThreadHolder::destruct):

  • wtf/ThreadSpecific.h:
  • wtf/Threading.cpp:

(WTF::Thread::normalizeThreadName):
(WTF::threadEntryPoint):
(WTF::Thread::create):
(WTF::Thread::setCurrentThreadIsUserInteractive):
(WTF::Thread::setCurrentThreadIsUserInitiated):
(WTF::Thread::setGlobalMaxQOSClass):
(WTF::Thread::adjustedQOSClass):
(WTF::Thread::dump):
(WTF::initializeThreading):
(WTF::normalizeThreadName): Deleted.
(WTF::createThread): Deleted.
(WTF::setCurrentThreadIsUserInteractive): Deleted.
(WTF::setCurrentThreadIsUserInitiated): Deleted.
(WTF::setGlobalMaxQOSClass): Deleted.
(WTF::adjustedQOSClass): Deleted.

  • wtf/Threading.h:

(WTF::Thread::id):
(WTF::Thread::operator==):
(WTF::Thread::operator!=):
(WTF::Thread::joinableState):
(WTF::Thread::didBecomeDetached):
(WTF::Thread::didJoin):
(WTF::Thread::hasExited):
(WTF::currentThread):

  • wtf/ThreadingPthreads.cpp:

(WTF::Thread::Thread):
(WTF::Thread::~Thread):
(WTF::Thread::signalHandlerSuspendResume):
(WTF::Thread::initializePlatformThreading):
(WTF::initializeCurrentThreadEvenIfNonWTFCreated):
(WTF::wtfThreadEntryPoint):
(WTF::Thread::createInternal):
(WTF::Thread::initializeCurrentThreadInternal):
(WTF::Thread::changePriority):
(WTF::Thread::waitForCompletion):
(WTF::Thread::detach):
(WTF::Thread::current):
(WTF::Thread::currentID):
(WTF::Thread::signal):
(WTF::Thread::resume):
(WTF::Thread::getRegisters):
(WTF::Thread::didExit):
(WTF::Thread::establish):
(WTF::PthreadState::PthreadState): Deleted.
(WTF::PthreadState::joinableState): Deleted.
(WTF::PthreadState::pthreadHandle): Deleted.
(WTF::PthreadState::didBecomeDetached): Deleted.
(WTF::PthreadState::didExit): Deleted.
(WTF::PthreadState::didJoin): Deleted.
(WTF::PthreadState::hasExited): Deleted.
(WTF::threadMapMutex): Deleted.
(WTF::initializeThreading): Deleted.
(WTF::threadMap): Deleted.
(WTF::identifierByPthreadHandle): Deleted.
(WTF::establishIdentifierForPthreadHandle): Deleted.
(WTF::pthreadHandleForIdentifierWithLockAlreadyHeld): Deleted.
(WTF::createThreadInternal): Deleted.
(WTF::initializeCurrentThreadInternal): Deleted.
(WTF::changeThreadPriority): Deleted.
(WTF::waitForThreadCompletion): Deleted.
(WTF::detachThread): Deleted.
(WTF::threadDidExit): Deleted.
(WTF::currentThread): Deleted.
(WTF::signalThread): Deleted.

  • wtf/ThreadingWin.cpp:

(WTF::Thread::Thread):
(WTF::Thread::~Thread):
(WTF::Thread::initializeCurrentThreadInternal):
(WTF::Thread::initializePlatformThreading):
(WTF::wtfThreadEntryPoint):
(WTF::Thread::createInternal):
(WTF::Thread::changePriority):
(WTF::Thread::waitForCompletion):
(WTF::Thread::detach):
(WTF::Thread::resume):
(WTF::Thread::getRegisters):
(WTF::Thread::current):
(WTF::Thread::currentID):
(WTF::Thread::didExit):
(WTF::Thread::establish):
(WTF::initializeCurrentThreadInternal): Deleted.
(WTF::threadMapMutex): Deleted.
(WTF::initializeThreading): Deleted.
(WTF::threadMap): Deleted.
(WTF::storeThreadHandleByIdentifier): Deleted.
(WTF::threadHandleForIdentifier): Deleted.
(WTF::clearThreadHandleForIdentifier): Deleted.
(WTF::createThreadInternal): Deleted.
(WTF::changeThreadPriority): Deleted.
(WTF::waitForThreadCompletion): Deleted.
(WTF::detachThread): Deleted.
(WTF::currentThread): Deleted.

  • wtf/WorkQueue.cpp:

(WTF::WorkQueue::concurrentApply):

  • wtf/WorkQueue.h:
  • wtf/cocoa/WorkQueueCocoa.cpp:

(WTF::dispatchQOSClass):

  • wtf/generic/WorkQueueGeneric.cpp:

(WorkQueue::platformInitialize):
(WorkQueue::platformInvalidate):

  • wtf/linux/MemoryPressureHandlerLinux.cpp:

(WTF::MemoryPressureHandler::EventFDPoller::EventFDPoller):
(WTF::MemoryPressureHandler::EventFDPoller::~EventFDPoller):

  • wtf/win/MainThreadWin.cpp:

(WTF::initializeMainThreadPlatform):

Tools:

Mechanical change. Use Thread:: APIs.

  • DumpRenderTree/JavaScriptThreading.cpp:

(runJavaScriptThread):
(startJavaScriptThreads):
(stopJavaScriptThreads):

  • DumpRenderTree/mac/DumpRenderTree.mm:

(testThreadIdentifierMap):

  • TestWebKitAPI/Tests/WTF/Condition.cpp:
  • TestWebKitAPI/Tests/WTF/Lock.cpp:

(TestWebKitAPI::runLockTest):

  • TestWebKitAPI/Tests/WTF/ParkingLot.cpp:
Location:
trunk/Source/JavaScriptCore
Files:
21 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/API/tests/CompareAndSwapTest.cpp

    r208209 r215265  
    9797    Bitmap bitmap;
    9898    const int numThreads = 5;
    99     ThreadIdentifier threadIDs[numThreads];
     99    RefPtr<Thread> threads[numThreads];
    100100    Data data[numThreads];
    101101
     
    108108        data[i].numThreads = numThreads;
    109109        std::function<void()> threadFunc = std::bind(setBitThreadFunc, &data[i]);
    110         threadIDs[i] = createThread("setBitThreadFunc", threadFunc);
     110        threads[i] = Thread::create("setBitThreadFunc", threadFunc);
    111111    }
    112112
    113113    printf("Waiting for %d threads to join\n", numThreads);
    114114    for (int i = 0; i < numThreads; i++)
    115         waitForThreadCompletion(threadIDs[i]);
     115        threads[i]->waitForCompletion();
    116116
    117117    printf("PASS: CompareAndSwap test completed without a hang\n");
  • trunk/Source/JavaScriptCore/ChangeLog

    r215250 r215265  
     12017-04-12  Yusuke Suzuki  <[email protected]>
     2
     3        [WTF] Introduce Thread class and use RefPtr<Thread> and align Windows Threading implementation semantics to Pthread one
     4        https://bugs.webkit.org/show_bug.cgi?id=170502
     5
     6        Reviewed by Mark Lam.
     7
     8        * API/tests/CompareAndSwapTest.cpp:
     9        (testCompareAndSwap):
     10        * JavaScriptCore.xcodeproj/project.pbxproj:
     11        * b3/air/testair.cpp:
     12        * b3/testb3.cpp:
     13        (JSC::B3::run):
     14        * bytecode/SuperSampler.cpp:
     15        (JSC::initializeSuperSampler):
     16        * dfg/DFGWorklist.cpp:
     17        * disassembler/Disassembler.cpp:
     18        * heap/Heap.cpp:
     19        (JSC::Heap::lastChanceToFinalize):
     20        (JSC::Heap::notifyIsSafeToCollect):
     21        * heap/Heap.h:
     22        * heap/MachineStackMarker.cpp:
     23        (JSC::MachineThreads::~MachineThreads):
     24        (JSC::MachineThreads::addCurrentThread):
     25        (JSC::MachineThreads::removeThread):
     26        (JSC::MachineThreads::removeThreadIfFound):
     27        (JSC::MachineThreads::MachineThread::MachineThread):
     28        (JSC::MachineThreads::MachineThread::getRegisters):
     29        (JSC::MachineThreads::MachineThread::Registers::stackPointer):
     30        (JSC::MachineThreads::MachineThread::Registers::framePointer):
     31        (JSC::MachineThreads::MachineThread::Registers::instructionPointer):
     32        (JSC::MachineThreads::MachineThread::Registers::llintPC):
     33        (JSC::MachineThreads::MachineThread::captureStack):
     34        (JSC::MachineThreads::tryCopyOtherThreadStack):
     35        (JSC::MachineThreads::tryCopyOtherThreadStacks):
     36        (pthreadSignalHandlerSuspendResume): Deleted.
     37        (JSC::threadData): Deleted.
     38        (JSC::MachineThreads::Thread::Thread): Deleted.
     39        (JSC::MachineThreads::Thread::createForCurrentThread): Deleted.
     40        (JSC::MachineThreads::Thread::operator==): Deleted.
     41        (JSC::MachineThreads::machineThreadForCurrentThread): Deleted.
     42        (JSC::MachineThreads::ThreadData::ThreadData): Deleted.
     43        (JSC::MachineThreads::ThreadData::~ThreadData): Deleted.
     44        (JSC::MachineThreads::ThreadData::suspend): Deleted.
     45        (JSC::MachineThreads::ThreadData::resume): Deleted.
     46        (JSC::MachineThreads::ThreadData::getRegisters): Deleted.
     47        (JSC::MachineThreads::ThreadData::Registers::stackPointer): Deleted.
     48        (JSC::MachineThreads::ThreadData::Registers::framePointer): Deleted.
     49        (JSC::MachineThreads::ThreadData::Registers::instructionPointer): Deleted.
     50        (JSC::MachineThreads::ThreadData::Registers::llintPC): Deleted.
     51        (JSC::MachineThreads::ThreadData::freeRegisters): Deleted.
     52        (JSC::MachineThreads::ThreadData::captureStack): Deleted.
     53        * heap/MachineStackMarker.h:
     54        (JSC::MachineThreads::MachineThread::suspend):
     55        (JSC::MachineThreads::MachineThread::resume):
     56        (JSC::MachineThreads::MachineThread::threadID):
     57        (JSC::MachineThreads::MachineThread::stackBase):
     58        (JSC::MachineThreads::MachineThread::stackEnd):
     59        (JSC::MachineThreads::threadsListHead):
     60        (JSC::MachineThreads::Thread::operator!=): Deleted.
     61        (JSC::MachineThreads::Thread::suspend): Deleted.
     62        (JSC::MachineThreads::Thread::resume): Deleted.
     63        (JSC::MachineThreads::Thread::getRegisters): Deleted.
     64        (JSC::MachineThreads::Thread::freeRegisters): Deleted.
     65        (JSC::MachineThreads::Thread::captureStack): Deleted.
     66        (JSC::MachineThreads::Thread::platformThread): Deleted.
     67        (JSC::MachineThreads::Thread::stackBase): Deleted.
     68        (JSC::MachineThreads::Thread::stackEnd): Deleted.
     69        * jit/ICStats.cpp:
     70        (JSC::ICStats::ICStats):
     71        (JSC::ICStats::~ICStats):
     72        * jit/ICStats.h:
     73        * jsc.cpp:
     74        (functionDollarAgentStart):
     75        (startTimeoutThreadIfNeeded):
     76        * runtime/JSLock.cpp:
     77        (JSC::JSLock::lock):
     78        * runtime/JSLock.h:
     79        (JSC::JSLock::ownerThread):
     80        (JSC::JSLock::currentThreadIsHoldingLock):
     81        * runtime/SamplingProfiler.cpp:
     82        (JSC::FrameWalker::isValidFramePointer):
     83        (JSC::SamplingProfiler::SamplingProfiler):
     84        (JSC::SamplingProfiler::createThreadIfNecessary):
     85        (JSC::SamplingProfiler::takeSample):
     86        * runtime/SamplingProfiler.h:
     87        * runtime/VM.h:
     88        (JSC::VM::ownerThread):
     89        * runtime/VMTraps.cpp:
     90        (JSC::findActiveVMAndStackBounds):
     91        (JSC::VMTraps::SignalSender::send):
     92        (JSC::VMTraps::fireTrap):
     93
    1942017-04-11  Dean Jackson  <[email protected]>
    295
  • trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r215103 r215265  
    24722472                FED94F2E171E3E2300BE77A4 /* Watchdog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FED94F2B171E3E2300BE77A4 /* Watchdog.cpp */; };
    24732473                FED94F2F171E3E2300BE77A4 /* Watchdog.h in Headers */ = {isa = PBXBuildFile; fileRef = FED94F2C171E3E2300BE77A4 /* Watchdog.h */; settings = {ATTRIBUTES = (Private, ); }; };
    2474                 FEE43FCE1E6641710077D6D1 /* PlatformThread.h in Headers */ = {isa = PBXBuildFile; fileRef = FEE43FCD1E6641400077D6D1 /* PlatformThread.h */; settings = {ATTRIBUTES = (Private, ); }; };
    24752474                FEF040511AAE662D00BD28B0 /* CompareAndSwapTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FEF040501AAE662D00BD28B0 /* CompareAndSwapTest.cpp */; };
    24762475                FEFD6FC61D5E7992008F2F0B /* JSStringInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = FEFD6FC51D5E7970008F2F0B /* JSStringInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
     
    51025101                FEDA50D41B97F442009A3B4F /* PingPongStackOverflowTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PingPongStackOverflowTest.cpp; path = API/tests/PingPongStackOverflowTest.cpp; sourceTree = "<group>"; };
    51035102                FEDA50D51B97F4D9009A3B4F /* PingPongStackOverflowTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PingPongStackOverflowTest.h; path = API/tests/PingPongStackOverflowTest.h; sourceTree = "<group>"; };
    5104                 FEE43FCD1E6641400077D6D1 /* PlatformThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlatformThread.h; sourceTree = "<group>"; };
    51055103                FEF040501AAE662D00BD28B0 /* CompareAndSwapTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CompareAndSwapTest.cpp; path = API/tests/CompareAndSwapTest.cpp; sourceTree = "<group>"; };
    51065104                FEF040521AAEC4ED00BD28B0 /* CompareAndSwapTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CompareAndSwapTest.h; path = API/tests/CompareAndSwapTest.h; sourceTree = "<group>"; };
     
    68676865                                0FE228EA1436AB2300196C48 /* Options.cpp */,
    68686866                                0FE228EB1436AB2300196C48 /* Options.h */,
    6869                                 FEE43FCD1E6641400077D6D1 /* PlatformThread.h */,
    68706867                                868916A9155F285400CB2B9A /* PrivateName.h */,
    68716868                                147341DF1DC2CE9600AA29BA /* ProgramExecutable.cpp */,
     
    93499346                                705B41AC1A6E501E00716757 /* Symbol.h in Headers */,
    93509347                                705B41AE1A6E501E00716757 /* SymbolConstructor.h in Headers */,
    9351                                 FEE43FCE1E6641710077D6D1 /* PlatformThread.h in Headers */,
    93529348                                996B73271BDA08EF00331B84 /* SymbolConstructor.lut.h in Headers */,
    93539349                                705B41B01A6E501E00716757 /* SymbolObject.h in Headers */,
  • trunk/Source/JavaScriptCore/b3/air/testair.cpp

    r214571 r215265  
    19141914    Lock lock;
    19151915
    1916     Vector<ThreadIdentifier> threads;
     1916    Vector<RefPtr<Thread>> threads;
    19171917    for (unsigned i = filter ? 1 : WTF::numberOfProcessorCores(); i--;) {
    19181918        threads.append(
    1919             createThread(
     1919            Thread::create(
    19201920                "testb3 thread",
    19211921                [&] () {
     
    19341934    }
    19351935
    1936     for (ThreadIdentifier thread : threads)
    1937         waitForThreadCompletion(thread);
     1936    for (RefPtr<Thread> thread : threads)
     1937        thread->waitForCompletion();
    19381938    crashLock.lock();
    19391939}
  • trunk/Source/JavaScriptCore/b3/testb3.cpp

    r214908 r215265  
    1685116851    Lock lock;
    1685216852
    16853     Vector<ThreadIdentifier> threads;
     16853    Vector<RefPtr<Thread>> threads;
    1685416854    for (unsigned i = filter ? 1 : WTF::numberOfProcessorCores(); i--;) {
    1685516855        threads.append(
    16856             createThread(
     16856            Thread::create(
    1685716857                "testb3 thread",
    1685816858                [&] () {
     
    1687116871    }
    1687216872
    16873     for (ThreadIdentifier thread : threads)
    16874         waitForThreadCompletion(thread);
     16873    for (RefPtr<Thread> thread : threads)
     16874        thread->waitForCompletion();
    1687516875    crashLock.lock();
    1687616876}
  • trunk/Source/JavaScriptCore/bytecode/SuperSampler.cpp

    r205463 r215265  
    4747        return;
    4848
    49     createThread(
     49    Thread::create(
    5050        "JSC Super Sampler",
    5151        [] () {
  • trunk/Source/JavaScriptCore/dfg/DFGWorklist.cpp

    r212778 r215265  
    145145       
    146146        if (m_relativePriority)
    147             changeThreadPriority(currentThread(), m_relativePriority);
     147            Thread::current().changePriority(m_relativePriority);
    148148       
    149149        m_compilationScope = std::make_unique<CompilationScope>();
  • trunk/Source/JavaScriptCore/disassembler/Disassembler.cpp

    r196729 r215265  
    7474    AsynchronousDisassembler()
    7575    {
    76         createThread("Asynchronous Disassembler", [&] () { run(); });
     76        Thread::create("Asynchronous Disassembler", [&] () { run(); });
    7777    }
    7878   
  • trunk/Source/JavaScriptCore/heap/Heap.cpp

    r214857 r215265  
    350350            m_collectContinuouslyCondition.notifyOne();
    351351        }
    352         waitForThreadCompletion(m_collectContinuouslyThread);
     352        m_collectContinuouslyThread->waitForCompletion();
    353353    }
    354354   
     
    26822682   
    26832683    if (Options::collectContinuously()) {
    2684         m_collectContinuouslyThread = createThread(
     2684        m_collectContinuouslyThread = WTF::Thread::create(
    26852685            "JSC DEBUG Continuous GC",
    26862686            [this] () {
  • trunk/Source/JavaScriptCore/heap/Heap.h

    r213883 r215265  
    5050#include <wtf/HashSet.h>
    5151#include <wtf/ParallelHelperPool.h>
     52#include <wtf/Threading.h>
    5253
    5354namespace JSC {
     
    667668    Condition m_collectContinuouslyCondition;
    668669    bool m_shouldStopCollectingContinuously { false };
    669     ThreadIdentifier m_collectContinuouslyThread { 0 };
     670    RefPtr<WTF::Thread> m_collectContinuouslyThread { nullptr };
    670671   
    671672    MonotonicTime m_lastGCStartTime;
  • trunk/Source/JavaScriptCore/heap/MachineStackMarker.cpp

    r214319 r215265  
    3737#include <wtf/StdLibExtras.h>
    3838
    39 #if OS(DARWIN)
    40 
    41 #include <mach/mach_init.h>
    42 #include <mach/mach_port.h>
    43 #include <mach/task.h>
    44 #include <mach/thread_act.h>
    45 #include <mach/vm_map.h>
    46 
    47 #elif OS(WINDOWS)
    48 
    49 #include <windows.h>
    50 #include <malloc.h>
    51 
    52 #elif OS(UNIX)
    53 
    54 #include <sys/mman.h>
    55 #include <unistd.h>
    56 
    57 #if OS(SOLARIS)
    58 #include <thread.h>
    59 #else
    60 #include <pthread.h>
    61 #endif
    62 
    63 #if HAVE(PTHREAD_NP_H)
    64 #include <pthread_np.h>
    65 #endif
    66 
    67 #if USE(PTHREADS) && !OS(WINDOWS) && !OS(DARWIN)
    68 #include <signal.h>
    69 
    70 // We use SIGUSR2 to suspend and resume machine threads in JavaScriptCore.
    71 static const int SigThreadSuspendResume = SIGUSR2;
    72 static StaticLock globalSignalLock;
    73 thread_local static std::atomic<JSC::MachineThreads::ThreadData*> threadLocalCurrentThread { nullptr };
    74 
    75 static void pthreadSignalHandlerSuspendResume(int, siginfo_t*, void* ucontext)
    76 {
    77     // Touching thread local atomic types from signal handlers is allowed.
    78     JSC::MachineThreads::ThreadData* threadData = threadLocalCurrentThread.load();
    79 
    80     if (threadData->suspended.load(std::memory_order_acquire)) {
    81         // This is signal handler invocation that is intended to be used to resume sigsuspend.
    82         // So this handler invocation itself should not process.
    83         //
    84         // When signal comes, first, the system calls signal handler. And later, sigsuspend will be resumed. Signal handler invocation always precedes.
    85         // So, the problem never happens that suspended.store(true, ...) will be executed before the handler is called.
    86         // http://pubs.opengroup.org/onlinepubs/009695399/functions/sigsuspend.html
    87         return;
    88     }
    89 
    90     ucontext_t* userContext = static_cast<ucontext_t*>(ucontext);
    91 #if CPU(PPC)
    92     threadData->suspendedMachineContext = *userContext->uc_mcontext.uc_regs;
    93 #else
    94     threadData->suspendedMachineContext = userContext->uc_mcontext;
    95 #endif
    96 
    97     // Allow suspend caller to see that this thread is suspended.
    98     // sem_post is async-signal-safe function. It means that we can call this from a signal handler.
    99     // http://pubs.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html#tag_02_04_03
    100     //
    101     // And sem_post emits memory barrier that ensures that suspendedMachineContext is correctly saved.
    102     // http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_11
    103     sem_post(&threadData->semaphoreForSuspendResume);
    104 
    105     // Reaching here, SigThreadSuspendResume is blocked in this handler (this is configured by sigaction's sa_mask).
    106     // So before calling sigsuspend, SigThreadSuspendResume to this thread is deferred. This ensures that the handler is not executed recursively.
    107     sigset_t blockedSignalSet;
    108     sigfillset(&blockedSignalSet);
    109     sigdelset(&blockedSignalSet, SigThreadSuspendResume);
    110     sigsuspend(&blockedSignalSet);
    111 
    112     // Allow resume caller to see that this thread is resumed.
    113     sem_post(&threadData->semaphoreForSuspendResume);
    114 }
    115 #endif // USE(PTHREADS) && !OS(WINDOWS) && !OS(DARWIN)
    116 
    117 #endif
    118 
    11939using namespace WTF;
    12040
    12141namespace JSC {
    122 
    123 using Thread = MachineThreads::Thread;
    12442
    12543class ActiveMachineThreadsManager;
     
    195113
    196114    LockHolder registeredThreadsLock(m_registeredThreadsMutex);
    197     for (Thread* t = m_registeredThreads; t;) {
    198         Thread* next = t->next;
     115    for (MachineThread* t = m_registeredThreads; t;) {
     116        MachineThread* next = t->next;
    199117        delete t;
    200118        t = next;
    201119    }
    202 }
    203 
    204 static MachineThreads::ThreadData* threadData()
    205 {
    206     static NeverDestroyed<ThreadSpecific<MachineThreads::ThreadData, CanBeGCThread::True>> threadData;
    207     return threadData.get();
    208 }
    209 
    210 MachineThreads::Thread::Thread(ThreadData* threadData)
    211     : data(threadData)
    212 {
    213     ASSERT(threadData);
    214 }
    215 
    216 Thread* MachineThreads::Thread::createForCurrentThread()
    217 {
    218     return new Thread(threadData());
    219 }
    220 
    221 bool MachineThreads::Thread::operator==(const PlatformThread& other) const
    222 {
    223 #if OS(DARWIN) || OS(WINDOWS)
    224     return data->platformThread == other;
    225 #elif USE(PTHREADS)
    226     return !!pthread_equal(data->platformThread, other);
    227 #else
    228 #error Need a way to compare threads on this platform
    229 #endif
    230120}
    231121
     
    240130    }
    241131
    242     Thread* thread = Thread::createForCurrentThread();
     132    MachineThread* thread = new MachineThread();
    243133    threadSpecificSet(m_threadSpecificForMachineThreads, this);
    244134
     
    249139}
    250140
    251 Thread* MachineThreads::machineThreadForCurrentThread()
     141auto MachineThreads::machineThreadForCurrentThread() -> MachineThread*
    252142{
    253143    LockHolder lock(m_registeredThreadsMutex);
    254     PlatformThread platformThread = currentPlatformThread();
    255     for (Thread* thread = m_registeredThreads; thread; thread = thread->next) {
    256         if (*thread == platformThread)
     144    ThreadIdentifier id = currentThread();
     145    for (MachineThread* thread = m_registeredThreads; thread; thread = thread->next) {
     146        if (thread->threadID() == id)
    257147            return thread;
    258148    }
     
    284174#endif
    285175
    286         machineThreads->removeThreadIfFound(currentPlatformThread());
    287     }
    288 }
    289 
    290 template<typename PlatformThread>
    291 void MachineThreads::removeThreadIfFound(PlatformThread platformThread)
     176        machineThreads->removeThreadIfFound(currentThread());
     177    }
     178}
     179
     180void MachineThreads::removeThreadIfFound(ThreadIdentifier id)
    292181{
    293182    LockHolder lock(m_registeredThreadsMutex);
    294     Thread* t = m_registeredThreads;
    295     if (*t == platformThread) {
     183    MachineThread* t = m_registeredThreads;
     184    if (t->threadID() == id) {
    296185        m_registeredThreads = m_registeredThreads->next;
    297186        delete t;
    298187    } else {
    299         Thread* last = m_registeredThreads;
     188        MachineThread* last = m_registeredThreads;
    300189        for (t = m_registeredThreads->next; t; t = t->next) {
    301             if (*t == platformThread) {
     190            if (t->threadID() == id) {
    302191                last->next = t->next;
    303192                break;
     
    321210}
    322211
    323 MachineThreads::ThreadData::ThreadData()
     212MachineThreads::MachineThread::MachineThread()
     213    : next(nullptr)
     214    , m_thread(WTF::Thread::current())
    324215{
    325216    auto stackBounds = wtfThreadData().stack();
    326     platformThread = currentPlatformThread();
    327     stackBase = stackBounds.origin();
    328     stackEnd = stackBounds.end();
    329 
    330 #if OS(WINDOWS)
    331     ASSERT(platformThread == GetCurrentThreadId());
    332     bool isSuccessful =
    333         DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(),
    334             &platformThreadHandle, 0, FALSE, DUPLICATE_SAME_ACCESS);
    335     RELEASE_ASSERT(isSuccessful);
    336 #elif USE(PTHREADS) && !OS(DARWIN)
    337     threadLocalCurrentThread.store(this);
    338 
    339     // Signal handlers are process global configuration.
    340     static std::once_flag initializeSignalHandler;
    341     std::call_once(initializeSignalHandler, [] {
    342         // Intentionally block SigThreadSuspendResume in the handler.
    343         // SigThreadSuspendResume will be allowed in the handler by sigsuspend.
    344         struct sigaction action;
    345         sigemptyset(&action.sa_mask);
    346         sigaddset(&action.sa_mask, SigThreadSuspendResume);
    347 
    348         action.sa_sigaction = pthreadSignalHandlerSuspendResume;
    349         action.sa_flags = SA_RESTART | SA_SIGINFO;
    350         sigaction(SigThreadSuspendResume, &action, 0);
    351     });
    352 
    353     sigset_t mask;
    354     sigemptyset(&mask);
    355     sigaddset(&mask, SigThreadSuspendResume);
    356     pthread_sigmask(SIG_UNBLOCK, &mask, 0);
    357 
    358     sem_init(&semaphoreForSuspendResume, /* Only available in this process. */ 0, /* Initial value for the semaphore. */ 0);
    359 #endif
    360 }
    361 
    362 MachineThreads::ThreadData::~ThreadData()
    363 {
    364 #if OS(WINDOWS)
    365     CloseHandle(platformThreadHandle);
    366 #elif USE(PTHREADS) && !OS(DARWIN)
    367     sem_destroy(&semaphoreForSuspendResume);
    368 #endif
    369 }
    370 
    371 bool MachineThreads::ThreadData::suspend()
    372 {
    373 #if OS(DARWIN)
    374     kern_return_t result = thread_suspend(platformThread);
    375     return result == KERN_SUCCESS;
    376 #elif OS(WINDOWS)
    377     bool threadIsSuspended = (SuspendThread(platformThreadHandle) != (DWORD)-1);
    378     ASSERT(threadIsSuspended);
    379     return threadIsSuspended;
    380 #elif USE(PTHREADS)
    381     ASSERT_WITH_MESSAGE(currentPlatformThread() != platformThread, "Currently we don't support suspend the current thread itself.");
    382     {
    383         // During suspend, suspend or resume should not be executed from the other threads.
    384         // We use global lock instead of per thread lock.
    385         // Consider the following case, there are threads A and B.
    386         // And A attempt to suspend B and B attempt to suspend A.
    387         // A and B send signals. And later, signals are delivered to A and B.
    388         // In that case, both will be suspended.
    389         LockHolder lock(globalSignalLock);
    390         if (!suspendCount) {
    391             // Ideally, we would like to use pthread_sigqueue. It allows us to pass the argument to the signal handler.
    392             // But it can be used in a few platforms, like Linux.
    393             // Instead, we use Thread* stored in the thread local storage to pass it to the signal handler.
    394             if (pthread_kill(platformThread, SigThreadSuspendResume) == ESRCH)
    395                 return false;
    396             sem_wait(&semaphoreForSuspendResume);
    397             // Release barrier ensures that this operation is always executed after all the above processing is done.
    398             suspended.store(true, std::memory_order_release);
    399         }
    400         ++suspendCount;
    401     }
    402     return true;
    403 #else
    404 #error Need a way to suspend threads on this platform
    405 #endif
    406 }
    407 
    408 void MachineThreads::ThreadData::resume()
    409 {
    410 #if OS(DARWIN)
    411     thread_resume(platformThread);
    412 #elif OS(WINDOWS)
    413     ResumeThread(platformThreadHandle);
    414 #elif USE(PTHREADS)
    415     {
    416         // During resume, suspend or resume should not be executed from the other threads.
    417         LockHolder lock(globalSignalLock);
    418         if (suspendCount == 1) {
    419             // When allowing SigThreadSuspendResume interrupt in the signal handler by sigsuspend and SigThreadSuspendResume is actually issued,
    420             // the signal handler itself will be called once again.
    421             // There are several ways to distinguish the handler invocation for suspend and resume.
    422             // 1. Use different signal numbers. And check the signal number in the handler.
    423             // 2. Use some arguments to distinguish suspend and resume in the handler. If pthread_sigqueue can be used, we can take this.
    424             // 3. Use thread local storage with atomic variables in the signal handler.
    425             // In this implementaiton, we take (3). suspended flag is used to distinguish it.
    426             if (pthread_kill(platformThread, SigThreadSuspendResume) == ESRCH)
    427                 return;
    428             sem_wait(&semaphoreForSuspendResume);
    429             // Release barrier ensures that this operation is always executed after all the above processing is done.
    430             suspended.store(false, std::memory_order_release);
    431         }
    432         --suspendCount;
    433     }
    434 #else
    435 #error Need a way to resume threads on this platform
    436 #endif
    437 }
    438 
    439 size_t MachineThreads::ThreadData::getRegisters(ThreadData::Registers& registers)
    440 {
    441     ThreadData::Registers::PlatformRegisters& regs = registers.regs;
    442 #if OS(DARWIN)
    443 #if CPU(X86)
    444     unsigned user_count = sizeof(regs)/sizeof(int);
    445     thread_state_flavor_t flavor = i386_THREAD_STATE;
    446 #elif CPU(X86_64)
    447     unsigned user_count = x86_THREAD_STATE64_COUNT;
    448     thread_state_flavor_t flavor = x86_THREAD_STATE64;
    449 #elif CPU(PPC)
    450     unsigned user_count = PPC_THREAD_STATE_COUNT;
    451     thread_state_flavor_t flavor = PPC_THREAD_STATE;
    452 #elif CPU(PPC64)
    453     unsigned user_count = PPC_THREAD_STATE64_COUNT;
    454     thread_state_flavor_t flavor = PPC_THREAD_STATE64;
    455 #elif CPU(ARM)
    456     unsigned user_count = ARM_THREAD_STATE_COUNT;
    457     thread_state_flavor_t flavor = ARM_THREAD_STATE;
    458 #elif CPU(ARM64)
    459     unsigned user_count = ARM_THREAD_STATE64_COUNT;
    460     thread_state_flavor_t flavor = ARM_THREAD_STATE64;
    461 #else
    462 #error Unknown Architecture
    463 #endif
    464 
    465     kern_return_t result = thread_get_state(platformThread, flavor, (thread_state_t)&regs, &user_count);
    466     if (result != KERN_SUCCESS) {
    467         WTFReportFatalError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION,
    468                             "JavaScript garbage collection failed because thread_get_state returned an error (%d). This is probably the result of running inside Rosetta, which is not supported.", result);
    469         CRASH();
    470     }
    471     return user_count * sizeof(uintptr_t);
    472 // end OS(DARWIN)
    473 
    474 #elif OS(WINDOWS)
    475     regs.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL;
    476     GetThreadContext(platformThreadHandle, &regs);
    477     return sizeof(CONTEXT);
    478 #elif ((OS(FREEBSD) || defined(__GLIBC__)) && ENABLE(JIT))
    479     regs = suspendedMachineContext;
    480     return sizeof(Registers::PlatformRegisters);
    481 #elif USE(PTHREADS)
    482     pthread_attr_init(&regs.attribute);
    483 #if HAVE(PTHREAD_NP_H) || OS(NETBSD)
    484 #if !OS(OPENBSD)
    485     // e.g. on FreeBSD 5.4, [email protected]
    486     pthread_attr_get_np(platformThread, &regs.attribute);
    487 #endif
    488 #else
    489     // FIXME: this function is non-portable; other POSIX systems may have different np alternatives
    490     pthread_getattr_np(platformThread, &regs.attribute);
    491 #endif
    492     return 0;
    493 #else
    494 #error Need a way to get thread registers on this platform
    495 #endif
    496 }
    497 
    498 void* MachineThreads::ThreadData::Registers::stackPointer() const
     217    m_stackBase = stackBounds.origin();
     218    m_stackEnd = stackBounds.end();
     219}
     220
     221size_t MachineThreads::MachineThread::getRegisters(MachineThread::Registers& registers)
     222{
     223    WTF::PlatformRegisters& regs = registers.regs;
     224    return m_thread->getRegisters(regs);
     225}
     226
     227void* MachineThreads::MachineThread::Registers::stackPointer() const
    499228{
    500229#if OS(DARWIN) || OS(WINDOWS) || ((OS(FREEBSD) || defined(__GLIBC__)) && ENABLE(JIT))
    501230    return MachineContext::stackPointer(regs);
    502231#elif USE(PTHREADS)
    503     void* stackBase = 0;
    504     size_t stackSize = 0;
    505 #if OS(OPENBSD)
    506     stack_t ss;
    507     int rc = pthread_stackseg_np(pthread_self(), &ss);
    508     stackBase = (void*)((size_t) ss.ss_sp - ss.ss_size);
    509     stackSize = ss.ss_size;
    510 #else
    511     int rc = pthread_attr_getstack(&regs.attribute, &stackBase, &stackSize);
    512 #endif
    513     (void)rc; // FIXME: Deal with error code somehow? Seems fatal.
    514     ASSERT(stackBase);
    515     return static_cast<char*>(stackBase) + stackSize;
     232    return regs.stackPointer;
    516233#else
    517234#error Need a way to get the stack pointer for another thread on this platform
     
    520237
    521238#if ENABLE(SAMPLING_PROFILER)
    522 void* MachineThreads::ThreadData::Registers::framePointer() const
     239void* MachineThreads::MachineThread::Registers::framePointer() const
    523240{
    524241#if OS(DARWIN) || OS(WINDOWS) || (OS(FREEBSD) || defined(__GLIBC__))
     
    529246}
    530247
    531 void* MachineThreads::ThreadData::Registers::instructionPointer() const
     248void* MachineThreads::MachineThread::Registers::instructionPointer() const
    532249{
    533250#if OS(DARWIN) || OS(WINDOWS) || (OS(FREEBSD) || defined(__GLIBC__))
     
    538255}
    539256
    540 void* MachineThreads::ThreadData::Registers::llintPC() const
     257void* MachineThreads::MachineThread::Registers::llintPC() const
    541258{
    542259    // LLInt uses regT4 as PC.
     
    548265}
    549266#endif // ENABLE(SAMPLING_PROFILER)
    550 
    551 void MachineThreads::ThreadData::freeRegisters(ThreadData::Registers& registers)
    552 {
    553     ThreadData::Registers::PlatformRegisters& regs = registers.regs;
    554 #if USE(PTHREADS) && !OS(WINDOWS) && !OS(DARWIN) && !((OS(FREEBSD) || defined(__GLIBC__)) && ENABLE(JIT))
    555     pthread_attr_destroy(&regs.attribute);
    556 #else
    557     UNUSED_PARAM(regs);
    558 #endif
    559 }
    560267
    561268static inline int osRedZoneAdjustment()
     
    574281}
    575282
    576 std::pair<void*, size_t> MachineThreads::ThreadData::captureStack(void* stackTop)
    577 {
    578     char* begin = reinterpret_cast_ptr<char*>(stackBase);
     283std::pair<void*, size_t> MachineThreads::MachineThread::captureStack(void* stackTop)
     284{
     285    char* begin = reinterpret_cast_ptr<char*>(m_stackBase);
    579286    char* end = bitwise_cast<char*>(WTF::roundUpToMultipleOf<sizeof(void*)>(reinterpret_cast<uintptr_t>(stackTop)));
    580287    ASSERT(begin >= end);
     
    583290    ASSERT(WTF::roundUpToMultipleOf<sizeof(void*)>(reinterpret_cast<uintptr_t>(endWithRedZone)) == reinterpret_cast<uintptr_t>(endWithRedZone));
    584291
    585     if (endWithRedZone < stackEnd)
    586         endWithRedZone = reinterpret_cast_ptr<char*>(stackEnd);
     292    if (endWithRedZone < m_stackEnd)
     293        endWithRedZone = reinterpret_cast_ptr<char*>(m_stackEnd);
    587294
    588295    std::swap(begin, endWithRedZone);
     
    617324// operation. As the heap is generally much larger than the stack the performance hit is minimal.
    618325// See: https://bugs.webkit.org/show_bug.cgi?id=146297
    619 void MachineThreads::tryCopyOtherThreadStack(Thread* thread, void* buffer, size_t capacity, size_t* size)
    620 {
    621     Thread::Registers registers;
     326void MachineThreads::tryCopyOtherThreadStack(MachineThread* thread, void* buffer, size_t capacity, size_t* size)
     327{
     328    MachineThread::Registers registers;
    622329    size_t registersSize = thread->getRegisters(registers);
    623330    std::pair<void*, size_t> stack = thread->captureStack(registers.stackPointer());
     
    632339        copyMemory(static_cast<char*>(buffer) + *size, stack.first, stack.second);
    633340    *size += stack.second;
    634 
    635     thread->freeRegisters(registers);
    636341}
    637342
     
    645350    *size = 0;
    646351
    647     PlatformThread platformThread = currentPlatformThread();
     352    ThreadIdentifier id = currentThread();
    648353    int numberOfThreads = 0; // Using 0 to denote that we haven't counted the number of threads yet.
    649354    int index = 1;
    650     Thread* threadsToBeDeleted = nullptr;
    651 
    652     Thread* previousThread = nullptr;
    653     for (Thread* thread = m_registeredThreads; thread; index++) {
    654         if (*thread != platformThread) {
    655             bool success = thread->suspend();
     355    MachineThread* threadsToBeDeleted = nullptr;
     356
     357    MachineThread* previousThread = nullptr;
     358    for (MachineThread* thread = m_registeredThreads; thread; index++) {
     359        if (thread->threadID() != id) {
     360            auto result = thread->suspend();
    656361#if OS(DARWIN)
    657             if (!success) {
     362            if (!result) {
    658363                if (!numberOfThreads) {
    659                     for (Thread* countedThread = m_registeredThreads; countedThread; countedThread = countedThread->next)
     364                    for (MachineThread* countedThread = m_registeredThreads; countedThread; countedThread = countedThread->next)
    660365                        numberOfThreads++;
    661366                }
    662                
    663                 // Re-do the suspension to get the actual failure result for logging.
    664                 kern_return_t error = thread_suspend(thread->platformThread());
    665                 ASSERT(error != KERN_SUCCESS);
     367
     368                ASSERT(result.error() != KERN_SUCCESS);
    666369
    667370                WTFReportError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION,
    668                     "JavaScript garbage collection encountered an invalid thread (err 0x%x): Thread [%d/%d: %p] platformThread %p.",
    669                     error, index, numberOfThreads, thread, reinterpret_cast<void*>(thread->platformThread()));
     371                    "JavaScript garbage collection encountered an invalid thread (err 0x%x): Thread [%d/%d: %p] id %u.",
     372                    result.error(), index, numberOfThreads, thread, thread->threadID());
    670373
    671374                // Put the invalid thread on the threadsToBeDeleted list.
     
    674377                // we need for deleting the invalid thread. Hence, we need to
    675378                // defer the deletion till after we have resumed all threads.
    676                 Thread* nextThread = thread->next;
     379                MachineThread* nextThread = thread->next;
    677380                thread->next = threadsToBeDeleted;
    678381                threadsToBeDeleted = thread;
     
    688391            UNUSED_PARAM(numberOfThreads);
    689392            UNUSED_PARAM(previousThread);
    690             ASSERT_UNUSED(success, success);
     393            ASSERT_UNUSED(result, result);
    691394#endif
    692395        }
     
    695398    }
    696399
    697     for (Thread* thread = m_registeredThreads; thread; thread = thread->next) {
    698         if (*thread != platformThread)
     400    for (MachineThread* thread = m_registeredThreads; thread; thread = thread->next) {
     401        if (thread->threadID() != id)
    699402            tryCopyOtherThreadStack(thread, buffer, capacity, size);
    700403    }
    701404
    702     for (Thread* thread = m_registeredThreads; thread; thread = thread->next) {
    703         if (*thread != platformThread)
     405    for (MachineThread* thread = m_registeredThreads; thread; thread = thread->next) {
     406        if (thread->threadID() != id)
    704407            thread->resume();
    705408    }
    706409
    707     for (Thread* thread = threadsToBeDeleted; thread; ) {
    708         Thread* nextThread = thread->next;
     410    for (MachineThread* thread = threadsToBeDeleted; thread; ) {
     411        MachineThread* nextThread = thread->next;
    709412        delete thread;
    710413        thread = nextThread;
  • trunk/Source/JavaScriptCore/heap/MachineStackMarker.h

    r214319 r215265  
    2323
    2424#include "MachineContext.h"
    25 #include "PlatformThread.h"
    2625#include "RegisterState.h"
    2726#include <wtf/Lock.h>
     
    2928#include <wtf/ScopedLambda.h>
    3029#include <wtf/ThreadSpecific.h>
    31 
    32 #if USE(PTHREADS) && !OS(WINDOWS) && !OS(DARWIN)
    33 #include <semaphore.h>
    34 #include <signal.h>
    35 // Using signal.h didn't make mcontext_t and ucontext_t available on FreeBSD.
    36 // This bug has been fixed in FreeBSD 11.0-CURRENT, so this workaround can be
    37 // removed after FreeBSD 10.x goes EOL.
    38 // https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=207079
    39 #if OS(FREEBSD)
    40 #include <ucontext.h>
    41 #endif
    42 #endif
    4330
    4431namespace JSC {
     
    6552    JS_EXPORT_PRIVATE void addCurrentThread(); // Only needs to be called by clients that can use the same heap from multiple threads.
    6653
    67     class ThreadData {
     54    class MachineThread {
    6855        WTF_MAKE_FAST_ALLOCATED;
    6956    public:
    70         ThreadData();
    71         ~ThreadData();
    72 
    73         static ThreadData* createForCurrentThread();
     57        MachineThread();
    7458
    7559        struct Registers {
     
    8064            void* llintPC() const;
    8165#endif // ENABLE(SAMPLING_PROFILER)
    82            
    83 #if OS(DARWIN) || OS(WINDOWS)
    84             using PlatformRegisters = MachineContext::PlatformRegisters;
    85 #elif (OS(FREEBSD) || defined(__GLIBC__)) && ENABLE(JIT)
    86             using PlatformRegisters = mcontext_t;
    87 #elif USE(PTHREADS)
    88             struct PlatformRegisters {
    89                 pthread_attr_t attribute;
    90             };
    91 #else
    92 #error Need a thread register struct for this platform
    93 #endif
    94 
    95             PlatformRegisters regs;
     66            WTF::PlatformRegisters regs;
    9667        };
    9768
    98         bool suspend();
    99         void resume();
    100         size_t getRegisters(Registers&);
    101         void freeRegisters(Registers&);
     69        Expected<void, Thread::PlatformSuspendError> suspend() { return m_thread->suspend(); }
     70        void resume() { m_thread->resume(); }
     71        size_t getRegisters(Registers& regs);
    10272        std::pair<void*, size_t> captureStack(void* stackTop);
    10373
    104         PlatformThread platformThread;
    105         void* stackBase;
    106         void* stackEnd;
    107 #if OS(WINDOWS)
    108         HANDLE platformThreadHandle;
    109 #elif USE(PTHREADS) && !OS(DARWIN)
    110         sem_t semaphoreForSuspendResume;
    111         mcontext_t suspendedMachineContext;
    112         int suspendCount { 0 };
    113         std::atomic<bool> suspended { false };
    114 #endif
    115     };
     74        WTF::ThreadIdentifier threadID() const { return m_thread->id(); }
     75        void* stackBase() const { return m_stackBase; }
     76        void* stackEnd() const { return m_stackEnd; }
    11677
    117     class Thread {
    118         WTF_MAKE_FAST_ALLOCATED;
    119         Thread(ThreadData*);
    120 
    121     public:
    122         using Registers = ThreadData::Registers;
    123 
    124         static Thread* createForCurrentThread();
    125 
    126         bool operator==(const PlatformThread& other) const;
    127         bool operator!=(const PlatformThread& other) const { return !(*this == other); }
    128 
    129         bool suspend() { return data->suspend(); }
    130         void resume() { data->resume(); }
    131         size_t getRegisters(Registers& regs) { return data->getRegisters(regs); }
    132         void freeRegisters(Registers& regs) { data->freeRegisters(regs); }
    133         std::pair<void*, size_t> captureStack(void* stackTop) { return data->captureStack(stackTop); }
    134 
    135         const PlatformThread& platformThread() { return data->platformThread; }
    136         void* stackBase() const { return data->stackBase; }
    137         void* stackEnd() const { return data->stackEnd; }
    138 
    139         Thread* next;
    140         ThreadData* data;
     78        MachineThread* next;
     79        Ref<WTF::Thread> m_thread;
     80        void* m_stackBase;
     81        void* m_stackEnd;
    14182    };
    14283
    14384    Lock& getLock() { return m_registeredThreadsMutex; }
    144     Thread* threadsListHead(const AbstractLocker&) const { ASSERT(m_registeredThreadsMutex.isLocked()); return m_registeredThreads; }
    145     Thread* machineThreadForCurrentThread();
     85    MachineThread* threadsListHead(const AbstractLocker&) const { ASSERT(m_registeredThreadsMutex.isLocked()); return m_registeredThreads; }
     86    MachineThread* machineThreadForCurrentThread();
    14687
    14788private:
    14889    void gatherFromCurrentThread(ConservativeRoots&, JITStubRoutineSet&, CodeBlockSet&, CurrentThreadState&);
    14990
    150     void tryCopyOtherThreadStack(Thread*, void*, size_t capacity, size_t*);
     91    void tryCopyOtherThreadStack(MachineThread*, void*, size_t capacity, size_t*);
    15192    bool tryCopyOtherThreadStacks(const AbstractLocker&, void*, size_t capacity, size_t*);
    15293
    15394    static void THREAD_SPECIFIC_CALL removeThread(void*);
    15495
    155     template<typename PlatformThread>
    156     void removeThreadIfFound(PlatformThread);
     96    void removeThreadIfFound(ThreadIdentifier);
    15797
    15898    Lock m_registeredThreadsMutex;
    159     Thread* m_registeredThreads;
     99    MachineThread* m_registeredThreads;
    160100    WTF::ThreadSpecificKey m_threadSpecificForMachineThreads;
    161101};
  • trunk/Source/JavaScriptCore/jit/ICStats.cpp

    r208415 r215265  
    5959ICStats::ICStats()
    6060{
    61     m_thread = createThread(
     61    m_thread = Thread::create(
    6262        "JSC ICStats",
    6363        [this] () {
     
    8585    }
    8686   
    87     waitForThreadCompletion(m_thread);
     87    m_thread->waitForCompletion();
    8888}
    8989
  • trunk/Source/JavaScriptCore/jit/ICStats.h

    r213467 r215265  
    180180
    181181    Spectrum<ICEvent, uint64_t> m_spectrum;
    182     ThreadIdentifier m_thread;
     182    RefPtr<Thread> m_thread;
    183183    Lock m_lock;
    184184    Condition m_condition;
  • trunk/Source/JavaScriptCore/jsc.cpp

    r215103 r215265  
    25452545    bool didStart = false;
    25462546   
    2547     ThreadIdentifier thread = createThread(
     2547    RefPtr<Thread> thread = Thread::create(
    25482548        "JSC Agent",
    25492549        [sourceCode, &didStartLock, &didStartCondition, &didStart] () {
     
    25722572                });
    25732573        });
    2574     detachThread(thread);
     2574    thread->detach();
    25752575   
    25762576    {
     
    33123312                " but expected a number. Not using a timeout.\n");
    33133313        } else
    3314             createThread(timeoutThreadMain, 0, "jsc Timeout Thread");
     3314            Thread::create(timeoutThreadMain, 0, "jsc Timeout Thread");
    33153315    }
    33163316}
  • trunk/Source/JavaScriptCore/runtime/JSLock.cpp

    r214489 r215265  
    110110    }
    111111
    112     m_ownerThread = currentThread();
     112    m_ownerThread = &Thread::current();
    113113    WTF::storeStoreFence();
    114114    m_hasOwnerThread = true;
  • trunk/Source/JavaScriptCore/runtime/JSLock.h

    r214489 r215265  
    9393    VM* vm() { return m_vm; }
    9494
    95     std::optional<ThreadIdentifier> ownerThread() const
     95    std::optional<RefPtr<Thread>> ownerThread() const
    9696    {
    9797        if (m_hasOwnerThread)
     
    9999        return std::nullopt;
    100100    }
    101     bool currentThreadIsHoldingLock() { return m_hasOwnerThread && m_ownerThread == currentThread(); }
     101    bool currentThreadIsHoldingLock() { return m_hasOwnerThread && m_ownerThread->id() == currentThread(); }
    102102
    103103    void willDestroyVM(VM*);
     
    136136    // See https://bugs.webkit.org/show_bug.cgi?id=169042#c6
    137137    bool m_hasOwnerThread { false };
    138     ThreadIdentifier m_ownerThread;
     138    RefPtr<Thread> m_ownerThread;
    139139    intptr_t m_lockCount;
    140140    unsigned m_lockDropDepth;
  • trunk/Source/JavaScriptCore/runtime/SamplingProfiler.cpp

    r214905 r215265  
    168168    {
    169169        uint8_t* fpCast = bitwise_cast<uint8_t*>(exec);
    170         for (MachineThreads::Thread* thread = m_vm.heap.machineThreads().threadsListHead(m_machineThreadsLocker); thread; thread = thread->next) {
     170        for (MachineThreads::MachineThread* thread = m_vm.heap.machineThreads().threadsListHead(m_machineThreadsLocker); thread; thread = thread->next) {
    171171            uint8_t* stackBase = static_cast<uint8_t*>(thread->stackBase());
    172172            uint8_t* stackLimit = static_cast<uint8_t*>(thread->stackEnd());
     
    280280    , m_stopwatch(WTFMove(stopwatch))
    281281    , m_timingInterval(std::chrono::microseconds(Options::sampleInterval()))
    282     , m_threadIdentifier(0)
    283282    , m_jscExecutionThread(nullptr)
    284283    , m_isPaused(false)
     
    301300    ASSERT(m_lock.isLocked());
    302301
    303     if (m_threadIdentifier)
     302    if (m_thread)
    304303        return;
    305304
    306305    RefPtr<SamplingProfiler> profiler = this;
    307     m_threadIdentifier = createThread("jsc.sampling-profiler.thread", [profiler] {
     306    m_thread = Thread::create("jsc.sampling-profiler.thread", [profiler] {
    308307        profiler->timerLoop();
    309308    });
     
    345344        LockHolder executableAllocatorLocker(ExecutableAllocator::singleton().getLock());
    346345
    347         bool didSuspend = m_jscExecutionThread->suspend();
     346        auto didSuspend = m_jscExecutionThread->suspend();
    348347        if (didSuspend) {
    349348            // While the JSC thread is suspended, we can't do things like malloc because the JSC thread
     
    355354            void* llintPC;
    356355            {
    357                 MachineThreads::Thread::Registers registers;
     356                MachineThreads::MachineThread::Registers registers;
    358357                m_jscExecutionThread->getRegisters(registers);
    359358                machineFrame = registers.framePointer();
     
    361360                machinePC = registers.instructionPointer();
    362361                llintPC = registers.llintPC();
    363                 m_jscExecutionThread->freeRegisters(registers);
    364362            }
    365363            // FIXME: Lets have a way of detecting when we're parsing code.
  • trunk/Source/JavaScriptCore/runtime/SamplingProfiler.h

    r214905 r215265  
    196196    double m_lastTime;
    197197    Lock m_lock;
    198     ThreadIdentifier m_threadIdentifier;
    199     MachineThreads::Thread* m_jscExecutionThread;
     198    RefPtr<Thread> m_thread;
     199    MachineThreads::MachineThread* m_jscExecutionThread;
    200200    bool m_isPaused;
    201201    bool m_isShutDown;
  • trunk/Source/JavaScriptCore/runtime/VM.h

    r214905 r215265  
    660660    void logEvent(CodeBlock*, const char* summary, const Func& func);
    661661
    662     std::optional<ThreadIdentifier> ownerThread() const { return m_apiLock->ownerThread(); }
     662    std::optional<RefPtr<Thread>> ownerThread() const { return m_apiLock->ownerThread(); }
    663663
    664664    VMTraps& traps() { return m_traps; }
  • trunk/Source/JavaScriptCore/runtime/VMTraps.cpp

    r214571 r215265  
    111111        }
    112112
    113         for (MachineThreads::Thread* thread = machineThreads.threadsListHead(machineThreadsLocker); thread; thread = thread->next) {
     113        for (MachineThreads::MachineThread* thread = machineThreads.threadsListHead(machineThreadsLocker); thread; thread = thread->next) {
    114114            RELEASE_ASSERT(thread->stackBase());
    115115            RELEASE_ASSERT(thread->stackEnd());
     
    456456            auto optionalOwnerThread = vm.ownerThread();
    457457            if (optionalOwnerThread) {
    458                 signalThread(optionalOwnerThread.value(), SIGUSR1);
     458                optionalOwnerThread.value()->signal(SIGUSR1);
    459459                break;
    460460            }
     
    494494        RefPtr<SignalSender> sender = adoptRef(new SignalSender(vm(), eventType));
    495495        addSignalSender(sender.get());
    496         createThread("jsc.vmtraps.signalling.thread", [sender] {
     496        Thread::create("jsc.vmtraps.signalling.thread", [sender] {
    497497            sender->send();
    498498        });
Note: See TracChangeset for help on using the changeset viewer.