Home | History | Annotate | Download | only in src
      1 // Copyright 2006-2008 the V8 project authors. All rights reserved.
      2 // Redistribution and use in source and binary forms, with or without
      3 // modification, are permitted provided that the following conditions are
      4 // met:
      5 //
      6 //     * Redistributions of source code must retain the above copyright
      7 //       notice, this list of conditions and the following disclaimer.
      8 //     * Redistributions in binary form must reproduce the above
      9 //       copyright notice, this list of conditions and the following
     10 //       disclaimer in the documentation and/or other materials provided
     11 //       with the distribution.
     12 //     * Neither the name of Google Inc. nor the names of its
     13 //       contributors may be used to endorse or promote products derived
     14 //       from this software without specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 //
     28 
     29 #ifndef V8_HANDLES_INL_H_
     30 #define V8_HANDLES_INL_H_
     31 
     32 #include "api.h"
     33 #include "apiutils.h"
     34 #include "handles.h"
     35 #include "heap.h"
     36 #include "isolate.h"
     37 
     38 namespace v8 {
     39 namespace internal {
     40 
     41 template<typename T>
     42 Handle<T>::Handle(T* obj) {
     43   ASSERT(!obj->IsFailure());
     44   location_ = HandleScope::CreateHandle(obj->GetIsolate(), obj);
     45 }
     46 
     47 
     48 template<typename T>
     49 Handle<T>::Handle(T* obj, Isolate* isolate) {
     50   ASSERT(!obj->IsFailure());
     51   location_ = HandleScope::CreateHandle(isolate, obj);
     52 }
     53 
     54 
     55 template <typename T>
     56 inline bool Handle<T>::is_identical_to(const Handle<T> other) const {
     57   ASSERT(location_ == NULL || !(*location_)->IsFailure());
     58   if (location_ == other.location_) return true;
     59   if (location_ == NULL || other.location_ == NULL) return false;
     60   // Dereferencing deferred handles to check object equality is safe.
     61   SLOW_ASSERT(IsDereferenceAllowed(NO_DEFERRED_CHECK) &&
     62               other.IsDereferenceAllowed(NO_DEFERRED_CHECK));
     63   return *location_ == *other.location_;
     64 }
     65 
     66 
     67 template <typename T>
     68 inline T* Handle<T>::operator*() const {
     69   ASSERT(location_ != NULL && !(*location_)->IsFailure());
     70   SLOW_ASSERT(IsDereferenceAllowed(INCLUDE_DEFERRED_CHECK));
     71   return *BitCast<T**>(location_);
     72 }
     73 
     74 template <typename T>
     75 inline T** Handle<T>::location() const {
     76   ASSERT(location_ == NULL || !(*location_)->IsFailure());
     77   SLOW_ASSERT(location_ == NULL ||
     78               IsDereferenceAllowed(INCLUDE_DEFERRED_CHECK));
     79   return location_;
     80 }
     81 
     82 #ifdef DEBUG
     83 template <typename T>
     84 bool Handle<T>::IsDereferenceAllowed(DereferenceCheckMode mode) const {
     85   ASSERT(location_ != NULL);
     86   Object* object = *BitCast<T**>(location_);
     87   if (object->IsSmi()) return true;
     88   HeapObject* heap_object = HeapObject::cast(object);
     89   Heap* heap = heap_object->GetHeap();
     90   Object** handle = reinterpret_cast<Object**>(location_);
     91   Object** roots_array_start = heap->roots_array_start();
     92   if (roots_array_start <= handle &&
     93       handle < roots_array_start + Heap::kStrongRootListLength &&
     94       heap->RootCanBeTreatedAsConstant(
     95         static_cast<Heap::RootListIndex>(handle - roots_array_start))) {
     96     return true;
     97   }
     98   if (!AllowHandleDereference::IsAllowed()) return false;
     99   if (mode == INCLUDE_DEFERRED_CHECK &&
    100       !AllowDeferredHandleDereference::IsAllowed()) {
    101     // Accessing maps and internalized strings is safe.
    102     if (heap_object->IsMap()) return true;
    103     if (heap_object->IsInternalizedString()) return true;
    104     return !heap->isolate()->IsDeferredHandle(handle);
    105   }
    106   return true;
    107 }
    108 #endif
    109 
    110 
    111 
    112 HandleScope::HandleScope(Isolate* isolate) {
    113   v8::ImplementationUtilities::HandleScopeData* current =
    114       isolate->handle_scope_data();
    115   isolate_ = isolate;
    116   prev_next_ = current->next;
    117   prev_limit_ = current->limit;
    118   current->level++;
    119 }
    120 
    121 
    122 HandleScope::~HandleScope() {
    123   CloseScope(isolate_, prev_next_, prev_limit_);
    124 }
    125 
    126 
    127 void HandleScope::CloseScope(Isolate* isolate,
    128                              Object** prev_next,
    129                              Object** prev_limit) {
    130   v8::ImplementationUtilities::HandleScopeData* current =
    131       isolate->handle_scope_data();
    132 
    133   std::swap(current->next, prev_next);
    134   current->level--;
    135   if (current->limit != prev_limit) {
    136     current->limit = prev_limit;
    137     DeleteExtensions(isolate);
    138 #ifdef ENABLE_HANDLE_ZAPPING
    139     ZapRange(current->next, prev_limit);
    140   } else {
    141     ZapRange(current->next, prev_next);
    142 #endif
    143   }
    144 }
    145 
    146 
    147 template <typename T>
    148 Handle<T> HandleScope::CloseAndEscape(Handle<T> handle_value) {
    149   v8::ImplementationUtilities::HandleScopeData* current =
    150       isolate_->handle_scope_data();
    151 
    152   T* value = *handle_value;
    153   // Throw away all handles in the current scope.
    154   CloseScope(isolate_, prev_next_, prev_limit_);
    155   // Allocate one handle in the parent scope.
    156   ASSERT(current->level > 0);
    157   Handle<T> result(CreateHandle<T>(isolate_, value));
    158   // Reinitialize the current scope (so that it's ready
    159   // to be used or closed again).
    160   prev_next_ = current->next;
    161   prev_limit_ = current->limit;
    162   current->level++;
    163   return result;
    164 }
    165 
    166 
    167 template <typename T>
    168 T** HandleScope::CreateHandle(Isolate* isolate, T* value) {
    169   ASSERT(AllowHandleAllocation::IsAllowed());
    170   v8::ImplementationUtilities::HandleScopeData* current =
    171       isolate->handle_scope_data();
    172 
    173   internal::Object** cur = current->next;
    174   if (cur == current->limit) cur = Extend(isolate);
    175   // Update the current next field, set the value in the created
    176   // handle, and return the result.
    177   ASSERT(cur < current->limit);
    178   current->next = cur + 1;
    179 
    180   T** result = reinterpret_cast<T**>(cur);
    181   *result = value;
    182   return result;
    183 }
    184 
    185 
    186 #ifdef DEBUG
    187 inline SealHandleScope::SealHandleScope(Isolate* isolate) : isolate_(isolate) {
    188   // Make sure the current thread is allowed to create handles to begin with.
    189   CHECK(AllowHandleAllocation::IsAllowed());
    190   v8::ImplementationUtilities::HandleScopeData* current =
    191       isolate_->handle_scope_data();
    192   // Shrink the current handle scope to make it impossible to do
    193   // handle allocations without an explicit handle scope.
    194   limit_ = current->limit;
    195   current->limit = current->next;
    196   level_ = current->level;
    197   current->level = 0;
    198 }
    199 
    200 
    201 inline SealHandleScope::~SealHandleScope() {
    202   // Restore state in current handle scope to re-enable handle
    203   // allocations.
    204   v8::ImplementationUtilities::HandleScopeData* current =
    205       isolate_->handle_scope_data();
    206   ASSERT_EQ(0, current->level);
    207   current->level = level_;
    208   ASSERT_EQ(current->next, current->limit);
    209   current->limit = limit_;
    210 }
    211 
    212 #endif
    213 
    214 } }  // namespace v8::internal
    215 
    216 #endif  // V8_HANDLES_INL_H_
    217