SP: plumb CapPtr through cache_friendly functions

Change these functions from being void* to void* to either consuming or
producing FreeObject*-s as appropriate.
This commit is contained in:
Nathaniel Filardo
2021-03-05 12:57:34 +00:00
committed by Nathaniel Wesley Filardo
parent 97f508e2b3
commit c5aff8ed74
4 changed files with 45 additions and 40 deletions

View File

@@ -641,20 +641,25 @@ namespace snmalloc
#ifdef CACHE_FRIENDLY_OFFSET
size_t remote_offset = 0;
void* apply_cache_friendly_offset(void* p, sizeclass_t sizeclass)
template<capptr_bounds B>
CapPtr<FreeObject, B>
apply_cache_friendly_offset(CapPtr<void, B> p, sizeclass_t sizeclass)
{
size_t mask = sizeclass_to_cache_friendly_mask(sizeclass);
size_t offset = remote_offset & mask;
remote_offset += CACHE_FRIENDLY_OFFSET;
return (void*)((uintptr_t)p + offset);
return CapPtr<FreeObject, B>(reinterpret_cast<FreeObject*>(
reinterpret_cast<uintptr_t>(p.unsafe_capptr) + offset));
}
#else
void* apply_cache_friendly_offset(void* p, sizeclass_t sizeclass)
template<capptr_bounds B>
static CapPtr<FreeObject, B>
apply_cache_friendly_offset(CapPtr<void, B> p, sizeclass_t sizeclass)
{
UNUSED(sizeclass);
return p;
return p.template as_static<FreeObject>();
}
#endif
@@ -855,10 +860,8 @@ namespace snmalloc
p->trunc_target_id() == super->get_allocator()->trunc_id(),
"Detected memory corruption. Potential use-after-free");
auto start_auth = CapPtr<void, CBArena>(
remove_cache_friendly_offset(p_auth.unsafe_capptr, p->sizeclass()));
dealloc_not_large_local(
super, start_auth, p_auth.as_void(), p->sizeclass());
auto start_auth = remove_cache_friendly_offset(p_auth, p->sizeclass());
dealloc_not_large_local(super, start_auth, p_auth, p->sizeclass());
}
else
{
@@ -872,23 +875,23 @@ namespace snmalloc
CapPtr<void, CBArena> p_auth,
sizeclass_t sizeclass)
{
auto offseted = CapPtr<void, CBArena>(
apply_cache_friendly_offset(p_auth.unsafe_capptr, sizeclass));
if (likely(target->trunc_id() == get_trunc_id()))
{
auto super = Superslab::get(p_auth);
auto offseted = apply_cache_friendly_offset(p_auth, sizeclass)
.template as_reinterpret<Remote>();
dealloc_not_large_local(super, p_auth, offseted, sizeclass);
}
else
{
remote_dealloc_and_post(target, offseted, sizeclass);
remote_dealloc_and_post(target, p_auth, sizeclass);
}
}
SNMALLOC_FAST_PATH void dealloc_not_large_local(
CapPtr<Superslab, CBArena> super,
CapPtr<void, CBArena> p_auth,
CapPtr<void, CBArena> p_auth_offseted,
CapPtr<Remote, CBArena> p_auth_offseted,
sizeclass_t sizeclass)
{
// Guard against remote queues that have colliding IDs
@@ -1056,8 +1059,7 @@ namespace snmalloc
{
stats().alloc_request(size);
stats().sizeclass_alloc(sizeclass);
void* p = remove_cache_friendly_offset(
fl.take(entropy).unsafe_capptr, sizeclass);
auto p = remove_cache_friendly_offset(fl.take(entropy), sizeclass);
if constexpr (zero_mem == YesZero)
{
pal_zero<typename MemoryProvider::Pal>(
@@ -1173,8 +1175,7 @@ namespace snmalloc
SNMALLOC_ASSERT(ffl.empty());
Slab::alloc_new_list(bp, ffl, rsize, entropy);
auto p = remove_cache_friendly_offset(
ffl.take(entropy).unsafe_capptr, sizeclass);
auto p = remove_cache_friendly_offset(ffl.take(entropy), sizeclass);
if constexpr (zero_mem == YesZero)
{
@@ -1258,13 +1259,8 @@ namespace snmalloc
if (likely(target == public_state()))
{
void* offseted =
apply_cache_friendly_offset(p_auth.unsafe_capptr, sizeclass);
small_dealloc_offseted(
super,
slab,
FreeObject::make(CapPtr<void, CBArena>(offseted)),
sizeclass);
auto offseted = apply_cache_friendly_offset(p_auth, sizeclass);
small_dealloc_offseted(super, slab, offseted, sizeclass);
}
else
remote_dealloc(target, p_auth, sizeclass);
@@ -1613,10 +1609,8 @@ namespace snmalloc
// this path.
if (remote.capacity > 0)
{
void* offseted =
apply_cache_friendly_offset(p.unsafe_capptr, sizeclass);
stats().remote_free(sizeclass);
remote.dealloc(target->trunc_id(), offseted, sizeclass);
remote.dealloc(target->trunc_id(), p.unsafe_capptr, sizeclass);
return;
}
@@ -1648,12 +1642,13 @@ namespace snmalloc
SNMALLOC_SLOW_PATH void remote_dealloc_and_post(
RemoteAllocator* target,
CapPtr<void, CBArena> offseted,
CapPtr<void, CBArena> p_auth,
sizeclass_t sizeclass)
{
handle_message_queue();
stats().remote_free(sizeclass);
auto offseted = apply_cache_friendly_offset(p_auth, sizeclass);
remote.dealloc(target->trunc_id(), offseted.unsafe_capptr, sizeclass);
stats().remote_post();

View File

@@ -141,6 +141,15 @@ namespace snmalloc
return p.template as_static<FreeObject>();
}
/**
* Construct a FreeObject for local slabs from a Remote message.
*/
static CapPtr<FreeObject, CBArena> make(CapPtr<Remote, CBArena> p)
{
// TODO: Zero the difference between a FreeObject and a Remote
return p.template as_reinterpret<FreeObject>();
}
/**
* Read the next pointer handling any required decoding of the pointer
*/

View File

@@ -176,8 +176,7 @@ namespace snmalloc
self->remove();
self->set_full(Metaslab::get_slab(n));
void* p =
remove_cache_friendly_offset(n.unsafe_capptr, self->sizeclass());
auto p = remove_cache_friendly_offset(n, self->sizeclass());
SNMALLOC_ASSERT(is_start_of_object(self, address_cast(p)));
self->debug_slab_invariant(Metaslab::get_slab(n), entropy);
@@ -194,7 +193,7 @@ namespace snmalloc
UNUSED(rsize);
}
return CapPtr<void, CBArena>(p);
return p;
}
void debug_slab_invariant(CapPtr<Slab, CBArena> slab, LocalEntropy& entropy)

View File

@@ -58,29 +58,31 @@ namespace snmalloc
bits::ADDRESS_BITS - SUPERSLAB_BITS;
#ifdef CACHE_FRIENDLY_OFFSET
SNMALLOC_FAST_PATH static void*
remove_cache_friendly_offset(void* p, sizeclass_t sizeclass)
template<typename T, capptr_bounds B>
SNMALLOC_FAST_PATH static CapPtr<void, B>
remove_cache_friendly_offset(CapPtr<T, B> p, sizeclass_t sizeclass)
{
size_t mask = sizeclass_to_inverse_cache_friendly_mask(sizeclass);
return p = (void*)((uintptr_t)p & mask);
return CapPtr<void, B>((void*)((uintptr_t)p.unsafe_capptr & mask));
}
SNMALLOC_FAST_PATH static uintptr_t
remove_cache_friendly_offset(uintptr_t relative, sizeclass_t sizeclass)
SNMALLOC_FAST_PATH static address_t
remove_cache_friendly_offset(address_t relative, sizeclass_t sizeclass)
{
size_t mask = sizeclass_to_inverse_cache_friendly_mask(sizeclass);
return relative & mask;
}
#else
SNMALLOC_FAST_PATH static void*
remove_cache_friendly_offset(void* p, sizeclass_t sizeclass)
template<typename T, capptr_bounds B>
SNMALLOC_FAST_PATH static CapPtr<void, B>
remove_cache_friendly_offset(CapPtr<T, B> p, sizeclass_t sizeclass)
{
UNUSED(sizeclass);
return p;
return p.as_void();
}
SNMALLOC_FAST_PATH static uintptr_t
remove_cache_friendly_offset(uintptr_t relative, sizeclass_t sizeclass)
SNMALLOC_FAST_PATH static address_t
remove_cache_friendly_offset(address_t relative, sizeclass_t sizeclass)
{
UNUSED(sizeclass);
return relative;