Skip to content

Commit

Permalink
Fix small chunk finaliser bug (#2257)
Browse files Browse the repository at this point in the history
Prior to this commit there was a bug which prevented the finaliser
from running for the first slot of a small `chunk` in an actors
`heap`. This would result in incorrect behavior but only on a subset
of all objects created depending on which slot in a small chunk the
object happened to occupy.

This commit fixes this issue and also adds a test to catch the
issue to prevent regression.
  • Loading branch information
dipinhora authored and Benoit Vey committed Oct 4, 2017
1 parent bdaaafb commit f6742a4
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 2 deletions.
7 changes: 5 additions & 2 deletions src/libponyrt/mem/heap.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,9 @@ static void final_small(chunk_t* chunk, uint32_t mark)
uint64_t bit = 0;

// if there's a finaliser to run for a used slot
while((finalisers != 0) && (0 != (bit = __pony_ctzl(finalisers))))
while(finalisers != 0)
{
bit = __pony_ctzl(finalisers);
p = chunk->m + (bit << HEAP_MINBITS);

// run finaliser
Expand All @@ -108,8 +109,9 @@ static void final_small_freed(chunk_t* chunk)
uint64_t bit = 0;

// if there's a finaliser to run for a used slot
while((finalisers != 0) && (0 != (bit = __pony_ctzl(finalisers))))
while(finalisers != 0)
{
bit = __pony_ctzl(finalisers);
p = chunk->m + (bit << HEAP_MINBITS);

// run finaliser
Expand All @@ -126,6 +128,7 @@ static void final_large(chunk_t* chunk, uint32_t mark)
if(chunk->finalisers == 1)
{
// run finaliser
pony_assert((*(pony_type_t**)chunk->m)->final != NULL);
(*(pony_type_t**)chunk->m)->final(chunk->m);
chunk->finalisers = 0;
}
Expand Down
38 changes: 38 additions & 0 deletions test/libponyc/codegen.cc
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,44 @@ TEST_F(CodegenTest, BoxBoolAsUnionIntoTuple)
}


extern "C"
{

uint32_t num_objects = 0;

EXPORT_SYMBOL void codegentest_small_finalisers_increment_num_objects() {
num_objects++;
pony_exitcode(num_objects);
}

}


TEST_F(CodegenTest, SmallFinalisers)
{
const char* src =
"use \"collections\"\n"

"class _Final\n"
" fun _final() =>\n"
" @codegentest_small_finalisers_increment_num_objects[None]()\n"

"actor Main\n"
" new create(env: Env) =>\n"
" for i in Range[I32](0, 42) do\n"
" _Final\n"
" end\n";

set_builtin(NULL);

TEST_COMPILE(src);

int exit_code = 0;
ASSERT_TRUE(run_program(&exit_code));
ASSERT_EQ(exit_code, 42);
}


extern "C"
{

Expand Down

0 comments on commit f6742a4

Please sign in to comment.