handles.h 8.52 KB
Newer Older
1
// Copyright 2011 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 7

#ifndef V8_HANDLES_H_
#define V8_HANDLES_H_

8
#include "src/objects.h"
9

10 11
namespace v8 {
namespace internal {
12

13 14 15
// A Handle can be converted into a MaybeHandle. Converting a MaybeHandle
// into a Handle requires checking that it does not point to NULL.  This
// ensures NULL checks before use.
16
// Do not use MaybeHandle as argument type.
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46

template<typename T>
class MaybeHandle {
 public:
  INLINE(MaybeHandle()) : location_(NULL) { }

  // Constructor for handling automatic up casting from Handle.
  // Ex. Handle<JSArray> can be passed when MaybeHandle<Object> is expected.
  template <class S> MaybeHandle(Handle<S> handle) {
#ifdef DEBUG
    T* a = NULL;
    S* b = NULL;
    a = b;  // Fake assignment to enforce type checks.
    USE(a);
#endif
    this->location_ = reinterpret_cast<T**>(handle.location());
  }

  // Constructor for handling automatic up casting.
  // Ex. MaybeHandle<JSArray> can be passed when Handle<Object> is expected.
  template <class S> MaybeHandle(MaybeHandle<S> maybe_handle) {
#ifdef DEBUG
    T* a = NULL;
    S* b = NULL;
    a = b;  // Fake assignment to enforce type checks.
    USE(a);
#endif
    location_ = reinterpret_cast<T**>(maybe_handle.location_);
  }

47
  INLINE(void Assert() const) { DCHECK(location_ != NULL); }
48
  INLINE(void Check() const) { CHECK(location_ != NULL); }
49

50
  INLINE(Handle<T> ToHandleChecked()) const {
51
    Check();
52 53 54
    return Handle<T>(location_);
  }

55
  // Convert to a Handle with a type that can be upcasted to.
56
  template <class S>
57
  V8_INLINE bool ToHandle(Handle<S>* out) const {
58 59 60 61 62 63 64 65 66
    if (location_ == NULL) {
      *out = Handle<T>::null();
      return false;
    } else {
      *out = Handle<T>(location_);
      return true;
    }
  }

67 68
  bool is_null() const { return location_ == NULL; }

69 70 71 72 73 74 75 76
 protected:
  T** location_;

  // MaybeHandles of different classes are allowed to access each
  // other's location_.
  template<class S> friend class MaybeHandle;
};

77 78 79
// ----------------------------------------------------------------------------
// A Handle provides a reference to an object that survives relocation by
// the garbage collector.
80
// Handles are only valid within a HandleScope.
81 82
// When a handle is created for an object a cell is allocated in the heap.

83
template<typename T>
84 85
class Handle {
 public:
86
  INLINE(explicit Handle(T** location)) { location_ = location; }
87
  INLINE(explicit Handle(T* obj));
88
  INLINE(Handle(T* obj, Isolate* isolate));
89

90 91 92
  // TODO(yangguo): Values that contain empty handles should be declared as
  // MaybeHandle to force validation before being used as handles.
  INLINE(Handle()) : location_(NULL) { }
93 94 95 96 97 98 99 100 101 102

  // Constructor for handling automatic up casting.
  // Ex. Handle<JSFunction> can be passed when Handle<Object> is expected.
  template <class S> Handle(Handle<S> handle) {
#ifdef DEBUG
    T* a = NULL;
    S* b = NULL;
    a = b;  // Fake assignment to enforce type checks.
    USE(a);
#endif
103
    location_ = reinterpret_cast<T**>(handle.location_);
104 105
  }

106
  INLINE(T* operator->() const) { return operator*(); }
107 108

  // Check if this handle refers to the exact same object as the other handle.
109
  INLINE(bool is_identical_to(const Handle<T> other) const);
110 111 112 113 114

  // Provides the C++ dereference operator.
  INLINE(T* operator*() const);

  // Returns the address to where the raw pointer is stored.
115
  INLINE(T** location() const);
116 117

  template <class S> static Handle<T> cast(Handle<S> that) {
118 119
    T::cast(*reinterpret_cast<T**>(that.location_));
    return Handle<T>(reinterpret_cast<T**>(that.location_));
120 121
  }

122 123
  // TODO(yangguo): Values that contain empty handles should be declared as
  // MaybeHandle to force validation before being used as handles.
124
  static Handle<T> null() { return Handle<T>(); }
125
  bool is_null() const { return location_ == NULL; }
126 127 128

  // Closes the given scope, but lets this handle escape. See
  // implementation in api.h.
129
  inline Handle<T> EscapeFrom(v8::EscapableHandleScope* scope);
130

131
#ifdef DEBUG
132 133 134
  enum DereferenceCheckMode { INCLUDE_DEFERRED_CHECK, NO_DEFERRED_CHECK };

  bool IsDereferenceAllowed(DereferenceCheckMode mode) const;
135 136
#endif  // DEBUG

137 138
 private:
  T** location_;
139 140 141

