1a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Copyright 2006-2008 the V8 project authors. All rights reserved. 2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file. 4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifndef V8_HANDLES_INL_H_ 7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define V8_HANDLES_INL_H_ 8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/api.h" 10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/handles.h" 11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/heap/heap.h" 12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/isolate.h" 13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 { 15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal { 16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 17e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochtemplate<typename T> 18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockHandle<T>::Handle(T* obj) { 19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch location_ = HandleScope::CreateHandle(obj->GetIsolate(), obj); 2044f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 2144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 2244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 2344f0eee88ff00398ff7f715fab053374d808c90dSteve Blocktemplate<typename T> 2444f0eee88ff00398ff7f715fab053374d808c90dSteve BlockHandle<T>::Handle(T* obj, Isolate* isolate) { 25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch location_ = HandleScope::CreateHandle(isolate, obj); 26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 27b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate <typename T> 30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochinline bool Handle<T>::is_identical_to(const Handle<T> o) const { 31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Dereferencing deferred handles to check object equality is safe. 32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SLOW_DCHECK( 33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (location_ == NULL || IsDereferenceAllowed(NO_DEFERRED_CHECK)) && 34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (o.location_ == NULL || o.IsDereferenceAllowed(NO_DEFERRED_CHECK))); 35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (location_ == o.location_) return true; 36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (location_ == NULL || o.location_ == NULL) return false; 37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return *location_ == *o.location_; 38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 41e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochtemplate <typename T> 42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockinline T* Handle<T>::operator*() const { 43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SLOW_DCHECK(IsDereferenceAllowed(INCLUDE_DEFERRED_CHECK)); 44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return *bit_cast<T**>(location_); 45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate <typename T> 48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochinline T** Handle<T>::location() const { 49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SLOW_DCHECK(location_ == NULL || 50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch IsDereferenceAllowed(INCLUDE_DEFERRED_CHECK)); 51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return location_; 52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG 55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochtemplate <typename T> 56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool Handle<T>::IsDereferenceAllowed(DereferenceCheckMode mode) const { 57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(location_ != NULL); 58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Object* object = *bit_cast<T**>(location_); 59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (object->IsSmi()) return true; 60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HeapObject* heap_object = HeapObject::cast(object); 61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Heap* heap = heap_object->GetHeap(); 62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Object** handle = reinterpret_cast<Object**>(location_); 63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Object** roots_array_start = heap->roots_array_start(); 64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (roots_array_start <= handle && 65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch handle < roots_array_start + Heap::kStrongRootListLength && 66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch heap->RootCanBeTreatedAsConstant( 67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static_cast<Heap::RootListIndex>(handle - roots_array_start))) { 68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return true; 69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!AllowHandleDereference::IsAllowed()) return false; 71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (mode == INCLUDE_DEFERRED_CHECK && 72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch !AllowDeferredHandleDereference::IsAllowed()) { 73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Accessing cells, maps and internalized strings is safe. 74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (heap_object->IsCell()) return true; 75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (heap_object->IsMap()) return true; 76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (heap_object->IsInternalizedString()) return true; 77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return !heap->isolate()->IsDeferredHandle(handle); 78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return true; 8044f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif 82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 8344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 8444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 8544f0eee88ff00398ff7f715fab053374d808c90dSteve BlockHandleScope::HandleScope(Isolate* isolate) { 86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HandleScopeData* current = isolate->handle_scope_data(); 8744f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate_ = isolate; 8844f0eee88ff00398ff7f715fab053374d808c90dSteve Block prev_next_ = current->next; 8944f0eee88ff00398ff7f715fab053374d808c90dSteve Block prev_limit_ = current->limit; 9044f0eee88ff00398ff7f715fab053374d808c90dSteve Block current->level++; 9144f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 9244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 9344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 9444f0eee88ff00398ff7f715fab053374d808c90dSteve BlockHandleScope::~HandleScope() { 95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CloseScope(isolate_, prev_next_, prev_limit_); 9644f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 9744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid HandleScope::CloseScope(Isolate* isolate, 100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Object** prev_next, 101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Object** prev_limit) { 102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HandleScopeData* current = isolate->handle_scope_data(); 103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch std::swap(current->next, prev_next); 10544f0eee88ff00398ff7f715fab053374d808c90dSteve Block current->level--; 106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (current->limit != prev_limit) { 107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch current->limit = prev_limit; 108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeleteExtensions(isolate); 109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef ENABLE_HANDLE_ZAPPING 110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ZapRange(current->next, prev_limit); 111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ZapRange(current->next, prev_next); 11344f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif 114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 11544f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 11644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 11744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 11844f0eee88ff00398ff7f715fab053374d808c90dSteve Blocktemplate <typename T> 11944f0eee88ff00398ff7f715fab053374d808c90dSteve BlockHandle<T> HandleScope::CloseAndEscape(Handle<T> handle_value) { 120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HandleScopeData* current = isolate_->handle_scope_data(); 121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 12244f0eee88ff00398ff7f715fab053374d808c90dSteve Block T* value = *handle_value; 12344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Throw away all handles in the current scope. 124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CloseScope(isolate_, prev_next_, prev_limit_); 12544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Allocate one handle in the parent scope. 126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(current->level > 0); 127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<T> result(CreateHandle<T>(isolate_, value)); 12844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Reinitialize the current scope (so that it's ready 12944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // to be used or closed again). 13044f0eee88ff00398ff7f715fab053374d808c90dSteve Block prev_next_ = current->next; 13144f0eee88ff00398ff7f715fab053374d808c90dSteve Block prev_limit_ = current->limit; 13244f0eee88ff00398ff7f715fab053374d808c90dSteve Block current->level++; 13344f0eee88ff00398ff7f715fab053374d808c90dSteve Block return result; 13444f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 13544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 13644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 13744f0eee88ff00398ff7f715fab053374d808c90dSteve Blocktemplate <typename T> 138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochT** HandleScope::CreateHandle(Isolate* isolate, T* value) { 139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(AllowHandleAllocation::IsAllowed()); 140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HandleScopeData* current = isolate->handle_scope_data(); 14144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 14244f0eee88ff00398ff7f715fab053374d808c90dSteve Block internal::Object** cur = current->next; 143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (cur == current->limit) cur = Extend(isolate); 14444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Update the current next field, set the value in the created 14544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // handle, and return the result. 146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(cur < current->limit); 14744f0eee88ff00398ff7f715fab053374d808c90dSteve Block current->next = cur + 1; 14844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 14944f0eee88ff00398ff7f715fab053374d808c90dSteve Block T** result = reinterpret_cast<T**>(cur); 15044f0eee88ff00398ff7f715fab053374d808c90dSteve Block *result = value; 15144f0eee88ff00398ff7f715fab053374d808c90dSteve Block return result; 15244f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 15344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 15444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochinline SealHandleScope::SealHandleScope(Isolate* isolate) : isolate_(isolate) { 157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Make sure the current thread is allowed to create handles to begin with. 158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CHECK(AllowHandleAllocation::IsAllowed()); 159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HandleScopeData* current = isolate_->handle_scope_data(); 160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Shrink the current handle scope to make it impossible to do 161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // handle allocations without an explicit handle scope. 162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch limit_ = current->limit; 163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block current->limit = current->next; 1645913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck level_ = current->level; 1655913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck current->level = 0; 166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochinline SealHandleScope::~SealHandleScope() { 170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Restore state in current handle scope to re-enable handle 171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // allocations. 172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HandleScopeData* current = isolate_->handle_scope_data(); 173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(0, current->level); 174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch current->level = level_; 175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(current->next, current->limit); 176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch current->limit = limit_; 177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif 180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} } // namespace v8::internal 182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif // V8_HANDLES_INL_H_ 184