Commit d11ccc5c authored by Maya Lekova's avatar Maya Lekova Committed by V8 LUCI CQ

Migrate PerIsolateAssertScope storage to separate booleans

This CL modifies the underlying storage of PerIsolateAssertScope from
a bitfield to separate booleans. This slightly increases the space taken
by the isolate, but allows for easier access to the individual fields,
which is a prerequisite for implementing assertion scopes in TurboFan.

It also refactors the template PerIsolateAssertScope class to separate
simple C++ scope classes, defined through macros.

Bug: chromium:1218898
Change-Id: Ia5e43352ebba28be6f013376b75f13ec8d5dc972
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2975303
Commit-Queue: Maya Lekova <mslekova@chromium.org>
Reviewed-by: 's avatarToon Verwaest <verwaest@chromium.org>
Cr-Commit-Position: refs/heads/master@{#75369}
parent 44e73e0b
......@@ -17,8 +17,6 @@ namespace {
template <PerThreadAssertType kType>
using PerThreadDataBit = base::BitField<bool, kType, 1>;
template <PerIsolateAssertType kType>
using PerIsolateDataBit = base::BitField<bool, kType, 1>;
// Thread-local storage for assert data. Default all asserts to "allow".
thread_local uint32_t current_per_thread_assert_data(~0);
......@@ -50,45 +48,41 @@ bool PerThreadAssertScope<kType, kAllow>::IsAllowed() {
return PerThreadDataBit<kType>::decode(current_per_thread_assert_data);
}
template <PerIsolateAssertType kType, bool kAllow>
PerIsolateAssertScope<kType, kAllow>::PerIsolateAssertScope(Isolate* isolate)
: isolate_(isolate), old_data_(isolate->per_isolate_assert_data()) {
DCHECK_NOT_NULL(isolate);
isolate_->set_per_isolate_assert_data(
PerIsolateDataBit<kType>::update(old_data_, kAllow));
}
template <PerIsolateAssertType kType, bool kAllow>
PerIsolateAssertScope<kType, kAllow>::~PerIsolateAssertScope() {
isolate_->set_per_isolate_assert_data(old_data_);
}
// static
template <PerIsolateAssertType kType, bool kAllow>
bool PerIsolateAssertScope<kType, kAllow>::IsAllowed(Isolate* isolate) {
return PerIsolateDataBit<kType>::decode(isolate->per_isolate_assert_data());
}
// static
template <PerIsolateAssertType kType, bool kAllow>
void PerIsolateAssertScope<kType, kAllow>::Open(Isolate* isolate,
bool* was_execution_allowed) {
DCHECK_NOT_NULL(isolate);
DCHECK_NOT_NULL(was_execution_allowed);
uint32_t old_data = isolate->per_isolate_assert_data();
*was_execution_allowed = PerIsolateDataBit<kType>::decode(old_data);
isolate->set_per_isolate_assert_data(
PerIsolateDataBit<kType>::update(old_data, kAllow));
}
// static
template <PerIsolateAssertType kType, bool kAllow>
void PerIsolateAssertScope<kType, kAllow>::Close(Isolate* isolate,
bool was_execution_allowed) {
DCHECK_NOT_NULL(isolate);
uint32_t old_data = isolate->per_isolate_assert_data();
isolate->set_per_isolate_assert_data(
PerIsolateDataBit<kType>::update(old_data, was_execution_allowed));
}
#define PER_ISOLATE_ASSERT_SCOPE_DEFINITION(ScopeType, field, enable) \
ScopeType::ScopeType(Isolate* isolate) \
: isolate_(isolate), old_data_(isolate->field()) { \
DCHECK_NOT_NULL(isolate); \
isolate_->set_##field(enable); \
} \
\
ScopeType::~ScopeType() { isolate_->set_##field(old_data_); } \
\
/* static */ \
bool ScopeType::IsAllowed(Isolate* isolate) { return isolate->field(); } \
\
/* static */ \
void ScopeType::Open(Isolate* isolate, bool* was_execution_allowed) { \
DCHECK_NOT_NULL(isolate); \
DCHECK_NOT_NULL(was_execution_allowed); \
*was_execution_allowed = isolate->field(); \
isolate->set_##field(enable); \
} \
/* static */ \
void ScopeType::Close(Isolate* isolate, bool was_execution_allowed) { \
DCHECK_NOT_NULL(isolate); \
isolate->set_##field(was_execution_allowed); \
}
#define PER_ISOLATE_ASSERT_ENABLE_SCOPE_DEFINITION(EnableType, _, field, \
enable) \
PER_ISOLATE_ASSERT_SCOPE_DEFINITION(EnableType, field, enable)
#define PER_ISOLATE_ASSERT_DISABLE_SCOPE_DEFINITION(_, DisableType, field, \
enable) \
PER_ISOLATE_ASSERT_SCOPE_DEFINITION(DisableType, field, enable)
PER_ISOLATE_ASSERT_TYPE(PER_ISOLATE_ASSERT_ENABLE_SCOPE_DEFINITION, true)
PER_ISOLATE_ASSERT_TYPE(PER_ISOLATE_ASSERT_DISABLE_SCOPE_DEFINITION, false)
// -----------------------------------------------------------------------------
// Instantiations.
......@@ -107,18 +101,5 @@ template class PerThreadAssertScope<CODE_ALLOCATION_ASSERT, false>;
template class PerThreadAssertScope<CODE_ALLOCATION_ASSERT, true>;
template class PerThreadAssertScope<GC_MOLE, false>;
template class PerIsolateAssertScope<JAVASCRIPT_EXECUTION_ASSERT, false>;
template class PerIsolateAssertScope<JAVASCRIPT_EXECUTION_ASSERT, true>;
template class PerIsolateAssertScope<JAVASCRIPT_EXECUTION_THROWS, false>;
template class PerIsolateAssertScope<JAVASCRIPT_EXECUTION_THROWS, true>;
template class PerIsolateAssertScope<JAVASCRIPT_EXECUTION_DUMP, false>;
template class PerIsolateAssertScope<JAVASCRIPT_EXECUTION_DUMP, true>;
template class PerIsolateAssertScope<DEOPTIMIZATION_ASSERT, false>;
template class PerIsolateAssertScope<DEOPTIMIZATION_ASSERT, true>;
template class PerIsolateAssertScope<COMPILATION_ASSERT, false>;
template class PerIsolateAssertScope<COMPILATION_ASSERT, true>;
template class PerIsolateAssertScope<NO_EXCEPTION_ASSERT, false>;
template class PerIsolateAssertScope<NO_EXCEPTION_ASSERT, true>;
} // namespace internal
} // namespace v8
......@@ -31,15 +31,6 @@ enum PerThreadAssertType {
GC_MOLE,
};
enum PerIsolateAssertType {
JAVASCRIPT_EXECUTION_ASSERT,
JAVASCRIPT_EXECUTION_THROWS,
JAVASCRIPT_EXECUTION_DUMP,
DEOPTIMIZATION_ASSERT,
COMPILATION_ASSERT,
NO_EXCEPTION_ASSERT,
};
template <PerThreadAssertType kType, bool kAllow>
class V8_NODISCARD PerThreadAssertScope {
public:
......@@ -57,25 +48,101 @@ class V8_NODISCARD PerThreadAssertScope {
base::Optional<uint32_t> old_data_;
};
template <PerIsolateAssertType kType, bool kAllow>
class V8_NODISCARD PerIsolateAssertScope {
public:
V8_EXPORT_PRIVATE explicit PerIsolateAssertScope(Isolate* isolate);
PerIsolateAssertScope(const PerIsolateAssertScope&) = delete;
PerIsolateAssertScope& operator=(const PerIsolateAssertScope&) = delete;
V8_EXPORT_PRIVATE ~PerIsolateAssertScope();
// Per-isolate assert scopes.
static bool IsAllowed(Isolate* isolate);
#define PER_ISOLATE_ASSERT_TYPE_DEBUG_ONLY(V, enable) \
/* Scope to document where we do not expect javascript execution. */ \
/* Scope to introduce an exception to DisallowJavascriptExecution. */ \
V(AllowJavascriptExecution, DisallowJavascriptExecution, \
javascript_execution_assert, enable) \
/* Scope to document where we do not expect deoptimization. */ \
/* Scope to introduce an exception to DisallowDeoptimization. */ \
V(AllowDeoptimization, DisallowDeoptimization, deoptimization_assert, \
enable) \
/* Scope to document where we do not expect deoptimization. */ \
/* Scope to introduce an exception to DisallowDeoptimization. */ \
V(AllowCompilation, DisallowCompilation, compilation_assert, enable) \
/* Scope to document where we do not expect exceptions. */ \
/* Scope to introduce an exception to DisallowExceptions. */ \
V(AllowExceptions, DisallowExceptions, no_exception_assert, enable)
#define PER_ISOLATE_ASSERT_TYPE(V, enable) \
/* Scope in which javascript execution leads to exception being thrown. */ \
/* Scope to introduce an exception to ThrowOnJavascriptExecution. */ \
V(NoThrowOnJavascriptExecution, ThrowOnJavascriptExecution, \
javascript_execution_throws, enable) \
/* Scope in which javascript execution causes dumps. */ \
/* Scope in which javascript execution doesn't cause dumps. */ \
V(NoDumpOnJavascriptExecution, DumpOnJavascriptExecution, \
javascript_execution_dump, enable) \
PER_ISOLATE_ASSERT_TYPE_DEBUG_ONLY(V, enable)
#define PER_ISOLATE_ASSERT_SCOPE_DECLARATION(ScopeType) \
class V8_NODISCARD ScopeType { \
public: \
V8_EXPORT_PRIVATE explicit ScopeType(Isolate* isolate); \
ScopeType(const ScopeType&) = delete; \
ScopeType& operator=(const ScopeType&) = delete; \
V8_EXPORT_PRIVATE ~ScopeType(); \
\
static bool IsAllowed(Isolate* isolate); \
\
V8_EXPORT_PRIVATE static void Open(Isolate* isolate, \
bool* was_execution_allowed); \
V8_EXPORT_PRIVATE static void Close(Isolate* isolate, \
bool was_execution_allowed); \
\
private: \
Isolate* isolate_; \
bool old_data_; \
};
#define PER_ISOLATE_ASSERT_ENABLE_SCOPE(EnableType, _1, _2, _3) \
PER_ISOLATE_ASSERT_SCOPE_DECLARATION(EnableType)
#define PER_ISOLATE_ASSERT_DISABLE_SCOPE(_1, DisableType, _2, _3) \
PER_ISOLATE_ASSERT_SCOPE_DECLARATION(DisableType)
PER_ISOLATE_ASSERT_TYPE(PER_ISOLATE_ASSERT_ENABLE_SCOPE, true)
PER_ISOLATE_ASSERT_TYPE(PER_ISOLATE_ASSERT_DISABLE_SCOPE, false)
V8_EXPORT_PRIVATE static void Open(Isolate* isolate,
bool* was_execution_allowed);
V8_EXPORT_PRIVATE static void Close(Isolate* isolate,
bool was_execution_allowed);
#ifdef DEBUG
#define PER_ISOLATE_ASSERT_ENABLE_SCOPE_DEBUG_ONLY(EnableType, DisableType, \
field, _) \
class EnableType##DebugOnly : public EnableType { \
public: \
explicit EnableType##DebugOnly(Isolate* isolate) : EnableType(isolate) {} \
};
#else
#define PER_ISOLATE_ASSERT_ENABLE_SCOPE_DEBUG_ONLY(EnableType, DisableType, \
field, _) \
class V8_NODISCARD EnableType##DebugOnly { \
public: \
explicit EnableType##DebugOnly(Isolate* isolate) {} \
};
#endif
private:
Isolate* isolate_;
uint32_t old_data_;
};
#ifdef DEBUG
#define PER_ISOLATE_ASSERT_DISABLE_SCOPE_DEBUG_ONLY(EnableType, DisableType, \
field, _) \
class DisableType##DebugOnly : public DisableType { \
public: \
explicit DisableType##DebugOnly(Isolate* isolate) \
: DisableType(isolate) {} \
};
#else
#define PER_ISOLATE_ASSERT_DISABLE_SCOPE_DEBUG_ONLY(EnableType, DisableType, \
field, _) \
class V8_NODISCARD DisableType##DebugOnly { \
public: \
explicit DisableType##DebugOnly(Isolate* isolate) {} \
};
#endif
PER_ISOLATE_ASSERT_TYPE_DEBUG_ONLY(PER_ISOLATE_ASSERT_ENABLE_SCOPE_DEBUG_ONLY,
true)
PER_ISOLATE_ASSERT_TYPE_DEBUG_ONLY(PER_ISOLATE_ASSERT_DISABLE_SCOPE_DEBUG_ONLY,
false)
template <typename... Scopes>
class CombinationAssertScope;
......@@ -131,20 +198,6 @@ class V8_NODISCARD PerThreadAssertScopeDebugOnly {
#endif
};
template <PerIsolateAssertType kType, bool kAllow>
#ifdef DEBUG
class PerIsolateAssertScopeDebugOnly
: public PerIsolateAssertScope<kType, kAllow> {
public:
explicit PerIsolateAssertScopeDebugOnly(Isolate* isolate)
: PerIsolateAssertScope<kType, kAllow>(isolate) {}
#else
class V8_NODISCARD PerIsolateAssertScopeDebugOnly {
public:
explicit PerIsolateAssertScopeDebugOnly(Isolate* isolate) {}
#endif
};
// Per-thread assert scopes.
// Scope to document where we do not expect handles to be created.
......@@ -259,64 +312,6 @@ class V8_NODISCARD NoGarbageCollectionMutexGuard {
std::unique_ptr<DisallowGarbageCollection> no_gc_;
};
// Per-isolate assert scopes.
// Scope to document where we do not expect javascript execution.
using DisallowJavascriptExecution =
PerIsolateAssertScope<JAVASCRIPT_EXECUTION_ASSERT, false>;
// Scope to introduce an exception to DisallowJavascriptExecution.
using AllowJavascriptExecution =
PerIsolateAssertScope<JAVASCRIPT_EXECUTION_ASSERT, true>;
// Scope to document where we do not expect javascript execution (debug only)
using DisallowJavascriptExecutionDebugOnly =
PerIsolateAssertScopeDebugOnly<JAVASCRIPT_EXECUTION_ASSERT, false>;
// Scope to introduce an exception to DisallowJavascriptExecutionDebugOnly.
using AllowJavascriptExecutionDebugOnly =
PerIsolateAssertScopeDebugOnly<JAVASCRIPT_EXECUTION_ASSERT, true>;
// Scope in which javascript execution leads to exception being thrown.
using ThrowOnJavascriptExecution =
PerIsolateAssertScope<JAVASCRIPT_EXECUTION_THROWS, false>;
// Scope to introduce an exception to ThrowOnJavascriptExecution.
using NoThrowOnJavascriptExecution =
PerIsolateAssertScope<JAVASCRIPT_EXECUTION_THROWS, true>;
// Scope in which javascript execution causes dumps.
using DumpOnJavascriptExecution =
PerIsolateAssertScope<JAVASCRIPT_EXECUTION_DUMP, false>;
// Scope in which javascript execution causes dumps.
using NoDumpOnJavascriptExecution =
PerIsolateAssertScope<JAVASCRIPT_EXECUTION_DUMP, true>;
// Scope to document where we do not expect deoptimization.
using DisallowDeoptimization =
PerIsolateAssertScopeDebugOnly<DEOPTIMIZATION_ASSERT, false>;
// Scope to introduce an exception to DisallowDeoptimization.
using AllowDeoptimization =
PerIsolateAssertScopeDebugOnly<DEOPTIMIZATION_ASSERT, true>;
// Scope to document where we do not expect deoptimization.
using DisallowCompilation =
PerIsolateAssertScopeDebugOnly<COMPILATION_ASSERT, false>;
// Scope to introduce an exception to DisallowDeoptimization.
using AllowCompilation =
PerIsolateAssertScopeDebugOnly<COMPILATION_ASSERT, true>;
// Scope to document where we do not expect exceptions.
using DisallowExceptions =
PerIsolateAssertScopeDebugOnly<NO_EXCEPTION_ASSERT, false>;
// Scope to introduce an exception to DisallowExceptions.
using AllowExceptions =
PerIsolateAssertScopeDebugOnly<NO_EXCEPTION_ASSERT, true>;
// Explicit instantiation declarations.
extern template class PerThreadAssertScope<HEAP_ALLOCATION_ASSERT, false>;
extern template class PerThreadAssertScope<HEAP_ALLOCATION_ASSERT, true>;
......@@ -333,19 +328,6 @@ extern template class PerThreadAssertScope<CODE_ALLOCATION_ASSERT, false>;
extern template class PerThreadAssertScope<CODE_ALLOCATION_ASSERT, true>;
extern template class PerThreadAssertScope<GC_MOLE, false>;
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
......
......@@ -453,7 +453,6 @@ using DebugObjectCache = std::vector<Handle<HeapObject>>;
V(MicrotaskQueue*, default_microtask_queue, nullptr) \
V(CompilationStatistics*, turbo_statistics, nullptr) \
V(CodeTracer*, code_tracer, nullptr) \
V(uint32_t, per_isolate_assert_data, 0xFFFFFFFFu) \
V(PromiseRejectCallback, promise_reject_callback, nullptr) \
V(const v8::StartupData*, snapshot_blob, nullptr) \
V(int, code_and_metadata_size, 0) \
......@@ -476,7 +475,13 @@ using DebugObjectCache = std::vector<Handle<HeapObject>>;
V(int, embedder_wrapper_object_index, -1) \
V(compiler::NodeObserver*, node_observer, nullptr) \
/* Used in combination with --script-run-delay-once */ \
V(bool, did_run_script_delay, false)
V(bool, did_run_script_delay, false) \
V(bool, javascript_execution_assert, true) \
V(bool, javascript_execution_throws, true) \
V(bool, javascript_execution_dump, true) \
V(bool, deoptimization_assert, true) \
V(bool, compilation_assert, true) \
V(bool, no_exception_assert, true)
#define THREAD_LOCAL_TOP_ACCESSOR(type, name) \
inline void set_##name(type v) { thread_local_top()->name##_ = v; } \
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment