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