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 12namespace v8 { 13namespace internal { 14 15namespace { 16 17struct PerThreadAssertKeyConstructTrait final { 18 static void Construct(base::Thread::LocalStorageKey* key) { 19 *key = base::Thread::CreateThreadLocalKey(); 20 } 21}; 22 23 24typedef base::LazyStaticInstance<base::Thread::LocalStorageKey, 25 PerThreadAssertKeyConstructTrait>::type 26 PerThreadAssertKey; 27 28 29PerThreadAssertKey kPerThreadAssertKey; 30 31} // namespace 32 33 34class 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 70template <PerThreadAssertType kType, bool kAllow> 71PerThreadAssertScope<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 83template <PerThreadAssertType kType, bool kAllow> 84PerThreadAssertScope<kType, kAllow>::~PerThreadAssertScope() { 85 if (data_ == nullptr) return; 86 Release(); 87} 88 89template <PerThreadAssertType kType, bool kAllow> 90void 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 101template <PerThreadAssertType kType, bool kAllow> 102bool PerThreadAssertScope<kType, kAllow>::IsAllowed() { 103 PerThreadAssertData* data = PerThreadAssertData::GetCurrent(); 104 return data == NULL || data->Get(kType); 105} 106 107 108template <PerIsolateAssertType kType, bool kAllow> 109class PerIsolateAssertScope<kType, kAllow>::DataBit 110 : public BitField<bool, kType, 1> {}; 111 112 113template <PerIsolateAssertType kType, bool kAllow> 114PerIsolateAssertScope<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 122template <PerIsolateAssertType kType, bool kAllow> 123PerIsolateAssertScope<kType, kAllow>::~PerIsolateAssertScope() { 124 isolate_->set_per_isolate_assert_data(old_data_); 125} 126 127 128// static 129template <PerIsolateAssertType kType, bool kAllow> 130bool PerIsolateAssertScope<kType, kAllow>::IsAllowed(Isolate* isolate) { 131 return DataBit::decode(isolate->per_isolate_assert_data()); 132} 133 134 135// ----------------------------------------------------------------------------- 136// Instantiations. 137 138template class PerThreadAssertScope<HEAP_ALLOCATION_ASSERT, false>; 139template class PerThreadAssertScope<HEAP_ALLOCATION_ASSERT, true>; 140template class PerThreadAssertScope<HANDLE_ALLOCATION_ASSERT, false>; 141template class PerThreadAssertScope<HANDLE_ALLOCATION_ASSERT, true>; 142template class PerThreadAssertScope<HANDLE_DEREFERENCE_ASSERT, false>; 143template class PerThreadAssertScope<HANDLE_DEREFERENCE_ASSERT, true>; 144template class PerThreadAssertScope<DEFERRED_HANDLE_DEREFERENCE_ASSERT, false>; 145template class PerThreadAssertScope<DEFERRED_HANDLE_DEREFERENCE_ASSERT, true>; 146template class PerThreadAssertScope<CODE_DEPENDENCY_CHANGE_ASSERT, false>; 147template class PerThreadAssertScope<CODE_DEPENDENCY_CHANGE_ASSERT, true>; 148 149template class PerIsolateAssertScope<JAVASCRIPT_EXECUTION_ASSERT, false>; 150template class PerIsolateAssertScope<JAVASCRIPT_EXECUTION_ASSERT, true>; 151template class PerIsolateAssertScope<JAVASCRIPT_EXECUTION_THROWS, false>; 152template class PerIsolateAssertScope<JAVASCRIPT_EXECUTION_THROWS, true>; 153template class PerIsolateAssertScope<DEOPTIMIZATION_ASSERT, false>; 154template class PerIsolateAssertScope<DEOPTIMIZATION_ASSERT, true>; 155template class PerIsolateAssertScope<COMPILATION_ASSERT, false>; 156template class PerIsolateAssertScope<COMPILATION_ASSERT, true>; 157template class PerIsolateAssertScope<NO_EXCEPTION_ASSERT, false>; 158template class PerIsolateAssertScope<NO_EXCEPTION_ASSERT, true>; 159 160} // namespace internal 161} // namespace v8 162