Commit f6e97c90 authored by bmeurer@chromium.org's avatar bmeurer@chromium.org

Fix initialization of assert scopes.

The thread local key for assert scopes can be lazily initialized and
should be independent of the Isolate initialization. Also cleanup the
assert-scope.{cc,h} implementation while I was at it.

R=dcarney@chromium.org

Review URL: https://codereview.chromium.org/609253002

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24275 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent b0fdeb1b
......@@ -2,20 +2,154 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/assert-scope.h"
#include "src/v8.h"
#include "src/base/lazy-instance.h"
#include "src/base/platform/platform.h"
#include "src/isolate-inl.h"
#include "src/utils.h"
namespace v8 {
namespace internal {
uint32_t PerIsolateAssertBase::GetData(Isolate* isolate) {
return isolate->per_isolate_assert_data();
namespace {
struct PerThreadAssertKeyConstructTrait FINAL {
static void Construct(base::Thread::LocalStorageKey* key) {
*key = base::Thread::CreateThreadLocalKey();
}
};
typedef base::LazyStaticInstance<base::Thread::LocalStorageKey,
PerThreadAssertKeyConstructTrait>::type
PerThreadAssertKey;
PerThreadAssertKey kPerThreadAssertKey;
} // namespace
class PerThreadAssertData FINAL {
public:
PerThreadAssertData() : nesting_level_(0) {
for (int i = 0; i < LAST_PER_THREAD_ASSERT_TYPE; i++) {
assert_states_[i] = true;
}
}
~PerThreadAssertData() {
for (int i = 0; i < LAST_PER_THREAD_ASSERT_TYPE; ++i) {
DCHECK(assert_states_[i]);
}
}
bool Get(PerThreadAssertType type) const { return assert_states_[type]; }
void Set(PerThreadAssertType type, bool x) { assert_states_[type] = x; }
void IncrementLevel() { ++nesting_level_; }
bool DecrementLevel() { return --nesting_level_ == 0; }
static PerThreadAssertData* GetCurrent() {
return reinterpret_cast<PerThreadAssertData*>(
base::Thread::GetThreadLocal(kPerThreadAssertKey.Get()));
}
static void SetCurrent(PerThreadAssertData* data) {
base::Thread::SetThreadLocal(kPerThreadAssertKey.Get(), data);
}
private:
bool assert_states_[LAST_PER_THREAD_ASSERT_TYPE];
int nesting_level_;
DISALLOW_COPY_AND_ASSIGN(PerThreadAssertData);
};
template <PerThreadAssertType kType, bool kAllow>
PerThreadAssertScope<kType, kAllow>::PerThreadAssertScope()
: data_(PerThreadAssertData::GetCurrent()) {
if (data_ == NULL) {
data_ = new PerThreadAssertData();
PerThreadAssertData::SetCurrent(data_);
}
data_->IncrementLevel();
old_state_ = data_->Get(kType);
data_->Set(kType, kAllow);
}
void PerIsolateAssertBase::SetData(Isolate* isolate, uint32_t data) {
isolate->set_per_isolate_assert_data(data);
template <PerThreadAssertType kType, bool kAllow>
PerThreadAssertScope<kType, kAllow>::~PerThreadAssertScope() {
DCHECK_NOT_NULL(data_);
data_->Set(kType, old_state_);
if (data_->DecrementLevel()) {
PerThreadAssertData::SetCurrent(NULL);
delete data_;
}
}
} } // namespace v8::internal
// static
template <PerThreadAssertType kType, bool kAllow>
bool PerThreadAssertScope<kType, kAllow>::IsAllowed() {
PerThreadAssertData* data = PerThreadAssertData::GetCurrent();
return data == NULL || data->Get(kType);
}
template <PerIsolateAssertType kType, bool kAllow>
class PerIsolateAssertScope<kType, kAllow>::DataBit
: public BitField<bool, kType, 1> {};
template <PerIsolateAssertType kType, bool kAllow>
PerIsolateAssertScope<kType, kAllow>::PerIsolateAssertScope(Isolate* isolate)
: isolate_(isolate), old_data_(isolate->per_isolate_assert_data()) {
DCHECK_NOT_NULL(isolate);
STATIC_ASSERT(kType < 32);
isolate_->set_per_isolate_assert_data(DataBit::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 DataBit::decode(isolate->per_isolate_assert_data());
}
// -----------------------------------------------------------------------------
// Instantiations.
template class PerThreadAssertScope<HEAP_ALLOCATION_ASSERT, false>;
template class PerThreadAssertScope<HEAP_ALLOCATION_ASSERT, true>;
template class PerThreadAssertScope<HANDLE_ALLOCATION_ASSERT, false>;
template class PerThreadAssertScope<HANDLE_ALLOCATION_ASSERT, true>;
template class PerThreadAssertScope<HANDLE_DEREFERENCE_ASSERT, false>;
template class PerThreadAssertScope<HANDLE_DEREFERENCE_ASSERT, true>;
template class PerThreadAssertScope<DEFERRED_HANDLE_DEREFERENCE_ASSERT, false>;
template class PerThreadAssertScope<DEFERRED_HANDLE_DEREFERENCE_ASSERT, true>;
template class PerThreadAssertScope<CODE_DEPENDENCY_CHANGE_ASSERT, false>;
template class PerThreadAssertScope<CODE_DEPENDENCY_CHANGE_ASSERT, true>;
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<ALLOCATION_FAILURE_ASSERT, false>;
template class PerIsolateAssertScope<ALLOCATION_FAILURE_ASSERT, 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>;
} // namespace internal
} // namespace v8
......@@ -5,14 +5,16 @@
#ifndef V8_ASSERT_SCOPE_H_
#define V8_ASSERT_SCOPE_H_
#include "src/allocation.h"
#include "src/base/platform/platform.h"
#include "src/utils.h"
#include "include/v8stdint.h"
#include "src/base/macros.h"
namespace v8 {
namespace internal {
// Forward declarations.
class Isolate;
class PerThreadAssertData;
enum PerThreadAssertType {
HEAP_ALLOCATION_ASSERT,
......@@ -33,120 +35,35 @@ enum PerIsolateAssertType {
};
class PerThreadAssertData {
template <PerThreadAssertType kType, bool kAllow>
class PerThreadAssertScope {
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];
}
PerThreadAssertScope();
~PerThreadAssertScope();
void increment_level() { ++nesting_level_; }
bool decrement_level() { return --nesting_level_ == 0; }
static bool IsAllowed();
private:
bool assert_states_[LAST_PER_THREAD_ASSERT_TYPE];
int nesting_level_;
DISALLOW_COPY_AND_ASSIGN(PerThreadAssertData);
};
class PerThreadAssertScopeBase {
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++) {
DCHECK(data_->get(static_cast<PerThreadAssertType>(i)));
}
delete data_;
SetThreadLocalData(NULL);
}
static PerThreadAssertData* GetAssertData() {
return reinterpret_cast<PerThreadAssertData*>(
base::Thread::GetThreadLocal(thread_local_key));
}
static base::Thread::LocalStorageKey thread_local_key;
PerThreadAssertData* data_;
friend class Isolate;
private:
static void SetThreadLocalData(PerThreadAssertData* data) {
base::Thread::SetThreadLocal(thread_local_key, data);
}
};
template <PerThreadAssertType type, bool allow>
class PerThreadAssertScope : public PerThreadAssertScopeBase {
public:
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_;
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 {
class PerIsolateAssertScope {
public:
explicit PerIsolateAssertScope(Isolate* isolate) : isolate_(isolate) {
STATIC_ASSERT(type < 32);
old_data_ = GetData(isolate_);
SetData(isolate_, DataBit::update(old_data_, allow));
}
explicit PerIsolateAssertScope(Isolate* isolate);
~PerIsolateAssertScope();
~PerIsolateAssertScope() {
SetData(isolate_, old_data_);
}
static bool IsAllowed(Isolate* isolate) {
return DataBit::decode(GetData(isolate));
}
static bool IsAllowed(Isolate* isolate);
private:
typedef BitField<bool, type, 1> DataBit;
class DataBit;
uint32_t old_data_;
Isolate* isolate_;
uint32_t old_data_;
DISALLOW_COPY_AND_ASSIGN(PerIsolateAssertScope);
};
......
......@@ -111,9 +111,6 @@ void ThreadLocalTop::Free() {
base::Thread::LocalStorageKey Isolate::isolate_key_;
base::Thread::LocalStorageKey Isolate::thread_id_key_;
base::Thread::LocalStorageKey Isolate::per_isolate_thread_data_key_;
#ifdef DEBUG
base::Thread::LocalStorageKey PerThreadAssertScopeBase::thread_local_key;
#endif // DEBUG
base::LazyMutex Isolate::thread_data_table_mutex_ = LAZY_MUTEX_INITIALIZER;
Isolate::ThreadDataTable* Isolate::thread_data_table_ = NULL;
base::Atomic32 Isolate::isolate_counter_ = 0;
......@@ -158,10 +155,6 @@ void Isolate::InitializeOncePerProcess() {
isolate_key_ = base::Thread::CreateThreadLocalKey();
thread_id_key_ = base::Thread::CreateThreadLocalKey();
per_isolate_thread_data_key_ = base::Thread::CreateThreadLocalKey();
#ifdef DEBUG
PerThreadAssertScopeBase::thread_local_key =
base::Thread::CreateThreadLocalKey();
#endif // DEBUG
thread_data_table_ = new Isolate::ThreadDataTable();
}
......
......@@ -5,7 +5,6 @@
#include "include/libplatform/libplatform.h"
#include "include/v8.h"
#include "src/base/compiler-specific.h"
#include "src/v8.h"
#include "testing/gmock/include/gmock/gmock.h"
namespace {
......@@ -39,9 +38,6 @@ class DefaultPlatformEnvironment FINAL : public ::testing::Environment {
int main(int argc, char** argv) {
// This forces some thread local key initialization that may be needed to
// print out the names of the unit tests.
i::V8::Initialize();
testing::InitGoogleMock(&argc, argv);
testing::AddGlobalTestEnvironment(new DefaultPlatformEnvironment);
v8::V8::SetFlagsFromCommandLine(&argc, argv, true);
......
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