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
13namespace v8 {
14namespace internal {
15
16namespace {
17
18template <PerThreadAssertType kType>
19using PerThreadDataBit = base::BitField<bool, kType, 1>;
20
21// Thread-local storage for assert data. Default all asserts to "allow".
22thread_local uint32_t current_per_thread_assert_data(~0);
23
24}  // namespace
25
26template <PerThreadAssertType kType, bool kAllow>
27PerThreadAssertScope<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
33template <PerThreadAssertType kType, bool kAllow>
34PerThreadAssertScope<kType, kAllow>::~PerThreadAssertScope() {
35  if (!old_data_.has_value()) return;
36  Release();
37}
38
39template <PerThreadAssertType kType, bool kAllow>
40void PerThreadAssertScope<kType, kAllow>::Release() {
41  current_per_thread_assert_data = old_data_.value();
42  old_data_.reset();
43}
44
45// static
46template <PerThreadAssertType kType, bool kAllow>
47bool 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
84PER_ISOLATE_ASSERT_TYPE(PER_ISOLATE_ASSERT_ENABLE_SCOPE_DEFINITION, true)
85PER_ISOLATE_ASSERT_TYPE(PER_ISOLATE_ASSERT_DISABLE_SCOPE_DEFINITION, false)
86
87// -----------------------------------------------------------------------------
88// Instantiations.
89
90template class PerThreadAssertScope<HEAP_ALLOCATION_ASSERT, false>;
91template class PerThreadAssertScope<HEAP_ALLOCATION_ASSERT, true>;
92template class PerThreadAssertScope<SAFEPOINTS_ASSERT, false>;
93template class PerThreadAssertScope<SAFEPOINTS_ASSERT, true>;
94template class PerThreadAssertScope<HANDLE_ALLOCATION_ASSERT, false>;
95template class PerThreadAssertScope<HANDLE_ALLOCATION_ASSERT, true>;
96template class PerThreadAssertScope<HANDLE_DEREFERENCE_ASSERT, false>;
97template class PerThreadAssertScope<HANDLE_DEREFERENCE_ASSERT, true>;
98template class PerThreadAssertScope<CODE_DEPENDENCY_CHANGE_ASSERT, false>;
99template class PerThreadAssertScope<CODE_DEPENDENCY_CHANGE_ASSERT, true>;
100template class PerThreadAssertScope<CODE_ALLOCATION_ASSERT, false>;
101template class PerThreadAssertScope<CODE_ALLOCATION_ASSERT, true>;
102template class PerThreadAssertScope<GC_MOLE, false>;
103
104}  // namespace internal
105}  // namespace v8
106