Fix initialization of assert scopes.
authorbmeurer@chromium.org <bmeurer@chromium.org>
Mon, 29 Sep 2014 09:39:22 +0000 (09:39 +0000)
committerbmeurer@chromium.org <bmeurer@chromium.org>
Mon, 29 Sep 2014 09:39:22 +0000 (09:39 +0000)
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
src/assert-scope.h
src/isolate.cc
src/test/run-all-unittests.cc

index c4aa987..4c10fdd 100644 (file)
 // 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
index 7cfec56..41baa65 100644 (file)
@@ -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);
 };
index edc8326..7d1f835 100644 (file)
@@ -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();
 }
 
index de56365..8c361dd 100644 (file)
@@ -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);