59fe961804
v8_enable_v8_checks has very little coverage outside of V8 itself. Move pointer verification checks behind DEBUG so that they fire in regular debug or dcheck_always_on builds. Change-Id: Ib2803240dd996f4223e403d20e927aff2955afbc Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3242006 Reviewed-by: Omer Katz <omerkatz@chromium.org> Commit-Queue: Michael Lippautz <mlippautz@chromium.org> Cr-Commit-Position: refs/heads/main@{#77534}
187 lines
5.9 KiB
C++
187 lines
5.9 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/sentinel-pointer.h"
|
|
#include "cppgc/source-location.h"
|
|
#include "cppgc/type-traits.h"
|
|
#include "v8config.h" // NOLINT(build/include_directory)
|
|
|
|
namespace cppgc {
|
|
namespace internal {
|
|
|
|
class HeapBase;
|
|
class PersistentRegion;
|
|
class CrossThreadPersistentRegion;
|
|
|
|
// 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::Params params;
|
|
switch (WriteBarrier::GetWriteBarrierType(slot, value, params)) {
|
|
case WriteBarrier::Type::kGenerational:
|
|
WriteBarrier::GenerationalBarrier(params, slot);
|
|
break;
|
|
case WriteBarrier::Type::kMarking:
|
|
WriteBarrier::DijkstraMarkingBarrier(params, value);
|
|
break;
|
|
case WriteBarrier::Type::kNone:
|
|
break;
|
|
}
|
|
}
|
|
};
|
|
|
|
struct NoWriteBarrierPolicy {
|
|
static void InitializingBarrier(const void*, const void*) {}
|
|
static void AssigningBarrier(const void*, const void*) {}
|
|
};
|
|
|
|
class V8_EXPORT SameThreadEnabledCheckingPolicyBase {
|
|
protected:
|
|
void CheckPointerImpl(const void* ptr, bool points_to_payload,
|
|
bool check_off_heap_assignments);
|
|
|
|
const HeapBase* heap_ = nullptr;
|
|
};
|
|
|
|
template <bool kCheckOffHeapAssignments>
|
|
class V8_EXPORT SameThreadEnabledCheckingPolicy
|
|
: private SameThreadEnabledCheckingPolicyBase {
|
|
protected:
|
|
template <typename T>
|
|
void CheckPointer(const T* ptr) {
|
|
if (!ptr || (kSentinelPointer == ptr)) return;
|
|
|
|
CheckPointersImplTrampoline<T>::Call(this, ptr);
|
|
}
|
|
|
|
private:
|
|
template <typename T, bool = IsCompleteV<T>>
|
|
struct CheckPointersImplTrampoline {
|
|
static void Call(SameThreadEnabledCheckingPolicy* policy, const T* ptr) {
|
|
policy->CheckPointerImpl(ptr, false, kCheckOffHeapAssignments);
|
|
}
|
|
};
|
|
|
|
template <typename T>
|
|
struct CheckPointersImplTrampoline<T, true> {
|
|
static void Call(SameThreadEnabledCheckingPolicy* policy, const T* ptr) {
|
|
policy->CheckPointerImpl(ptr, IsGarbageCollectedTypeV<T>,
|
|
kCheckOffHeapAssignments);
|
|
}
|
|
};
|
|
};
|
|
|
|
class DisabledCheckingPolicy {
|
|
protected:
|
|
void CheckPointer(const void*) {}
|
|
};
|
|
|
|
#ifdef DEBUG
|
|
// Off heap members are not connected to object graph and thus cannot ressurect
|
|
// dead objects.
|
|
using DefaultMemberCheckingPolicy =
|
|
SameThreadEnabledCheckingPolicy<false /* kCheckOffHeapAssignments*/>;
|
|
using DefaultPersistentCheckingPolicy =
|
|
SameThreadEnabledCheckingPolicy<true /* kCheckOffHeapAssignments*/>;
|
|
#else // !DEBUG
|
|
using DefaultMemberCheckingPolicy = DisabledCheckingPolicy;
|
|
using DefaultPersistentCheckingPolicy = DisabledCheckingPolicy;
|
|
#endif // !DEBUG
|
|
// For CT(W)P neither marking information (for value), nor objectstart bitmap
|
|
// (for slot) are guaranteed to be present because there's no synchronization
|
|
// between heaps after marking.
|
|
using DefaultCrossThreadPersistentCheckingPolicy = DisabledCheckingPolicy;
|
|
|
|
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(const void* object);
|
|
};
|
|
|
|
struct WeakPersistentPolicy {
|
|
using IsStrongPersistent = std::false_type;
|
|
static V8_EXPORT PersistentRegion& GetPersistentRegion(const void* object);
|
|
};
|
|
|
|
struct StrongCrossThreadPersistentPolicy {
|
|
using IsStrongPersistent = std::true_type;
|
|
static V8_EXPORT CrossThreadPersistentRegion& GetPersistentRegion(
|
|
const void* object);
|
|
};
|
|
|
|
struct WeakCrossThreadPersistentPolicy {
|
|
using IsStrongPersistent = std::false_type;
|
|
static V8_EXPORT CrossThreadPersistentRegion& GetPersistentRegion(
|
|
const void* object);
|
|
};
|
|
|
|
// Forward declarations setting up the default policies.
|
|
template <typename T, typename WeaknessPolicy,
|
|
typename LocationPolicy = DefaultLocationPolicy,
|
|
typename CheckingPolicy = DefaultCrossThreadPersistentCheckingPolicy>
|
|
class BasicCrossThreadPersistent;
|
|
template <typename T, typename WeaknessPolicy,
|
|
typename LocationPolicy = DefaultLocationPolicy,
|
|
typename CheckingPolicy = DefaultPersistentCheckingPolicy>
|
|
class BasicPersistent;
|
|
template <typename T, typename WeaknessTag, typename WriteBarrierPolicy,
|
|
typename CheckingPolicy = DefaultMemberCheckingPolicy>
|
|
class BasicMember;
|
|
|
|
} // namespace internal
|
|
|
|
} // namespace cppgc
|
|
|
|
#endif // INCLUDE_CPPGC_INTERNAL_POINTER_POLICIES_H_
|