]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - heap/MachineStackMarker.cpp
JavaScriptCore-1218.35.tar.gz
[apple/javascriptcore.git] / heap / MachineStackMarker.cpp
index 73a3db6778d2c4d2553dff142fe3241a1c3b2b81..63854482df4415ba111303d38edd8cdbe8ce2bdd 100644 (file)
 #include "ConservativeRoots.h"
 #include "Heap.h"
 #include "JSArray.h"
 #include "ConservativeRoots.h"
 #include "Heap.h"
 #include "JSArray.h"
-#include "JSGlobalData.h"
+#include "VM.h"
 #include <setjmp.h>
 #include <stdlib.h>
 #include <wtf/StdLibExtras.h>
 
 #include <setjmp.h>
 #include <stdlib.h>
 #include <wtf/StdLibExtras.h>
 
-#if USE(PTHREAD_BASED_QT) && !defined(WTF_USE_PTHREADS)
-#define WTF_USE_PTHREADS 1
-#endif
-
 #if OS(DARWIN)
 
 #include <mach/mach_init.h>
 #if OS(DARWIN)
 
 #include <mach/mach_init.h>
 #include <windows.h>
 #include <malloc.h>
 
 #include <windows.h>
 #include <malloc.h>
 
-#elif OS(HAIKU)
-
-#include <OS.h>
-
 #elif OS(UNIX)
 
 #elif OS(UNIX)
 
-#include <stdlib.h>
-#if !OS(HAIKU)
 #include <sys/mman.h>
 #include <sys/mman.h>
-#endif
 #include <unistd.h>
 
 #if OS(SOLARIS)
 #include <unistd.h>
 
 #if OS(SOLARIS)
@@ -78,9 +67,6 @@
 
 #if USE(PTHREADS) && !OS(WINDOWS) && !OS(DARWIN)
 #include <signal.h>
 
 #if USE(PTHREADS) && !OS(WINDOWS) && !OS(DARWIN)
 #include <signal.h>
-#ifndef SA_RESTART
-#error MachineThreads requires SA_RESTART
-#endif
 #endif
 
 #endif
 #endif
 
 #endif
@@ -101,8 +87,6 @@ UNUSED_PARAM(end);
 #endif
 }
 
 #endif
 }
 
-#if ENABLE(JSC_MULTIPLE_THREADS)
-
 #if OS(DARWIN)
 typedef mach_port_t PlatformThread;
 #elif OS(WINDOWS)
 #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;
 
 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);
 {
     sigset_t signalSet;
     sigemptyset(&signalSet);
@@ -119,15 +104,17 @@ static void pthreadSignalHandlerSuspendResume(int signo)
     sigsuspend(&signalSet);
 }
 #endif
     sigsuspend(&signalSet);
 }
 #endif
+#endif
 
 class MachineThreads::Thread {
 
 class MachineThreads::Thread {
+    WTF_MAKE_FAST_ALLOCATED;
 public:
 public:
-    Thread(pthread_t pthread, const PlatformThread& platThread, void* base) 
-        : posixThread(pthread)
-        , platformThread(platThread)
+    Thread(const PlatformThread& platThread, void* base)
+        : platformThread(platThread)
         , stackBase(base)
     {
         , 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);
         struct sigaction action;
         action.sa_handler = pthreadSignalHandlerSuspendResume;
         sigemptyset(&action.sa_mask);
@@ -142,29 +129,24 @@ public:
     }
 
     Thread* next;
     }
 
     Thread* next;
-    pthread_t posixThread;
     PlatformThread platformThread;
     void* stackBase;
 };
 
     PlatformThread platformThread;
     void* stackBase;
 };
 
-#endif
-
 MachineThreads::MachineThreads(Heap* heap)
 MachineThreads::MachineThreads(Heap* heap)
-    : m_heap(heap)
-#if ENABLE(JSC_MULTIPLE_THREADS)
-    , m_registeredThreads(0)
+    : m_registeredThreads(0)
     , m_threadSpecific(0)
     , m_threadSpecific(0)
+#if !ASSERT_DISABLED
+    , m_heap(heap)
 #endif
 {
 #endif
 {
+    UNUSED_PARAM(heap);
 }
 
 MachineThreads::~MachineThreads()
 {
 }
 
 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;) {
 
     MutexLocker registeredThreadsLock(m_registeredThreadsMutex);
     for (Thread* t = m_registeredThreads; t;) {
@@ -172,41 +154,47 @@ MachineThreads::~MachineThreads()
         delete t;
         t = next;
     }
         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)
 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
 }
 
 #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;
 
 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()
 {
 }
 
 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;
 
         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);
 
 
     MutexLocker lock(m_registeredThreadsMutex);
 
@@ -222,11 +210,11 @@ void MachineThreads::removeThread(void* p)
 
 void MachineThreads::removeCurrentThread()
 {
 
 void MachineThreads::removeCurrentThread()
 {
-    pthread_t currentPosixThread = pthread_self();
+    PlatformThread currentPlatformThread = getCurrentPlatformThread();
 
     MutexLocker lock(m_registeredThreadsMutex);
 
 
     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;
         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) {
         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;
             }
                 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
 #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;
     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);
 }
 
     swapIfBackwards(stackBegin, stackEnd);
     conservativeRoots.add(stackBegin, stackEnd);
 }
 
