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