Modified: trunk/Source/_javascript_Core/heap/MachineStackMarker.cpp (214318 => 214319)
--- trunk/Source/_javascript_Core/heap/MachineStackMarker.cpp 2017-03-23 21:45:08 UTC (rev 214318)
+++ trunk/Source/_javascript_Core/heap/MachineStackMarker.cpp 2017-03-23 21:54:58 UTC (rev 214319)
@@ -33,6 +33,7 @@
#include <setjmp.h>
#include <stdlib.h>
#include <wtf/MainThread.h>
+#include <wtf/NeverDestroyed.h>
#include <wtf/StdLibExtras.h>
#if OS(DARWIN)
@@ -69,14 +70,14 @@
// We use SIGUSR2 to suspend and resume machine threads in _javascript_Core.
static const int SigThreadSuspendResume = SIGUSR2;
static StaticLock globalSignalLock;
-thread_local static std::atomic<JSC::MachineThreads::Thread*> threadLocalCurrentThread;
+thread_local static std::atomic<JSC::MachineThreads::ThreadData*> threadLocalCurrentThread { nullptr };
static void pthreadSignalHandlerSuspendResume(int, siginfo_t*, void* ucontext)
{
// Touching thread local atomic types from signal handlers is allowed.
- JSC::MachineThreads::Thread* thread = threadLocalCurrentThread.load();
+ JSC::MachineThreads::ThreadData* threadData = threadLocalCurrentThread.load();
- if (thread->suspended.load(std::memory_order_acquire)) {
+ if (threadData->suspended.load(std::memory_order_acquire)) {
// This is signal handler invocation that is intended to be used to resume sigsuspend.
// So this handler invocation itself should not process.
//
@@ -88,9 +89,9 @@
ucontext_t* userContext = static_cast<ucontext_t*>(ucontext);
#if CPU(PPC)
- thread->suspendedMachineContext = *userContext->uc_mcontext.uc_regs;
+ threadData->suspendedMachineContext = *userContext->uc_mcontext.uc_regs;
#else
- thread->suspendedMachineContext = userContext->uc_mcontext;
+ threadData->suspendedMachineContext = userContext->uc_mcontext;
#endif
// Allow suspend caller to see that this thread is suspended.
@@ -99,7 +100,7 @@
//
// And sem_post emits memory barrier that ensures that suspendedMachineContext is correctly saved.
// http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_11
- sem_post(&thread->semaphoreForSuspendResume);
+ sem_post(&threadData->semaphoreForSuspendResume);
// Reaching here, SigThreadSuspendResume is blocked in this handler (this is configured by sigaction's sa_mask).
// So before calling sigsuspend, SigThreadSuspendResume to this thread is deferred. This ensures that the handler is not executed recursively.
@@ -109,7 +110,7 @@
sigsuspend(&blockedSignalSet);
// Allow resume caller to see that this thread is resumed.
- sem_post(&thread->semaphoreForSuspendResume);
+ sem_post(&threadData->semaphoreForSuspendResume);
}
#endif // USE(PTHREADS) && !OS(WINDOWS) && !OS(DARWIN)
@@ -200,18 +201,29 @@
}
}
+static MachineThreads::ThreadData* threadData()
+{
+ static NeverDestroyed<ThreadSpecific<MachineThreads::ThreadData, CanBeGCThread::True>> threadData;
+ return threadData.get();
+}
+
+MachineThreads::Thread::Thread(ThreadData* threadData)
+ : data(threadData)
+{
+ ASSERT(threadData);
+}
+
Thread* MachineThreads::Thread::createForCurrentThread()
{
- auto stackBounds = wtfThreadData().stack();
- return new Thread(currentPlatformThread(), stackBounds.origin(), stackBounds.end());
+ return new Thread(threadData());
}
bool MachineThreads::Thread::operator==(const PlatformThread& other) const
{
#if OS(DARWIN) || OS(WINDOWS)
- return platformThread == other;
+ return data->platformThread == other;
#elif USE(PTHREADS)
- return !!pthread_equal(platformThread, other);
+ return !!pthread_equal(data->platformThread, other);
#else
#error Need a way to compare threads on this platform
#endif
@@ -308,11 +320,13 @@
conservativeRoots.add(currentThreadState.stackTop, currentThreadState.stackOrigin, jitStubRoutines, codeBlocks);
}
-MachineThreads::Thread::Thread(const PlatformThread& platThread, void* base, void* end)
- : platformThread(platThread)
- , stackBase(base)
- , stackEnd(end)
+MachineThreads::ThreadData::ThreadData()
{
+ auto stackBounds = wtfThreadData().stack();
+ platformThread = currentPlatformThread();
+ stackBase = stackBounds.origin();
+ stackEnd = stackBounds.end();
+
#if OS(WINDOWS)
ASSERT(platformThread == GetCurrentThreadId());
bool isSuccessful =
@@ -345,7 +359,7 @@
#endif
}
-MachineThreads::Thread::~Thread()
+MachineThreads::ThreadData::~ThreadData()
{
#if OS(WINDOWS)
CloseHandle(platformThreadHandle);
@@ -354,7 +368,7 @@
#endif
}
-bool MachineThreads::Thread::suspend()
+bool MachineThreads::ThreadData::suspend()
{
#if OS(DARWIN)
kern_return_t result = thread_suspend(platformThread);
@@ -391,7 +405,7 @@
#endif
}
-void MachineThreads::Thread::resume()
+void MachineThreads::ThreadData::resume()
{
#if OS(DARWIN)
thread_resume(platformThread);
@@ -422,9 +436,9 @@
#endif
}
-size_t MachineThreads::Thread::getRegisters(Thread::Registers& registers)
+size_t MachineThreads::ThreadData::getRegisters(ThreadData::Registers& registers)
{
- Thread::Registers::PlatformRegisters& regs = registers.regs;
+ ThreadData::Registers::PlatformRegisters& regs = registers.regs;
#if OS(DARWIN)
#if CPU(X86)
unsigned user_count = sizeof(regs)/sizeof(int);
@@ -481,7 +495,7 @@
#endif
}
-void* MachineThreads::Thread::Registers::stackPointer() const
+void* MachineThreads::ThreadData::Registers::stackPointer() const
{
#if OS(DARWIN) || OS(WINDOWS) || ((OS(FREEBSD) || defined(__GLIBC__)) && ENABLE(JIT))
return MachineContext::stackPointer(regs);
@@ -505,7 +519,7 @@
}
#if ENABLE(SAMPLING_PROFILER)
-void* MachineThreads::Thread::Registers::framePointer() const
+void* MachineThreads::ThreadData::Registers::framePointer() const
{
#if OS(DARWIN) || OS(WINDOWS) || (OS(FREEBSD) || defined(__GLIBC__))
return MachineContext::framePointer(regs);
@@ -514,7 +528,7 @@
#endif
}
-void* MachineThreads::Thread::Registers::instructionPointer() const
+void* MachineThreads::ThreadData::Registers::instructionPointer() const
{
#if OS(DARWIN) || OS(WINDOWS) || (OS(FREEBSD) || defined(__GLIBC__))
return MachineContext::instructionPointer(regs);
@@ -523,7 +537,7 @@
#endif
}
-void* MachineThreads::Thread::Registers::llintPC() const
+void* MachineThreads::ThreadData::Registers::llintPC() const
{
// LLInt uses regT4 as PC.
#if OS(DARWIN) || OS(WINDOWS) || (OS(FREEBSD) || defined(__GLIBC__))
@@ -534,9 +548,9 @@
}
#endif // ENABLE(SAMPLING_PROFILER)
-void MachineThreads::Thread::freeRegisters(Thread::Registers& registers)
+void MachineThreads::ThreadData::freeRegisters(ThreadData::Registers& registers)
{
- Thread::Registers::PlatformRegisters& regs = registers.regs;
+ ThreadData::Registers::PlatformRegisters& regs = registers.regs;
#if USE(PTHREADS) && !OS(WINDOWS) && !OS(DARWIN) && !((OS(FREEBSD) || defined(__GLIBC__)) && ENABLE(JIT))
pthread_attr_destroy(®s.attribute);
#else
@@ -559,7 +573,7 @@
return redZoneAdjustment;
}
-std::pair<void*, size_t> MachineThreads::Thread::captureStack(void* stackTop)
+std::pair<void*, size_t> MachineThreads::ThreadData::captureStack(void* stackTop)
{
char* begin = reinterpret_cast_ptr<char*>(stackBase);
char* end = bitwise_cast<char*>(WTF::roundUpToMultipleOf<sizeof(void*)>(reinterpret_cast<uintptr_t>(stackTop)));
@@ -647,12 +661,12 @@
}
// Re-do the suspension to get the actual failure result for logging.
- kern_return_t error = thread_suspend(thread->platformThread);
+ kern_return_t error = thread_suspend(thread->platformThread());
ASSERT(error != KERN_SUCCESS);
WTFReportError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION,
"_javascript_ garbage collection encountered an invalid thread (err 0x%x): Thread [%d/%d: %p] platformThread %p.",
- error, index, numberOfThreads, thread, reinterpret_cast<void*>(thread->platformThread));
+ error, index, numberOfThreads, thread, reinterpret_cast<void*>(thread->platformThread()));
// Put the invalid thread on the threadsToBeDeleted list.
// We can't just delete it here because we have suspended other
Modified: trunk/Source/_javascript_Core/heap/MachineStackMarker.h (214318 => 214319)
--- trunk/Source/_javascript_Core/heap/MachineStackMarker.h 2017-03-23 21:45:08 UTC (rev 214318)
+++ trunk/Source/_javascript_Core/heap/MachineStackMarker.h 2017-03-23 21:54:58 UTC (rev 214319)
@@ -64,14 +64,13 @@
JS_EXPORT_PRIVATE void addCurrentThread(); // Only needs to be called by clients that can use the same heap from multiple threads.
- class Thread {
+ class ThreadData {
WTF_MAKE_FAST_ALLOCATED;
- Thread(const PlatformThread& platThread, void* base, void* end);
-
public:
- ~Thread();
+ ThreadData();
+ ~ThreadData();
- static Thread* createForCurrentThread();
+ static ThreadData* createForCurrentThread();
struct Registers {
void* stackPointer() const;
@@ -92,12 +91,9 @@
#else
#error Need a thread register struct for this platform
#endif
-
+
PlatformRegisters regs;
};
-
- bool operator==(const PlatformThread& other) const;
- bool operator!=(const PlatformThread& other) const { return !(*this == other); }
bool suspend();
void resume();
@@ -105,7 +101,6 @@
void freeRegisters(Registers&);
std::pair<void*, size_t> captureStack(void* stackTop);
- Thread* next;
PlatformThread platformThread;
void* stackBase;
void* stackEnd;
@@ -119,6 +114,32 @@
#endif
};
+ class Thread {
+ WTF_MAKE_FAST_ALLOCATED;
+ Thread(ThreadData*);
+
+ public:
+ using Registers = ThreadData::Registers;
+
+ static Thread* createForCurrentThread();
+
+ bool operator==(const PlatformThread& other) const;
+ bool operator!=(const PlatformThread& other) const { return !(*this == other); }
+
+ bool suspend() { return data->suspend(); }
+ void resume() { data->resume(); }
+ size_t getRegisters(Registers& regs) { return data->getRegisters(regs); }
+ void freeRegisters(Registers& regs) { data->freeRegisters(regs); }
+ std::pair<void*, size_t> captureStack(void* stackTop) { return data->captureStack(stackTop); }
+
+ const PlatformThread& platformThread() { return data->platformThread; }
+ void* stackBase() const { return data->stackBase; }
+ void* stackEnd() const { return data->stackEnd; }
+
+ Thread* next;
+ ThreadData* data;
+ };
+
Lock& getLock() { return m_registeredThreadsMutex; }
Thread* threadsListHead(const AbstractLocker&) const { ASSERT(m_registeredThreadsMutex.isLocked()); return m_registeredThreads; }
Thread* machineThreadForCurrentThread();