summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/heap/MachineStackMarker.h
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
commit1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch)
tree46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/JavaScriptCore/heap/MachineStackMarker.h
parent32761a6cee1d0dee366b885b7b9c777e67885688 (diff)
downloadWebKitGtk-tarball-master.tar.gz
Diffstat (limited to 'Source/JavaScriptCore/heap/MachineStackMarker.h')
-rw-r--r--Source/JavaScriptCore/heap/MachineStackMarker.h188
1 files changed, 163 insertions, 25 deletions
diff --git a/Source/JavaScriptCore/heap/MachineStackMarker.h b/Source/JavaScriptCore/heap/MachineStackMarker.h
index 49823d43e..da979c582 100644
--- a/Source/JavaScriptCore/heap/MachineStackMarker.h
+++ b/Source/JavaScriptCore/heap/MachineStackMarker.h
@@ -1,7 +1,7 @@
/*
* Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
* Copyright (C) 2001 Peter Kelly (pmk@post.com)
- * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2003-2017 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -19,47 +19,185 @@
*
*/
-#ifndef MachineThreads_h
-#define MachineThreads_h
+#pragma once
+#include "RegisterState.h"
+#include <wtf/Lock.h>
#include <wtf/Noncopyable.h>
+#include <wtf/ScopedLambda.h>
#include <wtf/ThreadSpecific.h>
-#include <wtf/ThreadingPrimitives.h>
+
+#if OS(DARWIN)
+#include <mach/thread_act.h>
+#endif
+
+#if USE(PTHREADS) && !OS(WINDOWS) && !OS(DARWIN)
+#include <semaphore.h>
+#include <signal.h>
+// Using signal.h didn't make mcontext_t and ucontext_t available on FreeBSD.
+// This bug has been fixed in FreeBSD 11.0-CURRENT, so this workaround can be
+// removed after FreeBSD 10.x goes EOL.
+// https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=207079
+#if OS(FREEBSD)
+#include <ucontext.h>
+#endif
+#endif
+
+#if OS(DARWIN)
+typedef mach_port_t PlatformThread;
+#elif OS(WINDOWS)
+typedef DWORD PlatformThread;
+#elif USE(PTHREADS)
+typedef pthread_t PlatformThread;
+#endif // OS(DARWIN)
namespace JSC {
- class ConservativeRoots;
- class Heap;
+class CodeBlockSet;
+class ConservativeRoots;
+class Heap;
+class JITStubRoutineSet;
+
+struct CurrentThreadState {
+ void* stackOrigin { nullptr };
+ void* stackTop { nullptr };
+ RegisterState* registerState { nullptr };
+};
+
+class MachineThreads {
+ WTF_MAKE_NONCOPYABLE(MachineThreads);
+public:
+ MachineThreads(Heap*);
+ ~MachineThreads();
+
+ void gatherConservativeRoots(ConservativeRoots&, JITStubRoutineSet&, CodeBlockSet&, CurrentThreadState*);
- class MachineThreads {
- WTF_MAKE_NONCOPYABLE(MachineThreads);
+ JS_EXPORT_PRIVATE void addCurrentThread(); // Only needs to be called by clients that can use the same heap from multiple threads.
+
+ class ThreadData {
+ WTF_MAKE_FAST_ALLOCATED;
public:
- MachineThreads(Heap*);
- ~MachineThreads();
+ ThreadData();
+ ~ThreadData();
- void gatherConservativeRoots(ConservativeRoots&, void* stackCurrent);
+ static ThreadData* createForCurrentThread();
- JS_EXPORT_PRIVATE void makeUsableFromMultipleThreads();
- JS_EXPORT_PRIVATE void addCurrentThread(); // Only needs to be called by clients that can use the same heap from multiple threads.
+ struct Registers {
+ void* stackPointer() const;
+#if ENABLE(SAMPLING_PROFILER)
+ void* framePointer() const;
+ void* instructionPointer() const;
+ void* llintPC() const;
+#endif // ENABLE(SAMPLING_PROFILER)
+
+#if OS(DARWIN)
+#if CPU(X86)
+ typedef i386_thread_state_t PlatformRegisters;
+#elif CPU(X86_64)
+ typedef x86_thread_state64_t PlatformRegisters;
+#elif CPU(PPC)
+ typedef ppc_thread_state_t PlatformRegisters;
+#elif CPU(PPC64)
+ typedef ppc_thread_state64_t PlatformRegisters;
+#elif CPU(ARM)
+ typedef arm_thread_state_t PlatformRegisters;
+#elif CPU(ARM64)
+ typedef arm_thread_state64_t PlatformRegisters;
+#else
+#error Unknown Architecture
+#endif
+
+#elif OS(WINDOWS)
+ typedef CONTEXT PlatformRegisters;
+#elif USE(PTHREADS)
+ struct PlatformRegisters {
+ pthread_attr_t attribute;
+ mcontext_t machineContext;
+ };
+#else
+#error Need a thread register struct for this platform
+#endif
- private:
- void gatherFromCurrentThread(ConservativeRoots&, void* stackCurrent);
+ PlatformRegisters regs;
+ };
- class Thread;
+ bool suspend();
+ void resume();
+ size_t getRegisters(Registers&);
+ void freeRegisters(Registers&);
+ std::pair<void*, size_t> captureStack(void* stackTop);
- static void removeThread(void*);
- void removeCurrentThread();
+ PlatformThread platformThread;
+ void* stackBase;
+ void* stackEnd;
+#if OS(WINDOWS)
+ HANDLE platformThreadHandle;
+#elif USE(PTHREADS) && !OS(DARWIN)
+ sem_t semaphoreForSuspendResume;
+ mcontext_t suspendedMachineContext;
+ int suspendCount { 0 };
+ std::atomic<bool> suspended { false };
+#endif
+ };
+
+ class Thread {
+ WTF_MAKE_FAST_ALLOCATED;
+ Thread(ThreadData*);
- void gatherFromOtherThread(ConservativeRoots&, Thread*);
+ public:
+ using Registers = ThreadData::Registers;
- Mutex m_registeredThreadsMutex;
- Thread* m_registeredThreads;
- WTF::ThreadSpecificKey m_threadSpecific;
+ 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 LockHolder&) const { ASSERT(m_registeredThreadsMutex.isLocked()); return m_registeredThreads; }
+ Thread* machineThreadForCurrentThread();
+
+private:
+ void gatherFromCurrentThread(ConservativeRoots&, JITStubRoutineSet&, CodeBlockSet&, CurrentThreadState&);
+
+ void tryCopyOtherThreadStack(Thread*, void*, size_t capacity, size_t*);
+ bool tryCopyOtherThreadStacks(LockHolder&, void*, size_t capacity, size_t*);
+
+ static void THREAD_SPECIFIC_CALL removeThread(void*);
+
+ template<typename PlatformThread>
+ void removeThreadIfFound(PlatformThread);
+
+ Lock m_registeredThreadsMutex;
+ Thread* m_registeredThreads;
+ WTF::ThreadSpecificKey m_threadSpecificForMachineThreads;
#if !ASSERT_DISABLED
- Heap* m_heap;
+ Heap* m_heap;
#endif
- };
+};
+
+#define DECLARE_AND_COMPUTE_CURRENT_THREAD_STATE(stateName) \
+ CurrentThreadState stateName; \
+ stateName.stackTop = &stateName; \
+ stateName.stackOrigin = wtfThreadData().stack().origin(); \
+ ALLOCATE_AND_GET_REGISTER_STATE(stateName ## _registerState); \
+ stateName.registerState = &stateName ## _registerState
+
+// The return value is meaningless. We just use it to suppress tail call optimization.
+int callWithCurrentThreadState(const ScopedLambda<void(CurrentThreadState&)>&);
} // namespace JSC
-#endif // MachineThreads_h