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/isolate.h" 10 #include "src/utils.h" 11 12 namespace v8 { 13 namespace internal { 14 15 namespace { 16 17 struct PerThreadAssertKeyConstructTrait final { 18 static void Construct(void* key_arg) { 19 auto key = reinterpret_cast<base::Thread::LocalStorageKey*>(key_arg); 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_ == nullptr) { 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 if (data_ == nullptr) return; 87 Release(); 88 } 89 90 template <PerThreadAssertType kType, bool kAllow> 91 void PerThreadAssertScope<kType, kAllow>::Release() { 92 DCHECK_NOT_NULL(data_); 93 data_->Set(kType, old_state_); 94 if (data_->DecrementLevel()) { 95 PerThreadAssertData::SetCurrent(nullptr); 96 delete data_; 97 } 98 data_ = nullptr; 99 } 100 101 // static 102 template <PerThreadAssertType kType, bool kAllow> 103 bool PerThreadAssertScope<kType, kAllow>::IsAllowed() { 104 PerThreadAssertData* data = PerThreadAssertData::GetCurrent(); 105 return data == nullptr || data->Get(kType); 106 } 107 108 109 template <PerIsolateAssertType kType, bool kAllow> 110 class PerIsolateAssertScope<kType, kAllow>::DataBit 111 : public BitField<bool, kType, 1> {}; 112 113 114 template <PerIsolateAssertType kType, bool kAllow> 115 PerIsolateAssertScope<kType, kAllow>::PerIsolateAssertScope(Isolate* isolate) 116 : isolate_(isolate), old_data_(isolate->per_isolate_assert_data()) { 117 DCHECK_NOT_NULL(isolate); 118 STATIC_ASSERT(kType < 32); 119 isolate_->set_per_isolate_assert_data(DataBit::update(old_data_, kAllow)); 120 } 121 122 123 template <PerIsolateAssertType kType, bool kAllow> 124 PerIsolateAssertScope<kType, kAllow>::~PerIsolateAssertScope() { 125 isolate_->set_per_isolate_assert_data(old_data_); 126 } 127 128 129 // static 130 template <PerIsolateAssertType kType, bool kAllow> 131 bool PerIsolateAssertScope<kType, kAllow>::IsAllowed(Isolate* isolate) { 132 return DataBit::decode(isolate->per_isolate_assert_data()); 133 } 134 135 136 // ----------------------------------------------------------------------------- 137 // Instantiations. 138 139 template class PerThreadAssertScope<HEAP_ALLOCATION_ASSERT, false>; 140 template class PerThreadAssertScope<HEAP_ALLOCATION_ASSERT, true>; 141 template class PerThreadAssertScope<HANDLE_ALLOCATION_ASSERT, false>; 142 template class PerThreadAssertScope<HANDLE_ALLOCATION_ASSERT, true>; 143 template class PerThreadAssertScope<HANDLE_DEREFERENCE_ASSERT, false>; 144 template class PerThreadAssertScope<HANDLE_DEREFERENCE_ASSERT, true>; 145 template class PerThreadAssertScope<DEFERRED_HANDLE_DEREFERENCE_ASSERT, false>; 146 template class PerThreadAssertScope<DEFERRED_HANDLE_DEREFERENCE_ASSERT, true>; 147 template class PerThreadAssertScope<CODE_DEPENDENCY_CHANGE_ASSERT, false>; 148 template class PerThreadAssertScope<CODE_DEPENDENCY_CHANGE_ASSERT, true>; 149 150 template class PerIsolateAssertScope<JAVASCRIPT_EXECUTION_ASSERT, false>; 151 template class PerIsolateAssertScope<JAVASCRIPT_EXECUTION_ASSERT, true>; 152 template class PerIsolateAssertScope<JAVASCRIPT_EXECUTION_THROWS, false>; 153 template class PerIsolateAssertScope<JAVASCRIPT_EXECUTION_THROWS, true>; 154 template class PerIsolateAssertScope<DEOPTIMIZATION_ASSERT, false>; 155 template class PerIsolateAssertScope<DEOPTIMIZATION_ASSERT, true>; 156 template class PerIsolateAssertScope<COMPILATION_ASSERT, false>; 157 template class PerIsolateAssertScope<COMPILATION_ASSERT, true>; 158 template class PerIsolateAssertScope<NO_EXCEPTION_ASSERT, false>; 159 template class PerIsolateAssertScope<NO_EXCEPTION_ASSERT, true>; 160 161 } // namespace internal 162 } // namespace v8 163