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: 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 58 void set(PerThreadAssertType type, bool allow) { 59 assert_states_[type] = allow; 60 } 61 62 bool get(PerThreadAssertType type) const { 63 return assert_states_[type]; 64 } 65 66 void increment_level() { ++nesting_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: 82 PerThreadAssertScopeBase() { 83 data_ = GetAssertData(); 84 if (data_ == NULL) { 85 data_ = new PerThreadAssertData(); 86 SetThreadLocalData(data_); 87 } 88 data_->increment_level(); 89 } 90 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 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: 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 122 PerThreadAssertScope() { } 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