27e47f31b8de085bb86e8a7fa5082adeb78e9e88
[WebKit-https.git] / Source / JavaScriptCore / runtime / ConcurrentJITLock.h
1 /*
2  * Copyright (C) 2013 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     enum NoLockingNecessaryTag { NoLockingNecessary };
57     explicit ConcurrentJITLockerBase(NoLockingNecessaryTag)
58         : m_locker(ConcurrentJITLockerImpl::NoLockingNecessary)
59     {
60     }
61
62     ~ConcurrentJITLockerBase()
63     {
64     }
65     
66     void unlockEarly()
67     {
68         m_locker.unlockEarly();
69     }
70
71 private:
72     ConcurrentJITLockerImpl m_locker;
73 };
74
75 class GCSafeConcurrentJITLocker : public ConcurrentJITLockerBase {
76 public:
77     GCSafeConcurrentJITLocker(ConcurrentJITLock& lockable, Heap& heap)
78         : ConcurrentJITLockerBase(lockable)
79         , m_deferGC(heap)
80     {
81     }
82
83     GCSafeConcurrentJITLocker(ConcurrentJITLock* lockable, Heap& heap)
84         : ConcurrentJITLockerBase(lockable)
85         , m_deferGC(heap)
86     {
87     }
88
89     ~GCSafeConcurrentJITLocker()
90     {
91         // We have to unlock early due to the destruction order of base
92         // vs. derived classes. If we didn't, then we would destroy the 
93         // DeferGC object before unlocking the lock which could cause a GC
94         // and resulting deadlock.
95         unlockEarly();
96     }
97
98 private:
99 #if ENABLE(CONCURRENT_JIT)
100     DeferGC m_deferGC;
101 #else
102     struct NoDefer {
103         NoDefer(Heap& heap) : m_heap(heap) { }
104         Heap& m_heap;
105     };
106     NoDefer m_deferGC;
107 #endif
108 };
109
110 class ConcurrentJITLocker : public ConcurrentJITLockerBase {
111 public:
112     ConcurrentJITLocker(ConcurrentJITLock& lockable)
113         : ConcurrentJITLockerBase(lockable)
114 #if ENABLE(CONCURRENT_JIT) && !defined(NDEBUG)
115         , m_disallowGC(InPlace)
116 #endif
117     {
118     }
119
120     ConcurrentJITLocker(ConcurrentJITLock* lockable)
121         : ConcurrentJITLockerBase(lockable)
122 #if ENABLE(CONCURRENT_JIT) && !defined(NDEBUG)
123         , m_disallowGC(InPlace)
124 #endif
125     {
126     }
127
128     ConcurrentJITLocker(ConcurrentJITLockerBase::NoLockingNecessaryTag)
129         : ConcurrentJITLockerBase(ConcurrentJITLockerBase::NoLockingNecessary)
130 #if ENABLE(CONCURRENT_JIT) && !defined(NDEBUG)
131         , m_disallowGC(Nullopt)
132 #endif
133     {
134     }
135
136 #if ENABLE(CONCURRENT_JIT) && !defined(NDEBUG)
137 private:
138     Optional<DisallowGC> m_disallowGC;
139 #endif
140 };
141
142 } // namespace JSC
143
144 #endif // ConcurrentJITLock_h