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

Reply via email to