handles-inl.h 4.93 KB
Newer Older
1
// Copyright 2006-2008 the V8 project authors. All rights reserved.
2 3
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
4 5 6

#ifndef V8_HANDLES_INL_H_
#define V8_HANDLES_INL_H_
7

8 9
#include "src/handles.h"
#include "src/isolate.h"
10
#include "src/msan.h"
11

12 13 14
namespace v8 {
namespace internal {

15
HandleBase::HandleBase(Address object, Isolate* isolate)
16 17 18
    : location_(HandleScope::GetHandle(isolate, object)) {}

// Allocate a new handle for the object, do not canonicalize.
19

20
template <typename T>
21 22 23
Handle<T> Handle<T>::New(T object, Isolate* isolate) {
  return Handle(HandleScope::CreateHandle(isolate, object.ptr()));
}
24

25 26 27
template <typename T>
template <typename S>
const Handle<T> Handle<T>::cast(Handle<S> that) {
28
  T::cast(*FullObjectSlot(that.location()));
29
  return Handle<T>(that.location_);
30
}
31 32

HandleScope::HandleScope(Isolate* isolate) {
33
  HandleScopeData* data = isolate->handle_scope_data();
34
  isolate_ = isolate;
35 36 37
  prev_next_ = data->next;
  prev_limit_ = data->limit;
  data->level++;
38 39
}

40
template <typename T>
41 42 43
Handle<T>::Handle(T object, Isolate* isolate)
    : HandleBase(object.ptr(), isolate) {}

44
template <typename T>
45 46 47 48
V8_INLINE Handle<T> handle(T object, Isolate* isolate) {
  return Handle<T>(object, isolate);
}

49 50 51
template <typename T>
inline std::ostream& operator<<(std::ostream& os, Handle<T> handle) {
  return os << Brief(*handle);
52
}
53

54
HandleScope::~HandleScope() {
55 56 57 58 59
#ifdef DEBUG
  if (FLAG_check_handle_count) {
    int before = NumberOfHandles(isolate_);
    CloseScope(isolate_, prev_next_, prev_limit_);
    int after = NumberOfHandles(isolate_);
60 61
    DCHECK_LT(after - before, kCheckHandleThreshold);
    DCHECK_LT(before, kCheckHandleThreshold);
62 63 64 65 66 67
  } else {
#endif  // DEBUG
    CloseScope(isolate_, prev_next_, prev_limit_);
#ifdef DEBUG
  }
#endif  // DEBUG
68 69
}

70 71
void HandleScope::CloseScope(Isolate* isolate, Address* prev_next,
                             Address* prev_limit) {
72 73 74 75
  HandleScopeData* current = isolate->handle_scope_data();

  std::swap(current->next, prev_next);
  current->level--;
76
  Address* limit = prev_next;
77 78
  if (current->limit != prev_limit) {
    current->limit = prev_limit;
79
    limit = prev_limit;
80
    DeleteExtensions(isolate);
81
  }
82
#ifdef ENABLE_HANDLE_ZAPPING
83
  ZapRange(current->next, limit);
84
#endif
85
  MSAN_ALLOCATED_UNINITIALIZED_MEMORY(
86 87 88
      current->next,
      static_cast<size_t>(reinterpret_cast<Address>(limit) -
                          reinterpret_cast<Address>(current->next)));
89 90 91 92 93
}

template <typename T>
Handle<T> HandleScope::CloseAndEscape(Handle<T> handle_value) {
  HandleScopeData* current = isolate_->handle_scope_data();
94
  T value = *handle_value;
95 96 97
  // Throw away all handles in the current scope.
  CloseScope(isolate_, prev_next_, prev_limit_);
  // Allocate one handle in the parent scope.
98
  DCHECK(current->level > current->sealed_level);
99
  Handle<T> result(value, isolate_);
100 101 102 103 104 105 106 107
  // 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;
}

108
Address* HandleScope::CreateHandle(Isolate* isolate, Address value) {
109 110
  DCHECK(AllowHandleAllocation::IsAllowed());
  HandleScopeData* data = isolate->handle_scope_data();
111 112 113
  Address* result = data->next;
  if (result == data->limit) {
    result = Extend(isolate);
114 115 116 117 118
  }
  // Update the current next field, set the value in the created handle,
  // and return the result.
  DCHECK_LT(reinterpret_cast<Address>(result),
            reinterpret_cast<Address>(data->limit));
119
  data->next = reinterpret_cast<Address*>(reinterpret_cast<Address>(result) +
120
                                          sizeof(Address));
121
  *result = value;
122 123
  return result;
}
124

125
Address* HandleScope::GetHandle(Isolate* isolate, Address value) {
126 127 128 129 130 131 132
  DCHECK(AllowHandleAllocation::IsAllowed());
  HandleScopeData* data = isolate->handle_scope_data();
  CanonicalHandleScope* canonical = data->canonical_scope;
  return canonical ? canonical->Lookup(value) : CreateHandle(isolate, value);
}


133 134 135
#ifdef DEBUG
inline SealHandleScope::SealHandleScope(Isolate* isolate) : isolate_(isolate) {
  // Make sure the current thread is allowed to create handles to begin with.
136
  DCHECK(AllowHandleAllocation::IsAllowed());
137 138 139
  HandleScopeData* current = isolate_->handle_scope_data();
  // Shrink the current handle scope to make it impossible to do
  // handle allocations without an explicit handle scope.
140
  prev_limit_ = current->limit;
141
  current->limit = current->next;
142 143
  prev_sealed_level_ = current->sealed_level;
  current->sealed_level = current->level;
144 145 146 147 148 149 150 151
}


inline SealHandleScope::~SealHandleScope() {
  // Restore state in current handle scope to re-enable handle
  // allocations.
  HandleScopeData* current = isolate_->handle_scope_data();
  DCHECK_EQ(current->next, current->limit);
152 153 154
  current->limit = prev_limit_;
  DCHECK_EQ(current->level, current->sealed_level);
  current->sealed_level = prev_sealed_level_;
155 156 157 158
}

#endif

159 160
}  // namespace internal
}  // namespace v8
161 162

#endif  // V8_HANDLES_INL_H_