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