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 <stdint.h>
9
10#include "src/base/macros.h"
11#include "src/base/optional.h"
12#include "src/globals.h"
13#include "src/pointer-with-payload.h"
14
15namespace v8 {
16namespace internal {
17
18// Forward declarations.
19class Isolate;
20class PerThreadAssertData;
21
22template <>
23struct PointerWithPayloadTraits<PerThreadAssertData> {
24 static constexpr int value = 1;
25};
26
27enum PerThreadAssertType {
28 HEAP_ALLOCATION_ASSERT,
29 HANDLE_ALLOCATION_ASSERT,
30 HANDLE_DEREFERENCE_ASSERT,
31 DEFERRED_HANDLE_DEREFERENCE_ASSERT,
32 CODE_DEPENDENCY_CHANGE_ASSERT,
33 LAST_PER_THREAD_ASSERT_TYPE
34};
35
36enum PerIsolateAssertType {
37 JAVASCRIPT_EXECUTION_ASSERT,
38 JAVASCRIPT_EXECUTION_THROWS,
39 JAVASCRIPT_EXECUTION_DUMP,
40 DEOPTIMIZATION_ASSERT,
41 COMPILATION_ASSERT,
42 NO_EXCEPTION_ASSERT
43};
44
45template <PerThreadAssertType kType, bool kAllow>
46class PerThreadAssertScope {
47 public:
48 V8_EXPORT_PRIVATE PerThreadAssertScope();
49 V8_EXPORT_PRIVATE ~PerThreadAssertScope();
50
51 V8_EXPORT_PRIVATE static bool IsAllowed();
52
53 void Release();
54
55 private:
56 PointerWithPayload<PerThreadAssertData, bool, 1> data_and_old_state_;
57
58 V8_INLINE void set_data(PerThreadAssertData* data) {
59 data_and_old_state_.SetPointer(data);
60 }
61
62 V8_INLINE PerThreadAssertData* data() const {
63 return data_and_old_state_.GetPointer();
64 }
65
66 V8_INLINE void set_old_state(bool old_state) {
67 return data_and_old_state_.SetPayload(old_state);
68 }
69
70 V8_INLINE bool old_state() const { return data_and_old_state_.GetPayload(); }
71
72 DISALLOW_COPY_AND_ASSIGN(PerThreadAssertScope);
73};
74
75
76template <PerIsolateAssertType type, bool allow>
77class PerIsolateAssertScope {
78 public:
79 V8_EXPORT_PRIVATE explicit PerIsolateAssertScope(Isolate* isolate);
80 V8_EXPORT_PRIVATE ~PerIsolateAssertScope();
81
82 static bool IsAllowed(Isolate* isolate);
83
84 private:
85 class DataBit;
86
87 Isolate* isolate_;
88 uint32_t old_data_;
89
90 DISALLOW_COPY_AND_ASSIGN(PerIsolateAssertScope);
91};
92
93
94template <PerThreadAssertType type, bool allow>
95#ifdef DEBUG
96class PerThreadAssertScopeDebugOnly : public
97 PerThreadAssertScope<type, allow> {
98#else
99class PerThreadAssertScopeDebugOnly {
100 public:
101 PerThreadAssertScopeDebugOnly() { // NOLINT (modernize-use-equals-default)
102 // Define a constructor to avoid unused variable warnings.
103 }
104 void Release() {}
105#endif
106};
107
108
109template <PerIsolateAssertType type, bool allow>
110#ifdef DEBUG
111class PerIsolateAssertScopeDebugOnly : public
112 PerIsolateAssertScope<type, allow> {
113 public:
114 explicit PerIsolateAssertScopeDebugOnly(Isolate* isolate)
115 : PerIsolateAssertScope<type, allow>(isolate) { }
116#else
117class PerIsolateAssertScopeDebugOnly {
118 public:
119 explicit PerIsolateAssertScopeDebugOnly(Isolate* isolate) { }
120#endif
121};
122
123// Per-thread assert scopes.
124
125// Scope to document where we do not expect handles to be created.
126typedef PerThreadAssertScopeDebugOnly<HANDLE_ALLOCATION_ASSERT, false>
127 DisallowHandleAllocation;
128
129// Scope to introduce an exception to DisallowHandleAllocation.
130typedef PerThreadAssertScopeDebugOnly<HANDLE_ALLOCATION_ASSERT, true>
131 AllowHandleAllocation;
132
133// Scope to document where we do not expect any allocation and GC.
134typedef PerThreadAssertScopeDebugOnly<HEAP_ALLOCATION_ASSERT, false>
135 DisallowHeapAllocation;
136#ifdef DEBUG
137#define DISALLOW_HEAP_ALLOCATION(name) DisallowHeapAllocation name;
138#else
139#define DISALLOW_HEAP_ALLOCATION(name)
140#endif
141
142// Scope to introduce an exception to DisallowHeapAllocation.
143typedef PerThreadAssertScopeDebugOnly<HEAP_ALLOCATION_ASSERT, true>
144 AllowHeapAllocation;
145
146// Scope to document where we do not expect any handle dereferences.
147typedef PerThreadAssertScopeDebugOnly<HANDLE_DEREFERENCE_ASSERT, false>
148 DisallowHandleDereference;
149
150// Scope to introduce an exception to DisallowHandleDereference.
151typedef PerThreadAssertScopeDebugOnly<HANDLE_DEREFERENCE_ASSERT, true>
152 AllowHandleDereference;
153
154// Scope to document where we do not expect deferred handles to be dereferenced.
155typedef PerThreadAssertScopeDebugOnly<DEFERRED_HANDLE_DEREFERENCE_ASSERT, false>
156 DisallowDeferredHandleDereference;
157
158// Scope to introduce an exception to DisallowDeferredHandleDereference.
159typedef PerThreadAssertScopeDebugOnly<DEFERRED_HANDLE_DEREFERENCE_ASSERT, true>
160 AllowDeferredHandleDereference;
161
162// Scope to document where we do not expect deferred handles to be dereferenced.
163typedef PerThreadAssertScopeDebugOnly<CODE_DEPENDENCY_CHANGE_ASSERT, false>
164 DisallowCodeDependencyChange;
165
166// Scope to introduce an exception to DisallowDeferredHandleDereference.
167typedef PerThreadAssertScopeDebugOnly<CODE_DEPENDENCY_CHANGE_ASSERT, true>
168 AllowCodeDependencyChange;
169
170class DisallowHeapAccess {
171 DisallowCodeDependencyChange no_dependency_change_;
172 DisallowHandleAllocation no_handle_allocation_;
173 DisallowHandleDereference no_handle_dereference_;
174 DisallowHeapAllocation no_heap_allocation_;
175};
176
177class DisallowHeapAccessIf {
178 public:
179 explicit DisallowHeapAccessIf(bool condition) {
180 if (condition) maybe_disallow_.emplace();
181 }
182
183 private:
184 base::Optional<DisallowHeapAccess> maybe_disallow_;
185};
186
187// Per-isolate assert scopes.
188
189// Scope to document where we do not expect javascript execution.
190typedef PerIsolateAssertScope<JAVASCRIPT_EXECUTION_ASSERT, false>
191 DisallowJavascriptExecution;
192
193// Scope to introduce an exception to DisallowJavascriptExecution.
194typedef PerIsolateAssertScope<JAVASCRIPT_EXECUTION_ASSERT, true>
195 AllowJavascriptExecution;
196
197// Scope to document where we do not expect javascript execution (debug only)
198typedef PerIsolateAssertScopeDebugOnly<JAVASCRIPT_EXECUTION_ASSERT, false>
199 DisallowJavascriptExecutionDebugOnly;
200
201// Scope to introduce an exception to DisallowJavascriptExecutionDebugOnly.
202typedef PerIsolateAssertScopeDebugOnly<JAVASCRIPT_EXECUTION_ASSERT, true>
203 AllowJavascriptExecutionDebugOnly;
204
205// Scope in which javascript execution leads to exception being thrown.
206typedef PerIsolateAssertScope<JAVASCRIPT_EXECUTION_THROWS, false>
207 ThrowOnJavascriptExecution;
208
209// Scope to introduce an exception to ThrowOnJavascriptExecution.
210typedef PerIsolateAssertScope<JAVASCRIPT_EXECUTION_THROWS, true>
211 NoThrowOnJavascriptExecution;
212
213// Scope in which javascript execution causes dumps.
214typedef PerIsolateAssertScope<JAVASCRIPT_EXECUTION_DUMP, false>
215 DumpOnJavascriptExecution;
216
217// Scope in which javascript execution causes dumps.
218typedef PerIsolateAssertScope<JAVASCRIPT_EXECUTION_DUMP, true>
219 NoDumpOnJavascriptExecution;
220
221// Scope to document where we do not expect deoptimization.
222typedef PerIsolateAssertScopeDebugOnly<DEOPTIMIZATION_ASSERT, false>
223 DisallowDeoptimization;
224
225// Scope to introduce an exception to DisallowDeoptimization.
226typedef PerIsolateAssertScopeDebugOnly<DEOPTIMIZATION_ASSERT, true>
227 AllowDeoptimization;
228
229// Scope to document where we do not expect deoptimization.
230typedef PerIsolateAssertScopeDebugOnly<COMPILATION_ASSERT, false>
231 DisallowCompilation;
232
233// Scope to introduce an exception to DisallowDeoptimization.
234typedef PerIsolateAssertScopeDebugOnly<COMPILATION_ASSERT, true>
235 AllowCompilation;
236
237// Scope to document where we do not expect exceptions.
238typedef PerIsolateAssertScopeDebugOnly<NO_EXCEPTION_ASSERT, false>
239 DisallowExceptions;
240
241// Scope to introduce an exception to DisallowExceptions.
242typedef PerIsolateAssertScopeDebugOnly<NO_EXCEPTION_ASSERT, true>
243 AllowExceptions;
244
245// Explicit instantiation declarations.
246extern template class PerThreadAssertScope<HEAP_ALLOCATION_ASSERT, false>;
247extern template class PerThreadAssertScope<HEAP_ALLOCATION_ASSERT, true>;
248extern template class PerThreadAssertScope<HANDLE_ALLOCATION_ASSERT, false>;
249extern template class PerThreadAssertScope<HANDLE_ALLOCATION_ASSERT, true>;
250extern template class PerThreadAssertScope<HANDLE_DEREFERENCE_ASSERT, false>;
251extern template class PerThreadAssertScope<HANDLE_DEREFERENCE_ASSERT, true>;
252extern template class PerThreadAssertScope<DEFERRED_HANDLE_DEREFERENCE_ASSERT,
253 false>;
254extern template class PerThreadAssertScope<DEFERRED_HANDLE_DEREFERENCE_ASSERT,
255 true>;
256extern template class PerThreadAssertScope<CODE_DEPENDENCY_CHANGE_ASSERT,
257 false>;
258extern template class PerThreadAssertScope<CODE_DEPENDENCY_CHANGE_ASSERT, true>;
259
260extern template class PerIsolateAssertScope<JAVASCRIPT_EXECUTION_ASSERT, false>;
261extern template class PerIsolateAssertScope<JAVASCRIPT_EXECUTION_ASSERT, true>;
262extern template class PerIsolateAssertScope<JAVASCRIPT_EXECUTION_THROWS, false>;
263extern template class PerIsolateAssertScope<JAVASCRIPT_EXECUTION_THROWS, true>;
264extern template class PerIsolateAssertScope<JAVASCRIPT_EXECUTION_DUMP, false>;
265extern template class PerIsolateAssertScope<JAVASCRIPT_EXECUTION_DUMP, true>;
266extern template class PerIsolateAssertScope<DEOPTIMIZATION_ASSERT, false>;
267extern template class PerIsolateAssertScope<DEOPTIMIZATION_ASSERT, true>;
268extern template class PerIsolateAssertScope<COMPILATION_ASSERT, false>;
269extern template class PerIsolateAssertScope<COMPILATION_ASSERT, true>;
270extern template class PerIsolateAssertScope<NO_EXCEPTION_ASSERT, false>;
271extern template class PerIsolateAssertScope<NO_EXCEPTION_ASSERT, true>;
272
273} // namespace internal
274} // namespace v8
275
276#endif // V8_ASSERT_SCOPE_H_
277