• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef V8_ASSERT_SCOPE_H_
6 #define V8_ASSERT_SCOPE_H_
7 
8 #include "src/allocation.h"
9 #include "src/platform.h"
10 #include "src/utils.h"
11 
12 namespace v8 {
13 namespace internal {
14 
15 class Isolate;
16 
17 enum PerThreadAssertType {
18   HEAP_ALLOCATION_ASSERT,
19   HANDLE_ALLOCATION_ASSERT,
20   HANDLE_DEREFERENCE_ASSERT,
21   DEFERRED_HANDLE_DEREFERENCE_ASSERT,
22   CODE_DEPENDENCY_CHANGE_ASSERT,
23   LAST_PER_THREAD_ASSERT_TYPE
24 };
25 
26 
27 enum PerIsolateAssertType {
28   JAVASCRIPT_EXECUTION_ASSERT,
29   JAVASCRIPT_EXECUTION_THROWS,
30   ALLOCATION_FAILURE_ASSERT,
31   DEOPTIMIZATION_ASSERT
32 };
33 
34 
35 class PerThreadAssertData {
36  public:
PerThreadAssertData()37   PerThreadAssertData() : nesting_level_(0) {
38     for (int i = 0; i < LAST_PER_THREAD_ASSERT_TYPE; i++) {
39       assert_states_[i] = true;
40     }
41   }
42 
set(PerThreadAssertType type,bool allow)43   void set(PerThreadAssertType type, bool allow) {
44     assert_states_[type] = allow;
45   }
46 
get(PerThreadAssertType type)47   bool get(PerThreadAssertType type) const {
48     return assert_states_[type];
49   }
50 
increment_level()51   void increment_level() { ++nesting_level_; }
decrement_level()52   bool decrement_level() { return --nesting_level_ == 0; }
53 
54  private:
55   bool assert_states_[LAST_PER_THREAD_ASSERT_TYPE];
56   int nesting_level_;
57 
58   DISALLOW_COPY_AND_ASSIGN(PerThreadAssertData);
59 };
60 
61 
62 class PerThreadAssertScopeBase {
63  protected:
PerThreadAssertScopeBase()64   PerThreadAssertScopeBase() {
65     data_ = GetAssertData();
66     if (data_ == NULL) {
67       data_ = new PerThreadAssertData();
68       SetThreadLocalData(data_);
69     }
70     data_->increment_level();
71   }
72 
~PerThreadAssertScopeBase()73   ~PerThreadAssertScopeBase() {
74     if (!data_->decrement_level()) return;
75     for (int i = 0; i < LAST_PER_THREAD_ASSERT_TYPE; i++) {
76       ASSERT(data_->get(static_cast<PerThreadAssertType>(i)));
77     }
78     delete data_;
79     SetThreadLocalData(NULL);
80   }
81 
GetAssertData()82   static PerThreadAssertData* GetAssertData() {
83     return reinterpret_cast<PerThreadAssertData*>(
84         Thread::GetThreadLocal(thread_local_key));
85   }
86 
87   static Thread::LocalStorageKey thread_local_key;
88   PerThreadAssertData* data_;
89   friend class Isolate;
90 
91  private:
SetThreadLocalData(PerThreadAssertData * data)92   static void SetThreadLocalData(PerThreadAssertData* data) {
93     Thread::SetThreadLocal(thread_local_key, data);
94   }
95 };
96 
97 
98 template <PerThreadAssertType type, bool allow>
99 class PerThreadAssertScope : public PerThreadAssertScopeBase {
100  public:
PerThreadAssertScope()101   PerThreadAssertScope() {
102     old_state_ = data_->get(type);
103     data_->set(type, allow);
104   }
105 
~PerThreadAssertScope()106   ~PerThreadAssertScope() { data_->set(type, old_state_); }
107 
IsAllowed()108   static bool IsAllowed() {
109     PerThreadAssertData* data = GetAssertData();
110     return data == NULL || data->get(type);
111   }
112 
113  private:
114   bool old_state_;
115 
116   DISALLOW_COPY_AND_ASSIGN(PerThreadAssertScope);
117 };
118 
119 
120 class PerIsolateAssertBase {
121  protected:
122   static uint32_t GetData(Isolate* isolate);
123   static void SetData(Isolate* isolate, uint32_t data);
124 };
125 
126 
127 template <PerIsolateAssertType type, bool allow>
128 class PerIsolateAssertScope : public PerIsolateAssertBase {
129  public:
PerIsolateAssertScope(Isolate * isolate)130   explicit PerIsolateAssertScope(Isolate* isolate) : isolate_(isolate) {
131     STATIC_ASSERT(type < 32);
132     old_data_ = GetData(isolate_);
133     SetData(isolate_, DataBit::update(old_data_, allow));
134   }
135 
~PerIsolateAssertScope()136   ~PerIsolateAssertScope() {
137     SetData(isolate_, old_data_);
138   }
139 
IsAllowed(Isolate * isolate)140   static bool IsAllowed(Isolate* isolate) {
141     return DataBit::decode(GetData(isolate));
142   }
143 
144  private:
145   typedef BitField<bool, type, 1> DataBit;
146 
147   uint32_t old_data_;
148   Isolate* isolate_;
149 
150   DISALLOW_COPY_AND_ASSIGN(PerIsolateAssertScope);
151 };
152 
153 
154 template <PerThreadAssertType type, bool allow>
155 #ifdef DEBUG
156 class PerThreadAssertScopeDebugOnly : public
157     PerThreadAssertScope<type, allow> {
158 #else
159 class PerThreadAssertScopeDebugOnly {
160  public:
161   PerThreadAssertScopeDebugOnly() { }
162 #endif
163 };
164 
165 
166 template <PerIsolateAssertType type, bool allow>
167 #ifdef DEBUG
168 class PerIsolateAssertScopeDebugOnly : public
169     PerIsolateAssertScope<type, allow> {
170  public:
PerIsolateAssertScopeDebugOnly(Isolate * isolate)171   explicit PerIsolateAssertScopeDebugOnly(Isolate* isolate)
172       : PerIsolateAssertScope<type, allow>(isolate) { }
173 #else
174 class PerIsolateAssertScopeDebugOnly {
175  public:
176   explicit PerIsolateAssertScopeDebugOnly(Isolate* isolate) { }
177 #endif
178 };
179 
180 // Per-thread assert scopes.
181 
182 // Scope to document where we do not expect handles to be created.
183 typedef PerThreadAssertScopeDebugOnly<HANDLE_ALLOCATION_ASSERT, false>
184     DisallowHandleAllocation;
185 
186 // Scope to introduce an exception to DisallowHandleAllocation.
187 typedef PerThreadAssertScopeDebugOnly<HANDLE_ALLOCATION_ASSERT, true>
188     AllowHandleAllocation;
189 
190 // Scope to document where we do not expect any allocation and GC.
191 typedef PerThreadAssertScopeDebugOnly<HEAP_ALLOCATION_ASSERT, false>
192     DisallowHeapAllocation;
193 
194 // Scope to introduce an exception to DisallowHeapAllocation.
195 typedef PerThreadAssertScopeDebugOnly<HEAP_ALLOCATION_ASSERT, true>
196     AllowHeapAllocation;
197 
198 // Scope to document where we do not expect any handle dereferences.
199 typedef PerThreadAssertScopeDebugOnly<HANDLE_DEREFERENCE_ASSERT, false>
200     DisallowHandleDereference;
201 
202 // Scope to introduce an exception to DisallowHandleDereference.
203 typedef PerThreadAssertScopeDebugOnly<HANDLE_DEREFERENCE_ASSERT, true>
204     AllowHandleDereference;
205 
206 // Scope to document where we do not expect deferred handles to be dereferenced.
207 typedef PerThreadAssertScopeDebugOnly<DEFERRED_HANDLE_DEREFERENCE_ASSERT, false>
208     DisallowDeferredHandleDereference;
209 
210 // Scope to introduce an exception to DisallowDeferredHandleDereference.
211 typedef PerThreadAssertScopeDebugOnly<DEFERRED_HANDLE_DEREFERENCE_ASSERT, true>
212     AllowDeferredHandleDereference;
213 
214 // Scope to document where we do not expect deferred handles to be dereferenced.
215 typedef PerThreadAssertScopeDebugOnly<CODE_DEPENDENCY_CHANGE_ASSERT, false>
216     DisallowCodeDependencyChange;
217 
218 // Scope to introduce an exception to DisallowDeferredHandleDereference.
219 typedef PerThreadAssertScopeDebugOnly<CODE_DEPENDENCY_CHANGE_ASSERT, true>
220     AllowCodeDependencyChange;
221 
222 
223 // Per-isolate assert scopes.
224 
225 // Scope to document where we do not expect javascript execution.
226 typedef PerIsolateAssertScope<JAVASCRIPT_EXECUTION_ASSERT, false>
227     DisallowJavascriptExecution;
228 
229 // Scope to introduce an exception to DisallowJavascriptExecution.
230 typedef PerIsolateAssertScope<JAVASCRIPT_EXECUTION_ASSERT, true>
231     AllowJavascriptExecution;
232 
233 // Scope in which javascript execution leads to exception being thrown.
234 typedef PerIsolateAssertScope<JAVASCRIPT_EXECUTION_THROWS, false>
235     ThrowOnJavascriptExecution;
236 
237 // Scope to introduce an exception to ThrowOnJavascriptExecution.
238 typedef PerIsolateAssertScope<JAVASCRIPT_EXECUTION_THROWS, true>
239     NoThrowOnJavascriptExecution;
240 
241 // Scope to document where we do not expect an allocation failure.
242 typedef PerIsolateAssertScopeDebugOnly<ALLOCATION_FAILURE_ASSERT, false>
243     DisallowAllocationFailure;
244 
245 // Scope to introduce an exception to DisallowAllocationFailure.
246 typedef PerIsolateAssertScopeDebugOnly<ALLOCATION_FAILURE_ASSERT, true>
247     AllowAllocationFailure;
248 
249 // Scope to document where we do not expect deoptimization.
250 typedef PerIsolateAssertScopeDebugOnly<DEOPTIMIZATION_ASSERT, false>
251     DisallowDeoptimization;
252 
253 // Scope to introduce an exception to DisallowDeoptimization.
254 typedef PerIsolateAssertScopeDebugOnly<DEOPTIMIZATION_ASSERT, true>
255     AllowDeoptimization;
256 
257 } }  // namespace v8::internal
258 
259 #endif  // V8_ASSERT_SCOPE_H_
260