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(Object* object, Isolate* isolate) 16 : location_(HandleScope::GetHandle(isolate, object)) {} 17 18 19 template <typename T> 20 // Allocate a new handle for the object, do not canonicalize. 21 Handle<T> Handle<T>::New(T* object, Isolate* isolate) { 22 return Handle( 23 reinterpret_cast<T**>(HandleScope::CreateHandle(isolate, object))); 24 } 25 26 template <typename T> 27 template <typename S> 28 const Handle<T> Handle<T>::cast(Handle<S> that) { 29 T::cast(*reinterpret_cast<T**>(that.location())); 30 return Handle<T>(reinterpret_cast<T**>(that.location_)); 31 } 32 33 HandleScope::HandleScope(Isolate* isolate) { 34 HandleScopeData* data = isolate->handle_scope_data(); 35 isolate_ = isolate; 36 prev_next_ = data->next; 37 prev_limit_ = data->limit; 38 data->level++; 39 } 40 41 template <typename T> 42 Handle<T>::Handle(T* object, Isolate* isolate) : HandleBase(object, 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 71 void HandleScope::CloseScope(Isolate* isolate, 72 Object** prev_next, 73 Object** prev_limit) { 74 HandleScopeData* current = isolate->handle_scope_data(); 75 76 std::swap(current->next, prev_next); 77 current->level--; 78 Object** limit = prev_next; 79 if (current->limit != prev_limit) { 80 current->limit = prev_limit; 81 limit = prev_limit; 82 DeleteExtensions(isolate); 83 } 84 #ifdef ENABLE_HANDLE_ZAPPING 85 ZapRange(current->next, limit); 86 #endif 87 MSAN_ALLOCATED_UNINITIALIZED_MEMORY( 88 current->next, static_cast<size_t>(limit - current->next)); 89 } 90 91 92 template <typename T> 93 Handle<T> HandleScope::CloseAndEscape(Handle<T> handle_value) { 94 HandleScopeData* current = isolate_->handle_scope_data(); 95 96 T* value = *handle_value; 97 // Throw away all handles in the current scope. 98 CloseScope(isolate_, prev_next_, prev_limit_); 99 // Allocate one handle in the parent scope. 100 DCHECK(current->level > current->sealed_level); 101 Handle<T> result(value, isolate_); 102 // Reinitialize the current scope (so that it's ready 103 // to be used or closed again). 104 prev_next_ = current->next; 105 prev_limit_ = current->limit; 106 current->level++; 107 return result; 108 } 109 110 Object** HandleScope::CreateHandle(Isolate* isolate, Object* value) { 111 DCHECK(AllowHandleAllocation::IsAllowed()); 112 HandleScopeData* data = isolate->handle_scope_data(); 113 114 Object** result = data->next; 115 if (result == data->limit) result = Extend(isolate); 116 // Update the current next field, set the value in the created 117 // handle, and return the result. 118 DCHECK(result < data->limit); 119 data->next = result + 1; 120 121 *result = value; 122 return result; 123 } 124 125 126 Object** HandleScope::GetHandle(Isolate* isolate, Object* value) { 127 DCHECK(AllowHandleAllocation::IsAllowed()); 128 HandleScopeData* data = isolate->handle_scope_data(); 129 CanonicalHandleScope* canonical = data->canonical_scope; 130 return canonical ? canonical->Lookup(value) : CreateHandle(isolate, value); 131 } 132 133 134 #ifdef DEBUG 135 inline SealHandleScope::SealHandleScope(Isolate* isolate) : isolate_(isolate) { 136 // Make sure the current thread is allowed to create handles to begin with. 137 DCHECK(AllowHandleAllocation::IsAllowed()); 138 HandleScopeData* current = isolate_->handle_scope_data(); 139 // Shrink the current handle scope to make it impossible to do 140 // handle allocations without an explicit handle scope. 141 prev_limit_ = current->limit; 142 current->limit = current->next; 143 prev_sealed_level_ = current->sealed_level; 144 current->sealed_level = current->level; 145 } 146 147 148 inline SealHandleScope::~SealHandleScope() { 149 // Restore state in current handle scope to re-enable handle 150 // allocations. 151 HandleScopeData* current = isolate_->handle_scope_data(); 152 DCHECK_EQ(current->next, current->limit); 153 current->limit = prev_limit_; 154 DCHECK_EQ(current->level, current->sealed_level); 155 current->sealed_level = prev_sealed_level_; 156 } 157 158 #endif 159 160 } // namespace internal 161 } // namespace v8 162 163 #endif // V8_HANDLES_INL_H_ 164