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