From f6e97c90fb9c78639ad9d06040a95879fd6b9abc Mon Sep 17 00:00:00 2001 From: "bmeurer@chromium.org" Date: Mon, 29 Sep 2014 09:39:22 +0000 Subject: [PATCH] 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 --- src/assert-scope.cc | 148 ++++++++++++++++++++++++++++++++++++++++-- src/assert-scope.h | 115 +++++--------------------------- src/isolate.cc | 7 -- src/test/run-all-unittests.cc | 4 -- 4 files changed, 157 insertions(+), 117 deletions(-) diff --git a/src/assert-scope.cc b/src/assert-scope.cc index c4aa987..4c10fdd 100644 --- a/src/assert-scope.cc +++ b/src/assert-scope.cc @@ -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::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( + 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 +PerThreadAssertScope::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 +PerThreadAssertScope::~PerThreadAssertScope() { + DCHECK_NOT_NULL(data_); + data_->Set(kType, old_state_); + if (data_->DecrementLevel()) { + PerThreadAssertData::SetCurrent(NULL); + delete data_; + } } -} } // namespace v8::internal + +// static +template +bool PerThreadAssertScope::IsAllowed() { + PerThreadAssertData* data = PerThreadAssertData::GetCurrent(); + return data == NULL || data->Get(kType); +} + + +template +class PerIsolateAssertScope::DataBit + : public BitField {}; + + +template +PerIsolateAssertScope::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 +PerIsolateAssertScope::~PerIsolateAssertScope() { + isolate_->set_per_isolate_assert_data(old_data_); +} + + +// static +template +bool PerIsolateAssertScope::IsAllowed(Isolate* isolate) { + return DataBit::decode(isolate->per_isolate_assert_data()); +} + + +// ----------------------------------------------------------------------------- +// Instantiations. + +template class PerThreadAssertScope; +template class PerThreadAssertScope; +template class PerThreadAssertScope; +template class PerThreadAssertScope; +template class PerThreadAssertScope; +template class PerThreadAssertScope; +template class PerThreadAssertScope; +template class PerThreadAssertScope; +template class PerThreadAssertScope; +template class PerThreadAssertScope; + +template class PerIsolateAssertScope; +template class PerIsolateAssertScope; +template class PerIsolateAssertScope; +template class PerIsolateAssertScope; +template class PerIsolateAssertScope; +template class PerIsolateAssertScope; +template class PerIsolateAssertScope; +template class PerIsolateAssertScope; +template class PerIsolateAssertScope; +template class PerIsolateAssertScope; + +} // namespace internal +} // namespace v8 diff --git a/src/assert-scope.h b/src/assert-scope.h index 7cfec56..41baa65 100644 --- a/src/assert-scope.h +++ b/src/assert-scope.h @@ -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 +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(i))); - } - delete data_; - SetThreadLocalData(NULL); - } - - static PerThreadAssertData* GetAssertData() { - return reinterpret_cast( - 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 -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 -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 DataBit; + class DataBit; - uint32_t old_data_; Isolate* isolate_; + uint32_t old_data_; DISALLOW_COPY_AND_ASSIGN(PerIsolateAssertScope); }; diff --git a/src/isolate.cc b/src/isolate.cc index edc8326..7d1f835 100644 --- a/src/isolate.cc +++ b/src/isolate.cc @@ -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(); } diff --git a/src/test/run-all-unittests.cc b/src/test/run-all-unittests.cc index de56365..8c361dd 100644 --- a/src/test/run-all-unittests.cc +++ b/src/test/run-all-unittests.cc @@ -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); -- 2.7.4