From 320ee19b61260a4774759fb3dcb6e04154d53dab Mon Sep 17 00:00:00 2001 From: slava Date: Mon, 4 Dec 2006 05:20:54 +0000 Subject: [PATCH] Fix bug in code GC free list handling --- vm/code_gc.c | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/vm/code_gc.c b/vm/code_gc.c index 56853faee3..b1205c0dea 100644 --- a/vm/code_gc.c +++ b/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; } -/* Called after reading the code heap from the image file. We must build the -free list, and add a large free block from compiling.base + size to +/* Called after reading the code heap from the image file, and after code GC. + +In the former case, we must add a large free block from compiling.base + size to compiling.limit. */ void build_free_list(F_HEAP *heap, CELL size) { F_BLOCK *prev = NULL; + F_BLOCK *prev_free = NULL; F_BLOCK *scan = (F_BLOCK *)heap->base; 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) { - update_free_list(heap,prev,scan); - prev = scan; + update_free_list(heap,prev_free,scan); + prev_free = scan; } + prev = 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) { end->status = B_FREE; end->next_free = NULL; 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 { - 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) 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 */