Fix bug in code GC free list handling

slava 2006-12-04 05:20:54 +00:00
parent 8780b1816f
commit 320ee19b61
1 changed files with 20 additions and 8 deletions

View File

@ -28,12 +28,14 @@ INLINE void update_free_list(F_HEAP *heap, F_BLOCK *prev, F_BLOCK *next_free)
heap->free_list = next_free; heap->free_list = next_free;
} }
/* Called after reading the code heap from the image file. We must build the /* Called after reading the code heap from the image file, and after code GC.
free list, and add a large free block from compiling.base + size to
In the former case, we must add a large free block from compiling.base + size to
compiling.limit. */ compiling.limit. */
void build_free_list(F_HEAP *heap, CELL size) void build_free_list(F_HEAP *heap, CELL size)
{ {
F_BLOCK *prev = NULL; F_BLOCK *prev = NULL;
F_BLOCK *prev_free = NULL;
F_BLOCK *scan = (F_BLOCK *)heap->base; F_BLOCK *scan = (F_BLOCK *)heap->base;
F_BLOCK *end = (F_BLOCK *)(heap->base + size); F_BLOCK *end = (F_BLOCK *)(heap->base + size);
@ -42,29 +44,39 @@ void build_free_list(F_HEAP *heap, CELL size)
{ {
if(scan->status == B_FREE) if(scan->status == B_FREE)
{ {
update_free_list(heap,prev,scan); update_free_list(heap,prev_free,scan);
prev = scan; prev_free = scan;
} }
prev = scan;
scan = next_block(heap,scan); scan = next_block(heap,scan);
} }
/* If there is room at the end of the heap, add a free block */ /* If there is room at the end of the heap, add a free block. This
branch is only taken after loading a new image, not after code GC */
if((CELL)(end + 1) <= heap->limit) if((CELL)(end + 1) <= heap->limit)
{ {
end->status = B_FREE; end->status = B_FREE;
end->next_free = NULL; end->next_free = NULL;
end->size = heap->limit - (CELL)end; end->size = heap->limit - (CELL)end;
/* add final free block */
update_free_list(heap,prev_free,end);
} }
/* This branch is taken if the newly loaded image fits exactly, or
after code GC */
else else
{ {
end = NULL; /* even if there's no room at the end of the heap for a new
free block, we might have to jigger it up by a few bytes in
case prev + prev->size */
if(prev) if(prev)
prev->size = heap->limit - (CELL)prev; prev->size = heap->limit - (CELL)prev;
/* this is the last free block */
update_free_list(heap,prev_free,NULL);
} }
update_free_list(heap,prev,end);
} }
/* Allocate a block of memory from the mark and sweep GC heap */ /* Allocate a block of memory from the mark and sweep GC heap */