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/common/assert-scope.h"
6
7 #include "src/base/bit-field.h"
8 #include "src/base/lazy-instance.h"
9 #include "src/base/platform/platform.h"
10 #include "src/execution/isolate.h"
11 #include "src/utils/utils.h"
12
13 namespace v8 {
14 namespace internal {
15
16 namespace {
17
18 template <PerThreadAssertType kType>
19 using PerThreadDataBit = base::BitField<bool, kType, 1>;
20
21 // Thread-local storage for assert data. Default all asserts to "allow".
22 thread_local uint32_t current_per_thread_assert_data(~0);
23
24 } // namespace
25
26 template <PerThreadAssertType kType, bool kAllow>
PerThreadAssertScope()27 PerThreadAssertScope<kType, kAllow>::PerThreadAssertScope()
28 : old_data_(current_per_thread_assert_data) {
29 current_per_thread_assert_data =
30 PerThreadDataBit<kType>::update(old_data_.value(), kAllow);
31 }
32
33 template <PerThreadAssertType kType, bool kAllow>
~PerThreadAssertScope()34 PerThreadAssertScope<kType, kAllow>::~PerThreadAssertScope() {
35 if (!old_data_.has_value()) return;
36 Release();
37 }
38
39 template <PerThreadAssertType kType, bool kAllow>
Release()40 void PerThreadAssertScope<kType, kAllow>::Release() {
41 current_per_thread_assert_data = old_data_.value();
42 old_data_.reset();
43 }
44
45 // static
46 template <PerThreadAssertType kType, bool kAllow>
IsAllowed()47 bool PerThreadAssertScope<kType, kAllow>::IsAllowed() {
48 return PerThreadDataBit<kType>::decode(current_per_thread_assert_data);
49 }
50
51 #define PER_ISOLATE_ASSERT_SCOPE_DEFINITION(ScopeType, field, enable) \
52 ScopeType::ScopeType(Isolate* isolate) \
53 : isolate_(isolate), old_data_(isolate->field()) { \
54 DCHECK_NOT_NULL(isolate); \
55 isolate_->set_##field(enable); \
56 } \
57 \
58 ScopeType::~ScopeType() { isolate_->set_##field(old_data_); } \
59 \
60 /* static */ \
61 bool ScopeType::IsAllowed(Isolate* isolate) { return isolate->field(); } \
62 \
63 /* static */ \
64 void ScopeType::Open(Isolate* isolate, bool* was_execution_allowed) { \
65 DCHECK_NOT_NULL(isolate); \
66 DCHECK_NOT_NULL(was_execution_allowed); \
67 *was_execution_allowed = isolate->field(); \
68 isolate->set_##field(enable); \
69 } \
70 /* static */ \
71 void ScopeType::Close(Isolate* isolate, bool was_execution_allowed) { \
72 DCHECK_NOT_NULL(isolate); \
73 isolate->set_##field(was_execution_allowed); \
74 }
75
76 #define PER_ISOLATE_ASSERT_ENABLE_SCOPE_DEFINITION(EnableType, _, field, \
77 enable) \
78 PER_ISOLATE_ASSERT_SCOPE_DEFINITION(EnableType, field, enable)
79
80 #define PER_ISOLATE_ASSERT_DISABLE_SCOPE_DEFINITION(_, DisableType, field, \
81 enable) \
82 PER_ISOLATE_ASSERT_SCOPE_DEFINITION(DisableType, field, enable)
83
84 PER_ISOLATE_ASSERT_TYPE(PER_ISOLATE_ASSERT_ENABLE_SCOPE_DEFINITION, true)
85 PER_ISOLATE_ASSERT_TYPE(PER_ISOLATE_ASSERT_DISABLE_SCOPE_DEFINITION, false)
86
87 // -----------------------------------------------------------------------------
88 // Instantiations.
89
90 template class PerThreadAssertScope<HEAP_ALLOCATION_ASSERT, false>;
91 template class PerThreadAssertScope<HEAP_ALLOCATION_ASSERT, true>;
92 template class PerThreadAssertScope<SAFEPOINTS_ASSERT, false>;
93 template class PerThreadAssertScope<SAFEPOINTS_ASSERT, true>;
94 template class PerThreadAssertScope<HANDLE_ALLOCATION_ASSERT, false>;
95 template class PerThreadAssertScope<HANDLE_ALLOCATION_ASSERT, true>;
96 template class PerThreadAssertScope<HANDLE_DEREFERENCE_ASSERT, false>;
97 template class PerThreadAssertScope<HANDLE_DEREFERENCE_ASSERT, true>;
98 template class PerThreadAssertScope<CODE_DEPENDENCY_CHANGE_ASSERT, false>;
99 template class PerThreadAssertScope<CODE_DEPENDENCY_CHANGE_ASSERT, true>;
100 template class PerThreadAssertScope<CODE_ALLOCATION_ASSERT, false>;
101 template class PerThreadAssertScope<CODE_ALLOCATION_ASSERT, true>;
102 template class PerThreadAssertScope<GC_MOLE, false>;
103
104 } // namespace internal
105 } // namespace v8
106