blob: 38527099667acc827a55f164af22ffda4d685307 [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// 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
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005#include "src/assert-scope.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -04006
7#include "src/base/lazy-instance.h"
8#include "src/base/platform/platform.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009#include "src/debug/debug.h"
10#include "src/isolate.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040011#include "src/utils.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000012
13namespace v8 {
14namespace internal {
15
Emily Bernierd0a1eb72015-03-24 16:35:39 -040016namespace {
17
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000018struct PerThreadAssertKeyConstructTrait final {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040019 static void Construct(base::Thread::LocalStorageKey* key) {
20 *key = base::Thread::CreateThreadLocalKey();
21 }
22};
23
24
25typedef base::LazyStaticInstance<base::Thread::LocalStorageKey,
26 PerThreadAssertKeyConstructTrait>::type
27 PerThreadAssertKey;
28
29
30PerThreadAssertKey kPerThreadAssertKey;
31
32} // namespace
33
34
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000035class PerThreadAssertData final {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040036 public:
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
43 ~PerThreadAssertData() {
44 for (int i = 0; i < LAST_PER_THREAD_ASSERT_TYPE; ++i) {
45 DCHECK(assert_states_[i]);
46 }
47 }
48
49 bool Get(PerThreadAssertType type) const { return assert_states_[type]; }
50 void Set(PerThreadAssertType type, bool x) { assert_states_[type] = x; }
51
52 void IncrementLevel() { ++nesting_level_; }
53 bool DecrementLevel() { return --nesting_level_ == 0; }
54
55 static PerThreadAssertData* GetCurrent() {
56 return reinterpret_cast<PerThreadAssertData*>(
57 base::Thread::GetThreadLocal(kPerThreadAssertKey.Get()));
58 }
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
71template <PerThreadAssertType kType, bool kAllow>
72PerThreadAssertScope<kType, kAllow>::PerThreadAssertScope()
73 : data_(PerThreadAssertData::GetCurrent()) {
74 if (data_ == NULL) {
75 data_ = new PerThreadAssertData();
76 PerThreadAssertData::SetCurrent(data_);
77 }
78 data_->IncrementLevel();
79 old_state_ = data_->Get(kType);
80 data_->Set(kType, kAllow);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000081}
82
83
Emily Bernierd0a1eb72015-03-24 16:35:39 -040084template <PerThreadAssertType kType, bool kAllow>
85PerThreadAssertScope<kType, kAllow>::~PerThreadAssertScope() {
86 DCHECK_NOT_NULL(data_);
87 data_->Set(kType, old_state_);
88 if (data_->DecrementLevel()) {
89 PerThreadAssertData::SetCurrent(NULL);
90 delete data_;
91 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000092}
93
Emily Bernierd0a1eb72015-03-24 16:35:39 -040094
95// static
96template <PerThreadAssertType kType, bool kAllow>
97bool PerThreadAssertScope<kType, kAllow>::IsAllowed() {
98 PerThreadAssertData* data = PerThreadAssertData::GetCurrent();
99 return data == NULL || data->Get(kType);
100}
101
102
103template <PerIsolateAssertType kType, bool kAllow>
104class PerIsolateAssertScope<kType, kAllow>::DataBit
105 : public BitField<bool, kType, 1> {};
106
107
108template <PerIsolateAssertType kType, bool kAllow>
109PerIsolateAssertScope<kType, kAllow>::PerIsolateAssertScope(Isolate* isolate)
110 : isolate_(isolate), old_data_(isolate->per_isolate_assert_data()) {
111 DCHECK_NOT_NULL(isolate);
112 STATIC_ASSERT(kType < 32);
113 isolate_->set_per_isolate_assert_data(DataBit::update(old_data_, kAllow));
114}
115
116
117template <PerIsolateAssertType kType, bool kAllow>
118PerIsolateAssertScope<kType, kAllow>::~PerIsolateAssertScope() {
119 isolate_->set_per_isolate_assert_data(old_data_);
120}
121
122
123// static
124template <PerIsolateAssertType kType, bool kAllow>
125bool PerIsolateAssertScope<kType, kAllow>::IsAllowed(Isolate* isolate) {
126 return DataBit::decode(isolate->per_isolate_assert_data());
127}
128
129
130// -----------------------------------------------------------------------------
131// Instantiations.
132
133template class PerThreadAssertScope<HEAP_ALLOCATION_ASSERT, false>;
134template class PerThreadAssertScope<HEAP_ALLOCATION_ASSERT, true>;
135template class PerThreadAssertScope<HANDLE_ALLOCATION_ASSERT, false>;
136template class PerThreadAssertScope<HANDLE_ALLOCATION_ASSERT, true>;
137template class PerThreadAssertScope<HANDLE_DEREFERENCE_ASSERT, false>;
138template class PerThreadAssertScope<HANDLE_DEREFERENCE_ASSERT, true>;
139template class PerThreadAssertScope<DEFERRED_HANDLE_DEREFERENCE_ASSERT, false>;
140template class PerThreadAssertScope<DEFERRED_HANDLE_DEREFERENCE_ASSERT, true>;
141template class PerThreadAssertScope<CODE_DEPENDENCY_CHANGE_ASSERT, false>;
142template class PerThreadAssertScope<CODE_DEPENDENCY_CHANGE_ASSERT, true>;
143
144template class PerIsolateAssertScope<JAVASCRIPT_EXECUTION_ASSERT, false>;
145template class PerIsolateAssertScope<JAVASCRIPT_EXECUTION_ASSERT, true>;
146template class PerIsolateAssertScope<JAVASCRIPT_EXECUTION_THROWS, false>;
147template class PerIsolateAssertScope<JAVASCRIPT_EXECUTION_THROWS, true>;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400148template class PerIsolateAssertScope<DEOPTIMIZATION_ASSERT, false>;
149template class PerIsolateAssertScope<DEOPTIMIZATION_ASSERT, true>;
150template class PerIsolateAssertScope<COMPILATION_ASSERT, false>;
151template class PerIsolateAssertScope<COMPILATION_ASSERT, true>;
152
153} // namespace internal
154} // namespace v8