Skip to content

Commit

Permalink
Make heap large chunk bit twiddling branchless
Browse files Browse the repository at this point in the history
We use some bit twiddling operations for setting some flags on large
chunks in actor heaps. Before this commit, the functionality was
implemented with a ternary operator which would result in a branch.

This commit changes the logic to use bit shifts instead to avoid
the branching.
  • Loading branch information
dipinhora committed Oct 9, 2024
1 parent 2ef3e4b commit 731f2c3
Showing 1 changed file with 12 additions and 3 deletions.
15 changes: 12 additions & 3 deletions src/libponyrt/mem/heap.c
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,10 @@ static void set_large_chunk_slot(large_chunk_t* chunk, uint32_t slot)
{
// `!!` to normalize to 1 or 0
slot = !!slot;
((chunk_t*)chunk)->m = (char*)(((uintptr_t)((chunk_t*)chunk)->m & ~LARGE_CHUNK_SLOT_BITMASK) | (slot == 1 ? LARGE_CHUNK_SLOT_BITMASK : 0));
// left shift size to get bits in the right spot for OR'ing into `chunk->m`
slot = slot << 2;
pony_assert(slot == LARGE_CHUNK_SLOT_BITMASK || slot == 0);
((chunk_t*)chunk)->m = (char*)(((uintptr_t)((chunk_t*)chunk)->m & ~LARGE_CHUNK_SLOT_BITMASK) | slot);
}

static uint32_t get_large_chunk_shallow(large_chunk_t* chunk)
Expand All @@ -185,7 +188,10 @@ static void set_large_chunk_shallow(large_chunk_t* chunk, uint32_t shallow)
{
// `!!` to normalize to 1 or 0
shallow = !!shallow;
((chunk_t*)chunk)->m = (char*)(((uintptr_t)((chunk_t*)chunk)->m & ~LARGE_CHUNK_SHALLOW_BITMASK) | (shallow == 1 ? LARGE_CHUNK_SHALLOW_BITMASK : 0));
// left shift size to get bits in the right spot for OR'ing into `chunk->m`
shallow = shallow << 3;
pony_assert(shallow == LARGE_CHUNK_SHALLOW_BITMASK || shallow == 0);
((chunk_t*)chunk)->m = (char*)(((uintptr_t)((chunk_t*)chunk)->m & ~LARGE_CHUNK_SHALLOW_BITMASK) | shallow);
}

static uint32_t get_large_chunk_finaliser(large_chunk_t* chunk)
Expand All @@ -198,7 +204,10 @@ static void set_large_chunk_finaliser(large_chunk_t* chunk, uint32_t finaliser)
{
// `!!` to normalize to 1 or 0
finaliser = !!finaliser;
((chunk_t*)chunk)->m = (char*)(((uintptr_t)((chunk_t*)chunk)->m & ~LARGE_CHUNK_FINALISER_BITMASK) | (finaliser == 1 ? LARGE_CHUNK_FINALISER_BITMASK : 0));
// left shift size to get bits in the right spot for OR'ing into `chunk->m`
finaliser = finaliser << 4;
pony_assert(finaliser == LARGE_CHUNK_FINALISER_BITMASK || finaliser == 0);
((chunk_t*)chunk)->m = (char*)(((uintptr_t)((chunk_t*)chunk)->m & ~LARGE_CHUNK_FINALISER_BITMASK) | finaliser);
}

static size_t get_small_chunk_size(small_chunk_t* chunk)
Expand Down

0 comments on commit 731f2c3

Please sign in to comment.