-#if ENABLE(JSC_MULTIPLE_THREADS)
-
 static inline void suspendThread(const PlatformThread& platformThread)
 {
 #if OS(DARWIN)
 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;
 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;
 #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
 #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(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
 #else
 #error Unknown Architecture
 #endif
@@ -364,9 +355,25 @@ static size_t getPlatformThreadRegisters(const PlatformThread& platformThread, P
 // end OS(DARWIN)
 
 #elif OS(WINDOWS)
 // end OS(DARWIN)
 
 #elif OS(WINDOWS)
-    regs.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL | CONTEXT_SEGMENTS;
+    regs.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL;
     GetThreadContext(platformThread, &regs);
     return sizeof(CONTEXT);
     GetThreadContext(platformThread, &regs);
     return sizeof(CONTEXT);
+#elif OS(QNX)
+    memset(&regs, 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, &regs, 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(&regs);
 #if HAVE(PTHREAD_NP_H) || OS(NETBSD)
 #elif USE(PTHREADS)
     pthread_attr_init(&regs);
 #if HAVE(PTHREAD_NP_H) || OS(NETBSD)
@@ -396,6 +403,8 @@ static inline void* otherThreadStackPointer(const PlatformThreadRegisters& regs)
     return reinterpret_cast<void*>(regs.__r1);
 #elif CPU(ARM)
     return reinterpret_cast<void*>(regs.__sp);
     return reinterpret_cast<void*>(regs.__r1);
 #elif CPU(ARM)
     return reinterpret_cast<void*>(regs.__sp);
+#elif CPU(ARM64)
+    return reinterpret_cast<void*>(regs.__sp);
 #else
 #error Unknown Architecture
 #endif
 #else
 #error Unknown Architecture
 #endif
@@ -415,10 +424,23 @@ static inline void* otherThreadStackPointer(const PlatformThreadRegisters& regs)
 #endif // __DARWIN_UNIX03
 
 // end OS(DARWIN)
 #endif // __DARWIN_UNIX03
 
 // end OS(DARWIN)
-#elif CPU(X86) && OS(WINDOWS)
+#elif OS(WINDOWS)
+
+#if CPU(ARM)
+    return reinterpret_cast<void*>((uintptr_t) regs.Sp);
+#elif CPU(MIPS)
+    return reinterpret_cast<void*>((uintptr_t) regs.IntSp);
+#elif CPU(X86)
     return reinterpret_cast<void*>((uintptr_t) regs.Esp);
     return reinterpret_cast<void*>((uintptr_t) regs.Esp);
-#elif CPU(X86_64) && OS(WINDOWS)
+#elif CPU(X86_64)
     return reinterpret_cast<void*>((uintptr_t) regs.Rsp);
     return reinterpret_cast<void*>((uintptr_t) regs.Rsp);
+#else
+#error Unknown Architecture
+#endif
+
+#elif OS(QNX)
+    return reinterpret_cast<void*>((uintptr_t) regs.sp);
+
 #elif USE(PTHREADS)
     void* stackBase = 0;
     size_t stackSize = 0;
 #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)
 {
 
 static void freePlatformThreadRegisters(PlatformThreadRegisters& regs)
 {
-#if USE(PTHREADS) && !OS(WINDOWS) && !OS(DARWIN)
+#if USE(PTHREADS) && !OS(WINDOWS) && !OS(DARWIN) && !OS(QNX)
     pthread_attr_destroy(&regs);
 #else
     UNUSED_PARAM(regs);
     pthread_attr_destroy(&regs);
 #else
     UNUSED_PARAM(regs);
@@ -442,8 +464,6 @@ static void freePlatformThreadRegisters(PlatformThreadRegisters& regs)
 
 void MachineThreads::gatherFromOtherThread(ConservativeRoots& conservativeRoots, Thread* thread)
 {
 
 void MachineThreads::gatherFromOtherThread(ConservativeRoots& conservativeRoots, Thread* thread)
 {
-    suspendThread(thread->platformThread);
-
     PlatformThreadRegisters regs;
     size_t regSize = getPlatformThreadRegisters(thread->platformThread, regs);
 
     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);
 
     swapIfBackwards(stackPointer, stackBase);
     conservativeRoots.add(stackPointer, stackBase);
 
-    resumeThread(thread->platformThread);
-
     freePlatformThreadRegisters(regs);
 }
 
     freePlatformThreadRegisters(regs);
 }
 
-#endif
-
 void MachineThreads::gatherConservativeRoots(ConservativeRoots& conservativeRoots, void* stackCurrent)
 {
     gatherFromCurrentThread(conservativeRoots, stackCurrent);
 
 void MachineThreads::gatherConservativeRoots(ConservativeRoots& conservativeRoots, void* stackCurrent)
 {
     gatherFromCurrentThread(conservativeRoots, stackCurrent);
 
-#if ENABLE(JSC_MULTIPLE_THREADS)
-
     if (m_threadSpecific) {
     if (m_threadSpecific) {
+        PlatformThread currentPlatformThread = getCurrentPlatformThread();
 
         MutexLocker lock(m_registeredThreadsMutex);
 
 
         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
         // 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) {
         // 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);
         }
                 gatherFromOtherThread(conservativeRoots, thread);
         }
+
+        for (Thread* thread = m_registeredThreads; thread; thread = thread->next) {
+            if (!equalThread(thread->platformThread, currentPlatformThread))
+                resumeThread(thread->platformThread);
+        }
+
 #ifndef NDEBUG
         fastMallocAllow();
 #endif
     }
 #ifndef NDEBUG
         fastMallocAllow();
 #endif
     }
-#endif
 }
 
 } // namespace JSC
 }
 
 } // namespace JSC