blob: 13adbd0f9c5179a850194f9d86ac66cc2cf8fed8 [file] [log] [blame]
rossberg@chromium.org79e79022013-06-03 15:43:46 +00001// 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
34namespace v8 {
35namespace internal {
36
37class Isolate;
38
39enum PerThreadAssertType {
40 HEAP_ALLOCATION_ASSERT,
41 HANDLE_ALLOCATION_ASSERT,
42 HANDLE_DEREFERENCE_ASSERT,
43 DEFERRED_HANDLE_DEREFERENCE_ASSERT,
44 LAST_PER_THREAD_ASSERT_TYPE
45};
46
47
48#ifdef DEBUG
49class PerThreadAssertData {
50 public:
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000051 PerThreadAssertData() : nesting_level_(0) {
rossberg@chromium.org79e79022013-06-03 15:43:46 +000052 for (int i = 0; i < LAST_PER_THREAD_ASSERT_TYPE; i++) {
53 assert_states_[i] = true;
54 }
55 }
56
57 void set(PerThreadAssertType type, bool allow) {
58 assert_states_[type] = allow;
59 }
60
61 bool get(PerThreadAssertType type) const {
62 return assert_states_[type];
63 }
64
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000065 void increment_level() { ++nesting_level_; }
66 bool decrement_level() { return --nesting_level_ == 0; }
67
rossberg@chromium.org79e79022013-06-03 15:43:46 +000068 private:
69 bool assert_states_[LAST_PER_THREAD_ASSERT_TYPE];
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000070 int nesting_level_;
rossberg@chromium.org79e79022013-06-03 15:43:46 +000071
72 DISALLOW_COPY_AND_ASSIGN(PerThreadAssertData);
73};
74#endif // DEBUG
75
76
77class PerThreadAssertScopeBase {
78#ifdef DEBUG
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000079
rossberg@chromium.org79e79022013-06-03 15:43:46 +000080 protected:
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000081 PerThreadAssertScopeBase() {
danno@chromium.orgf95d4b92013-06-13 14:40:17 +000082 data_ = GetAssertData();
83 if (data_ == NULL) {
84 data_ = new PerThreadAssertData();
85 SetThreadLocalData(data_);
86 }
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000087 data_->increment_level();
88 }
89
90 ~PerThreadAssertScopeBase() {
91 if (!data_->decrement_level()) return;
92 for (int i = 0; i < LAST_PER_THREAD_ASSERT_TYPE; i++) {
93 ASSERT(data_->get(static_cast<PerThreadAssertType>(i)));
94 }
95 delete data_;
danno@chromium.orgf95d4b92013-06-13 14:40:17 +000096 SetThreadLocalData(NULL);
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +000097 }
98
danno@chromium.orgf95d4b92013-06-13 14:40:17 +000099 static PerThreadAssertData* GetAssertData() {
100 return reinterpret_cast<PerThreadAssertData*>(
101 Thread::GetThreadLocal(thread_local_key));
rossberg@chromium.org79e79022013-06-03 15:43:46 +0000102 }
103
104 static Thread::LocalStorageKey thread_local_key;
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000105 PerThreadAssertData* data_;
rossberg@chromium.org79e79022013-06-03 15:43:46 +0000106 friend class Isolate;
danno@chromium.orgf95d4b92013-06-13 14:40:17 +0000107
108 private:
109 static void SetThreadLocalData(PerThreadAssertData* data) {
110 Thread::SetThreadLocal(thread_local_key, data);
111 }
rossberg@chromium.org79e79022013-06-03 15:43:46 +0000112#endif // DEBUG
113};
114
115
116
117template <PerThreadAssertType type, bool allow>
118class PerThreadAssertScope : public PerThreadAssertScopeBase {
119 public:
120#ifndef DEBUG
121 PerThreadAssertScope() { }
122 static void SetIsAllowed(bool is_allowed) { }
123#else
124 PerThreadAssertScope() {
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000125 old_state_ = data_->get(type);
126 data_->set(type, allow);
rossberg@chromium.org79e79022013-06-03 15:43:46 +0000127 }
128
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +0000129 ~PerThreadAssertScope() { data_->set(type, old_state_); }
rossberg@chromium.org79e79022013-06-03 15:43:46 +0000130
danno@chromium.orgf95d4b92013-06-13 14:40:17 +0000131 static bool IsAllowed() {
132 PerThreadAssertData* data = GetAssertData();
133 return data == NULL || data->get(type);
134 }
rossberg@chromium.org79e79022013-06-03 15:43:46 +0000135
136 private:
137 bool old_state_;
138#endif
139};
140
141// Scope to document where we do not expect handles to be created.
142typedef PerThreadAssertScope<HANDLE_ALLOCATION_ASSERT, false>
143 DisallowHandleAllocation;
144
145// Scope to introduce an exception to DisallowHandleAllocation.
146typedef PerThreadAssertScope<HANDLE_ALLOCATION_ASSERT, true>
147 AllowHandleAllocation;
148
149// Scope to document where we do not expect any allocation and GC.
150typedef PerThreadAssertScope<HEAP_ALLOCATION_ASSERT, false>
151 DisallowHeapAllocation;
152
153// Scope to introduce an exception to DisallowHeapAllocation.
154typedef PerThreadAssertScope<HEAP_ALLOCATION_ASSERT, true>
155 AllowHeapAllocation;
156
157// Scope to document where we do not expect any handle dereferences.
158typedef PerThreadAssertScope<HANDLE_DEREFERENCE_ASSERT, false>
159 DisallowHandleDereference;
160
161// Scope to introduce an exception to DisallowHandleDereference.
162typedef PerThreadAssertScope<HANDLE_DEREFERENCE_ASSERT, true>
163 AllowHandleDereference;
164
165// Scope to document where we do not expect deferred handles to be dereferenced.
166typedef PerThreadAssertScope<DEFERRED_HANDLE_DEREFERENCE_ASSERT, false>
167 DisallowDeferredHandleDereference;
168
169// Scope to introduce an exception to DisallowDeferredHandleDereference.
170typedef PerThreadAssertScope<DEFERRED_HANDLE_DEREFERENCE_ASSERT, true>
171 AllowDeferredHandleDereference;
172
173} } // namespace v8::internal
174
175#endif // V8_ASSERT_SCOPE_H_