// Copyright 2006-2008 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following // disclaimer in the documentation and/or other materials provided // with the distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // #ifndef V8_HANDLES_INL_H_ #define V8_HANDLES_INL_H_ #include "api.h" #include "apiutils.h" #include "handles.h" #include "heap.h" #include "isolate.h" namespace v8 { namespace internal { template Handle::Handle(T* obj) { ASSERT(!obj->IsFailure()); location_ = HandleScope::CreateHandle(obj->GetIsolate(), obj); } template Handle::Handle(T* obj, Isolate* isolate) { ASSERT(!obj->IsFailure()); location_ = HandleScope::CreateHandle(isolate, obj); } template inline bool Handle::is_identical_to(const Handle other) const { ASSERT(location_ == NULL || !(*location_)->IsFailure()); if (location_ == other.location_) return true; if (location_ == NULL || other.location_ == NULL) return false; // Dereferencing deferred handles to check object equality is safe. SLOW_ASSERT(IsDereferenceAllowed(NO_DEFERRED_CHECK) && other.IsDereferenceAllowed(NO_DEFERRED_CHECK)); return *location_ == *other.location_; } template inline T* Handle::operator*() const { ASSERT(location_ != NULL && !(*location_)->IsFailure()); SLOW_ASSERT(IsDereferenceAllowed(INCLUDE_DEFERRED_CHECK)); return *BitCast(location_); } template inline T** Handle::location() const { ASSERT(location_ == NULL || !(*location_)->IsFailure()); SLOW_ASSERT(location_ == NULL || IsDereferenceAllowed(INCLUDE_DEFERRED_CHECK)); return location_; } #ifdef DEBUG template bool Handle::IsDereferenceAllowed(DereferenceCheckMode mode) const { ASSERT(location_ != NULL); Object* object = *BitCast(location_); if (object->IsSmi()) return true; HeapObject* heap_object = HeapObject::cast(object); Heap* heap = heap_object->GetHeap(); Object** handle = reinterpret_cast(location_); Object** roots_array_start = heap->roots_array_start(); if (roots_array_start <= handle && handle < roots_array_start + Heap::kStrongRootListLength && heap->RootCanBeTreatedAsConstant( static_cast(handle - roots_array_start))) { return true; } if (!AllowHandleDereference::IsAllowed()) return false; if (mode == INCLUDE_DEFERRED_CHECK && !AllowDeferredHandleDereference::IsAllowed()) { // Accessing maps and internalized strings is safe. if (heap_object->IsMap()) return true; if (heap_object->IsInternalizedString()) return true; return !heap->isolate()->IsDeferredHandle(handle); } return true; } #endif HandleScope::HandleScope(Isolate* isolate) { v8::ImplementationUtilities::HandleScopeData* current = isolate->handle_scope_data(); isolate_ = isolate; prev_next_ = current->next; prev_limit_ = current->limit; current->level++; } HandleScope::~HandleScope() { CloseScope(isolate_, prev_next_, prev_limit_); } void HandleScope::CloseScope(Isolate* isolate, Object** prev_next, Object** prev_limit) { v8::ImplementationUtilities::HandleScopeData* current = isolate->handle_scope_data(); current->next = prev_next; current->level--; if (current->limit != prev_limit) { current->limit = prev_limit; DeleteExtensions(isolate); } #ifdef ENABLE_EXTRA_CHECKS ZapRange(prev_next, prev_limit); #endif } template Handle HandleScope::CloseAndEscape(Handle handle_value) { v8::ImplementationUtilities::HandleScopeData* current = isolate_->handle_scope_data(); T* value = *handle_value; // Throw away all handles in the current scope. CloseScope(isolate_, prev_next_, prev_limit_); // Allocate one handle in the parent scope. ASSERT(current->level > 0); Handle result(CreateHandle(isolate_, value)); // Reinitialize the current scope (so that it's ready // to be used or closed again). prev_next_ = current->next; prev_limit_ = current->limit; current->level++; return result; } template T** HandleScope::CreateHandle(Isolate* isolate, T* value) { ASSERT(AllowHandleAllocation::IsAllowed()); v8::ImplementationUtilities::HandleScopeData* current = isolate->handle_scope_data(); internal::Object** cur = current->next; if (cur == current->limit) cur = Extend(isolate); // Update the current next field, set the value in the created // handle, and return the result. ASSERT(cur < current->limit); current->next = cur + 1; T** result = reinterpret_cast(cur); *result = value; return result; } #ifdef DEBUG inline SealHandleScope::SealHandleScope(Isolate* isolate) : isolate_(isolate) { // Make sure the current thread is allowed to create handles to begin with. CHECK(AllowHandleAllocation::IsAllowed()); v8::ImplementationUtilities::HandleScopeData* current = isolate_->handle_scope_data(); // Shrink the current handle scope to make it impossible to do // handle allocations without an explicit handle scope. limit_ = current->limit; current->limit = current->next; level_ = current->level; current->level = 0; } inline SealHandleScope::~SealHandleScope() { // Restore state in current handle scope to re-enable handle // allocations. v8::ImplementationUtilities::HandleScopeData* current = isolate_->handle_scope_data(); ASSERT_EQ(0, current->level); current->level = level_; ASSERT_EQ(current->next, current->limit); current->limit = limit_; } #endif } } // namespace v8::internal #endif // V8_HANDLES_INL_H_