Home | History | Annotate | Download | only in src
      1 // Copyright 2013 the V8 project authors. All rights reserved.
      2 // Redistribution and use in source and binary forms, with or without
      3 // modification, are permitted provided that the following conditions are
      4 // met:
      5 //
      6 //     * Redistributions of source code must retain the above copyright
      7 //       notice, this list of conditions and the following disclaimer.
      8 //     * Redistributions in binary form must reproduce the above
      9 //       copyright notice, this list of conditions and the following
     10 //       disclaimer in the documentation and/or other materials provided
     11 //       with the distribution.
     12 //     * Neither the name of Google Inc. nor the names of its
     13 //       contributors may be used to endorse or promote products derived
     14 //       from this software without specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 
     28 #ifndef V8_ASSERT_SCOPE_H_
     29 #define V8_ASSERT_SCOPE_H_
     30 
     31 #include "allocation.h"
     32 #include "platform.h"
     33 
     34 namespace v8 {
     35 namespace internal {
     36 
     37 class Isolate;
     38 
     39 enum PerThreadAssertType {
     40   HEAP_ALLOCATION_ASSERT,
     41   HANDLE_ALLOCATION_ASSERT,
     42   HANDLE_DEREFERENCE_ASSERT,
     43   DEFERRED_HANDLE_DEREFERENCE_ASSERT,
     44   CODE_DEPENDENCY_CHANGE_ASSERT,
     45   LAST_PER_THREAD_ASSERT_TYPE
     46 };
     47 
     48 
     49 #ifdef DEBUG
     50 class PerThreadAssertData {
     51  public:
     52   PerThreadAssertData() : nesting_level_(0) {
     53     for (int i = 0; i < LAST_PER_THREAD_ASSERT_TYPE; i++) {
     54       assert_states_[i] = true;
     55     }
     56   }
     57 
     58   void set(PerThreadAssertType type, bool allow) {
     59     assert_states_[type] = allow;
     60   }
     61 
     62   bool get(PerThreadAssertType type) const {
     63     return assert_states_[type];
     64   }
     65 
     66   void increment_level() { ++nesting_level_; }
     67   bool decrement_level() { return --nesting_level_ == 0; }
     68 
     69  private:
     70   bool assert_states_[LAST_PER_THREAD_ASSERT_TYPE];
     71   int nesting_level_;
     72 
     73   DISALLOW_COPY_AND_ASSIGN(PerThreadAssertData);
     74 };
     75 #endif  // DEBUG
     76 
     77 
     78 class PerThreadAssertScopeBase {
     79 #ifdef DEBUG
     80 
     81  protected:
     82   PerThreadAssertScopeBase() {
     83     data_ = GetAssertData();
     84     if (data_ == NULL) {
     85       data_ = new PerThreadAssertData();
     86       SetThreadLocalData(data_);
     87     }
     88     data_->increment_level();
     89   }
     90 
     91   ~PerThreadAssertScopeBase() {
     92     if (!data_->decrement_level()) return;
     93     for (int i = 0; i < LAST_PER_THREAD_ASSERT_TYPE; i++) {
     94       ASSERT(data_->get(static_cast<PerThreadAssertType>(i)));
     95     }
     96     delete data_;
     97     SetThreadLocalData(NULL);
     98   }
     99 
    100   static PerThreadAssertData* GetAssertData() {
    101     return reinterpret_cast<PerThreadAssertData*>(
    102         Thread::GetThreadLocal(thread_local_key));
    103   }
    104 
    105   static Thread::LocalStorageKey thread_local_key;
    106   PerThreadAssertData* data_;
    107   friend class Isolate;
    108 
    109  private:
    110   static void SetThreadLocalData(PerThreadAssertData* data) {
    111     Thread::SetThreadLocal(thread_local_key, data);
    112   }
    113 #endif  // DEBUG
    114 };
    115 
    116 
    117 
    118 template <PerThreadAssertType type, bool allow>
    119 class PerThreadAssertScope : public PerThreadAssertScopeBase {
    120  public:
    121 #ifndef DEBUG
    122   PerThreadAssertScope() { }
    123   static void SetIsAllowed(bool is_allowed) { }
    124 #else
    125   PerThreadAssertScope() {
    126     old_state_ = data_->get(type);
    127     data_->set(type, allow);
    128   }
    129 
    130   ~PerThreadAssertScope() { data_->set(type, old_state_); }
    131 
    132   static bool IsAllowed() {
    133     PerThreadAssertData* data = GetAssertData();
    134     return data == NULL || data->get(type);
    135   }
    136 
    137  private:
    138   bool old_state_;
    139 #endif
    140 };
    141 
    142 // Scope to document where we do not expect handles to be created.
    143 typedef PerThreadAssertScope<HANDLE_ALLOCATION_ASSERT, false>
    144     DisallowHandleAllocation;
    145 
    146 // Scope to introduce an exception to DisallowHandleAllocation.
    147 typedef PerThreadAssertScope<HANDLE_ALLOCATION_ASSERT, true>
    148     AllowHandleAllocation;
    149 
    150 // Scope to document where we do not expect any allocation and GC.
    151 typedef PerThreadAssertScope<HEAP_ALLOCATION_ASSERT, false>
    152     DisallowHeapAllocation;
    153 
    154 // Scope to introduce an exception to DisallowHeapAllocation.
    155 typedef PerThreadAssertScope<HEAP_ALLOCATION_ASSERT, true>
    156     AllowHeapAllocation;
    157 
    158 // Scope to document where we do not expect any handle dereferences.
    159 typedef PerThreadAssertScope<HANDLE_DEREFERENCE_ASSERT, false>
    160     DisallowHandleDereference;
    161 
    162 // Scope to introduce an exception to DisallowHandleDereference.
    163 typedef PerThreadAssertScope<HANDLE_DEREFERENCE_ASSERT, true>
    164     AllowHandleDereference;
    165 
    166 // Scope to document where we do not expect deferred handles to be dereferenced.
    167 typedef PerThreadAssertScope<DEFERRED_HANDLE_DEREFERENCE_ASSERT, false>
    168     DisallowDeferredHandleDereference;
    169 
    170 // Scope to introduce an exception to DisallowDeferredHandleDereference.
    171 typedef PerThreadAssertScope<DEFERRED_HANDLE_DEREFERENCE_ASSERT, true>
    172     AllowDeferredHandleDereference;
    173 
    174 // Scope to document where we do not expect deferred handles to be dereferenced.
    175 typedef PerThreadAssertScope<CODE_DEPENDENCY_CHANGE_ASSERT, false>
    176     DisallowCodeDependencyChange;
    177 
    178 // Scope to introduce an exception to DisallowDeferredHandleDereference.
    179 typedef PerThreadAssertScope<CODE_DEPENDENCY_CHANGE_ASSERT, true>
    180     AllowCodeDependencyChange;
    181 
    182 } }  // namespace v8::internal
    183 
    184 #endif  // V8_ASSERT_SCOPE_H_
    185