  // Handles of different classes are allowed to access each other's location_.
  template<class S> friend class Handle;
142 143 144
};


145 146
// Convenience wrapper.
template<class T>
147 148
inline Handle<T> handle(T* t, Isolate* isolate) {
  return Handle<T>(t, isolate);
149 150 151
}


152 153 154 155 156 157 158
// Convenience wrapper.
template<class T>
inline Handle<T> handle(T* t) {
  return Handle<T>(t, t->GetIsolate());
}


159 160 161 162 163 164 165
// Key comparison function for Map handles.
inline bool operator<(const Handle<Map>& lhs, const Handle<Map>& rhs) {
  // This is safe because maps don't move.
  return *lhs < *rhs;
}


166
class DeferredHandles;
167 168 169
class HandleScopeImplementer;


170 171 172 173 174 175 176 177 178 179 180 181 182 183
// A stack-allocated class that governs a number of local handles.
// After a handle scope has been created, all local handles will be
// allocated within that handle scope until either the handle scope is
// deleted or another handle scope is created.  If there is already a
// handle scope and a new one is created, all allocations will take
// place in the new handle scope until it is deleted.  After that,
// new handles will again be allocated in the original handle scope.
//
// After the handle scope of a local handle has been deleted the
// garbage collector will no longer track the object stored in the
// handle and may deallocate it.  The behavior of accessing a handle
// for which the handle scope has been deleted is undefined.
class HandleScope {
 public:
184
  explicit inline HandleScope(Isolate* isolate);
185

186
  inline ~HandleScope();
187 188

  // Counts the number of allocated handles.
189
  static int NumberOfHandles(Isolate* isolate);
190 191

  // Creates a new handle with the given value.
192
  template <typename T>
193
  static inline T** CreateHandle(Isolate* isolate, T* value);
194

195
  // Deallocates any extensions used by the current scope.
196
  static void DeleteExtensions(Isolate* isolate);
197

198 199 200
  static Address current_next_address(Isolate* isolate);
  static Address current_limit_address(Isolate* isolate);
  static Address current_level_address(Isolate* isolate);
201

202 203 204 205 206
  // Closes the HandleScope (invalidating all handles
  // created in the scope of the HandleScope) and returns
  // a Handle backed by the parent scope holding the
  // value of the argument handle.
  template <typename T>
207 208 209
  Handle<T> CloseAndEscape(Handle<T> handle_value);

  Isolate* isolate() { return isolate_; }
210

211 212 213 214 215 216 217
 private:
  // Prevent heap allocation or illegal handle scopes.
  HandleScope(const HandleScope&);
  void operator=(const HandleScope&);
  void* operator new(size_t size);
  void operator delete(void* size_t);

218
  Isolate* isolate_;
219 220
  Object** prev_next_;
  Object** prev_limit_;
221

222 223 224 225 226
  // Close the handle scope resetting limits to a previous state.
  static inline void CloseScope(Isolate* isolate,
                                Object** prev_next,
                                Object** prev_limit);

227
  // Extend the handle scope making room for more handles.
228
  static internal::Object** Extend(Isolate* isolate);
229

230
#ifdef ENABLE_HANDLE_ZAPPING
231
  // Zaps the handles in the half-open interval [start, end).
232
  static void ZapRange(Object** start, Object** end);
233
#endif
234 235

  friend class v8::HandleScope;
236
  friend class v8::internal::DeferredHandles;
237
  friend class v8::internal::HandleScopeImplementer;
238
  friend class v8::internal::Isolate;
239 240 241
};


242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267
class DeferredHandles;


class DeferredHandleScope {
 public:
  explicit DeferredHandleScope(Isolate* isolate);
  // The DeferredHandles object returned stores the Handles created
  // since the creation of this DeferredHandleScope.  The Handles are
  // alive as long as the DeferredHandles object is alive.
  DeferredHandles* Detach();
  ~DeferredHandleScope();

 private:
  Object** prev_limit_;
  Object** prev_next_;
  HandleScopeImplementer* impl_;

#ifdef DEBUG
  bool handles_detached_;
  int prev_level_;
#endif

  friend class HandleScopeImplementer;
};


268 269 270
// Seal off the current HandleScope so that new handles can only be created
// if a new HandleScope is entered.
class SealHandleScope BASE_EMBEDDED {
271 272
 public:
#ifndef DEBUG
273 274
  explicit SealHandleScope(Isolate* isolate) {}
  ~SealHandleScope() {}
275
#else
276 277
  explicit inline SealHandleScope(Isolate* isolate);
  inline ~SealHandleScope();
278
 private:
279
  Isolate* isolate_;
280
  Object** limit_;
281
  int level_;
282 283 284
#endif
};

285 286 287 288 289 290 291 292 293 294 295
struct HandleScopeData {
  internal::Object** next;
  internal::Object** limit;
  int level;

  void Initialize() {
    next = limit = NULL;
    level = 0;
  }
};

296 297 298
} }  // namespace v8::internal

#endif  // V8_HANDLES_H_