diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
commit | 1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch) | |
tree | 46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/JavaScriptCore/heap/MachineStackMarker.h | |
parent | 32761a6cee1d0dee366b885b7b9c777e67885688 (diff) | |
download | WebKitGtk-tarball-master.tar.gz |
webkitgtk-2.16.5HEADwebkitgtk-2.16.5master
Diffstat (limited to 'Source/JavaScriptCore/heap/MachineStackMarker.h')
-rw-r--r-- | Source/JavaScriptCore/heap/MachineStackMarker.h | 188 |
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 |