diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2016-04-10 09:28:39 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2016-04-10 09:28:39 +0000 |
commit | 32761a6cee1d0dee366b885b7b9c777e67885688 (patch) | |
tree | d6bec92bebfb216f4126356e55518842c2f476a1 /Source/JavaScriptCore/runtime/JSLock.h | |
parent | a4e969f4965059196ca948db781e52f7cfebf19e (diff) | |
download | WebKitGtk-tarball-32761a6cee1d0dee366b885b7b9c777e67885688.tar.gz |
webkitgtk-2.4.11webkitgtk-2.4.11
Diffstat (limited to 'Source/JavaScriptCore/runtime/JSLock.h')
-rw-r--r-- | Source/JavaScriptCore/runtime/JSLock.h | 196 |
1 files changed, 90 insertions, 106 deletions
diff --git a/Source/JavaScriptCore/runtime/JSLock.h b/Source/JavaScriptCore/runtime/JSLock.h index 4d0d17420..3002add64 100644 --- a/Source/JavaScriptCore/runtime/JSLock.h +++ b/Source/JavaScriptCore/runtime/JSLock.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005, 2008, 2009, 2014 Apple Inc. All rights reserved. + * Copyright (C) 2005, 2008, 2009 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 @@ -21,125 +21,109 @@ #ifndef JSLock_h #define JSLock_h -#include <mutex> -#include <thread> #include <wtf/Assertions.h> -#include <wtf/Lock.h> #include <wtf/Noncopyable.h> #include <wtf/RefPtr.h> -#include <wtf/ThreadSafeRefCounted.h> -#include <wtf/WTFThreadData.h> +#include <wtf/TCSpinLock.h> +#include <wtf/Threading.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); -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; - } - JS_EXPORT_PRIVATE void setExclusiveThread(std::thread::id); - JS_EXPORT_PRIVATE bool currentThreadIsHoldingLock(); - - void willDestroyVM(VM*); - - class DropAllLocks { - WTF_MAKE_NONCOPYABLE(DropAllLocks); + // 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 DropAllLocks(ExecState*); - JS_EXPORT_PRIVATE DropAllLocks(VM*); - JS_EXPORT_PRIVATE DropAllLocks(VM&); - JS_EXPORT_PRIVATE ~DropAllLocks(); - - void setDropDepth(unsigned depth) { m_dropDepth = depth; } - unsigned dropDepth() const { return m_dropDepth; } + JS_EXPORT_PRIVATE GlobalJSLock(); + JS_EXPORT_PRIVATE ~GlobalJSLock(); + static void initialize(); private: - intptr_t m_droppedLockCount; - RefPtr<VM> m_vm; - unsigned m_dropDepth; + static Mutex* s_sharedInstanceLock; }; -private: - void lock(intptr_t lockCount); - void unlock(intptr_t unlockCount); + 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(); - void didAcquireLock(); - void willReleaseLock(); + RefPtr<VM> m_vm; + }; - unsigned dropAllLocks(DropAllLocks*); - void grabAllLocks(DropAllLocks*, unsigned lockCount); + 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; + }; - Lock m_lock; - std::thread::id m_ownerThreadID; - intptr_t m_lockCount; - unsigned m_lockDropDepth; - bool m_hasExclusiveThread; - VM* m_vm; - AtomicStringTable* m_entryAtomicStringTable; -}; + private: + SpinLock m_spinLock; + Mutex m_lock; + ThreadIdentifier m_ownerThread; + intptr_t m_lockCount; + unsigned m_lockDropDepth; + VM* m_vm; + }; } // namespace |