Store next_free pointer to free blocks only
parent
d72e395b2e
commit
44d61b71f6
42
vm/code_gc.c
42
vm/code_gc.c
|
@ -13,7 +13,7 @@ void new_heap(F_HEAP *heap, CELL size)
|
||||||
|
|
||||||
/* If there is no previous block, next_free becomes the head of the free list,
|
/* If there is no previous block, next_free becomes the head of the free list,
|
||||||
else its linked in */
|
else its linked in */
|
||||||
INLINE void update_free_list(F_HEAP *heap, F_BLOCK *prev, F_BLOCK *next_free)
|
INLINE void update_free_list(F_HEAP *heap, F_FREE_BLOCK *prev, F_FREE_BLOCK *next_free)
|
||||||
{
|
{
|
||||||
if(prev)
|
if(prev)
|
||||||
prev->next_free = next_free;
|
prev->next_free = next_free;
|
||||||
|
@ -28,18 +28,18 @@ 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_FREE_BLOCK *prev_free = NULL;
|
||||||
F_BLOCK *scan = first_block(heap);
|
F_BLOCK *scan = first_block(heap);
|
||||||
F_BLOCK *end = (F_BLOCK *)(heap->segment->start + size);
|
F_FREE_BLOCK *end = (F_FREE_BLOCK *)(heap->segment->start + size);
|
||||||
|
|
||||||
/* Add all free blocks to the free list */
|
/* Add all free blocks to the free list */
|
||||||
while(scan && scan < end)
|
while(scan && scan < (F_BLOCK *)end)
|
||||||
{
|
{
|
||||||
switch(scan->status)
|
switch(scan->status)
|
||||||
{
|
{
|
||||||
case B_FREE:
|
case B_FREE:
|
||||||
update_free_list(heap,prev_free,scan);
|
update_free_list(heap,prev_free,(F_FREE_BLOCK *)scan);
|
||||||
prev_free = scan;
|
prev_free = (F_FREE_BLOCK *)scan;
|
||||||
break;
|
break;
|
||||||
case B_ALLOCATED:
|
case B_ALLOCATED:
|
||||||
break;
|
break;
|
||||||
|
@ -56,9 +56,9 @@ void build_free_list(F_HEAP *heap, CELL size)
|
||||||
branch is only taken after loading a new image, not after code GC */
|
branch is only taken after loading a new image, not after code GC */
|
||||||
if((CELL)(end + 1) <= heap->segment->end)
|
if((CELL)(end + 1) <= heap->segment->end)
|
||||||
{
|
{
|
||||||
end->status = B_FREE;
|
end->block.status = B_FREE;
|
||||||
|
end->block.size = heap->segment->end - (CELL)end;
|
||||||
end->next_free = NULL;
|
end->next_free = NULL;
|
||||||
end->size = heap->segment->end - (CELL)end;
|
|
||||||
|
|
||||||
/* add final free block */
|
/* add final free block */
|
||||||
update_free_list(heap,prev_free,end);
|
update_free_list(heap,prev_free,end);
|
||||||
|
@ -82,18 +82,18 @@ void build_free_list(F_HEAP *heap, CELL size)
|
||||||
/* Allocate a block of memory from the mark and sweep GC heap */
|
/* Allocate a block of memory from the mark and sweep GC heap */
|
||||||
void *heap_allot(F_HEAP *heap, CELL size)
|
void *heap_allot(F_HEAP *heap, CELL size)
|
||||||
{
|
{
|
||||||
F_BLOCK *prev = NULL;
|
F_FREE_BLOCK *prev = NULL;
|
||||||
F_BLOCK *scan = heap->free_list;
|
F_FREE_BLOCK *scan = heap->free_list;
|
||||||
|
|
||||||
size = (size + 31) & ~31;
|
size = (size + 31) & ~31;
|
||||||
|
|
||||||
while(scan)
|
while(scan)
|
||||||
{
|
{
|
||||||
CELL this_size = scan->size - sizeof(F_BLOCK);
|
if(scan->block.status != B_FREE)
|
||||||
|
|
||||||
if(scan->status != B_FREE)
|
|
||||||
critical_error("Invalid block in free list",(CELL)scan);
|
critical_error("Invalid block in free list",(CELL)scan);
|
||||||
|
|
||||||
|
CELL this_size = scan->block.size - sizeof(F_BLOCK);
|
||||||
|
|
||||||
if(this_size < size)
|
if(this_size < size)
|
||||||
{
|
{
|
||||||
prev = scan;
|
prev = scan;
|
||||||
|
@ -102,9 +102,9 @@ void *heap_allot(F_HEAP *heap, CELL size)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* we found a candidate block */
|
/* we found a candidate block */
|
||||||
F_BLOCK *next_free;
|
F_FREE_BLOCK *next_free;
|
||||||
|
|
||||||
if(this_size - size <= sizeof(F_BLOCK))
|
if(this_size - size <= sizeof(F_BLOCK) * 2)
|
||||||
{
|
{
|
||||||
/* too small to be split */
|
/* too small to be split */
|
||||||
next_free = scan->next_free;
|
next_free = scan->next_free;
|
||||||
|
@ -113,11 +113,11 @@ void *heap_allot(F_HEAP *heap, CELL size)
|
||||||
{
|
{
|
||||||
/* split the block in two */
|
/* split the block in two */
|
||||||
CELL new_size = size + sizeof(F_BLOCK);
|
CELL new_size = size + sizeof(F_BLOCK);
|
||||||
F_BLOCK *split = (F_BLOCK *)((CELL)scan + new_size);
|
F_FREE_BLOCK *split = (F_FREE_BLOCK *)((CELL)scan + new_size);
|
||||||
split->status = B_FREE;
|
split->block.status = B_FREE;
|
||||||
split->size = scan->size - new_size;
|
split->block.size = scan->block.size - new_size;
|
||||||
split->next_free = scan->next_free;
|
split->next_free = scan->next_free;
|
||||||
scan->size = new_size;
|
scan->block.size = new_size;
|
||||||
next_free = split;
|
next_free = split;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,9 +125,9 @@ void *heap_allot(F_HEAP *heap, CELL size)
|
||||||
update_free_list(heap,prev,next_free);
|
update_free_list(heap,prev,next_free);
|
||||||
|
|
||||||
/* this is our new block */
|
/* this is our new block */
|
||||||
scan->status = B_ALLOCATED;
|
scan->block.status = B_ALLOCATED;
|
||||||
|
|
||||||
return scan + 1;
|
return &scan->block + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
13
vm/code_gc.h
13
vm/code_gc.h
|
@ -12,16 +12,21 @@ typedef struct _F_BLOCK
|
||||||
/* In bytes, includes this header */
|
/* In bytes, includes this header */
|
||||||
CELL size;
|
CELL size;
|
||||||
|
|
||||||
/* Filled in on image load */
|
|
||||||
struct _F_BLOCK *next_free;
|
|
||||||
|
|
||||||
/* Used during compaction */
|
/* Used during compaction */
|
||||||
struct _F_BLOCK *forwarding;
|
struct _F_BLOCK *forwarding;
|
||||||
} F_BLOCK;
|
} F_BLOCK;
|
||||||
|
|
||||||
|
typedef struct _F_FREE_BLOCK
|
||||||
|
{
|
||||||
|
F_BLOCK block;
|
||||||
|
|
||||||
|
/* Filled in on image load */
|
||||||
|
struct _F_FREE_BLOCK *next_free;
|
||||||
|
} F_FREE_BLOCK;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
F_SEGMENT *segment;
|
F_SEGMENT *segment;
|
||||||
F_BLOCK *free_list;
|
F_FREE_BLOCK *free_list;
|
||||||
} F_HEAP;
|
} F_HEAP;
|
||||||
|
|
||||||
void new_heap(F_HEAP *heap, CELL size);
|
void new_heap(F_HEAP *heap, CELL size);
|
||||||
|
|
Loading…
Reference in New Issue