]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - heap/MachineStackMarker.cpp
JavaScriptCore-7600.1.4.15.12.tar.gz
[apple/javascriptcore.git] / heap / MachineStackMarker.cpp
index 0654ffe2c872d3b835edddbaa49aa79e89587999..c354e7754be1d477d141bfa3b878cc549074f401 100644 (file)
@@ -227,25 +227,8 @@ void MachineThreads::removeCurrentThread()
     }
 }
 
-#if COMPILER(GCC)
-#define REGISTER_BUFFER_ALIGNMENT __attribute__ ((aligned (sizeof(void*))))
-#else
-#define REGISTER_BUFFER_ALIGNMENT
-#endif
-
-void MachineThreads::gatherFromCurrentThread(ConservativeRoots& conservativeRoots, JITStubRoutineSet& jitStubRoutines, CodeBlockSet& codeBlocks, void* stackCurrent)
+void MachineThreads::gatherFromCurrentThread(ConservativeRoots& conservativeRoots, JITStubRoutineSet& jitStubRoutines, CodeBlockSet& codeBlocks, void* stackCurrent, RegisterState& registers)
 {
-    // setjmp forces volatile registers onto the stack
-    jmp_buf registers REGISTER_BUFFER_ALIGNMENT;
-#if COMPILER(MSVC)
-#pragma warning(push)
-#pragma warning(disable: 4611)
-#endif
-    setjmp(registers);
-#if COMPILER(MSVC)
-#pragma warning(pop)
-#endif
-
     void* registersBegin = &registers;
     void* registersEnd = reinterpret_cast<void*>(roundUpToMultipleOf<sizeof(void*)>(reinterpret_cast<uintptr_t>(&registers + 1)));
     swapIfBackwards(registersBegin, registersEnd);
@@ -257,14 +240,18 @@ void MachineThreads::gatherFromCurrentThread(ConservativeRoots& conservativeRoot
     conservativeRoots.add(stackBegin, stackEnd, jitStubRoutines, codeBlocks);
 }
 
-static inline void suspendThread(const PlatformThread& platformThread)
+static inline bool suspendThread(const PlatformThread& platformThread)
 {
 #if OS(DARWIN)
-    thread_suspend(platformThread);
+    kern_return_t result = thread_suspend(platformThread);
+    return result == KERN_SUCCESS;
 #elif OS(WINDOWS)
-    SuspendThread(platformThread);
+    bool threadIsSuspended = (SuspendThread(platformThread) != (DWORD)-1);
+    ASSERT(threadIsSuspended);
+    return threadIsSuspended;
 #elif USE(PTHREADS)
     pthread_kill(platformThread, SigThreadSuspendResume);
+    return true;
 #else
 #error Need a way to suspend threads on this platform
 #endif
@@ -460,24 +447,67 @@ void MachineThreads::gatherFromOtherThread(ConservativeRoots& conservativeRoots,
     freePlatformThreadRegisters(regs);
 }
 
-void MachineThreads::gatherConservativeRoots(ConservativeRoots& conservativeRoots, JITStubRoutineSet& jitStubRoutines, CodeBlockSet& codeBlocks, void* stackCurrent)
+void MachineThreads::gatherConservativeRoots(ConservativeRoots& conservativeRoots, JITStubRoutineSet& jitStubRoutines, CodeBlockSet& codeBlocks, void* stackCurrent, RegisterState& registers)
 {
-    gatherFromCurrentThread(conservativeRoots, jitStubRoutines, codeBlocks, stackCurrent);
+    gatherFromCurrentThread(conservativeRoots, jitStubRoutines, codeBlocks, stackCurrent, registers);
 
     if (m_threadSpecific) {
         PlatformThread currentPlatformThread = getCurrentPlatformThread();
 
         MutexLocker lock(m_registeredThreadsMutex);
 
+        Thread* threadsToBeDeleted = nullptr;
+
 #ifndef NDEBUG
         // Forbid malloc during the gather phase. The gather phase suspends
         // threads, so a malloc during gather would risk a deadlock with a
         // 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);
+        int numberOfThreads = 0; // Using 0 to denote that we haven't counted the number of threads yet.
+        int index = 1;
+        Thread* previousThread = nullptr;
+        for (Thread* thread = m_registeredThreads; thread; index++) {
+            if (!equalThread(thread->platformThread, currentPlatformThread)) {
+                bool success = suspendThread(thread->platformThread);
+#if OS(DARWIN)
+                if (!success) {
+                    if (!numberOfThreads) {
+                        for (Thread* countedThread = m_registeredThreads; countedThread; countedThread = countedThread->next)
+                            numberOfThreads++;
+                    }
+                    
+                    // Re-do the suspension to get the actual failure result for logging.
+                    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));
+                    
+                    // Put the invalid thread on the threadsToBeDeleted list.
+                    // We can't just delete it here because we have suspended other
+                    // threads, and they may still be holding the C heap lock which
+                    // we need for deleting the invalid thread. Hence, we need to
+                    // defer the deletion till after we have resumed all threads.
+                    Thread* nextThread = thread->next;
+                    thread->next = threadsToBeDeleted;
+                    threadsToBeDeleted = thread;
+                    
+                    if (previousThread)
+                        previousThread->next = nextThread;
+                    else
+                        m_registeredThreads = nextThread;
+                    thread = nextThread;
+                    continue;
+                }
+#else
+                UNUSED_PARAM(numberOfThreads);
+                ASSERT_UNUSED(success, success);
+#endif
+            }
+            previousThread = thread;
+            thread = thread->next;
         }
 
         // It is safe to access the registeredThreads list, because we earlier asserted that locks are being held,
@@ -495,6 +525,11 @@ void MachineThreads::gatherConservativeRoots(ConservativeRoots& conservativeRoot
 #ifndef NDEBUG
         fastMallocAllow();
 #endif
+        for (Thread* thread = threadsToBeDeleted; thread; ) {
+            Thread* nextThread = thread->next;
+            delete thread;
+            thread = nextThread;
+        }
     }
 }