// Copyright 2011 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_HANDLES_H_
#define V8_HANDLES_H_
#include "include/v8.h"
#include "src/base/functional.h"
#include "src/base/macros.h"
#include "src/checks.h"
#include "src/globals.h"
#include "src/zone.h"
namespace v8 {
namespace internal {
// Forward declarations.
class DeferredHandles;
class HandleScopeImplementer;
class Isolate;
class Object;
// ----------------------------------------------------------------------------
// Base class for Handle instantiations. Don't use directly.
class HandleBase {
public:
V8_INLINE explicit HandleBase(Object** location) : location_(location) {}
V8_INLINE explicit HandleBase(Object* object, Isolate* isolate);
// Check if this handle refers to the exact same object as the other handle.
V8_INLINE bool is_identical_to(const HandleBase that) const {
// Dereferencing deferred handles to check object equality is safe.
SLOW_DCHECK((this->location_ == nullptr ||
this->IsDereferenceAllowed(NO_DEFERRED_CHECK)) &&
(that.location_ == nullptr ||
that.IsDereferenceAllowed(NO_DEFERRED_CHECK)));
if (this->location_ == that.location_) return true;
if (this->location_ == NULL || that.location_ == NULL) return false;
return *this->location_ == *that.location_;
}
V8_INLINE bool is_null() const { return location_ == nullptr; }
// Returns the raw address where this handle is stored. This should only be
// used for hashing handles; do not ever try to dereference it.
V8_INLINE Address address() const { return bit_cast
(location_); }
protected:
// Provides the C++ dereference operator.
V8_INLINE Object* operator*() const {
SLOW_DCHECK(IsDereferenceAllowed(INCLUDE_DEFERRED_CHECK));
return *location_;
}
// Returns the address to where the raw pointer is stored.
V8_INLINE Object** location() const {
SLOW_DCHECK(location_ == nullptr ||
IsDereferenceAllowed(INCLUDE_DEFERRED_CHECK));
return location_;
}
enum DereferenceCheckMode { INCLUDE_DEFERRED_CHECK, NO_DEFERRED_CHECK };
#ifdef DEBUG
bool IsDereferenceAllowed(DereferenceCheckMode mode) const;
#else
V8_INLINE
bool IsDereferenceAllowed(DereferenceCheckMode mode) const { return true; }
#endif // DEBUG
Object** location_;
};
// ----------------------------------------------------------------------------
// A Handle provides a reference to an object that survives relocation by
// the garbage collector.
//
// Handles are only valid within a HandleScope. When a handle is created
// for an object a cell is allocated in the current HandleScope.
//
// Also note that Handles do not provide default equality comparison or hashing
// operators on purpose. Such operators would be misleading, because intended
// semantics is ambiguous between Handle location and object identity. Instead
// use either {is_identical_to} or {location} explicitly.
template
class Handle final : public HandleBase {
public:
V8_INLINE explicit Handle(T** location = nullptr)
: HandleBase(reinterpret_cast