blob: 4c10fddb91243a7fbf4d8cfc371ca2e88a28dba4 [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"
9#include "src/isolate-inl.h"
10#include "src/utils.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000011
12namespace v8 {
13namespace internal {
14
Emily Bernierd0a1eb72015-03-24 16:35:39 -040015namespace {
16
17struct PerThreadAssertKeyConstructTrait FINAL {
18 static void Construct(base::Thread::LocalStorageKey* key) {
19 *key = base::Thread::CreateThreadLocalKey();
20 }
21};
22
23
24typedef base::LazyStaticInstance<base::Thread::LocalStorageKey,
25 PerThreadAssertKeyConstructTrait>::type
26 PerThreadAssertKey;
27
28
29PerThreadAssertKey kPerThreadAssertKey;
30
31} // namespace
32
33
34class PerThreadAssertData FINAL {
35 public:
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
42 ~PerThreadAssertData() {
43 for (int i = 0; i < LAST_PER_THREAD_ASSERT_TYPE; ++i) {
44 DCHECK(assert_states_[i]);
45 }
46 }
47
48 bool Get(PerThreadAssertType type) const { return assert_states_[type]; }
49 void Set(PerThreadAssertType type, bool x) { assert_states_[type] = x; }
50
51 void IncrementLevel() { ++nesting_level_; }
52 bool DecrementLevel() { return --nesting_level_ == 0; }
53
54 static PerThreadAssertData* GetCurrent() {
55 return reinterpret_cast<PerThreadAssertData*>(
56 base::Thread::GetThreadLocal(kPerThreadAssertKey.Get()));
57 }
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
70template <PerThreadAssertType kType, bool kAllow>
71PerThreadAssertScope<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);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000080}
81
82
Emily Bernierd0a1eb72015-03-24 16:35:39 -040083template <PerThreadAssertType kType, bool kAllow>
84PerThreadAssertScope<kType, kAllow>::~PerThreadAssertScope() {
85 DCHECK_NOT_NULL(data_);
86 data_->Set(kType, old_state_);
87 if (data_->DecrementLevel()) {
88 PerThreadAssertData::SetCurrent(NULL);
89 delete data_;
90 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000091}
92
Emily Bernierd0a1eb72015-03-24 16:35:39 -040093
94// static
95template <PerThreadAssertType kType, bool kAllow>
96bool PerThreadAssertScope<kType, kAllow>::IsAllowed() {
97 PerThreadAssertData* data = PerThreadAssertData::GetCurrent();
98 return data == NULL || data->Get(kType);
99}
100
101
102template <PerIsolateAssertType kType, bool kAllow>
103class PerIsolateAssertScope<kType, kAllow>::DataBit
104 : public BitField<bool, kType, 1> {};
105
106
107template <PerIsolateAssertType kType, bool kAllow>
108PerIsolateAssertScope<kType, kAllow>::PerIsolateAssertScope(Isolate* isolate)
109 : isolate_(isolate), old_data_(isolate->per_isolate_assert_data()) {
110 DCHECK_NOT_NULL(isolate);
111 STATIC_ASSERT(kType < 32);
112 isolate_->set_per_isolate_assert_data(DataBit::update(old_data_, kAllow));
113}
114
115
116template <PerIsolateAssertType kType, bool kAllow>
117PerIsolateAssertScope<kType, kAllow>::~PerIsolateAssertScope() {
118 isolate_->set_per_isolate_assert_data(old_data_);
119}
120
121
122// static
123template <PerIsolateAssertType kType, bool kAllow>
124bool PerIsolateAssertScope<kType, kAllow>::IsAllowed(Isolate* isolate) {
125 return DataBit::decode(isolate->per_isolate_assert_data());
126}
127
128
129// -----------------------------------------------------------------------------
130// Instantiations.
131
132template class PerThreadAssertScope<HEAP_ALLOCATION_ASSERT, false>;
133template class PerThreadAssertScope<HEAP_ALLOCATION_ASSERT, true>;
134template class PerThreadAssertScope<HANDLE_ALLOCATION_ASSERT, false>;
135template class PerThreadAssertScope<HANDLE_ALLOCATION_ASSERT, true>;
136template class PerThreadAssertScope<HANDLE_DEREFERENCE_ASSERT, false>;
137template class PerThreadAssertScope<HANDLE_DEREFERENCE_ASSERT, true>;
138template class PerThreadAssertScope<DEFERRED_HANDLE_DEREFERENCE_ASSERT, false>;
139template class PerThreadAssertScope<DEFERRED_HANDLE_DEREFERENCE_ASSERT, true>;
140template class PerThreadAssertScope<CODE_DEPENDENCY_CHANGE_ASSERT, false>;
141template class PerThreadAssertScope<CODE_DEPENDENCY_CHANGE_ASSERT, true>;
142
143template class PerIsolateAssertScope<JAVASCRIPT_EXECUTION_ASSERT, false>;
144template class PerIsolateAssertScope<JAVASCRIPT_EXECUTION_ASSERT, true>;
145template class PerIsolateAssertScope<JAVASCRIPT_EXECUTION_THROWS, false>;
146template class PerIsolateAssertScope<JAVASCRIPT_EXECUTION_THROWS, true>;
147template class PerIsolateAssertScope<ALLOCATION_FAILURE_ASSERT, false>;
148template class PerIsolateAssertScope<ALLOCATION_FAILURE_ASSERT, true>;
149template class PerIsolateAssertScope<DEOPTIMIZATION_ASSERT, false>;
150template class PerIsolateAssertScope<DEOPTIMIZATION_ASSERT, true>;
151template class PerIsolateAssertScope<COMPILATION_ASSERT, false>;
152template class PerIsolateAssertScope<COMPILATION_ASSERT, true>;
153
154} // namespace internal
155} // namespace v8