28db1d0ebd
R=svenpanne@chromium.org BUG=246567 Review URL: https://chromiumcodereview.appspot.com/15709020 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@15106 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
176 lines
5.3 KiB
C++
176 lines
5.3 KiB
C++
// Copyright 2013 the V8 project authors. All rights reserved.
|
|
// Redistribution and use in source and binary forms, with or without
|
|
// modification, are permitted provided that the following conditions are
|
|
// met:
|
|
//
|
|
// * Redistributions of source code must retain the above copyright
|
|
// notice, this list of conditions and the following disclaimer.
|
|
// * Redistributions in binary form must reproduce the above
|
|
// copyright notice, this list of conditions and the following
|
|
// disclaimer in the documentation and/or other materials provided
|
|
// with the distribution.
|
|
// * Neither the name of Google Inc. nor the names of its
|
|
// contributors may be used to endorse or promote products derived
|
|
// from this software without specific prior written permission.
|
|
//
|
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
#ifndef V8_ASSERT_SCOPE_H_
|
|
#define V8_ASSERT_SCOPE_H_
|
|
|
|
#include "allocation.h"
|
|
#include "platform.h"
|
|
|
|
namespace v8 {
|
|
namespace internal {
|
|
|
|
class Isolate;
|
|
|
|
enum PerThreadAssertType {
|
|
HEAP_ALLOCATION_ASSERT,
|
|
HANDLE_ALLOCATION_ASSERT,
|
|
HANDLE_DEREFERENCE_ASSERT,
|
|
DEFERRED_HANDLE_DEREFERENCE_ASSERT,
|
|
LAST_PER_THREAD_ASSERT_TYPE
|
|
};
|
|
|
|
|
|
#ifdef DEBUG
|
|
class PerThreadAssertData {
|
|
public:
|
|
PerThreadAssertData() : nesting_level_(0) {
|
|
for (int i = 0; i < LAST_PER_THREAD_ASSERT_TYPE; i++) {
|
|
assert_states_[i] = true;
|
|
}
|
|
}
|
|
|
|
void set(PerThreadAssertType type, bool allow) {
|
|
assert_states_[type] = allow;
|
|
}
|
|
|
|
bool get(PerThreadAssertType type) const {
|
|
return assert_states_[type];
|
|
}
|
|
|
|
void increment_level() { ++nesting_level_; }
|
|
bool decrement_level() { return --nesting_level_ == 0; }
|
|
|
|
private:
|
|
bool assert_states_[LAST_PER_THREAD_ASSERT_TYPE];
|
|
int nesting_level_;
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(PerThreadAssertData);
|
|
};
|
|
#endif // DEBUG
|
|
|
|
|
|
class PerThreadAssertScopeBase {
|
|
#ifdef DEBUG
|
|
|
|
protected:
|
|
PerThreadAssertScopeBase() {
|
|
data_ = GetAssertData();
|
|
if (data_ == NULL) {
|
|
data_ = new PerThreadAssertData();
|
|
SetThreadLocalData(data_);
|
|
}
|
|
data_->increment_level();
|
|
}
|
|
|
|
~PerThreadAssertScopeBase() {
|
|
if (!data_->decrement_level()) return;
|
|
for (int i = 0; i < LAST_PER_THREAD_ASSERT_TYPE; i++) {
|
|
ASSERT(data_->get(static_cast<PerThreadAssertType>(i)));
|
|
}
|
|
delete data_;
|
|
SetThreadLocalData(NULL);
|
|
}
|
|
|
|
static PerThreadAssertData* GetAssertData() {
|
|
return reinterpret_cast<PerThreadAssertData*>(
|
|
Thread::GetThreadLocal(thread_local_key));
|
|
}
|
|
|
|
static Thread::LocalStorageKey thread_local_key;
|
|
PerThreadAssertData* data_;
|
|
friend class Isolate;
|
|
|
|
private:
|
|
static void SetThreadLocalData(PerThreadAssertData* data) {
|
|
Thread::SetThreadLocal(thread_local_key, data);
|
|
}
|
|
#endif // DEBUG
|
|
};
|
|
|
|
|
|
|
|
template <PerThreadAssertType type, bool allow>
|
|
class PerThreadAssertScope : public PerThreadAssertScopeBase {
|
|
public:
|
|
#ifndef DEBUG
|
|
PerThreadAssertScope() { }
|
|
static void SetIsAllowed(bool is_allowed) { }
|
|
#else
|
|
PerThreadAssertScope() {
|
|
old_state_ = data_->get(type);
|
|
data_->set(type, allow);
|
|
}
|
|
|
|
~PerThreadAssertScope() { data_->set(type, old_state_); }
|
|
|
|
static bool IsAllowed() {
|
|
PerThreadAssertData* data = GetAssertData();
|
|
return data == NULL || data->get(type);
|
|
}
|
|
|
|
private:
|
|
bool old_state_;
|
|
#endif
|
|
};
|
|
|
|
// Scope to document where we do not expect handles to be created.
|
|
typedef PerThreadAssertScope<HANDLE_ALLOCATION_ASSERT, false>
|
|
DisallowHandleAllocation;
|
|
|
|
// Scope to introduce an exception to DisallowHandleAllocation.
|
|
typedef PerThreadAssertScope<HANDLE_ALLOCATION_ASSERT, true>
|
|
AllowHandleAllocation;
|
|
|
|
// Scope to document where we do not expect any allocation and GC.
|
|
typedef PerThreadAssertScope<HEAP_ALLOCATION_ASSERT, false>
|
|
DisallowHeapAllocation;
|
|
|
|
// Scope to introduce an exception to DisallowHeapAllocation.
|
|
typedef PerThreadAssertScope<HEAP_ALLOCATION_ASSERT, true>
|
|
AllowHeapAllocation;
|
|
|
|
// Scope to document where we do not expect any handle dereferences.
|
|
typedef PerThreadAssertScope<HANDLE_DEREFERENCE_ASSERT, false>
|
|
DisallowHandleDereference;
|
|
|
|
// Scope to introduce an exception to DisallowHandleDereference.
|
|
typedef PerThreadAssertScope<HANDLE_DEREFERENCE_ASSERT, true>
|
|
AllowHandleDereference;
|
|
|
|
// Scope to document where we do not expect deferred handles to be dereferenced.
|
|
typedef PerThreadAssertScope<DEFERRED_HANDLE_DEREFERENCE_ASSERT, false>
|
|
DisallowDeferredHandleDereference;
|
|
|
|
// Scope to introduce an exception to DisallowDeferredHandleDereference.
|
|
typedef PerThreadAssertScope<DEFERRED_HANDLE_DEREFERENCE_ASSERT, true>
|
|
AllowDeferredHandleDereference;
|
|
|
|
} } // namespace v8::internal
|
|
|
|
#endif // V8_ASSERT_SCOPE_H_
|