Make it easier to use NoLockingNecessary
[WebKit-https.git] / Source / JavaScriptCore / runtime / ConcurrentJITLock.h
1 /*
2  * Copyright (C) 2013, 2016 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #ifndef ConcurrentJITLock_h
27 #define ConcurrentJITLock_h
28
29 #include "DeferGC.h"
30 #include <wtf/Lock.h>
31 #include <wtf/NoLock.h>
32 #include <wtf/Optional.h>
33
34 namespace JSC {
35
36 #if ENABLE(CONCURRENT_JIT)
37 typedef Lock ConcurrentJITLock;
38 typedef LockHolder ConcurrentJITLockerImpl;
39 #else
40 typedef NoLock ConcurrentJITLock;
41 typedef NoLockLocker ConcurrentJITLockerImpl;
42 #endif
43
44 class ConcurrentJITLockerBase {
45     WTF_MAKE_NONCOPYABLE(ConcurrentJITLockerBase);
46 public:
47     explicit ConcurrentJITLockerBase(ConcurrentJITLock& lockable)
48         : m_locker(&lockable)
49     {
50     }
51     explicit ConcurrentJITLockerBase(ConcurrentJITLock* lockable)
52         : m_locker(lockable)
53     {
54     }
55
56     explicit ConcurrentJITLockerBase(NoLockingNecessaryTag)
57         : m_locker(NoLockingNecessary)
58     {
59     }
60
61     ~ConcurrentJITLockerBase()
62     {
63     }
64     
65     void unlockEarly()
66     {
67         m_locker.unlockEarly();
68     }
69
70 private:
71     ConcurrentJITLockerImpl m_locker;
72 };
73
74 class GCSafeConcurrentJITLocker : public ConcurrentJITLockerBase {
75 public:
76     GCSafeConcurrentJITLocker(ConcurrentJITLock& lockable, Heap& heap)
77         : ConcurrentJITLockerBase(lockable)
78         , m_deferGC(heap)
79     {
80     }
81
82     GCSafeConcurrentJITLocker(ConcurrentJITLock* lockable, Heap& heap)
83         : ConcurrentJITLockerBase(lockable)
84         , m_deferGC(heap)
85     {
86     }
87
88     ~GCSafeConcurrentJITLocker()
89     {
90         // We have to unlock early due to the destruction order of base
91         // vs. derived classes. If we didn't, then we would destroy the 
92         // DeferGC object before unlocking the lock which could cause a GC
93         // and resulting deadlock.
94         unlockEarly();
95     }
96
97 private:
98 #if ENABLE(CONCURRENT_JIT)
99     DeferGC m_deferGC;
100 #else
101     struct NoDefer {
102         NoDefer(Heap& heap) : m_heap(heap) { }
103         Heap& m_heap;
104     };
105     NoDefer m_deferGC;
106 #endif
107 };
108
109 class ConcurrentJITLocker : public ConcurrentJITLockerBase {
110 public:
111     ConcurrentJITLocker(ConcurrentJITLock& lockable)
112         : ConcurrentJITLockerBase(lockable)
113 #if ENABLE(CONCURRENT_JIT) && !defined(NDEBUG)
114         , m_disallowGC(InPlace)
115 #endif
116     {
117     }
118
119     ConcurrentJITLocker(ConcurrentJITLock* lockable)
120         : ConcurrentJITLockerBase(lockable)
121 #if ENABLE(CONCURRENT_JIT) && !defined(NDEBUG)
122         , m_disallowGC(InPlace)
123 #endif
124     {
125     }
126
127     ConcurrentJITLocker(NoLockingNecessaryTag)
128         : ConcurrentJITLockerBase(NoLockingNecessary)
129 #if ENABLE(CONCURRENT_JIT) && !defined(NDEBUG)
130         , m_disallowGC(Nullopt)
131 #endif
132     {
133     }
134
135 #if ENABLE(CONCURRENT_JIT) && !defined(NDEBUG)
136 private:
137     Optional<DisallowGC> m_disallowGC;
138 #endif
139 };
140
141 } // namespace JSC
142
143 #endif // ConcurrentJITLock_h