I've been digging into the Lua on Parrot source code to try to find out why there are GC problems (partly to fix them, partly so I can profile Lua programs and speed up the system). I ran into something suspicious in the LuaTable PMC.
It uses a custom function to mark all contained keys and values as live, if they're GC-able PObjs: static void lua_mark_table(PARROT_INTERP, Hash *t, STRING *mode) { Node *v = t->node; int i; int mark_key = 1; int mark_val = 1; if (mode) { mark_key = string_str_index(interp, mode, const_string(interp, "k"), 0) < 0; mark_val = string_str_index(interp, mode, const_string(interp, "v"), 0) < 0; } for (i = 0; i < t->size; i++) { if (v[i].val != NULL) { if (mark_key) pobject_lives(interp, (PObj *)v[i].key); if (mark_val) pobject_lives(interp, (PObj *)v[i].val); } } } However, the node member of a Hash isn't an array: typedef struct Node { PMC *key; PMC *val; struct Node *next; /* for chaining */ } Node; typedef struct Hash { Node *node; int size; Node *firstfree; /* this position is free; all positions after it are full */ PMC *container; } Hash; Now it may indeed be that the linked list happens to be the right size that this pointer math might work... but I'm not convinced. Instead, I expect the correct approach to look something more like: static void lua_mark_table(PARROT_INTERP, Hash *t, STRING *mode) { Node *v = t->node; int mark_key = 1; int mark_val = 1; if (mode) { mark_key = string_str_index(interp, mode, const_string(interp, "k"), 0) < 0; mark_val = string_str_index(interp, mode, const_string(interp, "v"), 0) < 0; } while (v) { if (v->val) { if (mark_key) pobject_lives(interp, (PObj *)v->key); if (mark_val) pobject_lives(interp, (PObj *)v->val); } v = v->next; } } Of course, that makes segfaults elsewhere, which may mean that it's wrong, or it may mean that there's more hash cleanup necessary in that PMC. At least when I run individual Lua files without --no-gc, they no longer segfault in DOD after saying "Method 'setfenv' not found". Patch (for experimentation, not commit) attached. -- c
=== pmc/luatable.pmc ================================================================== --- pmc/luatable.pmc (revision 6305) +++ pmc/luatable.pmc (local) @@ -270,21 +270,22 @@ static void lua_mark_table(PARROT_INTERP, Hash *t, STRING *mode) { - Node *v = t->node; - int i; + Node *v = t->node; int mark_key = 1; int mark_val = 1; if (mode) { mark_key = string_str_index(interp, mode, const_string(interp, "k"), 0) < 0; mark_val = string_str_index(interp, mode, const_string(interp, "v"), 0) < 0; } - for (i = 0; i < t->size; i++) { - if (v[i].val != NULL) { + + while (v) { + if (v->val) { if (mark_key) - pobject_lives(interp, (PObj *)v[i].key); + pobject_lives(interp, (PObj *)v->key); if (mark_val) - pobject_lives(interp, (PObj *)v[i].val); + pobject_lives(interp, (PObj *)v->val); } + v = v->next; } }