Andy Dougherty wrote:

On Thu, 1 Sep 2005, Nattfodd wrote:

today is the deadline for the google summer of code projects, and it's time
anyway for a "release" of GMC.
GMC is a generational garbage collector for parrot that allows copying of
objects and thus copying GC schemes.

Thanks for submitting this. I also appreciated the extensive comments in the source (even if I didn't actually read most of them :-).

svn co https://svn.perl.org/parrot/branches/gmc

First, I needed the following simple patch to MANIFEST

--- gmc/MANIFEST        Thu Sep  1 09:12:48 2005
+++ parrot-andy/MANIFEST        Thu Sep  1 10:19:20 2005
@@ -1639,6 +1639,7 @@
src/exec_start.c                                  []
src/exit.c                                        []
src/extend.c                                      []
+src/gc_gmc.c                                      []
src/gc_gms.c                                      []
src/gc_ims.c                                      []
src/generic_register.c                            []


After that, with Sparc/Solaris 8, with Sun's CC, I got a core dump
even on a simple

        ./miniparrot -h
If only miniparrot is called without arguments, the GC is never called, which narrows much the place to look for the bug...

I rebuilt with debugging, and it again core dumped (although somewhere else). Here's the backtrace:
(dbx) run -h
Running: miniparrot -h (process id 21433)
[EMAIL PROTECTED] ([EMAIL PROTECTED]) signal SEGV (no mapping at the fault address) in 
gc_gmc_copy_gen at line 879 in file "gc_gmc.c"
 879           PMC_body(Gmc_PMC_hdr_get_PMC(ptr)) = Gmc_PMC_hdr_get_BODY(ptr);
(dbx) where
current thread: [EMAIL PROTECTED]
=>[1] gc_gmc_copy_gen(from = 0x32dbe8, dest = 0x4d31f8), line 879 in "gc_gmc.c"
 [2] gc_gmc_more_bodies(interpreter = 0x2b6ce8, pool = 0x31d860), line 933 in 
"gc_gmc.c"
 [3] gc_gmc_new_body(interpreter = 0x2b6ce8, pool = 0x31d860, size = 40U, aggreg = 4), 
line 705 in "gc_gmc.c"
 [4] gc_gmc_get_free_object_of_size(interpreter = 0x2b6ce8, pool = 0x31d860, size = 40U, 
aggreg = 4), line 741 in "gc_gmc.c"
 [5] gc_gmc_get_free_typed_object(interpreter = 0x2b6ce8, pool = 0x31d860, base_type = 
62), line 796 in "gc_gmc.c"
 [6] new_pmc_alloc_header(interpreter = 0x2b6ce8, flags = 132096U, is_typed = 1, 
base_type = 62), line 270 in "headers.c"
 [7] new_pmc_typed_header(interpreter = 0x2b6ce8, flags = 132096U, base_type = 62), line 
343 in "headers.c"
 [8] get_new_pmc_header(interpreter = 0x2b6ce8, base_type = 62, flags = 132096U), line 
231 in "pmc.c"
 [9] constant_pmc_new(interpreter = 0x2b6ce8, base_type = 62), line 310 in 
"pmc.c"
 [10] mmd_create_builtin_multi_meth_2(interpreter = 0x2b6ce8, func_nr = 5, type = 33, right = 
-100, func_ptr = 0x1edce0 = &Parrot_Complex_i_multiply_int()), line 2116 in 
"mmd.c"
 [11] mmd_create_builtin_multi_meth(interpreter = 0x2b6ce8, type = 33, entry = 
0xffbef444), line 2139 in "mmd.c"
 [12] Parrot_mmd_register_table(interpreter = 0x2b6ce8, type = 33, mmd_table = 
0xffbef2e4, n = 35), line 2182 in "mmd.c"
 [13] Parrot_Complex_class_init(interp = 0x2b6ce8, entry = 33, pass = 1), line 1390 in 
"complex.c"
 [14] Parrot_initialize_core_pmcs(interp = 0x2b6ce8), line 126 in "core_pmcs.c"
 [15] init_world(interpreter = 0x2b6ce8), line 85 in "global_setup.c"
 [16] Parrot_init(interpreter = 0x2b6ce8), line 84 in "embed.c"
 [17] make_interpreter(parent = (nil), flags = PARROT_NO_FLAGS), line 165 in 
"inter_create.c"
 [18] Parrot_new(parent = (nil)), line 47 in "embed.c"
 [19] main(argc = 2, argv = 0xffbefa8c), line 452 in "main.c"

I #defined GMC_DEBUG and BIG_DUMP, and the last entries may be relevant:

Copying gen (32e730,32f760) to gen (4d3d40,4d4d70)
copy_gen: ptr 4c0904, old_body 32f554, new_body 4d4b64, struct_val: deadbeef
copy_gen: ptr 47e078, old_body 32f57c, new_body 4d4b8c, struct_val: deadbeef
copy_gen: ptr 46f7bc, old_body 32f5a4, new_body 4d4bb4, struct_val: deadbeef
copy_gen: ptr 4683d8, old_body 32f5cc, new_body 4d4bdc, struct_val: deadbeef
copy_gen: ptr 46845c, old_body 32f5f4, new_body 4d4c04, struct_val: deadbeef
copy_gen: ptr 4684d4, old_body 32f61c, new_body 4d4c2c, struct_val: deadbeef
copy_gen: ptr 3555a4, old_body 32f644, new_body 4d4c54, struct_val: deadbeef
copy_gen: ptr 3555b0, old_body 32f66c, new_body 4d4c7c, struct_val: deadbeef
copy_gen: ptr 355820, old_body 32f694, new_body 4d4ca4, struct_val: deadbeef

Overall, I wonder if it's an alignment issue, since SPARC tends to be
much more sensitve to that than x86.  I haven't looked deeply at the
code at all, but do you do anything special to ensure that the blocks
of memory you are moving around maintain their aligment?
Actually, no, I don't ensure it in any way... I don't know exactly what alignment constraints are, but here, a whole memory zone is allocated (in gc_gmc_gen_init() called from gc_gmc_more_bodies()). Then all the content of the old memory zone is memcpyed to the content of the new one in a single instruction (src/gc_gmc.c:871). Both old and new have exactly the same size. So I imagine that if the start of the two zones are aligned in the same way (does the fact that both are obtained from malloc guaranty that ?), then so does every object in it...

But I begin to have serious doubts about objects being correctly aligned in the first place. I'll try to see if I can make sure of alignment tonight...

On the other hand, I think compaction can break alignment, as bodies can have variable size (even if it's not yet the case here). However, the output you give seems to indicate that this is not corruption, as pointers all seem to be valid (I had a lot of errors here earlier, but it was always with either ptr or hdr->pmc being set to NULL).

I added a GMC_NO_GC_RUN symbol that you can define if you want to disable it completely (to be sure that compaction is not responsible).

Sorry :(

Regards,
Alexandre

Reply via email to