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 121 122CanonicalHandleScope::CanonicalHandleScope(Isolate* isolate) 123 : isolate_(isolate) { 124 HandleScopeData* handle_scope_data = isolate_->handle_scope_data(); 125 prev_canonical_scope_ = handle_scope_data->canonical_scope; 126 handle_scope_data->canonical_scope = this; 127 root_index_map_ = new RootIndexMap(isolate); 128 identity_map_ = new IdentityMap<Object**>(isolate->heap(), &zone_); 129 canonical_level_ = handle_scope_data->level; 130} 131 132 133CanonicalHandleScope::~CanonicalHandleScope() { 134 delete root_index_map_; 135 delete identity_map_; 136 isolate_->handle_scope_data()->canonical_scope = prev_canonical_scope_; 137} 138 139 140Object** 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 164DeferredHandleScope::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 184DeferredHandleScope::~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 191DeferredHandles* 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