As I mentioned in RT #43481, the garbage collector does some dodgy flag setting in memory pools, particularly in Parrot_add_to_free_list().
The attached patch fixes that, at least for PMC_EXT structures. See src/gc/smallobject.c:210: PObj_flags_SETTO((PObj *)object, PObj_on_free_list_FLAG); This converts down to: (PMC *)object)->obj.flags = PObj_on_free_list_FLAG; The relevant structures are: typedef struct Buffer { pobj_t obj; } Buffer; typedef Buffer PObj; typedef struct pobj_t { UnionVal u; Parrot_UInt flags; } pobj_t; All's good so far. Unfortunately, a pool can also contain PMC_EXT structs, which are: typedef struct PMC_EXT { #if PMC_DATA_IN_EXT DPOINTER *data; #endif /* PMC_DATA_IN_EXT */ struct _Sync *_synchronize; PMC *_next_for_GC; } PMC_EXT; If I do the offset math correctly (and I'm not sure I do), setting what would be flags in a PObj-like structure instead flips bits in the _next_for_GC PMC pointer, and those somewhere in its u member. Oops. This patch isn't clean enough for a final solution, but I think it may clean up some weird GC problems in other places. -- c
=== include/parrot/smallobject.h ================================================================== --- include/parrot/smallobject.h (revision 4643) +++ include/parrot/smallobject.h (local) @@ -101,6 +101,7 @@ size_t start_arena_memory; size_t end_arena_memory; const char *name; + int has_pobj; #if PARROT_GC_GMS struct _gc_gms_hdr marker; /* limit of list */ struct _gc_gms_hdr *black; /* alive */ === src/gc/smallobject.c ================================================================== --- src/gc/smallobject.c (revision 4643) +++ src/gc/smallobject.c (local) @@ -207,12 +207,14 @@ object = (void *)((char *)arena->start_objects + start * pool->object_size); for (i = start; i < end; i++) { - PObj_flags_SETTO((PObj *)object, PObj_on_free_list_FLAG); + if (pool->has_pobj) + PObj_flags_SETTO((PObj *)object, PObj_on_free_list_FLAG); /* * during GC buflen is used to check for objects on the * free_list */ - PObj_buflen((PObj*)object) = 0; + if (pool->has_pobj) + PObj_buflen((PObj*)object) = 0; pool->add_free_object(interp, pool, object); object = (void *)((char *)object + pool->object_size); } @@ -328,6 +330,7 @@ pool->mem_pool = NULL; pool->object_size = object_size; pool->objects_per_alloc = objects_per_alloc; + pool->has_pobj = 1; return pool; } === src/headers.c ================================================================== --- src/headers.c (revision 4643) +++ src/headers.c (local) @@ -553,6 +553,7 @@ /* pmc extension buffer */ arena_base->pmc_ext_pool = new_small_object_pool(sizeof (PMC_EXT), 1024); + arena_base->pmc_ext_pool->has_pobj = 0; /* * pmc_ext isn't a managed item. If a PMC has a pmc_ext structure * it is returned to the pool instantly - the structure is never