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/debug/debug.h"
     10 #include "src/isolate.h"
     11 #include "src/utils.h"
     12 
     13 namespace v8 {
     14 namespace internal {
     15 
     16 namespace {
     17 
     18 struct PerThreadAssertKeyConstructTrait final {
     19   static void Construct(base::Thread::LocalStorageKey* key) {
     20     *key = base::Thread::CreateThreadLocalKey();
     21   }
     22 };
     23 
     24 
     25 typedef base::LazyStaticInstance<base::Thread::LocalStorageKey,
     26                                  PerThreadAssertKeyConstructTrait>::type
     27     PerThreadAssertKey;
     28 
     29 
     30 PerThreadAssertKey kPerThreadAssertKey;
     31 
     32 }  // namespace
     33 
     34 
     35 class PerThreadAssertData final {
     36  public:
     37   PerThreadAssertData() : nesting_level_(0) {
     38     for (int i = 0; i < LAST_PER_THREAD_ASSERT_TYPE; i++) {
     39       assert_states_[i] = true;
     40     }
     41   }
     42 
     43   ~PerThreadAssertData() {
     44     for (int i = 0; i < LAST_PER_THREAD_ASSERT_TYPE; ++i) {
     45       DCHECK(assert_states_[i]);
     46     }
     47   }
     48 
     49   bool Get(PerThreadAssertType type) const { return assert_states_[type]; }
     50   void Set(PerThreadAssertType type, bool x) { assert_states_[type] = x; }
     51 
     52   void IncrementLevel() { ++nesting_level_; }
     53   bool DecrementLevel() { return --nesting_level_ == 0; }
     54 
     55   static PerThreadAssertData* GetCurrent() {
     56     return reinterpret_cast<PerThreadAssertData*>(
     57         base::Thread::GetThreadLocal(kPerThreadAssertKey.Get()));
     58   }
     59   static void SetCurrent(PerThreadAssertData* data) {
     60     base::Thread::SetThreadLocal(kPerThreadAssertKey.Get(), data);
     61   }
     62 
     63  private:
     64   bool assert_states_[LAST_PER_THREAD_ASSERT_TYPE];
     65   int nesting_level_;
     66 
     67   DISALLOW_COPY_AND_ASSIGN(PerThreadAssertData);
     68 };
     69 
     70 
     71 template <PerThreadAssertType kType, bool kAllow>
     72 PerThreadAssertScope<kType, kAllow>::PerThreadAssertScope()
     73     : data_(PerThreadAssertData::GetCurrent()) {
     74   if (data_ == NULL) {
     75     data_ = new PerThreadAssertData();
     76     PerThreadAssertData::SetCurrent(data_);
     77   }
     78   data_->IncrementLevel();
     79   old_state_ = data_->Get(kType);
     80   data_->Set(kType, kAllow);
     81 }
     82 
     83 
     84 template <PerThreadAssertType kType, bool kAllow>
     85 PerThreadAssertScope<kType, kAllow>::~PerThreadAssertScope() {
     86   DCHECK_NOT_NULL(data_);
     87   data_->Set(kType, old_state_);
     88   if (data_->DecrementLevel()) {
     89     PerThreadAssertData::SetCurrent(NULL);
     90     delete data_;
     91   }
     92 }
     93 
     94 
     95 // static
     96 template <PerThreadAssertType kType, bool kAllow>
     97 bool PerThreadAssertScope<kType, kAllow>::IsAllowed() {
     98   PerThreadAssertData* data = PerThreadAssertData::GetCurrent();
     99   return data == NULL || data->Get(kType);
    100 }
    101 
    102 
    103 template <PerIsolateAssertType kType, bool kAllow>
    104 class PerIsolateAssertScope<kType, kAllow>::DataBit
    105     : public BitField<bool, kType, 1> {};
    106 
    107 
    108 template <PerIsolateAssertType kType, bool kAllow>
    109 PerIsolateAssertScope<kType, kAllow>::PerIsolateAssertScope(Isolate* isolate)
    110     : isolate_(isolate), old_data_(isolate->per_isolate_assert_data()) {
    111   DCHECK_NOT_NULL(isolate);
    112   STATIC_ASSERT(kType < 32);
    113   isolate_->set_per_isolate_assert_data(DataBit::update(old_data_, kAllow));
    114 }
    115 
    116 
    117 template <PerIsolateAssertType kType, bool kAllow>
    118 PerIsolateAssertScope<kType, kAllow>::~PerIsolateAssertScope() {
    119   isolate_->set_per_isolate_assert_data(old_data_);
    120 }
    121 
    122 
    123 // static
    124 template <PerIsolateAssertType kType, bool kAllow>
    125 bool PerIsolateAssertScope<kType, kAllow>::IsAllowed(Isolate* isolate) {
    126   return DataBit::decode(isolate->per_isolate_assert_data());
    127 }
    128 
    129 
    130 // -----------------------------------------------------------------------------
    131 // Instantiations.
    132 
    133 template class PerThreadAssertScope<HEAP_ALLOCATION_ASSERT, false>;
    134 template class PerThreadAssertScope<HEAP_ALLOCATION_ASSERT, true>;
    135 template class PerThreadAssertScope<HANDLE_ALLOCATION_ASSERT, false>;
    136 template class PerThreadAssertScope<HANDLE_ALLOCATION_ASSERT, true>;
    137 template class PerThreadAssertScope<HANDLE_DEREFERENCE_ASSERT, false>;
    138 template class PerThreadAssertScope<HANDLE_DEREFERENCE_ASSERT, true>;
    139 template class PerThreadAssertScope<DEFERRED_HANDLE_DEREFERENCE_ASSERT, false>;
    140 template class PerThreadAssertScope<DEFERRED_HANDLE_DEREFERENCE_ASSERT, true>;
    141 template class PerThreadAssertScope<CODE_DEPENDENCY_CHANGE_ASSERT, false>;
    142 template class PerThreadAssertScope<CODE_DEPENDENCY_CHANGE_ASSERT, true>;
    143 
    144 template class PerIsolateAssertScope<JAVASCRIPT_EXECUTION_ASSERT, false>;
    145 template class PerIsolateAssertScope<JAVASCRIPT_EXECUTION_ASSERT, true>;
    146 template class PerIsolateAssertScope<JAVASCRIPT_EXECUTION_THROWS, false>;
    147 template class PerIsolateAssertScope<JAVASCRIPT_EXECUTION_THROWS, true>;
    148 template class PerIsolateAssertScope<DEOPTIMIZATION_ASSERT, false>;
    149 template class PerIsolateAssertScope<DEOPTIMIZATION_ASSERT, true>;
    150 template class PerIsolateAssertScope<COMPILATION_ASSERT, false>;
    151 template class PerIsolateAssertScope<COMPILATION_ASSERT, true>;
    152 
    153 }  // namespace internal
    154 }  // namespace v8
    155