• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 //     * Redistributions of source code must retain the above copyright
7 //       notice, this list of conditions and the following disclaimer.
8 //     * Redistributions in binary form must reproduce the above
9 //       copyright notice, this list of conditions and the following
10 //       disclaimer in the documentation and/or other materials provided
11 //       with the distribution.
12 //     * Neither the name of Google Inc. nor the names of its
13 //       contributors may be used to endorse or promote products derived
14 //       from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 #ifndef V8_ASSERT_SCOPE_H_
29 #define V8_ASSERT_SCOPE_H_
30 
31 #include "allocation.h"
32 #include "platform.h"
33 
34 namespace v8 {
35 namespace internal {
36 
37 class Isolate;
38 
39 enum PerThreadAssertType {
40   HEAP_ALLOCATION_ASSERT,
41   HANDLE_ALLOCATION_ASSERT,
42   HANDLE_DEREFERENCE_ASSERT,
43   DEFERRED_HANDLE_DEREFERENCE_ASSERT,
44   CODE_DEPENDENCY_CHANGE_ASSERT,
45   LAST_PER_THREAD_ASSERT_TYPE
46 };
47 
48 
49 #ifdef DEBUG
50 class PerThreadAssertData {
51  public:
PerThreadAssertData()52   PerThreadAssertData() : nesting_level_(0) {
53     for (int i = 0; i < LAST_PER_THREAD_ASSERT_TYPE; i++) {
54       assert_states_[i] = true;
55     }
56   }
57 
set(PerThreadAssertType type,bool allow)58   void set(PerThreadAssertType type, bool allow) {
59     assert_states_[type] = allow;
60   }
61 
get(PerThreadAssertType type)62   bool get(PerThreadAssertType type) const {
63     return assert_states_[type];
64   }
65 
increment_level()66   void increment_level() { ++nesting_level_; }
decrement_level()67   bool decrement_level() { return --nesting_level_ == 0; }
68 
69  private:
70   bool assert_states_[LAST_PER_THREAD_ASSERT_TYPE];
71   int nesting_level_;
72 
73   DISALLOW_COPY_AND_ASSIGN(PerThreadAssertData);
74 };
75 #endif  // DEBUG
76 
77 
78 class PerThreadAssertScopeBase {
79 #ifdef DEBUG
80 
81  protected:
PerThreadAssertScopeBase()82   PerThreadAssertScopeBase() {
83     data_ = GetAssertData();
84     if (data_ == NULL) {
85       data_ = new PerThreadAssertData();
86       SetThreadLocalData(data_);
87     }
88     data_->increment_level();
89   }
90 
~PerThreadAssertScopeBase()91   ~PerThreadAssertScopeBase() {
92     if (!data_->decrement_level()) return;
93     for (int i = 0; i < LAST_PER_THREAD_ASSERT_TYPE; i++) {
94       ASSERT(data_->get(static_cast<PerThreadAssertType>(i)));
95     }
96     delete data_;
97     SetThreadLocalData(NULL);
98   }
99 
GetAssertData()100   static PerThreadAssertData* GetAssertData() {
101     return reinterpret_cast<PerThreadAssertData*>(
102         Thread::GetThreadLocal(thread_local_key));
103   }
104 
105   static Thread::LocalStorageKey thread_local_key;
106   PerThreadAssertData* data_;
107   friend class Isolate;
108 
109  private:
SetThreadLocalData(PerThreadAssertData * data)110   static void SetThreadLocalData(PerThreadAssertData* data) {
111     Thread::SetThreadLocal(thread_local_key, data);
112   }
113 #endif  // DEBUG
114 };
115 
116 
117 
118 template <PerThreadAssertType type, bool allow>
119 class PerThreadAssertScope : public PerThreadAssertScopeBase {
120  public:
121 #ifndef DEBUG
PerThreadAssertScope()122   PerThreadAssertScope() { }
SetIsAllowed(bool is_allowed)123   static void SetIsAllowed(bool is_allowed) { }
124 #else
125   PerThreadAssertScope() {
126     old_state_ = data_->get(type);
127     data_->set(type, allow);
128   }
129 
130   ~PerThreadAssertScope() { data_->set(type, old_state_); }
131 
132   static bool IsAllowed() {
133     PerThreadAssertData* data = GetAssertData();
134     return data == NULL || data->get(type);
135   }
136 
137  private:
138   bool old_state_;
139 #endif
140 };
141 
142 // Scope to document where we do not expect handles to be created.
143 typedef PerThreadAssertScope<HANDLE_ALLOCATION_ASSERT, false>
144     DisallowHandleAllocation;
145 
146 // Scope to introduce an exception to DisallowHandleAllocation.
147 typedef PerThreadAssertScope<HANDLE_ALLOCATION_ASSERT, true>
148     AllowHandleAllocation;
149 
150 // Scope to document where we do not expect any allocation and GC.
151 typedef PerThreadAssertScope<HEAP_ALLOCATION_ASSERT, false>
152     DisallowHeapAllocation;
153 
154 // Scope to introduce an exception to DisallowHeapAllocation.
155 typedef PerThreadAssertScope<HEAP_ALLOCATION_ASSERT, true>
156     AllowHeapAllocation;
157 
158 // Scope to document where we do not expect any handle dereferences.
159 typedef PerThreadAssertScope<HANDLE_DEREFERENCE_ASSERT, false>
160     DisallowHandleDereference;
161 
162 // Scope to introduce an exception to DisallowHandleDereference.
163 typedef PerThreadAssertScope<HANDLE_DEREFERENCE_ASSERT, true>
164     AllowHandleDereference;
165 
166 // Scope to document where we do not expect deferred handles to be dereferenced.
167 typedef PerThreadAssertScope<DEFERRED_HANDLE_DEREFERENCE_ASSERT, false>
168     DisallowDeferredHandleDereference;
169 
170 // Scope to introduce an exception to DisallowDeferredHandleDereference.
171 typedef PerThreadAssertScope<DEFERRED_HANDLE_DEREFERENCE_ASSERT, true>
172     AllowDeferredHandleDereference;
173 
174 // Scope to document where we do not expect deferred handles to be dereferenced.
175 typedef PerThreadAssertScope<CODE_DEPENDENCY_CHANGE_ASSERT, false>
176     DisallowCodeDependencyChange;
177 
178 // Scope to introduce an exception to DisallowDeferredHandleDereference.
179 typedef PerThreadAssertScope<CODE_DEPENDENCY_CHANGE_ASSERT, true>
180     AllowCodeDependencyChange;
181 
182 } }  // namespace v8::internal
183 
184 #endif  // V8_ASSERT_SCOPE_H_
185