1b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Copyright 2014 the V8 project authors. All rights reserved.
2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file.
4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/assert-scope.h"
6958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
7958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/base/lazy-instance.h"
8958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/base/platform/platform.h"
9014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/isolate.h"
10958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/utils.h"
11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace v8 {
13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace internal {
14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
15958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniernamespace {
16958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
17014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochstruct PerThreadAssertKeyConstructTrait final {
18958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  static void Construct(base::Thread::LocalStorageKey* key) {
19958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    *key = base::Thread::CreateThreadLocalKey();
20958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
21958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier};
22958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
23958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
24958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniertypedef base::LazyStaticInstance<base::Thread::LocalStorageKey,
25958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                 PerThreadAssertKeyConstructTrait>::type
26958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    PerThreadAssertKey;
27958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
28958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
29958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierPerThreadAssertKey kPerThreadAssertKey;
30958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
31958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}  // namespace
32958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
33958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
34014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochclass PerThreadAssertData final {
35958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier public:
36958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  PerThreadAssertData() : nesting_level_(0) {
37958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    for (int i = 0; i < LAST_PER_THREAD_ASSERT_TYPE; i++) {
38958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      assert_states_[i] = true;
39958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
40958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
41958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
42958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  ~PerThreadAssertData() {
43958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    for (int i = 0; i < LAST_PER_THREAD_ASSERT_TYPE; ++i) {
44958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      DCHECK(assert_states_[i]);
45958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
46958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
47958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
48958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bool Get(PerThreadAssertType type) const { return assert_states_[type]; }
49958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void Set(PerThreadAssertType type, bool x) { assert_states_[type] = x; }
50958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
51958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void IncrementLevel() { ++nesting_level_; }
52958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bool DecrementLevel() { return --nesting_level_ == 0; }
53958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
54958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  static PerThreadAssertData* GetCurrent() {
55958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return reinterpret_cast<PerThreadAssertData*>(
56958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        base::Thread::GetThreadLocal(kPerThreadAssertKey.Get()));
57958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
58958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  static void SetCurrent(PerThreadAssertData* data) {
59958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    base::Thread::SetThreadLocal(kPerThreadAssertKey.Get(), data);
60958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
61958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
62958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier private:
63958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bool assert_states_[LAST_PER_THREAD_ASSERT_TYPE];
64958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int nesting_level_;
65958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
66958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DISALLOW_COPY_AND_ASSIGN(PerThreadAssertData);
67958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier};
68958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
69958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
70958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniertemplate <PerThreadAssertType kType, bool kAllow>
71958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierPerThreadAssertScope<kType, kAllow>::PerThreadAssertScope()
72958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    : data_(PerThreadAssertData::GetCurrent()) {
73958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (data_ == NULL) {
74958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    data_ = new PerThreadAssertData();
75958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    PerThreadAssertData::SetCurrent(data_);
76958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
77958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  data_->IncrementLevel();
78958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  old_state_ = data_->Get(kType);
79958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  data_->Set(kType, kAllow);
80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
83958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniertemplate <PerThreadAssertType kType, bool kAllow>
84958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierPerThreadAssertScope<kType, kAllow>::~PerThreadAssertScope() {
8562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (data_ == nullptr) return;
8662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Release();
8762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
8862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
8962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochtemplate <PerThreadAssertType kType, bool kAllow>
9062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochvoid PerThreadAssertScope<kType, kAllow>::Release() {
91958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK_NOT_NULL(data_);
92958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  data_->Set(kType, old_state_);
93958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (data_->DecrementLevel()) {
94958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    PerThreadAssertData::SetCurrent(NULL);
95958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    delete data_;
96958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
9762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  data_ = nullptr;
98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
100958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// static
101958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniertemplate <PerThreadAssertType kType, bool kAllow>
102958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierbool PerThreadAssertScope<kType, kAllow>::IsAllowed() {
103958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  PerThreadAssertData* data = PerThreadAssertData::GetCurrent();
104958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  return data == NULL || data->Get(kType);
105958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
106958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
107958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
108958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniertemplate <PerIsolateAssertType kType, bool kAllow>
109958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierclass PerIsolateAssertScope<kType, kAllow>::DataBit
110958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    : public BitField<bool, kType, 1> {};
111958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
112958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
113958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniertemplate <PerIsolateAssertType kType, bool kAllow>
114958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierPerIsolateAssertScope<kType, kAllow>::PerIsolateAssertScope(Isolate* isolate)
115958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    : isolate_(isolate), old_data_(isolate->per_isolate_assert_data()) {
116958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK_NOT_NULL(isolate);
117958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  STATIC_ASSERT(kType < 32);
118958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  isolate_->set_per_isolate_assert_data(DataBit::update(old_data_, kAllow));
119958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
120958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
121958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
122958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniertemplate <PerIsolateAssertType kType, bool kAllow>
123958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierPerIsolateAssertScope<kType, kAllow>::~PerIsolateAssertScope() {
124958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  isolate_->set_per_isolate_assert_data(old_data_);
125958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
126958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
127958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
128958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// static
129958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniertemplate <PerIsolateAssertType kType, bool kAllow>
130958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierbool PerIsolateAssertScope<kType, kAllow>::IsAllowed(Isolate* isolate) {
131958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  return DataBit::decode(isolate->per_isolate_assert_data());
132958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
133958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
134958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
135958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// -----------------------------------------------------------------------------
136958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Instantiations.
137958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
138958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniertemplate class PerThreadAssertScope<HEAP_ALLOCATION_ASSERT, false>;
139958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniertemplate class PerThreadAssertScope<HEAP_ALLOCATION_ASSERT, true>;
140958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniertemplate class PerThreadAssertScope<HANDLE_ALLOCATION_ASSERT, false>;
141958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniertemplate class PerThreadAssertScope<HANDLE_ALLOCATION_ASSERT, true>;
142958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniertemplate class PerThreadAssertScope<HANDLE_DEREFERENCE_ASSERT, false>;
143958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniertemplate class PerThreadAssertScope<HANDLE_DEREFERENCE_ASSERT, true>;
144958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniertemplate class PerThreadAssertScope<DEFERRED_HANDLE_DEREFERENCE_ASSERT, false>;
145958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniertemplate class PerThreadAssertScope<DEFERRED_HANDLE_DEREFERENCE_ASSERT, true>;
146958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniertemplate class PerThreadAssertScope<CODE_DEPENDENCY_CHANGE_ASSERT, false>;
147958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniertemplate class PerThreadAssertScope<CODE_DEPENDENCY_CHANGE_ASSERT, true>;
148958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
149958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniertemplate class PerIsolateAssertScope<JAVASCRIPT_EXECUTION_ASSERT, false>;
150958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniertemplate class PerIsolateAssertScope<JAVASCRIPT_EXECUTION_ASSERT, true>;
151958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniertemplate class PerIsolateAssertScope<JAVASCRIPT_EXECUTION_THROWS, false>;
152958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniertemplate class PerIsolateAssertScope<JAVASCRIPT_EXECUTION_THROWS, true>;
153958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniertemplate class PerIsolateAssertScope<DEOPTIMIZATION_ASSERT, false>;
154958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniertemplate class PerIsolateAssertScope<DEOPTIMIZATION_ASSERT, true>;
155958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniertemplate class PerIsolateAssertScope<COMPILATION_ASSERT, false>;
156958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniertemplate class PerIsolateAssertScope<COMPILATION_ASSERT, true>;
15762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochtemplate class PerIsolateAssertScope<NO_EXCEPTION_ASSERT, false>;
15862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochtemplate class PerIsolateAssertScope<NO_EXCEPTION_ASSERT, true>;
159958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
160958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}  // namespace internal
161958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}  // namespace v8
162