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();
+
+ static void initialize();
+private:
+ static std::mutex* 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);
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 std::mutex* s_sharedInstanceMutex;
- };
+ void setDropDepth(unsigned depth) { m_dropDepth = depth; }
+ unsigned dropDepth() const { return m_dropDepth; }
- 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();
-
+ 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; }
-
- 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);
- 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; }
-
- private:
- intptr_t m_droppedLockCount;
- RefPtr<VM> m_vm;
- unsigned m_dropDepth;
- };
+private:
+ void lock(intptr_t lockCount);
+ void unlock(intptr_t unlockCount);
- private:
- void lock(intptr_t lockCount);
- void unlock(intptr_t unlockCount);
-
- void didAcquireLock();
- void willReleaseLock();
-
- unsigned dropAllLocks(DropAllLocks*);
- void grabAllLocks(DropAllLocks*, unsigned lockCount);
-
- std::mutex m_lock;
- std::thread::id m_ownerThreadID;
- intptr_t m_lockCount;
- unsigned m_lockDropDepth;
- bool m_hasExclusiveThread;
- VM* m_vm;
- AtomicStringTable* m_entryAtomicStringTable;
- };
+ void didAcquireLock();
+ void willReleaseLock();
+
+ unsigned dropAllLocks(DropAllLocks*);
+ void grabAllLocks(DropAllLocks*, unsigned lockCount);
+
+ std::mutex m_lock;
+ std::thread::id m_ownerThreadID;
+ intptr_t m_lockCount;
+ unsigned m_lockDropDepth;
+ bool m_hasExclusiveThread;
+ VM* m_vm;
+ AtomicStringTable* m_entryAtomicStringTable;
+};
} // namespace