Add and plumb unsafe_{to,from}_uintptr<T> casts
These encapsulate the wildly powerful reinterpret_cast<> operator where one side is a uintptr_t and the other is a native pointer. In both cases we require the pointer type to be explicitly given.
This commit is contained in:
committed by
Nathaniel Wesley Filardo
parent
4ad99d7392
commit
26324e8bfc
@@ -28,8 +28,8 @@ namespace snmalloc
|
||||
inline U* pointer_offset(T* base, size_t diff)
|
||||
{
|
||||
SNMALLOC_ASSERT(base != nullptr); /* Avoid UB */
|
||||
return reinterpret_cast<U*>(
|
||||
reinterpret_cast<uintptr_t>(base) + static_cast<uintptr_t>(diff));
|
||||
return unsafe_from_uintptr<U>(
|
||||
unsafe_to_uintptr<T>(base) + static_cast<uintptr_t>(diff));
|
||||
}
|
||||
|
||||
template<SNMALLOC_CONCEPT(capptr::ConceptBound) bounds, typename T>
|
||||
@@ -129,8 +129,8 @@ namespace snmalloc
|
||||
template<size_t alignment, typename T = void>
|
||||
inline T* pointer_align_down(void* p)
|
||||
{
|
||||
return reinterpret_cast<T*>(
|
||||
pointer_align_down<alignment>(reinterpret_cast<uintptr_t>(p)));
|
||||
return unsafe_from_uintptr<T>(
|
||||
pointer_align_down<alignment>(unsafe_to_uintptr<void>(p)));
|
||||
}
|
||||
|
||||
template<
|
||||
@@ -164,8 +164,8 @@ namespace snmalloc
|
||||
#if __has_builtin(__builtin_align_up)
|
||||
return static_cast<T*>(__builtin_align_up(p, alignment));
|
||||
#else
|
||||
return reinterpret_cast<T*>(
|
||||
bits::align_up(reinterpret_cast<uintptr_t>(p), alignment));
|
||||
return unsafe_from_uintptr<T>(
|
||||
bits::align_up(unsafe_to_uintptr<void>(p), alignment));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -197,8 +197,8 @@ namespace snmalloc
|
||||
#if __has_builtin(__builtin_align_down)
|
||||
return static_cast<T*>(__builtin_align_down(p, alignment));
|
||||
#else
|
||||
return reinterpret_cast<T*>(
|
||||
bits::align_down(reinterpret_cast<uintptr_t>(p), alignment));
|
||||
return unsafe_from_uintptr<T>(
|
||||
bits::align_down(unsafe_to_uintptr<void>(p), alignment));
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -221,8 +221,8 @@ namespace snmalloc
|
||||
#if __has_builtin(__builtin_align_up)
|
||||
return static_cast<T*>(__builtin_align_up(p, alignment));
|
||||
#else
|
||||
return reinterpret_cast<T*>(
|
||||
bits::align_up(reinterpret_cast<uintptr_t>(p), alignment));
|
||||
return unsafe_from_uintptr<T>(
|
||||
bits::align_up(unsafe_to_uintptr<void>(p), alignment));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,30 @@
|
||||
|
||||
namespace snmalloc
|
||||
{
|
||||
/*
|
||||
* reinterpret_cast<> is a powerful primitive that, excitingly, does not
|
||||
* require the programmer to annotate the expected *source* type. We
|
||||
* therefore wrap its use to interconvert between uintptr_t and pointer types.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Convert a pointer to a uintptr_t. Template argument inference is
|
||||
* prohibited.
|
||||
*/
|
||||
template<typename T>
|
||||
SNMALLOC_FAST_PATH_INLINE uintptr_t
|
||||
unsafe_to_uintptr(std::enable_if_t<true, T>* p)
|
||||
{
|
||||
return reinterpret_cast<uintptr_t>(p);
|
||||
}
|
||||
|
||||
/** Convert a uintptr_t to a T*. */
|
||||
template<typename T>
|
||||
SNMALLOC_FAST_PATH_INLINE T* unsafe_from_uintptr(uintptr_t p)
|
||||
{
|
||||
return reinterpret_cast<T*>(p);
|
||||
}
|
||||
|
||||
/**
|
||||
* To assist in providing a uniform interface regardless of pointer wrapper,
|
||||
* we also export intrinsic pointer and atomic pointer aliases, as the postfix
|
||||
@@ -321,7 +345,7 @@ namespace snmalloc
|
||||
|
||||
[[nodiscard]] SNMALLOC_FAST_PATH uintptr_t unsafe_uintptr() const
|
||||
{
|
||||
return reinterpret_cast<uintptr_t>(this->unsafe_capptr);
|
||||
return unsafe_to_uintptr<T>(this->unsafe_capptr);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user