Home | History | Annotate | Download | only in src
      1 // Copyright 2006-2008 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 
      6 #ifndef V8_HANDLES_INL_H_
      7 #define V8_HANDLES_INL_H_
      8 
      9 #include "src/api.h"
     10 #include "src/handles.h"
     11 #include "src/heap/heap.h"
     12 #include "src/isolate.h"
     13 
     14 namespace v8 {
     15 namespace internal {
     16 
     17 template<typename T>
     18 Handle<T>::Handle(T* obj) {
     19   location_ = HandleScope::CreateHandle(obj->GetIsolate(), obj);
     20 }
     21 
     22 
     23 template<typename T>
     24 Handle<T>::Handle(T* obj, Isolate* isolate) {
     25   location_ = HandleScope::CreateHandle(isolate, obj);
     26 }
     27 
     28 
     29 template <typename T>
     30 inline bool Handle<T>::is_identical_to(const Handle<T> o) const {
     31   // Dereferencing deferred handles to check object equality is safe.
     32   SLOW_DCHECK(
     33       (location_ == NULL || IsDereferenceAllowed(NO_DEFERRED_CHECK)) &&
     34       (o.location_ == NULL || o.IsDereferenceAllowed(NO_DEFERRED_CHECK)));
     35   if (location_ == o.location_) return true;
     36   if (location_ == NULL || o.location_ == NULL) return false;
     37   return *location_ == *o.location_;
     38 }
     39 
     40 
     41 template <typename T>
     42 inline T* Handle<T>::operator*() const {
     43   SLOW_DCHECK(IsDereferenceAllowed(INCLUDE_DEFERRED_CHECK));
     44   return *bit_cast<T**>(location_);
     45 }
     46 
     47 template <typename T>
     48 inline T** Handle<T>::location() const {
     49   SLOW_DCHECK(location_ == NULL ||
     50               IsDereferenceAllowed(INCLUDE_DEFERRED_CHECK));
     51   return location_;
     52 }
     53 
     54 #ifdef DEBUG
     55 template <typename T>
     56 bool Handle<T>::IsDereferenceAllowed(DereferenceCheckMode mode) const {
     57   DCHECK(location_ != NULL);
     58   Object* object = *bit_cast<T**>(location_);
     59   if (object->IsSmi()) return true;
     60   HeapObject* heap_object = HeapObject::cast(object);
     61   Heap* heap = heap_object->GetHeap();
     62   Object** handle = reinterpret_cast<Object**>(location_);
     63   Object** roots_array_start = heap->roots_array_start();
     64   if (roots_array_start <= handle &&
     65       handle < roots_array_start + Heap::kStrongRootListLength &&
     66       heap->RootCanBeTreatedAsConstant(
     67         static_cast<Heap::RootListIndex>(handle - roots_array_start))) {
     68     return true;
     69   }
     70   if (!AllowHandleDereference::IsAllowed()) return false;
     71   if (mode == INCLUDE_DEFERRED_CHECK &&
     72       !AllowDeferredHandleDereference::IsAllowed()) {
     73     // Accessing cells, maps and internalized strings is safe.
     74     if (heap_object->IsCell()) return true;
     75     if (heap_object->IsMap()) return true;
     76     if (heap_object->IsInternalizedString()) return true;
     77     return !heap->isolate()->IsDeferredHandle(handle);
     78   }
     79   return true;
     80 }
     81 #endif
     82 
     83 
     84 
     85 HandleScope::HandleScope(Isolate* isolate) {
     86   HandleScopeData* current = isolate->handle_scope_data();
     87   isolate_ = isolate;
     88   prev_next_ = current->next;
     89   prev_limit_ = current->limit;
     90   current->level++;
     91 }
     92 
     93 
     94 HandleScope::~HandleScope() {
     95   CloseScope(isolate_, prev_next_, prev_limit_);
     96 }
     97 
     98 
     99 void HandleScope::CloseScope(Isolate* isolate,
    100                              Object** prev_next,
    101                              Object** prev_limit) {
    102   HandleScopeData* current = isolate->handle_scope_data();
    103 
    104   std::swap(current->next, prev_next);
    105   current->level--;
    106   if (current->limit != prev_limit) {
    107     current->limit = prev_limit;
    108     DeleteExtensions(isolate);
    109 #ifdef ENABLE_HANDLE_ZAPPING
    110     ZapRange(current->next, prev_limit);
    111   } else {
    112     ZapRange(current->next, prev_next);
    113 #endif
    114   }
    115 }
    116 
    117 
    118 template <typename T>
    119 Handle<T> HandleScope::CloseAndEscape(Handle<T> handle_value) {
    120   HandleScopeData* current = isolate_->handle_scope_data();
    121 
    122   T* value = *handle_value;
    123   // Throw away all handles in the current scope.
    124   CloseScope(isolate_, prev_next_, prev_limit_);
    125   // Allocate one handle in the parent scope.
    126   DCHECK(current->level > 0);
    127   Handle<T> result(CreateHandle<T>(isolate_, value));
    128   // Reinitialize the current scope (so that it's ready
    129   // to be used or closed again).
    130   prev_next_ = current->next;
    131   prev_limit_ = current->limit;
    132   current->level++;
    133   return result;
    134 }
    135 
    136 
    137 template <typename T>
    138 T** HandleScope::CreateHandle(Isolate* isolate, T* value) {
    139   DCHECK(AllowHandleAllocation::IsAllowed());
    140   HandleScopeData* current = isolate->handle_scope_data();
    141 
    142   internal::Object** cur = current->next;
    143   if (cur == current->limit) cur = Extend(isolate);
    144   // Update the current next field, set the value in the created
    145   // handle, and return the result.
    146   DCHECK(cur < current->limit);
    147   current->next = cur + 1;
    148 
    149   T** result = reinterpret_cast<T**>(cur);
    150   *result = value;
    151   return result;
    152 }
    153 
    154 
    155 #ifdef DEBUG
    156 inline SealHandleScope::SealHandleScope(Isolate* isolate) : isolate_(isolate) {
    157   // Make sure the current thread is allowed to create handles to begin with.
    158   CHECK(AllowHandleAllocation::IsAllowed());
    159   HandleScopeData* current = isolate_->handle_scope_data();
    160   // Shrink the current handle scope to make it impossible to do
    161   // handle allocations without an explicit handle scope.
    162   limit_ = current->limit;
    163   current->limit = current->next;
    164   level_ = current->level;
    165   current->level = 0;
    166 }
    167 
    168 
    169 inline SealHandleScope::~SealHandleScope() {
    170   // Restore state in current handle scope to re-enable handle
    171   // allocations.
    172   HandleScopeData* current = isolate_->handle_scope_data();
    173   DCHECK_EQ(0, current->level);
    174   current->level = level_;
    175   DCHECK_EQ(current->next, current->limit);
    176   current->limit = limit_;
    177 }
    178 
    179 #endif
    180 
    181 } }  // namespace v8::internal
    182 
    183 #endif  // V8_HANDLES_INL_H_
    184