assert-scope.cc 5.17 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/assert-scope.h"
6 7 8

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

namespace v8 {
namespace internal {

15 16
namespace {

17
struct PerThreadAssertKeyConstructTrait final {
18 19
  static void Construct(void* key_arg) {
    auto key = reinterpret_cast<base::Thread::LocalStorageKey*>(key_arg);
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
    *key = base::Thread::CreateThreadLocalKey();
  }
};


typedef base::LazyStaticInstance<base::Thread::LocalStorageKey,
                                 PerThreadAssertKeyConstructTrait>::type
    PerThreadAssertKey;


PerThreadAssertKey kPerThreadAssertKey;

}  // namespace


35
class PerThreadAssertData final {
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
 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*>(
        base::Thread::GetThreadLocal(kPerThreadAssertKey.Get()));
  }
  static void SetCurrent(PerThreadAssertData* data) {
    base::Thread::SetThreadLocal(kPerThreadAssertKey.Get(), data);
  }

 private:
  bool assert_states_[LAST_PER_THREAD_ASSERT_TYPE];
  int nesting_level_;

  DISALLOW_COPY_AND_ASSIGN(PerThreadAssertData);
};


template <PerThreadAssertType kType, bool kAllow>
PerThreadAssertScope<kType, kAllow>::PerThreadAssertScope()
    : data_(PerThreadAssertData::GetCurrent()) {
74
  if (data_ == nullptr) {
75 76 77 78 79 80
    data_ = new PerThreadAssertData();
    PerThreadAssertData::SetCurrent(data_);
  }
  data_->IncrementLevel();
  old_state_ = data_->Get(kType);
  data_->Set(kType, kAllow);
81 82 83
}


84 85
template <PerThreadAssertType kType, bool kAllow>
PerThreadAssertScope<kType, kAllow>::~PerThreadAssertScope() {
86 87 88 89 90 91
  if (data_ == nullptr) return;
  Release();
}

template <PerThreadAssertType kType, bool kAllow>
void PerThreadAssertScope<kType, kAllow>::Release() {
92 93 94
  DCHECK_NOT_NULL(data_);
  data_->Set(kType, old_state_);
  if (data_->DecrementLevel()) {
95
    PerThreadAssertData::SetCurrent(nullptr);
96 97
    delete data_;
  }
98
  data_ = nullptr;
99 100
}

101 102 103 104
// static
template <PerThreadAssertType kType, bool kAllow>
bool PerThreadAssertScope<kType, kAllow>::IsAllowed() {
  PerThreadAssertData* data = PerThreadAssertData::GetCurrent();
105
  return data == nullptr || data->Get(kType);
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
}


template <PerIsolateAssertType kType, bool kAllow>
class PerIsolateAssertScope<kType, kAllow>::DataBit
    : public BitField<bool, kType, 1> {};


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);
  isolate_->set_per_isolate_assert_data(DataBit::update(old_data_, kAllow));
}


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) {
  return DataBit::decode(isolate->per_isolate_assert_data());
}


// -----------------------------------------------------------------------------
// 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<DEFERRED_HANDLE_DEREFERENCE_ASSERT, false>;
template class PerThreadAssertScope<DEFERRED_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>;
template class PerIsolateAssertScope<DEOPTIMIZATION_ASSERT, false>;
template class PerIsolateAssertScope<DEOPTIMIZATION_ASSERT, true>;
template class PerIsolateAssertScope<COMPILATION_ASSERT, false>;
template class PerIsolateAssertScope<COMPILATION_ASSERT, true>;
158 159
template class PerIsolateAssertScope<NO_EXCEPTION_ASSERT, false>;
template class PerIsolateAssertScope<NO_EXCEPTION_ASSERT, true>;
160 161 162

}  // namespace internal
}  // namespace v8