RFC: Hide CapPtr constructor
Expose a static CapPtr<T,B>::unsafe_from() and use that everywhere instead (though continue to allow implicit and explicit construction of CapPtr from nullptr).
This commit is contained in:
committed by
Nathaniel Filardo
parent
41128a3387
commit
f41bb321f7
@@ -212,7 +212,8 @@ namespace snmalloc
|
||||
"capptr_bound must preserve non-spatial CapPtr dimensions");
|
||||
|
||||
UNUSED(size);
|
||||
return CapPtr<T, BOut>(a.template as_static<T>().unsafe_ptr());
|
||||
return CapPtr<T, BOut>::unsafe_from(
|
||||
a.template as_static<T>().unsafe_ptr());
|
||||
}
|
||||
};
|
||||
} // namespace snmalloc
|
||||
|
||||
@@ -86,7 +86,7 @@ namespace snmalloc
|
||||
}
|
||||
|
||||
void* pb = __builtin_cheri_bounds_set_exact(a.unsafe_ptr(), size);
|
||||
return CapPtr<T, BOut>(static_cast<T*>(pb));
|
||||
return CapPtr<T, BOut>::unsafe_from(static_cast<T*>(pb));
|
||||
}
|
||||
};
|
||||
} // namespace snmalloc
|
||||
|
||||
@@ -34,7 +34,8 @@ namespace snmalloc
|
||||
inline CapPtr<void, bounds>
|
||||
pointer_offset(CapPtr<T, bounds> base, size_t diff)
|
||||
{
|
||||
return CapPtr<void, bounds>(pointer_offset(base.unsafe_ptr(), diff));
|
||||
return CapPtr<void, bounds>::unsafe_from(
|
||||
pointer_offset(base.unsafe_ptr(), diff));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -51,7 +52,8 @@ namespace snmalloc
|
||||
inline CapPtr<void, bounds>
|
||||
pointer_offset_signed(CapPtr<T, bounds> base, ptrdiff_t diff)
|
||||
{
|
||||
return CapPtr<void, bounds>(pointer_offset_signed(base.unsafe_ptr(), diff));
|
||||
return CapPtr<void, bounds>::unsafe_from(
|
||||
pointer_offset_signed(base.unsafe_ptr(), diff));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -137,7 +139,8 @@ namespace snmalloc
|
||||
SNMALLOC_CONCEPT(capptr::ConceptBound) bounds>
|
||||
inline CapPtr<T, bounds> pointer_align_down(CapPtr<void, bounds> p)
|
||||
{
|
||||
return CapPtr<T, bounds>(pointer_align_down<alignment, T>(p.unsafe_ptr()));
|
||||
return CapPtr<T, bounds>::unsafe_from(
|
||||
pointer_align_down<alignment, T>(p.unsafe_ptr()));
|
||||
}
|
||||
|
||||
template<size_t alignment>
|
||||
@@ -174,7 +177,8 @@ namespace snmalloc
|
||||
SNMALLOC_CONCEPT(capptr::ConceptBound) bounds>
|
||||
inline CapPtr<T, bounds> pointer_align_up(CapPtr<void, bounds> p)
|
||||
{
|
||||
return CapPtr<T, bounds>(pointer_align_up<alignment, T>(p.unsafe_ptr()));
|
||||
return CapPtr<T, bounds>::unsafe_from(
|
||||
pointer_align_up<alignment, T>(p.unsafe_ptr()));
|
||||
}
|
||||
|
||||
template<size_t alignment>
|
||||
@@ -204,7 +208,8 @@ namespace snmalloc
|
||||
inline CapPtr<T, bounds>
|
||||
pointer_align_down(CapPtr<void, bounds> p, size_t alignment)
|
||||
{
|
||||
return CapPtr<T, bounds>(pointer_align_down<T>(p.unsafe_ptr(), alignment));
|
||||
return CapPtr<T, bounds>::unsafe_from(
|
||||
pointer_align_down<T>(p.unsafe_ptr(), alignment));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -228,7 +233,8 @@ namespace snmalloc
|
||||
inline CapPtr<T, bounds>
|
||||
pointer_align_up(CapPtr<void, bounds> p, size_t alignment)
|
||||
{
|
||||
return CapPtr<T, bounds>(pointer_align_up<T>(p.unsafe_ptr(), alignment));
|
||||
return CapPtr<T, bounds>::unsafe_from(
|
||||
pointer_align_up<T>(p.unsafe_ptr(), alignment));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -140,12 +140,12 @@ namespace snmalloc
|
||||
Pagemap::set_metaentry(address_cast(alloc), size, t);
|
||||
|
||||
local_state.get_meta_range().dealloc_range(
|
||||
capptr::Chunk<void>(&slab_metadata), sizeof(SlabMetadata));
|
||||
capptr::Chunk<void>::unsafe_from(&slab_metadata), sizeof(SlabMetadata));
|
||||
|
||||
// On non-CHERI platforms, we don't need to re-derive to get a pointer to
|
||||
// the chunk. On CHERI platforms this will need to be stored in the
|
||||
// SlabMetadata or similar.
|
||||
capptr::Chunk<void> chunk{alloc.unsafe_ptr()};
|
||||
auto chunk = capptr::Chunk<void>::unsafe_from(alloc.unsafe_ptr());
|
||||
local_state.object_range.dealloc_range(chunk, size);
|
||||
}
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ namespace snmalloc
|
||||
|
||||
// Push memory into the global range.
|
||||
range_to_pow_2_blocks<MIN_CHUNK_BITS>(
|
||||
capptr::Chunk<void>(heap_base),
|
||||
capptr::Chunk<void>::unsafe_from(heap_base),
|
||||
heap_length,
|
||||
[&](capptr::Chunk<void> p, size_t sz, bool) {
|
||||
typename LocalState::GlobalR g;
|
||||
@@ -108,8 +108,8 @@ namespace snmalloc
|
||||
|
||||
return CapPtr<
|
||||
T,
|
||||
typename B::template with_wildness<capptr::dimension::Wildness::Tame>>(
|
||||
p.unsafe_ptr());
|
||||
typename B::template with_wildness<capptr::dimension::Wildness::Tame>>::
|
||||
unsafe_from(p.unsafe_ptr());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -262,8 +262,9 @@ namespace snmalloc
|
||||
{
|
||||
range_to_pow_2_blocks<MIN_CHUNK_BITS>(
|
||||
base, length, [this](capptr::Chunk<void> base, size_t align, bool) {
|
||||
auto overflow = capptr::Chunk<void>(reinterpret_cast<void*>(
|
||||
buddy_large.add_block(base.unsafe_uintptr(), align)));
|
||||
auto overflow =
|
||||
capptr::Chunk<void>::unsafe_from(reinterpret_cast<void*>(
|
||||
buddy_large.add_block(base.unsafe_uintptr(), align)));
|
||||
|
||||
dealloc_overflow(overflow);
|
||||
});
|
||||
@@ -358,7 +359,7 @@ namespace snmalloc
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto result = capptr::Chunk<void>(
|
||||
auto result = capptr::Chunk<void>::unsafe_from(
|
||||
reinterpret_cast<void*>(buddy_large.remove_block(size)));
|
||||
|
||||
if (result != nullptr)
|
||||
@@ -381,8 +382,9 @@ namespace snmalloc
|
||||
}
|
||||
}
|
||||
|
||||
auto overflow = capptr::Chunk<void>(reinterpret_cast<void*>(
|
||||
buddy_large.add_block(base.unsafe_uintptr(), size)));
|
||||
auto overflow =
|
||||
capptr::Chunk<void>::unsafe_from(reinterpret_cast<void*>(
|
||||
buddy_large.add_block(base.unsafe_uintptr(), size)));
|
||||
dealloc_overflow(overflow);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -28,8 +28,8 @@ namespace snmalloc
|
||||
if constexpr (pal_supports<AlignedAllocation, PAL>)
|
||||
{
|
||||
SNMALLOC_ASSERT(size >= PAL::minimum_alloc_size);
|
||||
auto result =
|
||||
capptr::Chunk<void>(PAL::template reserve_aligned<false>(size));
|
||||
auto result = capptr::Chunk<void>::unsafe_from(
|
||||
PAL::template reserve_aligned<false>(size));
|
||||
|
||||
#ifdef SNMALLOC_TRACING
|
||||
message<1024>("Pal range alloc: {} ({})", result.unsafe_ptr(), size);
|
||||
@@ -38,7 +38,7 @@ namespace snmalloc
|
||||
}
|
||||
else
|
||||
{
|
||||
auto result = capptr::Chunk<void>(PAL::reserve(size));
|
||||
auto result = capptr::Chunk<void>::unsafe_from(PAL::reserve(size));
|
||||
|
||||
#ifdef SNMALLOC_TRACING
|
||||
message<1024>("Pal range alloc: {} ({})", result.unsafe_ptr(), size);
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace snmalloc
|
||||
{
|
||||
SNMALLOC_ASSERT((address_cast(r) & MASK) == 0);
|
||||
if (r == nullptr)
|
||||
*ptr = capptr::Chunk<FreeChunk>(
|
||||
*ptr = capptr::Chunk<FreeChunk>::unsafe_from(
|
||||
reinterpret_cast<FreeChunk*>((*ptr).unsafe_uintptr() & MASK));
|
||||
else
|
||||
// Preserve lower bit.
|
||||
@@ -71,7 +71,8 @@ namespace snmalloc
|
||||
if (new_is_red)
|
||||
{
|
||||
if (old_addr == nullptr)
|
||||
*r = capptr::Chunk<FreeChunk>(reinterpret_cast<FreeChunk*>(MASK));
|
||||
*r = capptr::Chunk<FreeChunk>::unsafe_from(
|
||||
reinterpret_cast<FreeChunk*>(MASK));
|
||||
else
|
||||
*r = pointer_offset(old_addr, MASK).template as_static<FreeChunk>();
|
||||
}
|
||||
|
||||
@@ -283,6 +283,7 @@ namespace snmalloc
|
||||
|
||||
constexpr SNMALLOC_FAST_PATH CapPtr() : CapPtr(nullptr) {}
|
||||
|
||||
private:
|
||||
/**
|
||||
* all other constructions must be explicit
|
||||
*
|
||||
@@ -302,13 +303,25 @@ namespace snmalloc
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
public:
|
||||
/**
|
||||
* The CapPtr constructor is not sufficiently intimidating, given that it
|
||||
* can be used to break annotation correctness. Expose it with a better
|
||||
* name.
|
||||
*/
|
||||
static constexpr SNMALLOC_FAST_PATH CapPtr unsafe_from(T* p)
|
||||
{
|
||||
return CapPtr<T, bounds>(p);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow static_cast<>-s that preserve bounds but vary the target type.
|
||||
*/
|
||||
template<typename U>
|
||||
[[nodiscard]] SNMALLOC_FAST_PATH CapPtr<U, bounds> as_static() const
|
||||
{
|
||||
return CapPtr<U, bounds>(static_cast<U*>(this->unsafe_capptr));
|
||||
return CapPtr<U, bounds>::unsafe_from(
|
||||
static_cast<U*>(this->unsafe_capptr));
|
||||
}
|
||||
|
||||
[[nodiscard]] SNMALLOC_FAST_PATH CapPtr<void, bounds> as_void() const
|
||||
@@ -322,7 +335,8 @@ namespace snmalloc
|
||||
template<typename U>
|
||||
[[nodiscard]] SNMALLOC_FAST_PATH CapPtr<U, bounds> as_reinterpret() const
|
||||
{
|
||||
return CapPtr<U, bounds>(reinterpret_cast<U*>(this->unsafe_capptr));
|
||||
return CapPtr<U, bounds>::unsafe_from(
|
||||
reinterpret_cast<U*>(this->unsafe_capptr));
|
||||
}
|
||||
|
||||
SNMALLOC_FAST_PATH bool operator==(const CapPtr& rhs) const
|
||||
@@ -396,7 +410,7 @@ namespace snmalloc
|
||||
inline SNMALLOC_FAST_PATH capptr::Alloc<T>
|
||||
capptr_chunk_is_alloc(capptr::ChunkUser<T> p)
|
||||
{
|
||||
return capptr::Alloc<T>(p.unsafe_ptr());
|
||||
return capptr::Alloc<T>::unsafe_from(p.unsafe_ptr());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -426,7 +440,7 @@ namespace snmalloc
|
||||
static inline SNMALLOC_FAST_PATH capptr::AllocWild<void>
|
||||
capptr_from_client(void* p)
|
||||
{
|
||||
return capptr::AllocWild<void>(p);
|
||||
return capptr::AllocWild<void>::unsafe_from(p);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -440,8 +454,8 @@ namespace snmalloc
|
||||
{
|
||||
return CapPtr<
|
||||
T,
|
||||
typename B::template with_wildness<capptr::dimension::Wildness::Wild>>(
|
||||
p.unsafe_ptr());
|
||||
typename B::template with_wildness<capptr::dimension::Wildness::Wild>>::
|
||||
unsafe_from(p.unsafe_ptr());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -490,7 +504,7 @@ namespace snmalloc
|
||||
SNMALLOC_FAST_PATH CapPtr<T, bounds>
|
||||
load(std::memory_order order = std::memory_order_seq_cst) noexcept
|
||||
{
|
||||
return CapPtr<T, bounds>(this->unsafe_capptr.load(order));
|
||||
return CapPtr<T, bounds>::unsafe_from(this->unsafe_capptr.load(order));
|
||||
}
|
||||
|
||||
SNMALLOC_FAST_PATH void store(
|
||||
@@ -504,7 +518,7 @@ namespace snmalloc
|
||||
CapPtr<T, bounds> desired,
|
||||
std::memory_order order = std::memory_order_seq_cst) noexcept
|
||||
{
|
||||
return CapPtr<T, bounds>(
|
||||
return CapPtr<T, bounds>::unsafe_from(
|
||||
this->unsafe_capptr.exchange(desired.unsafe_ptr(), order));
|
||||
}
|
||||
|
||||
|
||||
@@ -102,8 +102,8 @@ namespace snmalloc
|
||||
UNUSED(ls);
|
||||
return CapPtr<
|
||||
T,
|
||||
typename B::template with_wildness<capptr::dimension::Wildness::Tame>>(
|
||||
p.unsafe_ptr());
|
||||
typename B::template with_wildness<capptr::dimension::Wildness::Tame>>::
|
||||
unsafe_from(p.unsafe_ptr());
|
||||
}
|
||||
}
|
||||
} // namespace snmalloc
|
||||
|
||||
@@ -506,10 +506,10 @@ namespace snmalloc
|
||||
* The front of the queue has already been validated; just change the
|
||||
* annotating type.
|
||||
*/
|
||||
auto domesticate_first = [](freelist::QueuePtr p)
|
||||
SNMALLOC_FAST_PATH_LAMBDA {
|
||||
return freelist::HeadPtr(p.unsafe_ptr());
|
||||
};
|
||||
auto domesticate_first =
|
||||
[](freelist::QueuePtr p) SNMALLOC_FAST_PATH_LAMBDA {
|
||||
return freelist::HeadPtr::unsafe_from(p.unsafe_ptr());
|
||||
};
|
||||
message_queue().dequeue(key_global, domesticate_first, domesticate, cb);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -270,7 +270,8 @@ namespace snmalloc
|
||||
inline static BQueuePtr<BQueue> encode_next(
|
||||
address_t curr, BHeadPtr<BView, BQueue> next, const FreeListKey& key)
|
||||
{
|
||||
return BQueuePtr<BQueue>(code_next(curr, next.unsafe_ptr(), key));
|
||||
return BQueuePtr<BQueue>::unsafe_from(
|
||||
code_next(curr, next.unsafe_ptr(), key));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -294,7 +295,8 @@ namespace snmalloc
|
||||
inline static BHeadPtr<BView, BQueue> decode_next(
|
||||
address_t curr, BHeadPtr<BView, BQueue> next, const FreeListKey& key)
|
||||
{
|
||||
return BHeadPtr<BView, BQueue>(code_next(curr, next.unsafe_ptr(), key));
|
||||
return BHeadPtr<BView, BQueue>::unsafe_from(
|
||||
code_next(curr, next.unsafe_ptr(), key));
|
||||
}
|
||||
|
||||
template<
|
||||
@@ -543,7 +545,7 @@ namespace snmalloc
|
||||
|
||||
Object::BHeadPtr<BView, BQueue> cast_head(uint32_t ix)
|
||||
{
|
||||
return Object::BHeadPtr<BView, BQueue>(
|
||||
return Object::BHeadPtr<BView, BQueue>::unsafe_from(
|
||||
static_cast<Object::T<BQueue>*>(head[ix]));
|
||||
}
|
||||
|
||||
@@ -715,8 +717,8 @@ namespace snmalloc
|
||||
// this is doing a CONTAINING_RECORD like cast to get back
|
||||
// to the actual object. This isn't true if the builder is
|
||||
// empty, but you are not allowed to call this in the empty case.
|
||||
auto last =
|
||||
Object::BHeadPtr<BView, BQueue>(Object::from_next_ptr(cast_end(0)));
|
||||
auto last = Object::BHeadPtr<BView, BQueue>::unsafe_from(
|
||||
Object::from_next_ptr(cast_end(0)));
|
||||
init();
|
||||
return {first, last};
|
||||
}
|
||||
|
||||
@@ -115,7 +115,7 @@ namespace snmalloc
|
||||
if constexpr (Config::Options.QueueHeadsAreTame)
|
||||
{
|
||||
auto domesticate_nop = [](freelist::QueuePtr p) {
|
||||
return freelist::HeadPtr(p.unsafe_ptr());
|
||||
return freelist::HeadPtr::unsafe_from(p.unsafe_ptr());
|
||||
};
|
||||
remote->enqueue(first, last, key, domesticate_nop);
|
||||
}
|
||||
|
||||
@@ -90,7 +90,8 @@ namespace snmalloc
|
||||
CapPtr<T, capptr::user_address_control_type<B>>>
|
||||
capptr_to_user_address_control(CapPtr<T, B> p)
|
||||
{
|
||||
return CapPtr<T, capptr::user_address_control_type<B>>(p.unsafe_ptr());
|
||||
return CapPtr<T, capptr::user_address_control_type<B>>::unsafe_from(
|
||||
p.unsafe_ptr());
|
||||
}
|
||||
|
||||
template<
|
||||
|
||||
@@ -135,7 +135,7 @@ namespace snmalloc
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
return CapPtr<T, capptr::user_address_control_type<B>>(
|
||||
return CapPtr<T, capptr::user_address_control_type<B>>::unsafe_from(
|
||||
__builtin_cheri_perms_and(
|
||||
p.unsafe_ptr(), ~static_cast<unsigned int>(CHERI_PERM_SW_VMEM)));
|
||||
}
|
||||
|
||||
@@ -108,8 +108,8 @@ namespace snmalloc
|
||||
|
||||
return CapPtr<
|
||||
T,
|
||||
typename B::template with_wildness<capptr::dimension::Wildness::Tame>>(
|
||||
p.unsafe_ptr());
|
||||
typename B::template with_wildness<capptr::dimension::Wildness::Tame>>::
|
||||
unsafe_from(p.unsafe_ptr());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user