Index: src/handles.cc |
diff --git a/src/handles.cc b/src/handles.cc |
index d9b130f3cac3d0d25dfd8072e347e4e5614fa1e7..c5410ab41e494b5974c77e4f057d15f7257bdee0 100644 |
--- a/src/handles.cc |
+++ b/src/handles.cc |
@@ -2,14 +2,64 @@ |
// Use of this source code is governed by a BSD-style license that can be |
// found in the LICENSE file. |
-#include "src/v8.h" |
- |
#include "src/handles.h" |
+#include "src/api.h" |
+#include "src/isolate.h" |
+ |
namespace v8 { |
namespace internal { |
+HandleBase::HandleBase(HeapObject* object) |
+ : HandleBase(object, object->GetIsolate()) {} |
+ |
+ |
+HandleBase::HandleBase(Object* object, Isolate* isolate) |
+ : HandleBase(HandleScope::CreateHandle(isolate, object)) {} |
+ |
+ |
+#ifdef DEBUG |
+ |
+bool HandleBase::IsDereferenceAllowed(DereferenceCheckMode mode) const { |
+ DCHECK_NOT_NULL(location_); |
+ Object* const object = *location_; |
+ if (object->IsSmi()) return true; |
+ HeapObject* const heap_object = HeapObject::cast(object); |
+ Heap* const heap = heap_object->GetHeap(); |
+ Object** roots_array_start = heap->roots_array_start(); |
+ if (roots_array_start <= location_ && |
+ location_ < roots_array_start + Heap::kStrongRootListLength && |
+ heap->RootCanBeTreatedAsConstant( |
+ static_cast<Heap::RootListIndex>(location_ - roots_array_start))) { |
+ return true; |
+ } |
+ if (!AllowHandleDereference::IsAllowed()) return false; |
+ if (mode == INCLUDE_DEFERRED_CHECK && |
+ !AllowDeferredHandleDereference::IsAllowed()) { |
+ // Accessing cells, maps and internalized strings is safe. |
+ if (heap_object->IsCell()) return true; |
+ if (heap_object->IsMap()) return true; |
+ if (heap_object->IsInternalizedString()) return true; |
+ return !heap->isolate()->IsDeferredHandle(location_); |
+ } |
+ return true; |
+} |
+ |
+#endif // DEBUG |
+ |
+ |
+HandleScope::HandleScope(Isolate* isolate) : isolate_(isolate) { |
+ HandleScopeData* const current = isolate->handle_scope_data(); |
+ prev_next_ = current->next; |
+ prev_limit_ = current->limit; |
+ current->level++; |
+} |
+ |
+HandleScope::~HandleScope() { CloseScope(isolate_, prev_next_, prev_limit_); } |
+ |
+ |
+// static |
int HandleScope::NumberOfHandles(Isolate* isolate) { |
HandleScopeImplementer* impl = isolate->handle_scope_implementer(); |
int n = impl->blocks()->length(); |
@@ -19,12 +69,73 @@ int HandleScope::NumberOfHandles(Isolate* isolate) { |
} |
+// static |
+Object** HandleScope::CreateHandle(Isolate* isolate, Object* value) { |
+ DCHECK(AllowHandleAllocation::IsAllowed()); |
+ HandleScopeData* const current = isolate->handle_scope_data(); |
+ |
+ Object** result = current->next; |
+ if (result == current->limit) result = Extend(isolate); |
+ // Update the current next field, set the value in the created |
+ // handle, and return the result. |
+ DCHECK_LT(result, current->limit); |
+ current->next = result + 1; |
+ |
+ *result = value; |
+ return result; |
+} |
+ |
+ |
+// static |
+void HandleScope::DeleteExtensions(Isolate* isolate) { |
+ HandleScopeData* const current = isolate->handle_scope_data(); |
+ isolate->handle_scope_implementer()->DeleteExtensions(current->limit); |
+} |
+ |
+ |
+Handle<Object> HandleScope::CloseAndEscape(Handle<Object> handle) { |
+ HandleScopeData* const current = isolate_->handle_scope_data(); |
+ |
+ Object* value = *handle; |
+ // Throw away all handles in the current scope. |
+ CloseScope(isolate_, prev_next_, prev_limit_); |
+ // Allocate one handle in the parent scope. |
+ DCHECK_LT(0, current->level); |
+ Handle<Object> 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; |
+} |
+ |
+ |
+// static |
+void HandleScope::CloseScope(Isolate* isolate, Object** prev_next, |
+ Object** prev_limit) { |
+ HandleScopeData* const current = isolate->handle_scope_data(); |
+ |
+ std::swap(current->next, prev_next); |
+ current->level--; |
+ if (current->limit != prev_limit) { |
+ current->limit = prev_limit; |
+ DeleteExtensions(isolate); |
+#ifdef ENABLE_HANDLE_ZAPPING |
+ ZapRange(current->next, prev_limit); |
+ } else { |
+ ZapRange(current->next, prev_next); |
+#endif |
+ } |
+} |
+ |
+ |
+// static |
Object** HandleScope::Extend(Isolate* isolate) { |
HandleScopeData* current = isolate->handle_scope_data(); |
Object** result = current->next; |
- |
- DCHECK(result == current->limit); |
+ DCHECK_EQ(result, current->limit); |
// Make sure there's at least one scope on the stack and that the |
// top of the scope stack isn't a barrier. |
if (!Utils::ApiCheck(current->level != 0, |
@@ -58,12 +169,6 @@ Object** HandleScope::Extend(Isolate* isolate) { |
} |
-void HandleScope::DeleteExtensions(Isolate* isolate) { |
- HandleScopeData* current = isolate->handle_scope_data(); |
- isolate->handle_scope_implementer()->DeleteExtensions(current->limit); |
-} |
- |
- |
#ifdef ENABLE_HANDLE_ZAPPING |
void HandleScope::ZapRange(Object** start, Object** end) { |
DCHECK(end - start <= kHandleBlockSize); |
@@ -127,4 +232,33 @@ DeferredHandles* DeferredHandleScope::Detach() { |
return deferred; |
} |
-} } // namespace v8::internal |
+ |
+#ifdef DEBUG |
+ |
+SealHandleScope::SealHandleScope(Isolate* isolate) : isolate_(isolate) { |
+ // Make sure the current thread is allowed to create handles to begin with. |
+ CHECK(AllowHandleAllocation::IsAllowed()); |
+ HandleScopeData* const 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; |
+} |
+ |
+ |
+SealHandleScope::~SealHandleScope() { |
+ // Restore state in current handle scope to re-enable handle |
+ // allocations. |
+ HandleScopeData* const current = isolate_->handle_scope_data(); |
+ DCHECK_EQ(0, current->level); |
+ current->level = level_; |
+ DCHECK_EQ(current->next, current->limit); |
+ current->limit = limit_; |
+} |
+ |
+#endif // DEBUG |
+ |
+} // namespace internal |
+} // namespace v8 |