• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 {
Constructv8::internal::__anon7fcf625b0111::PerThreadAssertKeyConstructTrait18   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:
PerThreadAssertData()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 
~PerThreadAssertData()43   ~PerThreadAssertData() {
44     for (int i = 0; i < LAST_PER_THREAD_ASSERT_TYPE; ++i) {
45       DCHECK(assert_states_[i]);
46     }
47   }
48 
Get(PerThreadAssertType type) const49   bool Get(PerThreadAssertType type) const { return assert_states_[type]; }
Set(PerThreadAssertType type,bool x)50   void Set(PerThreadAssertType type, bool x) { assert_states_[type] = x; }
51 
IncrementLevel()52   void IncrementLevel() { ++nesting_level_; }
DecrementLevel()53   bool DecrementLevel() { return --nesting_level_ == 0; }
54 
GetCurrent()55   static PerThreadAssertData* GetCurrent() {
56     return reinterpret_cast<PerThreadAssertData*>(
57         base::Thread::GetThreadLocal(kPerThreadAssertKey.Get()));
58   }
SetCurrent(PerThreadAssertData * data)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>
PerThreadAssertScope()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>
~PerThreadAssertScope()85 PerThreadAssertScope<kType, kAllow>::~PerThreadAssertScope() {
86   if (data_ == nullptr) return;
87   Release();
88 }
89 
90 template <PerThreadAssertType kType, bool kAllow>
Release()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>
IsAllowed()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>
PerIsolateAssertScope(Isolate * isolate)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>
~PerIsolateAssertScope()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>
IsAllowed(Isolate * isolate)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