Home | History | Annotate | Download | only in src
      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/assert-scope.h"
      6 
      7 #include "src/base/lazy-instance.h"
      8 #include "src/base/platform/platform.h"
      9 #include "src/isolate.h"
     10 #include "src/utils.h"
     11 
     12 namespace v8 {
     13 namespace internal {
     14 
     15 namespace {
     16 
     17 struct PerThreadAssertKeyConstructTrait final {
     18   static void Construct(base::Thread::LocalStorageKey* key) {
     19     *key = base::Thread::CreateThreadLocalKey();
     20   }
     21 };
     22 
     23 
     24 typedef base::LazyStaticInstance<base::Thread::LocalStorageKey,
     25                                  PerThreadAssertKeyConstructTrait>::type
     26     PerThreadAssertKey;
     27 
     28 
     29 PerThreadAssertKey kPerThreadAssertKey;
     30 
     31 }  // namespace
     32 
     33 
     34 class 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 
     70 template <PerThreadAssertType kType, bool kAllow>
     71 PerThreadAssertScope<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);
     80 }
     81 
     82 
     83 template <PerThreadAssertType kType, bool kAllow>
     84 PerThreadAssertScope<kType, kAllow>::~PerThreadAssertScope() {
     85   if (data_ == nullptr) return;
     86   Release();
     87 }
     88 
     89 template <PerThreadAssertType kType, bool kAllow>
     90 void PerThreadAssertScope<kType, kAllow>::Release() {
     91   DCHECK_NOT_NULL(data_);
     92   data_->Set(kType, old_state_);
     93   if (data_->DecrementLevel()) {
     94     PerThreadAssertData::SetCurrent(NULL);
     95     delete data_;
     96   }
     97   data_ = nullptr;
     98 }
     99 
    100 // static
    101 template <PerThreadAssertType kType, bool kAllow>
    102 bool PerThreadAssertScope<kType, kAllow>::IsAllowed() {
    103   PerThreadAssertData* data = PerThreadAssertData::GetCurrent();
    104   return data == NULL || data->Get(kType);
    105 }
    106 
    107 
    108 template <PerIsolateAssertType kType, bool kAllow>
    109 class PerIsolateAssertScope<kType, kAllow>::DataBit
    110     : public BitField<bool, kType, 1> {};
    111 
    112 
    113 template <PerIsolateAssertType kType, bool kAllow>
    114 PerIsolateAssertScope<kType, kAllow>::PerIsolateAssertScope(Isolate* isolate)
    115     : isolate_(isolate), old_data_(isolate->per_isolate_assert_data()) {
    116   DCHECK_NOT_NULL(isolate);
    117   STATIC_ASSERT(kType < 32);
    118   isolate_->set_per_isolate_assert_data(DataBit::update(old_data_, kAllow));
    119 }
    120 
    121 
    122 template <PerIsolateAssertType kType, bool kAllow>
    123 PerIsolateAssertScope<kType, kAllow>::~PerIsolateAssertScope() {
    124   isolate_->set_per_isolate_assert_data(old_data_);
    125 }
    126 
    127 
    128 // static
    129 template <PerIsolateAssertType kType, bool kAllow>
    130 bool PerIsolateAssertScope<kType, kAllow>::IsAllowed(Isolate* isolate) {
    131   return DataBit::decode(isolate->per_isolate_assert_data());
    132 }
    133 
    134 
    135 // -----------------------------------------------------------------------------
    136 // Instantiations.
    137 
    138 template class PerThreadAssertScope<HEAP_ALLOCATION_ASSERT, false>;
    139 template class PerThreadAssertScope<HEAP_ALLOCATION_ASSERT, true>;
    140 template class PerThreadAssertScope<HANDLE_ALLOCATION_ASSERT, false>;
    141 template class PerThreadAssertScope<HANDLE_ALLOCATION_ASSERT, true>;
    142 template class PerThreadAssertScope<HANDLE_DEREFERENCE_ASSERT, false>;
    143 template class PerThreadAssertScope<HANDLE_DEREFERENCE_ASSERT, true>;
    144 template class PerThreadAssertScope<DEFERRED_HANDLE_DEREFERENCE_ASSERT, false>;
    145 template class PerThreadAssertScope<DEFERRED_HANDLE_DEREFERENCE_ASSERT, true>;
    146 template class PerThreadAssertScope<CODE_DEPENDENCY_CHANGE_ASSERT, false>;
    147 template class PerThreadAssertScope<CODE_DEPENDENCY_CHANGE_ASSERT, true>;
    148 
    149 template class PerIsolateAssertScope<JAVASCRIPT_EXECUTION_ASSERT, false>;
    150 template class PerIsolateAssertScope<JAVASCRIPT_EXECUTION_ASSERT, true>;
    151 template class PerIsolateAssertScope<JAVASCRIPT_EXECUTION_THROWS, false>;
    152 template class PerIsolateAssertScope<JAVASCRIPT_EXECUTION_THROWS, true>;
    153 template class PerIsolateAssertScope<DEOPTIMIZATION_ASSERT, false>;
    154 template class PerIsolateAssertScope<DEOPTIMIZATION_ASSERT, true>;
    155 template class PerIsolateAssertScope<COMPILATION_ASSERT, false>;
    156 template class PerIsolateAssertScope<COMPILATION_ASSERT, true>;
    157 template class PerIsolateAssertScope<NO_EXCEPTION_ASSERT, false>;
    158 template class PerIsolateAssertScope<NO_EXCEPTION_ASSERT, true>;
    159 
    160 }  // namespace internal
    161 }  // namespace v8
    162