1 // Copyright 2014 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 #include "src/assert-scope.h" 6 7 #include "src/base/lazy-instance.h" 8 #include "src/base/platform/platform.h" 9 #include "src/debug/debug.h" 10 #include "src/isolate.h" 11 #include "src/utils.h" 12 13 namespace v8 { 14 namespace internal { 15 16 namespace { 17 18 struct PerThreadAssertKeyConstructTrait final { 19 static void Construct(base::Thread::LocalStorageKey* key) { 20 *key = base::Thread::CreateThreadLocalKey(); 21 } 22 }; 23 24 25 typedef base::LazyStaticInstance<base::Thread::LocalStorageKey, 26 PerThreadAssertKeyConstructTrait>::type 27 PerThreadAssertKey; 28 29 30 PerThreadAssertKey kPerThreadAssertKey; 31 32 } // namespace 33 34 35 class PerThreadAssertData final { 36 public: 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 43 ~PerThreadAssertData() { 44 for (int i = 0; i < LAST_PER_THREAD_ASSERT_TYPE; ++i) { 45 DCHECK(assert_states_[i]); 46 } 47 } 48 49 bool Get(PerThreadAssertType type) const { return assert_states_[type]; } 50 void Set(PerThreadAssertType type, bool x) { assert_states_[type] = x; } 51 52 void IncrementLevel() { ++nesting_level_; } 53 bool DecrementLevel() { return --nesting_level_ == 0; } 54 55 static PerThreadAssertData* GetCurrent() { 56 return reinterpret_cast<PerThreadAssertData*>( 57 base::Thread::GetThreadLocal(kPerThreadAssertKey.Get())); 58 } 59 static void SetCurrent(PerThreadAssertData* data) { 60 base::Thread::SetThreadLocal(kPerThreadAssertKey.Get(), data); 61 } 62 63 private: 64 bool assert_states_[LAST_PER_THREAD_ASSERT_TYPE]; 65 int nesting_level_; 66 67 DISALLOW_COPY_AND_ASSIGN(PerThreadAssertData); 68 }; 69 70 71 template <PerThreadAssertType kType, bool kAllow> 72 PerThreadAssertScope<kType, kAllow>::PerThreadAssertScope() 73 : data_(PerThreadAssertData::GetCurrent()) { 74 if (data_ == NULL) { 75 data_ = new PerThreadAssertData(); 76 PerThreadAssertData::SetCurrent(data_); 77 } 78 data_->IncrementLevel(); 79 old_state_ = data_->Get(kType); 80 data_->Set(kType, kAllow); 81 } 82 83 84 template <PerThreadAssertType kType, bool kAllow> 85 PerThreadAssertScope<kType, kAllow>::~PerThreadAssertScope() { 86 DCHECK_NOT_NULL(data_); 87 data_->Set(kType, old_state_); 88 if (data_->DecrementLevel()) { 89 PerThreadAssertData::SetCurrent(NULL); 90 delete data_; 91 } 92 } 93 94 95 // static 96 template <PerThreadAssertType kType, bool kAllow> 97 bool PerThreadAssertScope<kType, kAllow>::IsAllowed() { 98 PerThreadAssertData* data = PerThreadAssertData::GetCurrent(); 99 return data == NULL || data->Get(kType); 100 } 101 102 103 template <PerIsolateAssertType kType, bool kAllow> 104 class PerIsolateAssertScope<kType, kAllow>::DataBit 105 : public BitField<bool, kType, 1> {}; 106 107 108 template <PerIsolateAssertType kType, bool kAllow> 109 PerIsolateAssertScope<kType, kAllow>::PerIsolateAssertScope(Isolate* isolate) 110 : isolate_(isolate), old_data_(isolate->per_isolate_assert_data()) { 111 DCHECK_NOT_NULL(isolate); 112 STATIC_ASSERT(kType < 32); 113 isolate_->set_per_isolate_assert_data(DataBit::update(old_data_, kAllow)); 114 } 115 116 117 template <PerIsolateAssertType kType, bool kAllow> 118 PerIsolateAssertScope<kType, kAllow>::~PerIsolateAssertScope() { 119 isolate_->set_per_isolate_assert_data(old_data_); 120 } 121 122 123 // static 124 template <PerIsolateAssertType kType, bool kAllow> 125 bool PerIsolateAssertScope<kType, kAllow>::IsAllowed(Isolate* isolate) { 126 return DataBit::decode(isolate->per_isolate_assert_data()); 127 } 128 129 130 // ----------------------------------------------------------------------------- 131 // Instantiations. 132 133 template class PerThreadAssertScope<HEAP_ALLOCATION_ASSERT, false>; 134 template class PerThreadAssertScope<HEAP_ALLOCATION_ASSERT, true>; 135 template class PerThreadAssertScope<HANDLE_ALLOCATION_ASSERT, false>; 136 template class PerThreadAssertScope<HANDLE_ALLOCATION_ASSERT, true>; 137 template class PerThreadAssertScope<HANDLE_DEREFERENCE_ASSERT, false>; 138 template class PerThreadAssertScope<HANDLE_DEREFERENCE_ASSERT, true>; 139 template class PerThreadAssertScope<DEFERRED_HANDLE_DEREFERENCE_ASSERT, false>; 140 template class PerThreadAssertScope<DEFERRED_HANDLE_DEREFERENCE_ASSERT, true>; 141 template class PerThreadAssertScope<CODE_DEPENDENCY_CHANGE_ASSERT, false>; 142 template class PerThreadAssertScope<CODE_DEPENDENCY_CHANGE_ASSERT, true>; 143 144 template class PerIsolateAssertScope<JAVASCRIPT_EXECUTION_ASSERT, false>; 145 template class PerIsolateAssertScope<JAVASCRIPT_EXECUTION_ASSERT, true>; 146 template class PerIsolateAssertScope<JAVASCRIPT_EXECUTION_THROWS, false>; 147 template class PerIsolateAssertScope<JAVASCRIPT_EXECUTION_THROWS, true>; 148 template class PerIsolateAssertScope<DEOPTIMIZATION_ASSERT, false>; 149 template class PerIsolateAssertScope<DEOPTIMIZATION_ASSERT, true>; 150 template class PerIsolateAssertScope<COMPILATION_ASSERT, false>; 151 template class PerIsolateAssertScope<COMPILATION_ASSERT, true>; 152 153 } // namespace internal 154 } // namespace v8 155