Fix bug in code GC free list handling
parent
8780b1816f
commit
320ee19b61
28
vm/code_gc.c
28
vm/code_gc.c
|
@ -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 */
|
||||||
|
|
Loading…
Reference in New Issue