My project.

This post assumes that the reader has read my last post.

This was a week full of segfaults, failed assertions, changes in the user data and other crazy stuff. I started working on the allocation of memory on the freed lines. In the first glance, it seemed to be much harder than the small changes I’ve done to free memory in lines, because of the a never-seen-before-by-me datatypes being dealed with in alloc_for_copy() , from rts/sm/Evac.c : gen_workspace . But in a short time the code of alloc_for_copy() has shown itself to be simple, and it was easy to do an initial implementation. I went in the same path I was going on before, trying the simplest solution that works. For instance, the line representation used is not ideal, because groups of lines are not considered, but it was the simplest at that time, and I plan to improve it latter.

The gen_workspace data type contains a pointer to an area of a block that is not being used ( todo_free ) and a pointer to the end of that area ( todo_lim ). When a space for an object is requested, it’s allocated in this area, and todo_free is adjusted. If the area is full, a new block is requested. My intended change was to return the first free line of the generation when the object is smaller or equal to the size of a line, and use the current approach otherwise. This is the simplest way I could think, but has the problem that the only one object is allocated per line. This was a known issue.

if(size <= BITS_IN(W_) && gen->first_line != NULL) { to = gen->first_line; gen->first_line = (StgPtr) *gen->first_line; return to; } ws = &gct->gens[gen->no];

After that I got the first round of segfaults. One problem I could spot so far was in the code in rts/sm/Sweep.c , related to the liberation of the lines. The block is allocated by need, and there’s a pointer to the first free byte, free . This free space is used by alloc_for_copy() . So, we should only think of lines in the region already allocated in the block, that is, where the address is smaller than free .

if(bd->u.bitmap[i] == 0 && bd->u.bitmap[i - 1] == 0 && start + BITS_IN(W_) <= bd->free)

But the segfaults, memory corruptions, etc, kept going on. I tried some restrictions, like allocating in lines only objects with the exact size of a line, or very small objects (size == 2), or allocating just one object for generation, or only one object at all. I also tried checking for the type of the allocated object, to see a correlation with the problems I was having. Nothing helped by now.

So I thought I should work on other things, so that maybe my mind gets clearer and I can spot the problem. I followed the suggestion of using todo_free and todo_lim to make it possible to allocate more than one object in a line. I liked this change, since I had the impression that it fits better with the rest of the code than the initial implementation, and it will be easier to addapt it when I improve the representation of the free lines. As I said, I wanted something to work while I think in how I’ll solve the segfault problems. The bad side of this choice is that I’ll not be able to test it, since it’s just a reimplementation of the same idea in the allocation code, and is not expected to work. The good size is that it may work, and solve the problems I was having by accident.

if (ws->todo_free > ws->todo_lim) { if (size <= BITS_IN(W_) && gen->first_line != NULL) { ws->todo_free = gen->first_line; gen->first_line = (StgPtr) *gen->first_line; to = ws->todo_free; ws->todo_lim = ws->todo_free + BITS_IN(W_); } else { to = todo_block_full(size, ws); } }

I got the same results as with the older implementation, and no ideas about how to solve it (yet). So I thought about another thing to work on, which I’m talking about all through this post: improve the free line representation. This has the advantage of being testable, since it’s unrelated to the allocation code, and may give me an idea about how I can fix the segfaults. The bad side is that it probably won’t fix my problems directly. I’m working on it right now.

Following a suggestion, I’ve started using gdb to see what was happening in the GC instead of including printf s everywhere, and it’s been useful. I’ve noticed that sometimes printf is more effective, but sometimes gdb is much better.

Share this: Twitter

Facebook

Curtir isso: Curtir Carregando... Relacionado