X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/14957cd040308e3eeec43d26bae5d76da13fcd85..4be4e30906bcb8ee30b4d189205cb70bad6707ce:/heap/MachineStackMarker.cpp diff --git a/heap/MachineStackMarker.cpp b/heap/MachineStackMarker.cpp index 73a3db6..6385448 100644 --- a/heap/MachineStackMarker.cpp +++ b/heap/MachineStackMarker.cpp @@ -25,15 +25,11 @@ #include "ConservativeRoots.h" #include "Heap.h" #include "JSArray.h" -#include "JSGlobalData.h" +#include "VM.h" #include #include #include -#if USE(PTHREAD_BASED_QT) && !defined(WTF_USE_PTHREADS) -#define WTF_USE_PTHREADS 1 -#endif - #if OS(DARWIN) #include @@ -47,16 +43,9 @@ #include #include -#elif OS(HAIKU) - -#include - #elif OS(UNIX) -#include -#if !OS(HAIKU) #include -#endif #include #if OS(SOLARIS) @@ -78,9 +67,6 @@ #if USE(PTHREADS) && !OS(WINDOWS) && !OS(DARWIN) #include -#ifndef SA_RESTART -#error MachineThreads requires SA_RESTART -#endif #endif #endif @@ -101,8 +87,6 @@ UNUSED_PARAM(end); #endif } -#if ENABLE(JSC_MULTIPLE_THREADS) - #if OS(DARWIN) typedef mach_port_t PlatformThread; #elif OS(WINDOWS) @@ -111,7 +95,8 @@ typedef HANDLE PlatformThread; typedef pthread_t PlatformThread; static const int SigThreadSuspendResume = SIGUSR2; -static void pthreadSignalHandlerSuspendResume(int signo) +#if defined(SA_RESTART) +static void pthreadSignalHandlerSuspendResume(int) { sigset_t signalSet; sigemptyset(&signalSet); @@ -119,15 +104,17 @@ static void pthreadSignalHandlerSuspendResume(int signo) sigsuspend(&signalSet); } #endif +#endif class MachineThreads::Thread { + WTF_MAKE_FAST_ALLOCATED; public: - Thread(pthread_t pthread, const PlatformThread& platThread, void* base) - : posixThread(pthread) - , platformThread(platThread) + Thread(const PlatformThread& platThread, void* base) + : platformThread(platThread) , stackBase(base) { -#if USE(PTHREADS) && !OS(WINDOWS) && !OS(DARWIN) +#if USE(PTHREADS) && !OS(WINDOWS) && !OS(DARWIN) && defined(SA_RESTART) + // if we have SA_RESTART, enable SIGUSR2 debugging mechanism struct sigaction action; action.sa_handler = pthreadSignalHandlerSuspendResume; sigemptyset(&action.sa_mask); @@ -142,29 +129,24 @@ public: } Thread* next; - pthread_t posixThread; PlatformThread platformThread; void* stackBase; }; -#endif - MachineThreads::MachineThreads(Heap* heap) - : m_heap(heap) -#if ENABLE(JSC_MULTIPLE_THREADS) - , m_registeredThreads(0) + : m_registeredThreads(0) , m_threadSpecific(0) +#if !ASSERT_DISABLED + , m_heap(heap) #endif { + UNUSED_PARAM(heap); } MachineThreads::~MachineThreads() { -#if ENABLE(JSC_MULTIPLE_THREADS) - if (m_threadSpecific) { - int error = pthread_key_delete(m_threadSpecific); - ASSERT_UNUSED(error, !error); - } + if (m_threadSpecific) + threadSpecificKeyDelete(m_threadSpecific); MutexLocker registeredThreadsLock(m_registeredThreadsMutex); for (Thread* t = m_registeredThreads; t;) { @@ -172,41 +154,47 @@ MachineThreads::~MachineThreads() delete t; t = next; } -#endif } -#if ENABLE(JSC_MULTIPLE_THREADS) - static inline PlatformThread getCurrentPlatformThread() { #if OS(DARWIN) return pthread_mach_thread_np(pthread_self()); #elif OS(WINDOWS) - return pthread_getw32threadhandle_np(pthread_self()); + return GetCurrentThread(); #elif USE(PTHREADS) return pthread_self(); #endif } +static inline bool equalThread(const PlatformThread& first, const PlatformThread& second) +{ +#if OS(DARWIN) || OS(WINDOWS) + return first == second; +#elif USE(PTHREADS) + return !!pthread_equal(first, second); +#else +#error Need a way to compare threads on this platform +#endif +} + void MachineThreads::makeUsableFromMultipleThreads() { if (m_threadSpecific) return; - int error = pthread_key_create(&m_threadSpecific, removeThread); - if (error) - CRASH(); + threadSpecificKeyCreate(&m_threadSpecific, removeThread); } void MachineThreads::addCurrentThread() { - ASSERT(!m_heap->globalData()->exclusiveThread || m_heap->globalData()->exclusiveThread == currentThread()); + ASSERT(!m_heap->vm()->exclusiveThread || m_heap->vm()->exclusiveThread == currentThread()); - if (!m_threadSpecific || pthread_getspecific(m_threadSpecific)) + if (!m_threadSpecific || threadSpecificGet(m_threadSpecific)) return; - pthread_setspecific(m_threadSpecific, this); - Thread* thread = new Thread(pthread_self(), getCurrentPlatformThread(), m_heap->globalData()->stack().origin()); + threadSpecificSet(m_threadSpecific, this); + Thread* thread = new Thread(getCurrentPlatformThread(), wtfThreadData().stack().origin()); MutexLocker lock(m_registeredThreadsMutex); @@ -222,11 +210,11 @@ void MachineThreads::removeThread(void* p) void MachineThreads::removeCurrentThread() { - pthread_t currentPosixThread = pthread_self(); + PlatformThread currentPlatformThread = getCurrentPlatformThread(); MutexLocker lock(m_registeredThreadsMutex); - if (pthread_equal(currentPosixThread, m_registeredThreads->posixThread)) { + if (equalThread(currentPlatformThread, m_registeredThreads->platformThread)) { Thread* t = m_registeredThreads; m_registeredThreads = m_registeredThreads->next; delete t; @@ -234,7 +222,7 @@ void MachineThreads::removeCurrentThread() Thread* last = m_registeredThreads; Thread* t; for (t = m_registeredThreads->next; t; t = t->next) { - if (pthread_equal(t->posixThread, currentPosixThread)) { + if (equalThread(t->platformThread, currentPlatformThread)) { last->next = t->next; break; } @@ -245,8 +233,6 @@ void MachineThreads::removeCurrentThread() } } -#endif - #if COMPILER(GCC) #define REGISTER_BUFFER_ALIGNMENT __attribute__ ((aligned (sizeof(void*)))) #else @@ -272,13 +258,11 @@ void MachineThreads::gatherFromCurrentThread(ConservativeRoots& conservativeRoot conservativeRoots.add(registersBegin, registersEnd); void* stackBegin = stackCurrent; - void* stackEnd = m_heap->globalData()->stack().origin(); + void* stackEnd = wtfThreadData().stack().origin(); swapIfBackwards(stackBegin, stackEnd); conservativeRoots.add(stackBegin, stackEnd); } -#if ENABLE(JSC_MULTIPLE_THREADS) - static inline void suspendThread(const PlatformThread& platformThread) { #if OS(DARWIN) @@ -319,12 +303,16 @@ typedef ppc_thread_state_t PlatformThreadRegisters; typedef ppc_thread_state64_t PlatformThreadRegisters; #elif CPU(ARM) typedef arm_thread_state_t PlatformThreadRegisters; +#elif CPU(ARM64) +typedef arm_thread_state64_t PlatformThreadRegisters; #else #error Unknown Architecture #endif #elif OS(WINDOWS) typedef CONTEXT PlatformThreadRegisters; +#elif OS(QNX) +typedef struct _debug_thread_info PlatformThreadRegisters; #elif USE(PTHREADS) typedef pthread_attr_t PlatformThreadRegisters; #else @@ -350,6 +338,9 @@ static size_t getPlatformThreadRegisters(const PlatformThread& platformThread, P #elif CPU(ARM) unsigned user_count = ARM_THREAD_STATE_COUNT; thread_state_flavor_t flavor = ARM_THREAD_STATE; +#elif CPU(ARM64) + unsigned user_count = ARM_THREAD_STATE64_COUNT; + thread_state_flavor_t flavor = ARM_THREAD_STATE64; #else #error Unknown Architecture #endif @@ -364,9 +355,25 @@ static size_t getPlatformThreadRegisters(const PlatformThread& platformThread, P // end OS(DARWIN) #elif OS(WINDOWS) - regs.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL | CONTEXT_SEGMENTS; + regs.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL; GetThreadContext(platformThread, ®s); return sizeof(CONTEXT); +#elif OS(QNX) + memset(®s, 0, sizeof(regs)); + regs.tid = platformThread; + // FIXME: If we find this hurts performance, we can consider caching the fd and keeping it open. + int fd = open("/proc/self/as", O_RDONLY); + if (fd == -1) { + LOG_ERROR("Unable to open /proc/self/as (errno: %d)", errno); + CRASH(); + } + int rc = devctl(fd, DCMD_PROC_TIDSTATUS, ®s, sizeof(regs), 0); + if (rc != EOK) { + LOG_ERROR("devctl(DCMD_PROC_TIDSTATUS) failed (error: %d)", rc); + CRASH(); + } + close(fd); + return sizeof(struct _debug_thread_info); #elif USE(PTHREADS) pthread_attr_init(®s); #if HAVE(PTHREAD_NP_H) || OS(NETBSD) @@ -396,6 +403,8 @@ static inline void* otherThreadStackPointer(const PlatformThreadRegisters& regs) return reinterpret_cast(regs.__r1); #elif CPU(ARM) return reinterpret_cast(regs.__sp); +#elif CPU(ARM64) + return reinterpret_cast(regs.__sp); #else #error Unknown Architecture #endif @@ -415,10 +424,23 @@ static inline void* otherThreadStackPointer(const PlatformThreadRegisters& regs) #endif // __DARWIN_UNIX03 // end OS(DARWIN) -#elif CPU(X86) && OS(WINDOWS) +#elif OS(WINDOWS) + +#if CPU(ARM) + return reinterpret_cast((uintptr_t) regs.Sp); +#elif CPU(MIPS) + return reinterpret_cast((uintptr_t) regs.IntSp); +#elif CPU(X86) return reinterpret_cast((uintptr_t) regs.Esp); -#elif CPU(X86_64) && OS(WINDOWS) +#elif CPU(X86_64) return reinterpret_cast((uintptr_t) regs.Rsp); +#else +#error Unknown Architecture +#endif + +#elif OS(QNX) + return reinterpret_cast((uintptr_t) regs.sp); + #elif USE(PTHREADS) void* stackBase = 0; size_t stackSize = 0; @@ -433,7 +455,7 @@ static inline void* otherThreadStackPointer(const PlatformThreadRegisters& regs) static void freePlatformThreadRegisters(PlatformThreadRegisters& regs) { -#if USE(PTHREADS) && !OS(WINDOWS) && !OS(DARWIN) +#if USE(PTHREADS) && !OS(WINDOWS) && !OS(DARWIN) && !OS(QNX) pthread_attr_destroy(®s); #else UNUSED_PARAM(regs); @@ -442,8 +464,6 @@ static void freePlatformThreadRegisters(PlatformThreadRegisters& regs) void MachineThreads::gatherFromOtherThread(ConservativeRoots& conservativeRoots, Thread* thread) { - suspendThread(thread->platformThread); - PlatformThreadRegisters regs; size_t regSize = getPlatformThreadRegisters(thread->platformThread, regs); @@ -454,20 +474,15 @@ void MachineThreads::gatherFromOtherThread(ConservativeRoots& conservativeRoots, swapIfBackwards(stackPointer, stackBase); conservativeRoots.add(stackPointer, stackBase); - resumeThread(thread->platformThread); - freePlatformThreadRegisters(regs); } -#endif - void MachineThreads::gatherConservativeRoots(ConservativeRoots& conservativeRoots, void* stackCurrent) { gatherFromCurrentThread(conservativeRoots, stackCurrent); -#if ENABLE(JSC_MULTIPLE_THREADS) - if (m_threadSpecific) { + PlatformThread currentPlatformThread = getCurrentPlatformThread(); MutexLocker lock(m_registeredThreadsMutex); @@ -477,17 +492,27 @@ void MachineThreads::gatherConservativeRoots(ConservativeRoots& conservativeRoot // thread that had been suspended while holding the malloc lock. fastMallocForbid(); #endif + for (Thread* thread = m_registeredThreads; thread; thread = thread->next) { + if (!equalThread(thread->platformThread, currentPlatformThread)) + suspendThread(thread->platformThread); + } + // It is safe to access the registeredThreads list, because we earlier asserted that locks are being held, // and since this is a shared heap, they are real locks. for (Thread* thread = m_registeredThreads; thread; thread = thread->next) { - if (!pthread_equal(thread->posixThread, pthread_self())) + if (!equalThread(thread->platformThread, currentPlatformThread)) gatherFromOtherThread(conservativeRoots, thread); } + + for (Thread* thread = m_registeredThreads; thread; thread = thread->next) { + if (!equalThread(thread->platformThread, currentPlatformThread)) + resumeThread(thread->platformThread); + } + #ifndef NDEBUG fastMallocAllow(); #endif } -#endif } } // namespace JSC