1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2  * vim: set ts=8 sts=2 et sw=2 tw=80:
3  * This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #include "threading/ProtectedData.h"
8 
9 #include "gc/Zone.h"
10 #include "vm/HelperThreads.h"
11 #include "vm/JSContext.h"
12 
13 namespace js {
14 
15 #ifdef JS_HAS_PROTECTED_DATA_CHECKS
16 
17 /* static */ mozilla::Atomic<size_t, mozilla::SequentiallyConsistent>
18     AutoNoteSingleThreadedRegion::count(0);
19 
20 template <AllowedHelperThread Helper>
OnHelperThread()21 static inline bool OnHelperThread() {
22   if (Helper == AllowedHelperThread::IonCompile ||
23       Helper == AllowedHelperThread::GCTaskOrIonCompile) {
24     if (CurrentThreadIsIonCompiling()) {
25       return true;
26     }
27   }
28 
29   if (Helper == AllowedHelperThread::GCTask ||
30       Helper == AllowedHelperThread::GCTaskOrIonCompile) {
31     JSContext* cx = TlsContext.get();
32     if (cx->defaultFreeOp()->isCollecting()) {
33       return true;
34     }
35   }
36 
37   if (Helper == AllowedHelperThread::ParseTask) {
38     if (CurrentThreadIsParseThread()) {
39       return true;
40     }
41   }
42 
43   return false;
44 }
45 
check() const46 void CheckThreadLocal::check() const {
47   JSContext* cx = TlsContext.get();
48   MOZ_ASSERT(cx);
49   MOZ_ASSERT_IF(cx->isMainThreadContext(),
50                 CurrentThreadCanAccessRuntime(cx->runtime()));
51   MOZ_ASSERT(id == ThreadId::ThisThreadId());
52 }
53 
check() const54 void CheckContextLocal::check() const {
55   if (!cx_->isInitialized()) {
56     return;
57   }
58 
59   JSContext* cx = TlsContext.get();
60   MOZ_ASSERT(cx);
61   MOZ_ASSERT_IF(cx->isMainThreadContext(),
62                 CurrentThreadCanAccessRuntime(cx->runtime()));
63   MOZ_ASSERT(cx_ == cx);
64 }
65 
66 template <AllowedHelperThread Helper>
check() const67 void CheckMainThread<Helper>::check() const {
68   if (OnHelperThread<Helper>()) {
69     return;
70   }
71 
72   JSContext* cx = TlsContext.get();
73   MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx->runtime()));
74 }
75 
76 template class CheckMainThread<AllowedHelperThread::None>;
77 template class CheckMainThread<AllowedHelperThread::GCTask>;
78 template class CheckMainThread<AllowedHelperThread::ParseTask>;
79 template class CheckMainThread<AllowedHelperThread::IonCompile>;
80 
81 template <AllowedHelperThread Helper>
check() const82 void CheckZone<Helper>::check() const {
83   if (OnHelperThread<Helper>()) {
84     return;
85   }
86 
87   // The main thread is permitted access to all zones. These accesses
88   // are threadsafe if the zone is not in use by a helper thread.
89   MOZ_ASSERT(CurrentThreadCanAccessRuntime(TlsContext.get()->runtime()));
90 }
91 
92 template class CheckZone<AllowedHelperThread::None>;
93 template class CheckZone<AllowedHelperThread::GCTask>;
94 template class CheckZone<AllowedHelperThread::IonCompile>;
95 template class CheckZone<AllowedHelperThread::GCTaskOrIonCompile>;
96 
97 template <GlobalLock Lock, AllowedHelperThread Helper>
check() const98 void CheckGlobalLock<Lock, Helper>::check() const {
99   if (OnHelperThread<Helper>()) {
100     return;
101   }
102 
103   switch (Lock) {
104     case GlobalLock::GCLock:
105       TlsContext.get()->runtime()->gc.assertCurrentThreadHasLockedGC();
106       break;
107     case GlobalLock::ScriptDataLock:
108       TlsContext.get()->runtime()->assertCurrentThreadHasScriptDataAccess();
109       break;
110     case GlobalLock::HelperThreadLock:
111       gHelperThreadLock.assertOwnedByCurrentThread();
112       break;
113   }
114 }
115 
116 template class CheckGlobalLock<GlobalLock::GCLock, AllowedHelperThread::None>;
117 template class CheckGlobalLock<GlobalLock::ScriptDataLock,
118                                AllowedHelperThread::None>;
119 template class CheckGlobalLock<GlobalLock::HelperThreadLock,
120                                AllowedHelperThread::None>;
121 
122 template <AllowedHelperThread Helper>
check() const123 void CheckArenaListAccess<Helper>::check() const {
124   MOZ_ASSERT(zone);
125 
126   if (OnHelperThread<Helper>()) {
127     return;
128   }
129 
130   if (zone->isAtomsZone()) {
131     return;
132   }
133 
134   CheckZone<AllowedHelperThread::None>::check();
135 }
136 
137 template class CheckArenaListAccess<AllowedHelperThread::GCTask>;
138 
139 #endif  // JS_HAS_PROTECTED_DATA_CHECKS
140 
141 }  // namespace js
142