Home | History | Annotate | Download | only in src
      1 // Copyright 2012 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 #include "src/v8.h"
      6 
      7 #include "src/handles.h"
      8 
      9 namespace v8 {
     10 namespace internal {
     11 
     12 
     13 int HandleScope::NumberOfHandles(Isolate* isolate) {
     14   HandleScopeImplementer* impl = isolate->handle_scope_implementer();
     15   int n = impl->blocks()->length();
     16   if (n == 0) return 0;
     17   return ((n - 1) * kHandleBlockSize) + static_cast<int>(
     18       (isolate->handle_scope_data()->next - impl->blocks()->last()));
     19 }
     20 
     21 
     22 Object** HandleScope::Extend(Isolate* isolate) {
     23   HandleScopeData* current = isolate->handle_scope_data();
     24 
     25   Object** result = current->next;
     26 
     27   DCHECK(result == current->limit);
     28   // Make sure there's at least one scope on the stack and that the
     29   // top of the scope stack isn't a barrier.
     30   if (!Utils::ApiCheck(current->level != 0,
     31                        "v8::HandleScope::CreateHandle()",
     32                        "Cannot create a handle without a HandleScope")) {
     33     return NULL;
     34   }
     35   HandleScopeImplementer* impl = isolate->handle_scope_implementer();
     36   // If there's more room in the last block, we use that. This is used
     37   // for fast creation of scopes after scope barriers.
     38   if (!impl->blocks()->is_empty()) {
     39     Object** limit = &impl->blocks()->last()[kHandleBlockSize];
     40     if (current->limit != limit) {
     41       current->limit = limit;
     42       DCHECK(limit - current->next < kHandleBlockSize);
     43     }
     44   }
     45 
     46   // If we still haven't found a slot for the handle, we extend the
     47   // current handle scope by allocating a new handle block.
     48   if (result == current->limit) {
     49     // If there's a spare block, use it for growing the current scope.
     50     result = impl->GetSpareOrNewBlock();
     51     // Add the extension to the global list of blocks, but count the
     52     // extension as part of the current scope.
     53     impl->blocks()->Add(result);
     54     current->limit = &result[kHandleBlockSize];
     55   }
     56 
     57   return result;
     58 }
     59 
     60 
     61 void HandleScope::DeleteExtensions(Isolate* isolate) {
     62   HandleScopeData* current = isolate->handle_scope_data();
     63   isolate->handle_scope_implementer()->DeleteExtensions(current->limit);
     64 }
     65 
     66 
     67 #ifdef ENABLE_HANDLE_ZAPPING
     68 void HandleScope::ZapRange(Object** start, Object** end) {
     69   DCHECK(end - start <= kHandleBlockSize);
     70   for (Object** p = start; p != end; p++) {
     71     *reinterpret_cast<Address*>(p) = v8::internal::kHandleZapValue;
     72   }
     73 }
     74 #endif
     75 
     76 
     77 Address HandleScope::current_level_address(Isolate* isolate) {
     78   return reinterpret_cast<Address>(&isolate->handle_scope_data()->level);
     79 }
     80 
     81 
     82 Address HandleScope::current_next_address(Isolate* isolate) {
     83   return reinterpret_cast<Address>(&isolate->handle_scope_data()->next);
     84 }
     85 
     86 
     87 Address HandleScope::current_limit_address(Isolate* isolate) {
     88   return reinterpret_cast<Address>(&isolate->handle_scope_data()->limit);
     89 }
     90 
     91 
     92 DeferredHandleScope::DeferredHandleScope(Isolate* isolate)
     93     : impl_(isolate->handle_scope_implementer()) {
     94   impl_->BeginDeferredScope();
     95   HandleScopeData* data = impl_->isolate()->handle_scope_data();
     96   Object** new_next = impl_->GetSpareOrNewBlock();
     97   Object** new_limit = &new_next[kHandleBlockSize];
     98   DCHECK(data->limit == &impl_->blocks()->last()[kHandleBlockSize]);
     99   impl_->blocks()->Add(new_next);
    100 
    101 #ifdef DEBUG
    102   prev_level_ = data->level;
    103 #endif
    104   data->level++;
    105   prev_limit_ = data->limit;
    106   prev_next_ = data->next;
    107   data->next = new_next;
    108   data->limit = new_limit;
    109 }
    110 
    111 
    112 DeferredHandleScope::~DeferredHandleScope() {
    113   impl_->isolate()->handle_scope_data()->level--;
    114   DCHECK(handles_detached_);
    115   DCHECK(impl_->isolate()->handle_scope_data()->level == prev_level_);
    116 }
    117 
    118 
    119 DeferredHandles* DeferredHandleScope::Detach() {
    120   DeferredHandles* deferred = impl_->Detach(prev_limit_);
    121   HandleScopeData* data = impl_->isolate()->handle_scope_data();
    122   data->next = prev_next_;
    123   data->limit = prev_limit_;
    124 #ifdef DEBUG
    125   handles_detached_ = true;
    126 #endif
    127   return deferred;
    128 }
    129 
    130 } }  // namespace v8::internal
    131