2013-06-03 15:32:22 +00:00
|
|
|
// Copyright 2013 the V8 project authors. All rights reserved.
|
2014-04-29 06:42:26 +00:00
|
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
|
|
// found in the LICENSE file.
|
2013-06-03 15:32:22 +00:00
|
|
|
|
|
|
|
#ifndef V8_ASSERT_SCOPE_H_
|
|
|
|
#define V8_ASSERT_SCOPE_H_
|
|
|
|
|
2014-06-03 08:12:43 +00:00
|
|
|
#include "src/allocation.h"
|
2014-06-30 13:25:46 +00:00
|
|
|
#include "src/base/platform/platform.h"
|
2014-06-03 08:12:43 +00:00
|
|
|
#include "src/utils.h"
|
2013-06-03 15:32:22 +00:00
|
|
|
|
|
|
|
namespace v8 {
|
|
|
|
namespace internal {
|
|
|
|
|
|
|
|
class Isolate;
|
|
|
|
|
|
|
|
enum PerThreadAssertType {
|
|
|
|
HEAP_ALLOCATION_ASSERT,
|
|
|
|
HANDLE_ALLOCATION_ASSERT,
|
|
|
|
HANDLE_DEREFERENCE_ASSERT,
|
|
|
|
DEFERRED_HANDLE_DEREFERENCE_ASSERT,
|
2013-08-12 14:10:25 +00:00
|
|
|
CODE_DEPENDENCY_CHANGE_ASSERT,
|
2013-06-03 15:32:22 +00:00
|
|
|
LAST_PER_THREAD_ASSERT_TYPE
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2014-03-19 11:31:43 +00:00
|
|
|
enum PerIsolateAssertType {
|
|
|
|
JAVASCRIPT_EXECUTION_ASSERT,
|
2014-03-19 13:06:53 +00:00
|
|
|
JAVASCRIPT_EXECUTION_THROWS,
|
2014-04-28 06:47:05 +00:00
|
|
|
ALLOCATION_FAILURE_ASSERT,
|
|
|
|
DEOPTIMIZATION_ASSERT
|
2014-03-19 11:31:43 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2013-06-03 15:32:22 +00:00
|
|
|
class PerThreadAssertData {
|
|
|
|
public:
|
2013-06-05 09:41:24 +00:00
|
|
|
PerThreadAssertData() : nesting_level_(0) {
|
2013-06-03 15:32:22 +00:00
|
|
|
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];
|
|
|
|
}
|
|
|
|
|
2013-06-05 09:41:24 +00:00
|
|
|
void increment_level() { ++nesting_level_; }
|
|
|
|
bool decrement_level() { return --nesting_level_ == 0; }
|
|
|
|
|
2013-06-03 15:32:22 +00:00
|
|
|
private:
|
|
|
|
bool assert_states_[LAST_PER_THREAD_ASSERT_TYPE];
|
2013-06-05 09:41:24 +00:00
|
|
|
int nesting_level_;
|
2013-06-03 15:32:22 +00:00
|
|
|
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(PerThreadAssertData);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class PerThreadAssertScopeBase {
|
|
|
|
protected:
|
2013-06-05 09:41:24 +00:00
|
|
|
PerThreadAssertScopeBase() {
|
2013-06-13 07:47:42 +00:00
|
|
|
data_ = GetAssertData();
|
|
|
|
if (data_ == NULL) {
|
|
|
|
data_ = new PerThreadAssertData();
|
|
|
|
SetThreadLocalData(data_);
|
|
|
|
}
|
2013-06-05 09:41:24 +00:00
|
|
|
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_;
|
2013-06-13 07:47:42 +00:00
|
|
|
SetThreadLocalData(NULL);
|
2013-06-05 09:41:24 +00:00
|
|
|
}
|
|
|
|
|
2013-06-13 07:47:42 +00:00
|
|
|
static PerThreadAssertData* GetAssertData() {
|
|
|
|
return reinterpret_cast<PerThreadAssertData*>(
|
2014-06-30 13:25:46 +00:00
|
|
|
base::Thread::GetThreadLocal(thread_local_key));
|
2013-06-03 15:32:22 +00:00
|
|
|
}
|
|
|
|
|
2014-06-30 13:25:46 +00:00
|
|
|
static base::Thread::LocalStorageKey thread_local_key;
|
2013-06-05 09:41:24 +00:00
|
|
|
PerThreadAssertData* data_;
|
2013-06-03 15:32:22 +00:00
|
|
|
friend class Isolate;
|
2013-06-13 07:47:42 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
static void SetThreadLocalData(PerThreadAssertData* data) {
|
2014-06-30 13:25:46 +00:00
|
|
|
base::Thread::SetThreadLocal(thread_local_key, data);
|
2013-06-13 07:47:42 +00:00
|
|
|
}
|
2013-06-03 15:32:22 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
template <PerThreadAssertType type, bool allow>
|
|
|
|
class PerThreadAssertScope : public PerThreadAssertScopeBase {
|
|
|
|
public:
|
|
|
|
PerThreadAssertScope() {
|
2013-06-05 09:41:24 +00:00
|
|
|
old_state_ = data_->get(type);
|
|
|
|
data_->set(type, allow);
|
2013-06-03 15:32:22 +00:00
|
|
|
}
|
|
|
|
|
2013-06-05 09:41:24 +00:00
|
|
|
~PerThreadAssertScope() { data_->set(type, old_state_); }
|
2013-06-03 15:32:22 +00:00
|
|
|
|
2013-06-13 07:47:42 +00:00
|
|
|
static bool IsAllowed() {
|
|
|
|
PerThreadAssertData* data = GetAssertData();
|
|
|
|
return data == NULL || data->get(type);
|
|
|
|
}
|
2013-06-03 15:32:22 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
bool old_state_;
|
2014-03-19 11:31:43 +00:00
|
|
|
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(PerThreadAssertScope);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
class PerIsolateAssertBase {
|
|
|
|
protected:
|
|
|
|
static uint32_t GetData(Isolate* isolate);
|
|
|
|
static void SetData(Isolate* isolate, uint32_t data);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
template <PerIsolateAssertType type, bool allow>
|
|
|
|
class PerIsolateAssertScope : public PerIsolateAssertBase {
|
|
|
|
public:
|
|
|
|
explicit PerIsolateAssertScope(Isolate* isolate) : isolate_(isolate) {
|
|
|
|
STATIC_ASSERT(type < 32);
|
|
|
|
old_data_ = GetData(isolate_);
|
|
|
|
SetData(isolate_, DataBit::update(old_data_, allow));
|
|
|
|
}
|
|
|
|
|
|
|
|
~PerIsolateAssertScope() {
|
|
|
|
SetData(isolate_, old_data_);
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool IsAllowed(Isolate* isolate) {
|
|
|
|
return DataBit::decode(GetData(isolate));
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
typedef BitField<bool, type, 1> DataBit;
|
|
|
|
|
|
|
|
uint32_t old_data_;
|
|
|
|
Isolate* isolate_;
|
|
|
|
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(PerIsolateAssertScope);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
template <PerThreadAssertType type, bool allow>
|
|
|
|
#ifdef DEBUG
|
|
|
|
class PerThreadAssertScopeDebugOnly : public
|
|
|
|
PerThreadAssertScope<type, allow> {
|
|
|
|
#else
|
|
|
|
class PerThreadAssertScopeDebugOnly {
|
|
|
|
public:
|
|
|
|
PerThreadAssertScopeDebugOnly() { }
|
|
|
|
#endif
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
template <PerIsolateAssertType type, bool allow>
|
|
|
|
#ifdef DEBUG
|
|
|
|
class PerIsolateAssertScopeDebugOnly : public
|
|
|
|
PerIsolateAssertScope<type, allow> {
|
|
|
|
public:
|
|
|
|
explicit PerIsolateAssertScopeDebugOnly(Isolate* isolate)
|
|
|
|
: PerIsolateAssertScope<type, allow>(isolate) { }
|
|
|
|
#else
|
|
|
|
class PerIsolateAssertScopeDebugOnly {
|
|
|
|
public:
|
|
|
|
explicit PerIsolateAssertScopeDebugOnly(Isolate* isolate) { }
|
2013-06-03 15:32:22 +00:00
|
|
|
#endif
|
|
|
|
};
|
|
|
|
|
2014-03-19 11:31:43 +00:00
|
|
|
// Per-thread assert scopes.
|
|
|
|
|
2013-06-03 15:32:22 +00:00
|
|
|
// Scope to document where we do not expect handles to be created.
|
2014-03-19 11:31:43 +00:00
|
|
|
typedef PerThreadAssertScopeDebugOnly<HANDLE_ALLOCATION_ASSERT, false>
|
2013-06-03 15:32:22 +00:00
|
|
|
DisallowHandleAllocation;
|
|
|
|
|
|
|
|
// Scope to introduce an exception to DisallowHandleAllocation.
|
2014-03-19 11:31:43 +00:00
|
|
|
typedef PerThreadAssertScopeDebugOnly<HANDLE_ALLOCATION_ASSERT, true>
|
2013-06-03 15:32:22 +00:00
|
|
|
AllowHandleAllocation;
|
|
|
|
|
|
|
|
// Scope to document where we do not expect any allocation and GC.
|
2014-03-19 11:31:43 +00:00
|
|
|
typedef PerThreadAssertScopeDebugOnly<HEAP_ALLOCATION_ASSERT, false>
|
2013-06-03 15:32:22 +00:00
|
|
|
DisallowHeapAllocation;
|
|
|
|
|
|
|
|
// Scope to introduce an exception to DisallowHeapAllocation.
|
2014-03-19 11:31:43 +00:00
|
|
|
typedef PerThreadAssertScopeDebugOnly<HEAP_ALLOCATION_ASSERT, true>
|
2013-06-03 15:32:22 +00:00
|
|
|
AllowHeapAllocation;
|
|
|
|
|
|
|
|
// Scope to document where we do not expect any handle dereferences.
|
2014-03-19 11:31:43 +00:00
|
|
|
typedef PerThreadAssertScopeDebugOnly<HANDLE_DEREFERENCE_ASSERT, false>
|
2013-06-03 15:32:22 +00:00
|
|
|
DisallowHandleDereference;
|
|
|
|
|
|
|
|
// Scope to introduce an exception to DisallowHandleDereference.
|
2014-03-19 11:31:43 +00:00
|
|
|
typedef PerThreadAssertScopeDebugOnly<HANDLE_DEREFERENCE_ASSERT, true>
|
2013-06-03 15:32:22 +00:00
|
|
|
AllowHandleDereference;
|
|
|
|
|
|
|
|
// Scope to document where we do not expect deferred handles to be dereferenced.
|
2014-03-19 11:31:43 +00:00
|
|
|
typedef PerThreadAssertScopeDebugOnly<DEFERRED_HANDLE_DEREFERENCE_ASSERT, false>
|
2013-06-03 15:32:22 +00:00
|
|
|
DisallowDeferredHandleDereference;
|
|
|
|
|
|
|
|
// Scope to introduce an exception to DisallowDeferredHandleDereference.
|
2014-03-19 11:31:43 +00:00
|
|
|
typedef PerThreadAssertScopeDebugOnly<DEFERRED_HANDLE_DEREFERENCE_ASSERT, true>
|
2013-06-03 15:32:22 +00:00
|
|
|
AllowDeferredHandleDereference;
|
|
|
|
|
2013-08-12 14:10:25 +00:00
|
|
|
// Scope to document where we do not expect deferred handles to be dereferenced.
|
2014-03-19 11:31:43 +00:00
|
|
|
typedef PerThreadAssertScopeDebugOnly<CODE_DEPENDENCY_CHANGE_ASSERT, false>
|
2013-08-12 14:10:25 +00:00
|
|
|
DisallowCodeDependencyChange;
|
|
|
|
|
|
|
|
// Scope to introduce an exception to DisallowDeferredHandleDereference.
|
2014-03-19 11:31:43 +00:00
|
|
|
typedef PerThreadAssertScopeDebugOnly<CODE_DEPENDENCY_CHANGE_ASSERT, true>
|
2013-08-12 14:10:25 +00:00
|
|
|
AllowCodeDependencyChange;
|
|
|
|
|
2014-03-19 11:31:43 +00:00
|
|
|
|
|
|
|
// Per-isolate assert scopes.
|
|
|
|
|
|
|
|
// Scope to document where we do not expect javascript execution.
|
|
|
|
typedef PerIsolateAssertScope<JAVASCRIPT_EXECUTION_ASSERT, false>
|
|
|
|
DisallowJavascriptExecution;
|
|
|
|
|
|
|
|
// Scope to introduce an exception to DisallowJavascriptExecution.
|
|
|
|
typedef PerIsolateAssertScope<JAVASCRIPT_EXECUTION_ASSERT, true>
|
|
|
|
AllowJavascriptExecution;
|
|
|
|
|
2014-03-19 13:06:53 +00:00
|
|
|
// Scope in which javascript execution leads to exception being thrown.
|
|
|
|
typedef PerIsolateAssertScope<JAVASCRIPT_EXECUTION_THROWS, false>
|
|
|
|
ThrowOnJavascriptExecution;
|
|
|
|
|
|
|
|
// Scope to introduce an exception to ThrowOnJavascriptExecution.
|
|
|
|
typedef PerIsolateAssertScope<JAVASCRIPT_EXECUTION_THROWS, true>
|
|
|
|
NoThrowOnJavascriptExecution;
|
|
|
|
|
2014-03-19 11:31:43 +00:00
|
|
|
// Scope to document where we do not expect an allocation failure.
|
|
|
|
typedef PerIsolateAssertScopeDebugOnly<ALLOCATION_FAILURE_ASSERT, false>
|
|
|
|
DisallowAllocationFailure;
|
|
|
|
|
|
|
|
// Scope to introduce an exception to DisallowAllocationFailure.
|
|
|
|
typedef PerIsolateAssertScopeDebugOnly<ALLOCATION_FAILURE_ASSERT, true>
|
|
|
|
AllowAllocationFailure;
|
|
|
|
|
2014-04-28 06:47:05 +00:00
|
|
|
// Scope to document where we do not expect deoptimization.
|
|
|
|
typedef PerIsolateAssertScopeDebugOnly<DEOPTIMIZATION_ASSERT, false>
|
|
|
|
DisallowDeoptimization;
|
|
|
|
|
|
|
|
// Scope to introduce an exception to DisallowDeoptimization.
|
|
|
|
typedef PerIsolateAssertScopeDebugOnly<DEOPTIMIZATION_ASSERT, true>
|
|
|
|
AllowDeoptimization;
|
|
|
|
|
2013-06-03 15:32:22 +00:00
|
|
|
} } // namespace v8::internal
|
|
|
|
|
|
|
|
#endif // V8_ASSERT_SCOPE_H_
|