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/runtime/JSLock.h | |
parent | 32761a6cee1d0dee366b885b7b9c777e67885688 (diff) | |
download | WebKitGtk-tarball-master.tar.gz |
webkitgtk-2.16.5HEADwebkitgtk-2.16.5master
Diffstat (limited to 'Source/JavaScriptCore/runtime/JSLock.h')
-rw-r--r-- | Source/JavaScriptCore/runtime/JSLock.h | 203 |
1 files changed, 109 insertions, 94 deletions
diff --git a/Source/JavaScriptCore/runtime/JSLock.h b/Source/JavaScriptCore/runtime/JSLock.h index 3002add64..31171b488 100644 --- a/Source/JavaScriptCore/runtime/JSLock.h +++ b/Source/JavaScriptCore/runtime/JSLock.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2005, 2008, 2009, 2014, 2016 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -18,113 +18,128 @@ * */ -#ifndef JSLock_h -#define JSLock_h +#pragma once +#include <mutex> +#include <thread> #include <wtf/Assertions.h> +#include <wtf/Lock.h> #include <wtf/Noncopyable.h> #include <wtf/RefPtr.h> -#include <wtf/TCSpinLock.h> -#include <wtf/Threading.h> +#include <wtf/ThreadSafeRefCounted.h> +#include <wtf/WTFThreadData.h> namespace JSC { - // To make it safe to use JavaScript on multiple threads, it is - // important to lock before doing anything that allocates a - // JavaScript data structure or that interacts with shared state - // such as the protect count hash table. The simplest way to lock - // is to create a local JSLockHolder object in the scope where the lock - // must be held and pass it the context that requires protection. - // The lock is recursive so nesting is ok. The JSLock - // object also acts as a convenience short-hand for running important - // initialization routines. - - // To avoid deadlock, sometimes it is necessary to temporarily - // release the lock. Since it is recursive you actually have to - // release all locks held by your thread. This is safe to do if - // you are executing code that doesn't require the lock, and you - // reacquire the right number of locks at the end. You can do this - // by constructing a locally scoped JSLock::DropAllLocks object. The - // DropAllLocks object takes care to release the JSLock only if your - // thread acquired it to begin with. - - class ExecState; - class VM; - - // This class is used to protect the initialization of the legacy single - // shared VM. - class GlobalJSLock { - WTF_MAKE_NONCOPYABLE(GlobalJSLock); +// To make it safe to use JavaScript on multiple threads, it is +// important to lock before doing anything that allocates a +// JavaScript data structure or that interacts with shared state +// such as the protect count hash table. The simplest way to lock +// is to create a local JSLockHolder object in the scope where the lock +// must be held and pass it the context that requires protection. +// The lock is recursive so nesting is ok. The JSLock +// object also acts as a convenience short-hand for running important +// initialization routines. + +// To avoid deadlock, sometimes it is necessary to temporarily +// release the lock. Since it is recursive you actually have to +// release all locks held by your thread. This is safe to do if +// you are executing code that doesn't require the lock, and you +// reacquire the right number of locks at the end. You can do this +// by constructing a locally scoped JSLock::DropAllLocks object. The +// DropAllLocks object takes care to release the JSLock only if your +// thread acquired it to begin with. + +class ExecState; +class VM; + +// This class is used to protect the initialization of the legacy single +// shared VM. +class GlobalJSLock { + WTF_MAKE_NONCOPYABLE(GlobalJSLock); +public: + JS_EXPORT_PRIVATE GlobalJSLock(); + JS_EXPORT_PRIVATE ~GlobalJSLock(); +private: + static StaticLock s_sharedInstanceMutex; +}; + +class JSLockHolder { +public: + JS_EXPORT_PRIVATE JSLockHolder(VM*); + JS_EXPORT_PRIVATE JSLockHolder(VM&); + JS_EXPORT_PRIVATE JSLockHolder(ExecState*); + + JS_EXPORT_PRIVATE ~JSLockHolder(); +private: + void init(); + + RefPtr<VM> m_vm; +}; + +class JSLock : public ThreadSafeRefCounted<JSLock> { + WTF_MAKE_NONCOPYABLE(JSLock); +public: + JSLock(VM*); + JS_EXPORT_PRIVATE ~JSLock(); + + JS_EXPORT_PRIVATE void lock(); + JS_EXPORT_PRIVATE void unlock(); + + static void lock(ExecState*); + static void unlock(ExecState*); + static void lock(VM&); + static void unlock(VM&); + + VM* vm() { return m_vm; } + + bool hasExclusiveThread() const { return m_hasExclusiveThread; } + std::thread::id exclusiveThread() const + { + ASSERT(m_hasExclusiveThread); + return m_ownerThreadID; + } + std::thread::id ownerThread() const { return m_ownerThreadID; } + JS_EXPORT_PRIVATE void setExclusiveThread(std::thread::id); + JS_EXPORT_PRIVATE bool currentThreadIsHoldingLock(); + + void willDestroyVM(VM*); + + class DropAllLocks { + WTF_MAKE_NONCOPYABLE(DropAllLocks); public: - JS_EXPORT_PRIVATE GlobalJSLock(); - JS_EXPORT_PRIVATE ~GlobalJSLock(); + JS_EXPORT_PRIVATE DropAllLocks(ExecState*); + JS_EXPORT_PRIVATE DropAllLocks(VM*); + JS_EXPORT_PRIVATE DropAllLocks(VM&); + JS_EXPORT_PRIVATE ~DropAllLocks(); - static void initialize(); - private: - static Mutex* s_sharedInstanceLock; - }; - - class JSLockHolder { - public: - JS_EXPORT_PRIVATE JSLockHolder(VM*); - JS_EXPORT_PRIVATE JSLockHolder(VM&); - JS_EXPORT_PRIVATE JSLockHolder(ExecState*); + void setDropDepth(unsigned depth) { m_dropDepth = depth; } + unsigned dropDepth() const { return m_dropDepth; } - JS_EXPORT_PRIVATE ~JSLockHolder(); private: - void init(); - + intptr_t m_droppedLockCount; RefPtr<VM> m_vm; + unsigned m_dropDepth; }; - class JSLock : public ThreadSafeRefCounted<JSLock> { - WTF_MAKE_NONCOPYABLE(JSLock); - public: - JSLock(VM*); - JS_EXPORT_PRIVATE ~JSLock(); - - JS_EXPORT_PRIVATE void lock(); - JS_EXPORT_PRIVATE void unlock(); - - static void lock(ExecState*); - static void unlock(ExecState*); - static void lock(VM&); - static void unlock(VM&); - - VM* vm() { return m_vm; } - - JS_EXPORT_PRIVATE bool currentThreadIsHoldingLock(); - - unsigned dropAllLocks(SpinLock&); - unsigned dropAllLocksUnconditionally(SpinLock&); - void grabAllLocks(unsigned lockCount, SpinLock&); - - void willDestroyVM(VM*); - - class DropAllLocks { - WTF_MAKE_NONCOPYABLE(DropAllLocks); - public: - // By default, we release all locks conditionally. Some clients, such as Mobile Safari, - // may require that we release all locks unconditionally. - enum AlwaysDropLocksTag { DontAlwaysDropLocks = 0, AlwaysDropLocks }; - JS_EXPORT_PRIVATE DropAllLocks(ExecState*, AlwaysDropLocksTag = DontAlwaysDropLocks); - JS_EXPORT_PRIVATE DropAllLocks(VM*, AlwaysDropLocksTag = DontAlwaysDropLocks); - JS_EXPORT_PRIVATE ~DropAllLocks(); - - private: - intptr_t m_lockCount; - RefPtr<VM> m_vm; - }; +private: + void lock(intptr_t lockCount); + void unlock(intptr_t unlockCount); - private: - SpinLock m_spinLock; - Mutex m_lock; - ThreadIdentifier m_ownerThread; - intptr_t m_lockCount; - unsigned m_lockDropDepth; - VM* m_vm; - }; + void didAcquireLock(); + void willReleaseLock(); -} // namespace + unsigned dropAllLocks(DropAllLocks*); + void grabAllLocks(DropAllLocks*, unsigned lockCount); -#endif // JSLock_h + Lock m_lock; + std::thread::id m_ownerThreadID; + intptr_t m_lockCount; + unsigned m_lockDropDepth; + bool m_hasExclusiveThread; + bool m_shouldReleaseHeapAccess; + VM* m_vm; + AtomicStringTable* m_entryAtomicStringTable; +}; + +} // namespace |