4569ffae0b
Adds a cross-thread reference for strongly and weakly retaining objects on a thread other than the thread that owns the object. The intended use of the reference is by setting it up on the originating thread, holding the object alive from another thread, and ultimately accessing the object again on the originating thread. The reference has known caveats: - It's unsafe to use when the heap may terminate; - It's unsafe to transitively reach through the graph because of compaction; Change-Id: I84fbdde69a099eb54af5b93c34e2169915b17e64 Bug: chromium:1056170 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2436449 Commit-Queue: Michael Lippautz <mlippautz@chromium.org> Reviewed-by: Omer Katz <omerkatz@chromium.org> Reviewed-by: Anton Bikineev <bikineev@chromium.org> Cr-Commit-Position: refs/heads/master@{#70428}
149 lines
4.4 KiB
C++
149 lines
4.4 KiB
C++
// Copyright 2020 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 INCLUDE_CPPGC_INTERNAL_POINTER_POLICIES_H_
|
|
#define INCLUDE_CPPGC_INTERNAL_POINTER_POLICIES_H_
|
|
|
|
#include <cstdint>
|
|
#include <type_traits>
|
|
|
|
#include "cppgc/internal/write-barrier.h"
|
|
#include "cppgc/source-location.h"
|
|
#include "v8config.h" // NOLINT(build/include_directory)
|
|
|
|
namespace cppgc {
|
|
namespace internal {
|
|
|
|
class PersistentRegion;
|
|
|
|
// Tags to distinguish between strong and weak member types.
|
|
class StrongMemberTag;
|
|
class WeakMemberTag;
|
|
class UntracedMemberTag;
|
|
|
|
struct DijkstraWriteBarrierPolicy {
|
|
static void InitializingBarrier(const void*, const void*) {
|
|
// Since in initializing writes the source object is always white, having no
|
|
// barrier doesn't break the tri-color invariant.
|
|
}
|
|
static void AssigningBarrier(const void* slot, const void* value) {
|
|
WriteBarrier::MarkingBarrier(slot, value);
|
|
}
|
|
};
|
|
|
|
struct NoWriteBarrierPolicy {
|
|
static void InitializingBarrier(const void*, const void*) {}
|
|
static void AssigningBarrier(const void*, const void*) {}
|
|
};
|
|
|
|
class V8_EXPORT EnabledCheckingPolicy {
|
|
protected:
|
|
EnabledCheckingPolicy();
|
|
void CheckPointer(const void* ptr);
|
|
|
|
private:
|
|
void* impl_;
|
|
};
|
|
|
|
class DisabledCheckingPolicy {
|
|
protected:
|
|
void CheckPointer(const void* raw) {}
|
|
};
|
|
|
|
#if V8_ENABLE_CHECKS
|
|
using DefaultCheckingPolicy = EnabledCheckingPolicy;
|
|
#else
|
|
using DefaultCheckingPolicy = DisabledCheckingPolicy;
|
|
#endif
|
|
|
|
class KeepLocationPolicy {
|
|
public:
|
|
constexpr const SourceLocation& Location() const { return location_; }
|
|
|
|
protected:
|
|
constexpr KeepLocationPolicy() = default;
|
|
constexpr explicit KeepLocationPolicy(const SourceLocation& location)
|
|
: location_(location) {}
|
|
|
|
// KeepLocationPolicy must not copy underlying source locations.
|
|
KeepLocationPolicy(const KeepLocationPolicy&) = delete;
|
|
KeepLocationPolicy& operator=(const KeepLocationPolicy&) = delete;
|
|
|
|
// Location of the original moved from object should be preserved.
|
|
KeepLocationPolicy(KeepLocationPolicy&&) = default;
|
|
KeepLocationPolicy& operator=(KeepLocationPolicy&&) = default;
|
|
|
|
private:
|
|
SourceLocation location_;
|
|
};
|
|
|
|
class IgnoreLocationPolicy {
|
|
public:
|
|
constexpr SourceLocation Location() const { return {}; }
|
|
|
|
protected:
|
|
constexpr IgnoreLocationPolicy() = default;
|
|
constexpr explicit IgnoreLocationPolicy(const SourceLocation&) {}
|
|
};
|
|
|
|
#if CPPGC_SUPPORTS_OBJECT_NAMES
|
|
using DefaultLocationPolicy = KeepLocationPolicy;
|
|
#else
|
|
using DefaultLocationPolicy = IgnoreLocationPolicy;
|
|
#endif
|
|
|
|
struct StrongPersistentPolicy {
|
|
using IsStrongPersistent = std::true_type;
|
|
static V8_EXPORT PersistentRegion& GetPersistentRegion(void* object);
|
|
};
|
|
|
|
struct WeakPersistentPolicy {
|
|
using IsStrongPersistent = std::false_type;
|
|
static V8_EXPORT PersistentRegion& GetPersistentRegion(void* object);
|
|
};
|
|
|
|
struct StrongCrossThreadPersistentPolicy {
|
|
using IsStrongPersistent = std::true_type;
|
|
static V8_EXPORT PersistentRegion& GetPersistentRegion(void* object);
|
|
};
|
|
|
|
struct WeakCrossThreadPersistentPolicy {
|
|
using IsStrongPersistent = std::false_type;
|
|
static V8_EXPORT PersistentRegion& GetPersistentRegion(void* object);
|
|
};
|
|
|
|
// Forward declarations setting up the default policies.
|
|
template <typename T, typename WeaknessPolicy,
|
|
typename LocationPolicy = DefaultLocationPolicy,
|
|
typename CheckingPolicy = DisabledCheckingPolicy>
|
|
class BasicCrossThreadPersistent;
|
|
template <typename T, typename WeaknessPolicy,
|
|
typename LocationPolicy = DefaultLocationPolicy,
|
|
typename CheckingPolicy = DefaultCheckingPolicy>
|
|
class BasicPersistent;
|
|
template <typename T, typename WeaknessTag, typename WriteBarrierPolicy,
|
|
typename CheckingPolicy = DefaultCheckingPolicy>
|
|
class BasicMember;
|
|
|
|
// Special tag type used to denote some sentinel member. The semantics of the
|
|
// sentinel is defined by the embedder.
|
|
struct SentinelPointer {
|
|
template <typename T>
|
|
operator T*() const { // NOLINT
|
|
static constexpr intptr_t kSentinelValue = 1;
|
|
return reinterpret_cast<T*>(kSentinelValue);
|
|
}
|
|
// Hidden friends.
|
|
friend bool operator==(SentinelPointer, SentinelPointer) { return true; }
|
|
friend bool operator!=(SentinelPointer, SentinelPointer) { return false; }
|
|
};
|
|
|
|
} // namespace internal
|
|
|
|
constexpr internal::SentinelPointer kSentinelPointer;
|
|
|
|
} // namespace cppgc
|
|
|
|
#endif // INCLUDE_CPPGC_INTERNAL_POINTER_POLICIES_H_
|