assert-scope.cc 5.09 KB
Newer Older
1 2 3 4
// Copyright 2014 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5
#include "src/common/assert-scope.h"
6 7 8

#include "src/base/lazy-instance.h"
#include "src/base/platform/platform.h"
9
#include "src/execution/isolate.h"
10
#include "src/utils/utils.h"
11 12 13 14

namespace v8 {
namespace internal {

15 16
namespace {

17 18
DEFINE_LAZY_LEAKY_OBJECT_GETTER(base::Thread::LocalStorageKey,
                                GetPerThreadAssertKey,
19
                                base::Thread::CreateThreadLocalKey())
20 21 22

}  // namespace

23
class PerThreadAssertData final {
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
 public:
  PerThreadAssertData() : nesting_level_(0) {
    for (int i = 0; i < LAST_PER_THREAD_ASSERT_TYPE; i++) {
      assert_states_[i] = true;
    }
  }

  ~PerThreadAssertData() {
    for (int i = 0; i < LAST_PER_THREAD_ASSERT_TYPE; ++i) {
      DCHECK(assert_states_[i]);
    }
  }

  bool Get(PerThreadAssertType type) const { return assert_states_[type]; }
  void Set(PerThreadAssertType type, bool x) { assert_states_[type] = x; }

  void IncrementLevel() { ++nesting_level_; }
  bool DecrementLevel() { return --nesting_level_ == 0; }

  static PerThreadAssertData* GetCurrent() {
    return reinterpret_cast<PerThreadAssertData*>(
45
        base::Thread::GetThreadLocal(*GetPerThreadAssertKey()));
46 47
  }
  static void SetCurrent(PerThreadAssertData* data) {
48
    base::Thread::SetThreadLocal(*GetPerThreadAssertKey(), data);
49 50 51 52 53 54 55 56 57 58
  }

 private:
  bool assert_states_[LAST_PER_THREAD_ASSERT_TYPE];
  int nesting_level_;

  DISALLOW_COPY_AND_ASSIGN(PerThreadAssertData);
};

template <PerThreadAssertType kType, bool kAllow>
59 60 61 62 63
PerThreadAssertScope<kType, kAllow>::PerThreadAssertScope() {
  PerThreadAssertData* current_data = PerThreadAssertData::GetCurrent();
  if (current_data == nullptr) {
    current_data = new PerThreadAssertData();
    PerThreadAssertData::SetCurrent(current_data);
64
  }
65 66 67
  data_and_old_state_.update(current_data, current_data->Get(kType));
  current_data->IncrementLevel();
  current_data->Set(kType, kAllow);
68 69
}

70 71
template <PerThreadAssertType kType, bool kAllow>
PerThreadAssertScope<kType, kAllow>::~PerThreadAssertScope() {
72
  if (data() == nullptr) return;
73 74 75 76 77
  Release();
}

template <PerThreadAssertType kType, bool kAllow>
void PerThreadAssertScope<kType, kAllow>::Release() {
78 79 80 81
  auto* current_data = data();
  DCHECK_NOT_NULL(current_data);
  current_data->Set(kType, old_state());
  if (current_data->DecrementLevel()) {
82
    PerThreadAssertData::SetCurrent(nullptr);
83
    delete current_data;
84
  }
85
  set_data(nullptr);
86 87
}

88 89 90
// static
template <PerThreadAssertType kType, bool kAllow>
bool PerThreadAssertScope<kType, kAllow>::IsAllowed() {
91 92
  PerThreadAssertData* current_data = PerThreadAssertData::GetCurrent();
  return current_data == nullptr || current_data->Get(kType);
93 94
}

95 96
namespace {
template <PerIsolateAssertType kType>
97
using DataBit = base::BitField<bool, kType, 1>;
98
}
99 100 101 102 103 104

template <PerIsolateAssertType kType, bool kAllow>
PerIsolateAssertScope<kType, kAllow>::PerIsolateAssertScope(Isolate* isolate)
    : isolate_(isolate), old_data_(isolate->per_isolate_assert_data()) {
  DCHECK_NOT_NULL(isolate);
  STATIC_ASSERT(kType < 32);
105 106
  isolate_->set_per_isolate_assert_data(
      DataBit<kType>::update(old_data_, kAllow));
107 108 109 110 111 112 113 114 115 116
}

template <PerIsolateAssertType kType, bool kAllow>
PerIsolateAssertScope<kType, kAllow>::~PerIsolateAssertScope() {
  isolate_->set_per_isolate_assert_data(old_data_);
}

// static
template <PerIsolateAssertType kType, bool kAllow>
bool PerIsolateAssertScope<kType, kAllow>::IsAllowed(Isolate* isolate) {
117
  return DataBit<kType>::decode(isolate->per_isolate_assert_data());
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
}

// -----------------------------------------------------------------------------
// Instantiations.

template class PerThreadAssertScope<HEAP_ALLOCATION_ASSERT, false>;
template class PerThreadAssertScope<HEAP_ALLOCATION_ASSERT, true>;
template class PerThreadAssertScope<HANDLE_ALLOCATION_ASSERT, false>;
template class PerThreadAssertScope<HANDLE_ALLOCATION_ASSERT, true>;
template class PerThreadAssertScope<HANDLE_DEREFERENCE_ASSERT, false>;
template class PerThreadAssertScope<HANDLE_DEREFERENCE_ASSERT, true>;
template class PerThreadAssertScope<CODE_DEPENDENCY_CHANGE_ASSERT, false>;
template class PerThreadAssertScope<CODE_DEPENDENCY_CHANGE_ASSERT, true>;

template class PerIsolateAssertScope<JAVASCRIPT_EXECUTION_ASSERT, false>;
template class PerIsolateAssertScope<JAVASCRIPT_EXECUTION_ASSERT, true>;
template class PerIsolateAssertScope<JAVASCRIPT_EXECUTION_THROWS, false>;
template class PerIsolateAssertScope<JAVASCRIPT_EXECUTION_THROWS, true>;
136 137
template class PerIsolateAssertScope<JAVASCRIPT_EXECUTION_DUMP, false>;
template class PerIsolateAssertScope<JAVASCRIPT_EXECUTION_DUMP, true>;
138 139 140 141
template class PerIsolateAssertScope<DEOPTIMIZATION_ASSERT, false>;
template class PerIsolateAssertScope<DEOPTIMIZATION_ASSERT, true>;
template class PerIsolateAssertScope<COMPILATION_ASSERT, false>;
template class PerIsolateAssertScope<COMPILATION_ASSERT, true>;
142 143
template class PerIsolateAssertScope<NO_EXCEPTION_ASSERT, false>;
template class PerIsolateAssertScope<NO_EXCEPTION_ASSERT, true>;
144 145 146

}  // namespace internal
}  // namespace v8