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