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 0 : 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 0 : PerThreadAssertData() : nesting_level_(0) {
27 0 : for (int i = 0; i < LAST_PER_THREAD_ASSERT_TYPE; i++) {
28 0 : assert_states_[i] = true;
29 : }
30 : }
31 :
32 0 : ~PerThreadAssertData() {
33 : for (int i = 0; i < LAST_PER_THREAD_ASSERT_TYPE; ++i) {
34 : DCHECK(assert_states_[i]);
35 : }
36 : }
37 :
38 0 : bool Get(PerThreadAssertType type) const { return assert_states_[type]; }
39 0 : void Set(PerThreadAssertType type, bool x) { assert_states_[type] = x; }
40 :
41 0 : void IncrementLevel() { ++nesting_level_; }
42 0 : bool DecrementLevel() { return --nesting_level_ == 0; }
43 :
44 : static PerThreadAssertData* GetCurrent() {
45 : return reinterpret_cast<PerThreadAssertData*>(
46 0 : base::Thread::GetThreadLocal(*GetPerThreadAssertKey()));
47 : }
48 : static void SetCurrent(PerThreadAssertData* data) {
49 0 : 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 0 : PerThreadAssertScope<kType, kAllow>::PerThreadAssertScope() {
61 : PerThreadAssertData* current_data = PerThreadAssertData::GetCurrent();
62 0 : if (current_data == nullptr) {
63 0 : 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 0 : }
70 :
71 : template <PerThreadAssertType kType, bool kAllow>
72 0 : PerThreadAssertScope<kType, kAllow>::~PerThreadAssertScope() {
73 0 : if (data() == nullptr) return;
74 0 : Release();
75 0 : }
76 :
77 : template <PerThreadAssertType kType, bool kAllow>
78 0 : void PerThreadAssertScope<kType, kAllow>::Release() {
79 : auto* current_data = data();
80 : DCHECK_NOT_NULL(current_data);
81 : current_data->Set(kType, old_state());
82 0 : if (current_data->DecrementLevel()) {
83 : PerThreadAssertData::SetCurrent(nullptr);
84 0 : delete current_data;
85 : }
86 : set_data(nullptr);
87 0 : }
88 :
89 : // static
90 : template <PerThreadAssertType kType, bool kAllow>
91 0 : bool PerThreadAssertScope<kType, kAllow>::IsAllowed() {
92 : PerThreadAssertData* current_data = PerThreadAssertData::GetCurrent();
93 0 : 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 14053147 : PerIsolateAssertScope<kType, kAllow>::PerIsolateAssertScope(Isolate* isolate)
103 14053147 : : 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 14053147 : }
108 :
109 :
110 : template <PerIsolateAssertType kType, bool kAllow>
111 14053177 : PerIsolateAssertScope<kType, kAllow>::~PerIsolateAssertScope() {
112 14053177 : isolate_->set_per_isolate_assert_data(old_data_);
113 14053177 : }
114 :
115 :
116 : // static
117 : template <PerIsolateAssertType kType, bool kAllow>
118 53967143 : bool PerIsolateAssertScope<kType, kAllow>::IsAllowed(Isolate* isolate) {
119 53967143 : 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 121996 : } // namespace v8
|