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 12namespace v8 { 13namespace internal { 14 15#ifdef DEBUG 16bool 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 43int 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 52Object** 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 91void 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 98void 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 107Address HandleScope::current_level_address(Isolate* isolate) { 108 return reinterpret_cast<Address>(&isolate->handle_scope_data()->level); 109} 110 111 112Address HandleScope::current_next_address(Isolate* isolate) { 113 return reinterpret_cast<Address>(&isolate->handle_scope_data()->next); 114} 115 116 117Address HandleScope::current_limit_address(Isolate* isolate) { 118 return reinterpret_cast<Address>(&isolate->handle_scope_data()->limit); 119} 120 121CanonicalHandleScope::CanonicalHandleScope(Isolate* isolate) 122 : isolate_(isolate), zone_(isolate->allocator()) { 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**>(isolate->heap(), &zone_); 128 canonical_level_ = handle_scope_data->level; 129} 130 131 132CanonicalHandleScope::~CanonicalHandleScope() { 133 delete root_index_map_; 134 delete identity_map_; 135 isolate_->handle_scope_data()->canonical_scope = prev_canonical_scope_; 136} 137 138 139Object** CanonicalHandleScope::Lookup(Object* object) { 140 DCHECK_LE(canonical_level_, isolate_->handle_scope_data()->level); 141 if (isolate_->handle_scope_data()->level != canonical_level_) { 142 // We are in an inner handle scope. Do not canonicalize since we will leave 143 // this handle scope while still being in the canonical scope. 144 return HandleScope::CreateHandle(isolate_, object); 145 } 146 if (object->IsHeapObject()) { 147 int index = root_index_map_->Lookup(HeapObject::cast(object)); 148 if (index != RootIndexMap::kInvalidRootIndex) { 149 return isolate_->heap() 150 ->root_handle(static_cast<Heap::RootListIndex>(index)) 151 .location(); 152 } 153 } 154 Object*** entry = identity_map_->Get(object); 155 if (*entry == nullptr) { 156 // Allocate new handle location. 157 *entry = HandleScope::CreateHandle(isolate_, object); 158 } 159 return reinterpret_cast<Object**>(*entry); 160} 161 162 163DeferredHandleScope::DeferredHandleScope(Isolate* isolate) 164 : impl_(isolate->handle_scope_implementer()) { 165 impl_->BeginDeferredScope(); 166 HandleScopeData* data = impl_->isolate()->handle_scope_data(); 167 Object** new_next = impl_->GetSpareOrNewBlock(); 168 Object** new_limit = &new_next[kHandleBlockSize]; 169 DCHECK(data->limit == &impl_->blocks()->last()[kHandleBlockSize]); 170 impl_->blocks()->Add(new_next); 171 172#ifdef DEBUG 173 prev_level_ = data->level; 174#endif 175 data->level++; 176 prev_limit_ = data->limit; 177 prev_next_ = data->next; 178 data->next = new_next; 179 data->limit = new_limit; 180} 181 182 183DeferredHandleScope::~DeferredHandleScope() { 184 impl_->isolate()->handle_scope_data()->level--; 185 DCHECK(handles_detached_); 186 DCHECK(impl_->isolate()->handle_scope_data()->level == prev_level_); 187} 188 189 190DeferredHandles* DeferredHandleScope::Detach() { 191 DeferredHandles* deferred = impl_->Detach(prev_limit_); 192 HandleScopeData* data = impl_->isolate()->handle_scope_data(); 193 data->next = prev_next_; 194 data->limit = prev_limit_; 195#ifdef DEBUG 196 handles_detached_ = true; 197#endif 198 return deferred; 199} 200 201} // namespace internal 202} // namespace v8 203