Line data Source code
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(void* key_arg) {
19 : auto key = reinterpret_cast<base::Thread::LocalStorageKey*>(key_arg);
20 0 : *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:
37 0 : PerThreadAssertData() : nesting_level_(0) {
38 0 : for (int i = 0; i < LAST_PER_THREAD_ASSERT_TYPE; i++) {
39 0 : assert_states_[i] = true;
40 : }
41 : }
42 :
43 : ~PerThreadAssertData() {
44 : for (int i = 0; i < LAST_PER_THREAD_ASSERT_TYPE; ++i) {
45 : DCHECK(assert_states_[i]);
46 : }
47 : }
48 :
49 0 : bool Get(PerThreadAssertType type) const { return assert_states_[type]; }
50 0 : void Set(PerThreadAssertType type, bool x) { assert_states_[type] = x; }
51 :
52 0 : void IncrementLevel() { ++nesting_level_; }
53 0 : bool DecrementLevel() { return --nesting_level_ == 0; }
54 :
55 0 : static PerThreadAssertData* GetCurrent() {
56 : return reinterpret_cast<PerThreadAssertData*>(
57 0 : base::Thread::GetThreadLocal(kPerThreadAssertKey.Get()));
58 : }
59 0 : static void SetCurrent(PerThreadAssertData* data) {
60 0 : base::Thread::SetThreadLocal(kPerThreadAssertKey.Get(), data);
61 0 : }
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>
72 0 : PerThreadAssertScope<kType, kAllow>::PerThreadAssertScope()
73 0 : : data_(PerThreadAssertData::GetCurrent()) {
74 0 : if (data_ == nullptr) {
75 0 : data_ = new PerThreadAssertData();
76 0 : PerThreadAssertData::SetCurrent(data_);
77 : }
78 0 : data_->IncrementLevel();
79 0 : old_state_ = data_->Get(kType);
80 : data_->Set(kType, kAllow);
81 0 : }
82 :
83 :
84 : template <PerThreadAssertType kType, bool kAllow>
85 0 : PerThreadAssertScope<kType, kAllow>::~PerThreadAssertScope() {
86 0 : if (data_ == nullptr) return;
87 0 : Release();
88 0 : }
89 :
90 : template <PerThreadAssertType kType, bool kAllow>
91 0 : void PerThreadAssertScope<kType, kAllow>::Release() {
92 : DCHECK_NOT_NULL(data_);
93 0 : data_->Set(kType, old_state_);
94 0 : if (data_->DecrementLevel()) {
95 0 : PerThreadAssertData::SetCurrent(nullptr);
96 0 : delete data_;
97 : }
98 0 : data_ = nullptr;
99 0 : }
100 :
101 : // static
102 : template <PerThreadAssertType kType, bool kAllow>
103 0 : bool PerThreadAssertScope<kType, kAllow>::IsAllowed() {
104 0 : PerThreadAssertData* data = PerThreadAssertData::GetCurrent();
105 0 : 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>
115 26807498 : PerIsolateAssertScope<kType, kAllow>::PerIsolateAssertScope(Isolate* isolate)
116 26807498 : : 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 13403749 : }
121 :
122 :
123 : template <PerIsolateAssertType kType, bool kAllow>
124 13403752 : PerIsolateAssertScope<kType, kAllow>::~PerIsolateAssertScope() {
125 13403752 : isolate_->set_per_isolate_assert_data(old_data_);
126 13403752 : }
127 :
128 :
129 : // static
130 : template <PerIsolateAssertType kType, bool kAllow>
131 46085148 : bool PerIsolateAssertScope<kType, kAllow>::IsAllowed(Isolate* isolate) {
132 46085148 : 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
|