Andy Dougherty wrote:

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...

On SPARC, doubles should be aligned on 8-byte boundaries. The compiler normally handles this correctly and automatically (e.g. by adding padding within structures as necessary, etc.) but if you're playing memory games and casting everything to (char *) and manipulating addresses, then the compiler obeys your commands and does what you request.

If indeed you're just copying one contiguous block from one malloc()-ed spot to another, and the size is obtained from sizeof(), then you should be fine. Malloc() is supposed to return memory suitably aligned for any use.

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 initially suspected alignment because with a optimized compile, I get

signal BUS (invalid address alignment) in gc_gmc_more_bodies at 0x7c278
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).
I added in the last revision some very basic memory alignment control (basically, headers and bodies are rounded up to the nearest multiple of GMC_ALIGN, which has a value of 8 now but can be changed at will. As headers were previously using 12 bytes, this may solve your problem (I hope so...). There are assert for alignment pretty much everywhere in object allocation, so that should help too. However, it seems to strongly disagree with the compaction functions, and causes t/library/md5_6.pir, for instance, to segfault. I spent some hours trying to find the bug without success, but it should be fine as long as you define GMC_GC_RUN (at least to see if it can run correctly miniparrot).


Defining that (on an optimized compile) changes the specific type of crash:

signal SEGV (no mapping at the fault address) in gc_gmc_more_bodies at 0x7c258

One last thought about alignment:  In macros such as the following one
in include/parrot/smallobject.h

#define Gmc_PMC_hdr_get_BODY(pmc_hdr) ((PMC_BODY*)((char*)(pmc_hdr) + sizeof(Gc_gmc_hdr)))

you have to be very careful about alignment and padding issues.  That
is, if you have a struct p { int a, double b }, you can't assume that
'b' is located at &p + sizeof(a).  There might be padding.  Instead,
use the offsetof() macro.
I would have liked to use offsetof but I don't think it will be possible, because we are not using a structure. This is because we want a field to have the size we decided without using a pointer (which would be useless as body is always just after the header). If you see some way to declare a struct or an union with a variable sized field, I would be really grateful... We just have to pray here that Gmc_align(sizeof(Gc_gmc_hdr)) includes all the padding (and if needed increase GMC_ALIGN).

Regards,
Alexandre

Reply via email to