1 | // Copyright 2006-2008 the V8 project authors. All rights reserved. |
2 | // Use of this source code is governed by a BSD-style license that can be |
3 | // found in the LICENSE file. |
4 | |
5 | #ifndef V8_HANDLES_INL_H_ |
6 | #define V8_HANDLES_INL_H_ |
7 | |
8 | #include "src/handles.h" |
9 | #include "src/isolate.h" |
10 | #include "src/msan.h" |
11 | |
12 | namespace v8 { |
13 | namespace internal { |
14 | |
15 | HandleBase::HandleBase(Address object, Isolate* isolate) |
16 | : location_(HandleScope::GetHandle(isolate, object)) {} |
17 | |
18 | // Allocate a new handle for the object, do not canonicalize. |
19 | |
20 | template <typename T> |
21 | Handle<T> Handle<T>::New(T object, Isolate* isolate) { |
22 | return Handle(HandleScope::CreateHandle(isolate, object.ptr())); |
23 | } |
24 | |
25 | template <typename T> |
26 | template <typename S> |
27 | const Handle<T> Handle<T>::cast(Handle<S> that) { |
28 | T::cast(*FullObjectSlot(that.location())); |
29 | return Handle<T>(that.location_); |
30 | } |
31 | |
32 | HandleScope::HandleScope(Isolate* isolate) { |
33 | HandleScopeData* data = isolate->handle_scope_data(); |
34 | isolate_ = isolate; |
35 | prev_next_ = data->next; |
36 | prev_limit_ = data->limit; |
37 | data->level++; |
38 | } |
39 | |
40 | template <typename T> |
41 | Handle<T>::Handle(T object, Isolate* isolate) |
42 | : HandleBase(object.ptr(), isolate) {} |
43 | |
44 | template <typename T> |
45 | V8_INLINE Handle<T> handle(T object, Isolate* isolate) { |
46 | return Handle<T>(object, isolate); |
47 | } |
48 | |
49 | template <typename T> |
50 | inline std::ostream& operator<<(std::ostream& os, Handle<T> handle) { |
51 | return os << Brief(*handle); |
52 | } |
53 | |
54 | HandleScope::~HandleScope() { |
55 | #ifdef DEBUG |
56 | if (FLAG_check_handle_count) { |
57 | int before = NumberOfHandles(isolate_); |
58 | CloseScope(isolate_, prev_next_, prev_limit_); |
59 | int after = NumberOfHandles(isolate_); |
60 | DCHECK_LT(after - before, kCheckHandleThreshold); |
61 | DCHECK_LT(before, kCheckHandleThreshold); |
62 | } else { |
63 | #endif // DEBUG |
64 | CloseScope(isolate_, prev_next_, prev_limit_); |
65 | #ifdef DEBUG |
66 | } |
67 | #endif // DEBUG |
68 | } |
69 | |
70 | void HandleScope::CloseScope(Isolate* isolate, Address* prev_next, |
71 | Address* prev_limit) { |
72 | HandleScopeData* current = isolate->handle_scope_data(); |
73 | |
74 | std::swap(current->next, prev_next); |
75 | current->level--; |
76 | Address* limit = prev_next; |
77 | if (current->limit != prev_limit) { |
78 | current->limit = prev_limit; |
79 | limit = prev_limit; |
80 | DeleteExtensions(isolate); |
81 | } |
82 | #ifdef ENABLE_HANDLE_ZAPPING |
83 | ZapRange(current->next, limit); |
84 | #endif |
85 | MSAN_ALLOCATED_UNINITIALIZED_MEMORY( |
86 | current->next, |
87 | static_cast<size_t>(reinterpret_cast<Address>(limit) - |
88 | reinterpret_cast<Address>(current->next))); |
89 | } |
90 | |
91 | template <typename T> |
92 | Handle<T> HandleScope::CloseAndEscape(Handle<T> handle_value) { |
93 | HandleScopeData* current = isolate_->handle_scope_data(); |
94 | T value = *handle_value; |
95 | // Throw away all handles in the current scope. |
96 | CloseScope(isolate_, prev_next_, prev_limit_); |
97 | // Allocate one handle in the parent scope. |
98 | DCHECK(current->level > current->sealed_level); |
99 | Handle<T> result(value, isolate_); |
100 | // Reinitialize the current scope (so that it's ready |
101 | // to be used or closed again). |
102 | prev_next_ = current->next; |
103 | prev_limit_ = current->limit; |
104 | current->level++; |
105 | return result; |
106 | } |
107 | |
108 | Address* HandleScope::CreateHandle(Isolate* isolate, Address value) { |
109 | DCHECK(AllowHandleAllocation::IsAllowed()); |
110 | HandleScopeData* data = isolate->handle_scope_data(); |
111 | Address* result = data->next; |
112 | if (result == data->limit) { |
113 | result = Extend(isolate); |
114 | } |
115 | // Update the current next field, set the value in the created handle, |
116 | // and return the result. |
117 | DCHECK_LT(reinterpret_cast<Address>(result), |
118 | reinterpret_cast<Address>(data->limit)); |
119 | data->next = reinterpret_cast<Address*>(reinterpret_cast<Address>(result) + |
120 | sizeof(Address)); |
121 | *result = value; |
122 | return result; |
123 | } |
124 | |
125 | Address* HandleScope::GetHandle(Isolate* isolate, Address value) { |
126 | DCHECK(AllowHandleAllocation::IsAllowed()); |
127 | HandleScopeData* data = isolate->handle_scope_data(); |
128 | CanonicalHandleScope* canonical = data->canonical_scope; |
129 | return canonical ? canonical->Lookup(value) : CreateHandle(isolate, value); |
130 | } |
131 | |
132 | |
133 | #ifdef DEBUG |
134 | inline SealHandleScope::SealHandleScope(Isolate* isolate) : isolate_(isolate) { |
135 | // Make sure the current thread is allowed to create handles to begin with. |
136 | DCHECK(AllowHandleAllocation::IsAllowed()); |
137 | HandleScopeData* current = isolate_->handle_scope_data(); |
138 | // Shrink the current handle scope to make it impossible to do |
139 | // handle allocations without an explicit handle scope. |
140 | prev_limit_ = current->limit; |
141 | current->limit = current->next; |
142 | prev_sealed_level_ = current->sealed_level; |
143 | current->sealed_level = current->level; |
144 | } |
145 | |
146 | |
147 | inline SealHandleScope::~SealHandleScope() { |
148 | // Restore state in current handle scope to re-enable handle |
149 | // allocations. |
150 | HandleScopeData* current = isolate_->handle_scope_data(); |
151 | DCHECK_EQ(current->next, current->limit); |
152 | current->limit = prev_limit_; |
153 | DCHECK_EQ(current->level, current->sealed_level); |
154 | current->sealed_level = prev_sealed_level_; |
155 | } |
156 | |
157 | #endif |
158 | |
159 | } // namespace internal |
160 | } // namespace v8 |
161 | |
162 | #endif // V8_HANDLES_INL_H_ |
163 | |