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_HANDLES_INL_H_ 6#define V8_HANDLES_HANDLES_INL_H_ 7 8#include "src/base/sanitizer/msan.h" 9#include "src/execution/isolate.h" 10#include "src/execution/local-isolate.h" 11#include "src/handles/handles.h" 12#include "src/handles/local-handles-inl.h" 13#include "src/objects/objects.h" 14 15namespace v8 { 16namespace internal { 17 18class LocalHeap; 19 20HandleBase::HandleBase(Address object, Isolate* isolate) 21 : location_(HandleScope::GetHandle(isolate, object)) {} 22 23HandleBase::HandleBase(Address object, LocalIsolate* isolate) 24 : location_(LocalHandleScope::GetHandle(isolate->heap(), object)) {} 25 26HandleBase::HandleBase(Address object, LocalHeap* local_heap) 27 : location_(LocalHandleScope::GetHandle(local_heap, object)) {} 28 29bool HandleBase::is_identical_to(const HandleBase that) const { 30 SLOW_DCHECK((this->location_ == nullptr || this->IsDereferenceAllowed()) && 31 (that.location_ == nullptr || that.IsDereferenceAllowed())); 32 if (this->location_ == that.location_) return true; 33 if (this->location_ == nullptr || that.location_ == nullptr) return false; 34 return Object(*this->location_) == Object(*that.location_); 35} 36 37// Allocate a new handle for the object, do not canonicalize. 38template <typename T> 39Handle<T> Handle<T>::New(T object, Isolate* isolate) { 40 return Handle(HandleScope::CreateHandle(isolate, object.ptr())); 41} 42 43template <typename T> 44template <typename S> 45const Handle<T> Handle<T>::cast(Handle<S> that) { 46 T::cast(*FullObjectSlot(that.location())); 47 return Handle<T>(that.location_); 48} 49 50template <typename T> 51Handle<T>::Handle(T object, Isolate* isolate) 52 : HandleBase(object.ptr(), isolate) {} 53 54template <typename T> 55Handle<T>::Handle(T object, LocalIsolate* isolate) 56 : HandleBase(object.ptr(), isolate) {} 57 58template <typename T> 59Handle<T>::Handle(T object, LocalHeap* local_heap) 60 : HandleBase(object.ptr(), local_heap) {} 61 62template <typename T> 63V8_INLINE Handle<T> handle(T object, Isolate* isolate) { 64 return Handle<T>(object, isolate); 65} 66 67template <typename T> 68V8_INLINE Handle<T> handle(T object, LocalIsolate* isolate) { 69 return Handle<T>(object, isolate); 70} 71 72template <typename T> 73V8_INLINE Handle<T> handle(T object, LocalHeap* local_heap) { 74 return Handle<T>(object, local_heap); 75} 76 77template <typename T> 78inline std::ostream& operator<<(std::ostream& os, Handle<T> handle) { 79 return os << Brief(*handle); 80} 81 82HandleScope::HandleScope(Isolate* isolate) { 83 HandleScopeData* data = isolate->handle_scope_data(); 84 isolate_ = isolate; 85 prev_next_ = data->next; 86 prev_limit_ = data->limit; 87 data->level++; 88} 89 90HandleScope::HandleScope(HandleScope&& other) V8_NOEXCEPT 91 : isolate_(other.isolate_), 92 prev_next_(other.prev_next_), 93 prev_limit_(other.prev_limit_) { 94 other.isolate_ = nullptr; 95} 96 97HandleScope::~HandleScope() { 98 if (V8_UNLIKELY(isolate_ == nullptr)) return; 99 CloseScope(isolate_, prev_next_, prev_limit_); 100} 101 102HandleScope& HandleScope::operator=(HandleScope&& other) V8_NOEXCEPT { 103 if (isolate_ == nullptr) { 104 isolate_ = other.isolate_; 105 } else { 106 DCHECK_EQ(isolate_, other.isolate_); 107 CloseScope(isolate_, prev_next_, prev_limit_); 108 } 109 prev_next_ = other.prev_next_; 110 prev_limit_ = other.prev_limit_; 111 other.isolate_ = nullptr; 112 return *this; 113} 114 115void HandleScope::CloseScope(Isolate* isolate, Address* prev_next, 116 Address* prev_limit) { 117#ifdef DEBUG 118 int before = FLAG_check_handle_count ? NumberOfHandles(isolate) : 0; 119#endif 120 DCHECK_NOT_NULL(isolate); 121 HandleScopeData* current = isolate->handle_scope_data(); 122 123 std::swap(current->next, prev_next); 124 current->level--; 125 Address* limit = prev_next; 126 if (V8_UNLIKELY(current->limit != prev_limit)) { 127 current->limit = prev_limit; 128 limit = prev_limit; 129 DeleteExtensions(isolate); 130 } 131#ifdef ENABLE_HANDLE_ZAPPING 132 ZapRange(current->next, limit); 133#endif 134 MSAN_ALLOCATED_UNINITIALIZED_MEMORY( 135 current->next, 136 static_cast<size_t>(reinterpret_cast<Address>(limit) - 137 reinterpret_cast<Address>(current->next))); 138#ifdef DEBUG 139 int after = FLAG_check_handle_count ? NumberOfHandles(isolate) : 0; 140 DCHECK_LT(after - before, kCheckHandleThreshold); 141 DCHECK_LT(before, kCheckHandleThreshold); 142#endif 143} 144 145template <typename T> 146Handle<T> HandleScope::CloseAndEscape(Handle<T> handle_value) { 147 HandleScopeData* current = isolate_->handle_scope_data(); 148 T value = *handle_value; 149 // Throw away all handles in the current scope. 150 CloseScope(isolate_, prev_next_, prev_limit_); 151 // Allocate one handle in the parent scope. 152 DCHECK(current->level > current->sealed_level); 153 Handle<T> result(value, isolate_); 154 // Reinitialize the current scope (so that it's ready 155 // to be used or closed again). 156 prev_next_ = current->next; 157 prev_limit_ = current->limit; 158 current->level++; 159 return result; 160} 161 162Address* HandleScope::CreateHandle(Isolate* isolate, Address value) { 163 DCHECK(AllowHandleAllocation::IsAllowed()); 164 HandleScopeData* data = isolate->handle_scope_data(); 165 Address* result = data->next; 166 if (result == data->limit) { 167 result = Extend(isolate); 168 } 169 // Update the current next field, set the value in the created handle, 170 // and return the result. 171 DCHECK_LT(reinterpret_cast<Address>(result), 172 reinterpret_cast<Address>(data->limit)); 173 data->next = reinterpret_cast<Address*>(reinterpret_cast<Address>(result) + 174 sizeof(Address)); 175 *result = value; 176 return result; 177} 178 179Address* HandleScope::GetHandle(Isolate* isolate, Address value) { 180 DCHECK(AllowHandleAllocation::IsAllowed()); 181 DCHECK(isolate->main_thread_local_heap()->IsRunning()); 182 DCHECK_WITH_MSG(isolate->thread_id() == ThreadId::Current(), 183 "main-thread handle can only be created on the main thread."); 184 HandleScopeData* data = isolate->handle_scope_data(); 185 CanonicalHandleScope* canonical = data->canonical_scope; 186 return canonical ? canonical->Lookup(value) : CreateHandle(isolate, value); 187} 188 189#ifdef DEBUG 190inline SealHandleScope::SealHandleScope(Isolate* isolate) : isolate_(isolate) { 191 // Make sure the current thread is allowed to create handles to begin with. 192 DCHECK(AllowHandleAllocation::IsAllowed()); 193 HandleScopeData* current = isolate_->handle_scope_data(); 194 // Shrink the current handle scope to make it impossible to do 195 // handle allocations without an explicit handle scope. 196 prev_limit_ = current->limit; 197 current->limit = current->next; 198 prev_sealed_level_ = current->sealed_level; 199 current->sealed_level = current->level; 200} 201 202inline SealHandleScope::~SealHandleScope() { 203 // Restore state in current handle scope to re-enable handle 204 // allocations. 205 HandleScopeData* current = isolate_->handle_scope_data(); 206 DCHECK_EQ(current->next, current->limit); 207 current->limit = prev_limit_; 208 DCHECK_EQ(current->level, current->sealed_level); 209 current->sealed_level = prev_sealed_level_; 210} 211 212#endif 213 214} // namespace internal 215} // namespace v8 216 217#endif // V8_HANDLES_HANDLES_INL_H_ 218