1 // Copyright 2012 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 #include "src/handles.h" 6 7 #include "src/address-map.h" 8 #include "src/base/logging.h" 9 #include "src/identity-map.h" 10 #include "src/objects-inl.h" 11 12 namespace v8 { 13 namespace internal { 14 15 #ifdef DEBUG 16 bool HandleBase::IsDereferenceAllowed(DereferenceCheckMode mode) const { 17 DCHECK_NOT_NULL(location_); 18 Object* object = *location_; 19 if (object->IsSmi()) return true; 20 HeapObject* heap_object = HeapObject::cast(object); 21 Heap* heap = heap_object->GetHeap(); 22 Object** roots_array_start = heap->roots_array_start(); 23 if (roots_array_start <= location_ && 24 location_ < roots_array_start + Heap::kStrongRootListLength && 25 heap->RootCanBeTreatedAsConstant( 26 static_cast<Heap::RootListIndex>(location_ - roots_array_start))) { 27 return true; 28 } 29 if (!AllowHandleDereference::IsAllowed()) return false; 30 if (mode == INCLUDE_DEFERRED_CHECK && 31 !AllowDeferredHandleDereference::IsAllowed()) { 32 // Accessing cells, maps and internalized strings is safe. 33 if (heap_object->IsCell()) return true; 34 if (heap_object->IsMap()) return true; 35 if (heap_object->IsInternalizedString()) return true; 36 return !heap->isolate()->IsDeferredHandle(location_); 37 } 38 return true; 39 } 40 #endif 41 42 43 int HandleScope::NumberOfHandles(Isolate* isolate) { 44 HandleScopeImplementer* impl = isolate->handle_scope_implementer(); 45 int n = impl->blocks()->length(); 46 if (n == 0) return 0; 47 return ((n - 1) * kHandleBlockSize) + static_cast<int>( 48 (isolate->handle_scope_data()->next - impl->blocks()->last())); 49 } 50 51 52 Object** HandleScope::Extend(Isolate* isolate) { 53 HandleScopeData* current = isolate->handle_scope_data(); 54 55 Object** result = current->next; 56 57 DCHECK(result == current->limit); 58 // Make sure there's at least one scope on the stack and that the 59 // top of the scope stack isn't a barrier. 60 if (!Utils::ApiCheck(current->level != current->sealed_level, 61 "v8::HandleScope::CreateHandle()", 62 "Cannot create a handle without a HandleScope")) { 63 return NULL; 64 } 65 HandleScopeImplementer* impl = isolate->handle_scope_implementer(); 66 // If there's more room in the last block, we use that. This is used 67 // for fast creation of scopes after scope barriers. 68 if (!impl->blocks()->is_empty()) { 69 Object** limit = &impl->blocks()->last()[kHandleBlockSize]; 70 if (current->limit != limit) { 71 current->limit = limit; 72 DCHECK(limit - current->next < kHandleBlockSize); 73 } 74 } 75 76 // If we still haven't found a slot for the handle, we extend the 77 // current handle scope by allocating a new handle block. 78 if (result == current->limit) { 79 // If there's a spare block, use it for growing the current scope. 80 result = impl->GetSpareOrNewBlock(); 81 // Add the extension to the global list of blocks, but count the 82 // extension as part of the current scope. 83 impl->blocks()->Add(result); 84 current->limit = &result[kHandleBlockSize]; 85 } 86 87 return result; 88 } 89 90 91 void HandleScope::DeleteExtensions(Isolate* isolate) { 92 HandleScopeData* current = isolate->handle_scope_data(); 93 isolate->handle_scope_implementer()->DeleteExtensions(current->limit); 94 } 95 96 97 #ifdef ENABLE_HANDLE_ZAPPING 98 void HandleScope::ZapRange(Object** start, Object** end) { 99 DCHECK(end - start <= kHandleBlockSize); 100 for (Object** p = start; p != end; p++) { 101 *reinterpret_cast<Address*>(p) = kHandleZapValue; 102 } 103 } 104 #endif 105 106 107 Address HandleScope::current_level_address(Isolate* isolate) { 108 return reinterpret_cast<Address>(&isolate->handle_scope_data()->level); 109 } 110 111 112 Address HandleScope::current_next_address(Isolate* isolate) { 113 return reinterpret_cast<Address>(&isolate->handle_scope_data()->next); 114 } 115 116 117 Address HandleScope::current_limit_address(Isolate* isolate) { 118 return reinterpret_cast<Address>(&isolate->handle_scope_data()->limit); 119 } 120 121 CanonicalHandleScope::CanonicalHandleScope(Isolate* isolate) 122 : isolate_(isolate), zone_(isolate->allocator(), ZONE_NAME) { 123 HandleScopeData* handle_scope_data = isolate_->handle_scope_data(); 124 prev_canonical_scope_ = handle_scope_data->canonical_scope; 125 handle_scope_data->canonical_scope = this; 126 root_index_map_ = new RootIndexMap(isolate); 127 identity_map_ = new IdentityMap<Object**, ZoneAllocationPolicy>( 128 isolate->heap(), ZoneAllocationPolicy(&zone_)); 129 canonical_level_ = handle_scope_data->level; 130 } 131 132 133 CanonicalHandleScope::~CanonicalHandleScope() { 134 delete root_index_map_; 135 delete identity_map_; 136 isolate_->handle_scope_data()->canonical_scope = prev_canonical_scope_; 137 } 138 139 140 Object** CanonicalHandleScope::Lookup(Object* object) { 141 DCHECK_LE(canonical_level_, isolate_->handle_scope_data()->level); 142 if (isolate_->handle_scope_data()->level != canonical_level_) { 143 // We are in an inner handle scope. Do not canonicalize since we will leave 144 // this handle scope while still being in the canonical scope. 145 return HandleScope::CreateHandle(isolate_, object); 146 } 147 if (object->IsHeapObject()) { 148 int index = root_index_map_->Lookup(HeapObject::cast(object)); 149 if (index != RootIndexMap::kInvalidRootIndex) { 150 return isolate_->heap() 151 ->root_handle(static_cast<Heap::RootListIndex>(index)) 152 .location(); 153 } 154 } 155 Object*** entry = identity_map_->Get(object); 156 if (*entry == nullptr) { 157 // Allocate new handle location. 158 *entry = HandleScope::CreateHandle(isolate_, object); 159 } 160 return reinterpret_cast<Object**>(*entry); 161 } 162 163 164 DeferredHandleScope::DeferredHandleScope(Isolate* isolate) 165 : impl_(isolate->handle_scope_implementer()) { 166 impl_->BeginDeferredScope(); 167 HandleScopeData* data = impl_->isolate()->handle_scope_data(); 168 Object** new_next = impl_->GetSpareOrNewBlock(); 169 Object** new_limit = &new_next[kHandleBlockSize]; 170 DCHECK(data->limit == &impl_->blocks()->last()[kHandleBlockSize]); 171 impl_->blocks()->Add(new_next); 172 173 #ifdef DEBUG 174 prev_level_ = data->level; 175 #endif 176 data->level++; 177 prev_limit_ = data->limit; 178 prev_next_ = data->next; 179 data->next = new_next; 180 data->limit = new_limit; 181 } 182 183 184 DeferredHandleScope::~DeferredHandleScope() { 185 impl_->isolate()->handle_scope_data()->level--; 186 DCHECK(handles_detached_); 187 DCHECK(impl_->isolate()->handle_scope_data()->level == prev_level_); 188 } 189 190 191 DeferredHandles* DeferredHandleScope::Detach() { 192 DeferredHandles* deferred = impl_->Detach(prev_limit_); 193 HandleScopeData* data = impl_->isolate()->handle_scope_data(); 194 data->next = prev_next_; 195 data->limit = prev_limit_; 196 #ifdef DEBUG 197 handles_detached_ = true; 198 #endif 199 return deferred; 200 } 201 202 } // namespace internal 203 } // namespace v8 204