blob: ac2f2c857330f38dc68e13012634d99949b04a3e [file] [log] [blame]
// Copyright 2013 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_COMMON_ASSERT_SCOPE_H_
#define V8_COMMON_ASSERT_SCOPE_H_
#include <stdint.h>
#include "src/base/macros.h"
#include "src/base/optional.h"
#include "src/common/globals.h"
#include "src/utils/pointer-with-payload.h"
namespace v8 {
namespace internal {
// Forward declarations.
class Isolate;
class PerThreadAssertData;
template <>
struct PointerWithPayloadTraits<PerThreadAssertData> {
static constexpr int value = 1;
};
enum PerThreadAssertType {
HEAP_ALLOCATION_ASSERT,
HANDLE_ALLOCATION_ASSERT,
HANDLE_DEREFERENCE_ASSERT,
DEFERRED_HANDLE_DEREFERENCE_ASSERT,
CODE_DEPENDENCY_CHANGE_ASSERT,
LAST_PER_THREAD_ASSERT_TYPE
};
enum PerIsolateAssertType {
JAVASCRIPT_EXECUTION_ASSERT,
JAVASCRIPT_EXECUTION_THROWS,
JAVASCRIPT_EXECUTION_DUMP,
DEOPTIMIZATION_ASSERT,
COMPILATION_ASSERT,
NO_EXCEPTION_ASSERT
};
template <PerThreadAssertType kType, bool kAllow>
class PerThreadAssertScope {
public:
V8_EXPORT_PRIVATE PerThreadAssertScope();
V8_EXPORT_PRIVATE ~PerThreadAssertScope();
V8_EXPORT_PRIVATE static bool IsAllowed();
void Release();
private:
PointerWithPayload<PerThreadAssertData, bool, 1> data_and_old_state_;
V8_INLINE void set_data(PerThreadAssertData* data) {
data_and_old_state_.SetPointer(data);
}
V8_INLINE PerThreadAssertData* data() const {
return data_and_old_state_.GetPointer();
}
V8_INLINE void set_old_state(bool old_state) {
return data_and_old_state_.SetPayload(old_state);
}
V8_INLINE bool old_state() const { return data_and_old_state_.GetPayload(); }
DISALLOW_COPY_AND_ASSIGN(PerThreadAssertScope);
};
template <PerIsolateAssertType type, bool allow>
class PerIsolateAssertScope {
public:
V8_EXPORT_PRIVATE explicit PerIsolateAssertScope(Isolate* isolate);
V8_EXPORT_PRIVATE ~PerIsolateAssertScope();
static bool IsAllowed(Isolate* isolate);
private:
class DataBit;
Isolate* isolate_;
uint32_t old_data_;
DISALLOW_COPY_AND_ASSIGN(PerIsolateAssertScope);
};
template <PerThreadAssertType type, bool allow>
#ifdef DEBUG
class PerThreadAssertScopeDebugOnly : public PerThreadAssertScope<type, allow> {
#else
class PerThreadAssertScopeDebugOnly {
public:
PerThreadAssertScopeDebugOnly() { // NOLINT (modernize-use-equals-default)
// Define a constructor to avoid unused variable warnings.
}
void Release() {}
#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) {}
#endif
};
// Per-thread assert scopes.
// Scope to document where we do not expect handles to be created.
typedef PerThreadAssertScopeDebugOnly<HANDLE_ALLOCATION_ASSERT, false>
DisallowHandleAllocation;
// Scope to introduce an exception to DisallowHandleAllocation.
typedef PerThreadAssertScopeDebugOnly<HANDLE_ALLOCATION_ASSERT, true>
AllowHandleAllocation;
// Scope to document where we do not expect any allocation and GC.
typedef PerThreadAssertScopeDebugOnly<HEAP_ALLOCATION_ASSERT, false>
DisallowHeapAllocation;
#ifdef DEBUG
#define DISALLOW_HEAP_ALLOCATION(name) DisallowHeapAllocation name;
#else
#define DISALLOW_HEAP_ALLOCATION(name)
#endif
// Scope to introduce an exception to DisallowHeapAllocation.
typedef PerThreadAssertScopeDebugOnly<HEAP_ALLOCATION_ASSERT, true>
AllowHeapAllocation;
// Scope to document where we do not expect any handle dereferences.
typedef PerThreadAssertScopeDebugOnly<HANDLE_DEREFERENCE_ASSERT, false>
DisallowHandleDereference;
// Scope to introduce an exception to DisallowHandleDereference.
typedef PerThreadAssertScopeDebugOnly<HANDLE_DEREFERENCE_ASSERT, true>
AllowHandleDereference;
// Scope to document where we do not expect deferred handles to be dereferenced.
typedef PerThreadAssertScopeDebugOnly<DEFERRED_HANDLE_DEREFERENCE_ASSERT, false>
DisallowDeferredHandleDereference;
// Scope to introduce an exception to DisallowDeferredHandleDereference.
typedef PerThreadAssertScopeDebugOnly<DEFERRED_HANDLE_DEREFERENCE_ASSERT, true>
AllowDeferredHandleDereference;
// Scope to document where we do not expect deferred handles to be dereferenced.
typedef PerThreadAssertScopeDebugOnly<CODE_DEPENDENCY_CHANGE_ASSERT, false>
DisallowCodeDependencyChange;
// Scope to introduce an exception to DisallowDeferredHandleDereference.
typedef PerThreadAssertScopeDebugOnly<CODE_DEPENDENCY_CHANGE_ASSERT, true>
AllowCodeDependencyChange;
class DisallowHeapAccess {
DisallowCodeDependencyChange no_dependency_change_;
DisallowHandleAllocation no_handle_allocation_;
DisallowHandleDereference no_handle_dereference_;
DisallowHeapAllocation no_heap_allocation_;
};
class DisallowHeapAccessIf {
public:
explicit DisallowHeapAccessIf(bool condition) {
if (condition) maybe_disallow_.emplace();
}
private:
base::Optional<DisallowHeapAccess> maybe_disallow_;
};
// 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;
// Scope to document where we do not expect javascript execution (debug only)
typedef PerIsolateAssertScopeDebugOnly<JAVASCRIPT_EXECUTION_ASSERT, false>
DisallowJavascriptExecutionDebugOnly;
// Scope to introduce an exception to DisallowJavascriptExecutionDebugOnly.
typedef PerIsolateAssertScopeDebugOnly<JAVASCRIPT_EXECUTION_ASSERT, true>
AllowJavascriptExecutionDebugOnly;
// 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;
// Scope in which javascript execution causes dumps.
typedef PerIsolateAssertScope<JAVASCRIPT_EXECUTION_DUMP, false>
DumpOnJavascriptExecution;
// Scope in which javascript execution causes dumps.
typedef PerIsolateAssertScope<JAVASCRIPT_EXECUTION_DUMP, true>
NoDumpOnJavascriptExecution;
// 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;
// Scope to document where we do not expect deoptimization.
typedef PerIsolateAssertScopeDebugOnly<COMPILATION_ASSERT, false>
DisallowCompilation;
// Scope to introduce an exception to DisallowDeoptimization.
typedef PerIsolateAssertScopeDebugOnly<COMPILATION_ASSERT, true>
AllowCompilation;
// Scope to document where we do not expect exceptions.
typedef PerIsolateAssertScopeDebugOnly<NO_EXCEPTION_ASSERT, false>
DisallowExceptions;
// Scope to introduce an exception to DisallowExceptions.
typedef PerIsolateAssertScopeDebugOnly<NO_EXCEPTION_ASSERT, true>
AllowExceptions;
// Explicit instantiation declarations.
extern template class PerThreadAssertScope<HEAP_ALLOCATION_ASSERT, false>;
extern template class PerThreadAssertScope<HEAP_ALLOCATION_ASSERT, true>;
extern template class PerThreadAssertScope<HANDLE_ALLOCATION_ASSERT, false>;
extern template class PerThreadAssertScope<HANDLE_ALLOCATION_ASSERT, true>;
extern template class PerThreadAssertScope<HANDLE_DEREFERENCE_ASSERT, false>;
extern template class PerThreadAssertScope<HANDLE_DEREFERENCE_ASSERT, true>;
extern template class PerThreadAssertScope<DEFERRED_HANDLE_DEREFERENCE_ASSERT,
false>;
extern template class PerThreadAssertScope<DEFERRED_HANDLE_DEREFERENCE_ASSERT,
true>;
extern template class PerThreadAssertScope<CODE_DEPENDENCY_CHANGE_ASSERT,
false>;
extern template class PerThreadAssertScope<CODE_DEPENDENCY_CHANGE_ASSERT, true>;
extern template class PerIsolateAssertScope<JAVASCRIPT_EXECUTION_ASSERT, false>;
extern template class PerIsolateAssertScope<JAVASCRIPT_EXECUTION_ASSERT, true>;
extern template class PerIsolateAssertScope<JAVASCRIPT_EXECUTION_THROWS, false>;
extern template class PerIsolateAssertScope<JAVASCRIPT_EXECUTION_THROWS, true>;
extern template class PerIsolateAssertScope<JAVASCRIPT_EXECUTION_DUMP, false>;
extern template class PerIsolateAssertScope<JAVASCRIPT_EXECUTION_DUMP, true>;
extern template class PerIsolateAssertScope<DEOPTIMIZATION_ASSERT, false>;
extern template class PerIsolateAssertScope<DEOPTIMIZATION_ASSERT, true>;
extern template class PerIsolateAssertScope<COMPILATION_ASSERT, false>;
extern template class PerIsolateAssertScope<COMPILATION_ASSERT, true>;
extern template class PerIsolateAssertScope<NO_EXCEPTION_ASSERT, false>;
extern template class PerIsolateAssertScope<NO_EXCEPTION_ASSERT, true>;
} // namespace internal
} // namespace v8
#endif // V8_COMMON_ASSERT_SCOPE_H_