vm: make heap data-type object-oriented

db4
Slava Pestov 2009-09-25 20:32:00 -05:00
parent d017a53227
commit c046ff4b23
14 changed files with 163 additions and 160 deletions

View File

@ -38,7 +38,6 @@ DLL_OBJS = $(PLAF_DLL_OBJS) \
vm/byte_arrays.o \ vm/byte_arrays.o \
vm/callstack.o \ vm/callstack.o \
vm/code_block.o \ vm/code_block.o \
vm/code_gc.o \
vm/code_heap.o \ vm/code_heap.o \
vm/contexts.o \ vm/contexts.o \
vm/data_gc.o \ vm/data_gc.o \
@ -47,6 +46,7 @@ DLL_OBJS = $(PLAF_DLL_OBJS) \
vm/dispatch.o \ vm/dispatch.o \
vm/errors.o \ vm/errors.o \
vm/factor.o \ vm/factor.o \
vm/heap.o \
vm/image.o \ vm/image.o \
vm/inline_cache.o \ vm/inline_cache.o \
vm/io.o \ vm/io.o \

View File

@ -371,7 +371,7 @@ void factor_vm::update_word_references(code_block *compiled)
the code heap with dead PICs that will be freed on the next the code heap with dead PICs that will be freed on the next
GC, we add them to the free list immediately. */ GC, we add them to the free list immediately. */
else if(compiled->type == PIC_TYPE) else if(compiled->type == PIC_TYPE)
heap_free(&code,compiled); code->heap_free(compiled);
else else
{ {
iterate_relocations(compiled,factor::update_word_references_step); iterate_relocations(compiled,factor::update_word_references_step);
@ -411,7 +411,7 @@ void factor_vm::mark_code_block(code_block *compiled)
{ {
check_code_address((cell)compiled); check_code_address((cell)compiled);
mark_block(compiled); code->mark_block(compiled);
copy_handle(&compiled->literals); copy_handle(&compiled->literals);
copy_handle(&compiled->relocation); copy_handle(&compiled->relocation);
@ -503,19 +503,19 @@ void factor_vm::fixup_labels(array *labels, code_block *compiled)
/* Might GC */ /* Might GC */
code_block *factor_vm::allot_code_block(cell size) code_block *factor_vm::allot_code_block(cell size)
{ {
heap_block *block = heap_allot(&code,size + sizeof(code_block)); heap_block *block = code->heap_allot(size + sizeof(code_block));
/* If allocation failed, do a code GC */ /* If allocation failed, do a code GC */
if(block == NULL) if(block == NULL)
{ {
gc(); gc();
block = heap_allot(&code,size + sizeof(code_block)); block = code->heap_allot(size + sizeof(code_block));
/* Insufficient room even after code GC, give up */ /* Insufficient room even after code GC, give up */
if(block == NULL) if(block == NULL)
{ {
cell used, total_free, max_free; cell used, total_free, max_free;
heap_usage(&code,&used,&total_free,&max_free); code->heap_usage(&used,&total_free,&max_free);
print_string("Code heap stats:\n"); print_string("Code heap stats:\n");
print_string("Used: "); print_cell(used); nl(); print_string("Used: "); print_cell(used); nl();

View File

@ -1,38 +0,0 @@
namespace factor
{
static const cell free_list_count = 16;
static const cell block_size_increment = 32;
struct heap_free_list {
free_heap_block *small_blocks[free_list_count];
free_heap_block *large_blocks;
};
struct heap {
segment *seg;
heap_free_list free;
};
typedef void (*heap_iterator)(heap_block *compiled,factor_vm *vm);
inline static heap_block *next_block(heap *h, heap_block *block)
{
cell next = ((cell)block + block->size);
if(next == h->seg->end)
return NULL;
else
return (heap_block *)next;
}
inline static heap_block *first_block(heap *h)
{
return (heap_block *)h->seg->start;
}
inline static heap_block *last_block(heap *h)
{
return (heap_block *)h->seg->end;
}
}

View File

@ -6,12 +6,12 @@ namespace factor
/* Allocate a code heap during startup */ /* Allocate a code heap during startup */
void factor_vm::init_code_heap(cell size) void factor_vm::init_code_heap(cell size)
{ {
new_heap(&code,size); code = new heap(this,size);
} }
bool factor_vm::in_code_heap_p(cell ptr) bool factor_vm::in_code_heap_p(cell ptr)
{ {
return (ptr >= code.seg->start && ptr <= code.seg->end); return (ptr >= code->seg->start && ptr <= code->seg->end);
} }
/* Compile a word definition with the non-optimizing compiler. Allocates memory */ /* Compile a word definition with the non-optimizing compiler. Allocates memory */
@ -31,13 +31,13 @@ void factor_vm::jit_compile_word(cell word_, cell def_, bool relocate)
/* Apply a function to every code block */ /* Apply a function to every code block */
void factor_vm::iterate_code_heap(code_heap_iterator iter) void factor_vm::iterate_code_heap(code_heap_iterator iter)
{ {
heap_block *scan = first_block(&code); heap_block *scan = code->first_block();
while(scan) while(scan)
{ {
if(scan->status != B_FREE) if(scan->status != B_FREE)
iter((code_block *)scan,this); iter((code_block *)scan,this);
scan = next_block(&code,scan); scan = code->next_block(scan);
} }
} }
@ -112,8 +112,8 @@ PRIMITIVE_FORWARD(modify_code_heap)
inline void factor_vm::primitive_code_room() inline void factor_vm::primitive_code_room()
{ {
cell used, total_free, max_free; cell used, total_free, max_free;
heap_usage(&code,&used,&total_free,&max_free); code->heap_usage(&used,&total_free,&max_free);
dpush(tag_fixnum(code.seg->size / 1024)); dpush(tag_fixnum(code->seg->size / 1024));
dpush(tag_fixnum(used / 1024)); dpush(tag_fixnum(used / 1024));
dpush(tag_fixnum(total_free / 1024)); dpush(tag_fixnum(total_free / 1024));
dpush(tag_fixnum(max_free / 1024)); dpush(tag_fixnum(max_free / 1024));
@ -220,20 +220,20 @@ void factor_vm::compact_code_heap()
gc(); gc();
/* Figure out where the code heap blocks are going to end up */ /* Figure out where the code heap blocks are going to end up */
cell size = compute_heap_forwarding(&code, forwarding); cell size = code->compute_heap_forwarding(forwarding);
/* Update word and quotation code pointers */ /* Update word and quotation code pointers */
forward_object_xts(); forward_object_xts();
/* Actually perform the compaction */ /* Actually perform the compaction */
compact_heap(&code,forwarding); code->compact_heap(forwarding);
/* Update word and quotation XTs */ /* Update word and quotation XTs */
fixup_object_xts(); fixup_object_xts();
/* Now update the free list; there will be a single free block at /* Now update the free list; there will be a single free block at
the end */ the end */
build_free_list(&code,size); code->build_free_list(size);
} }
} }

View File

@ -1,7 +1,8 @@
namespace factor namespace factor
{ {
struct factor_vm; struct factor_vm;
typedef void (*code_heap_iterator)(code_block *compiled,factor_vm *myvm); typedef void (*code_heap_iterator)(code_block *compiled, factor_vm *myvm);
PRIMITIVE(modify_code_heap); PRIMITIVE(modify_code_heap);
PRIMITIVE(code_room); PRIMITIVE(code_room);

View File

@ -509,7 +509,7 @@ void factor_vm::garbage_collection(cell gen,bool growing_data_heap_,cell request
growing_data_heap = true; growing_data_heap = true;
/* see the comment in unmark_marked() */ /* see the comment in unmark_marked() */
unmark_marked(&code); code->unmark_marked();
} }
/* we try collecting aging space twice before going on to /* we try collecting aging space twice before going on to
collect tenured */ collect tenured */
@ -546,7 +546,7 @@ void factor_vm::garbage_collection(cell gen,bool growing_data_heap_,cell request
code_heap_scans++; code_heap_scans++;
if(collecting_gen == data->tenured()) if(collecting_gen == data->tenured())
free_unmarked(&code,(heap_iterator)factor::update_literal_and_word_references); code->free_unmarked((heap_iterator)factor::update_literal_and_word_references);
else else
copy_code_heap_roots(); copy_code_heap_roots();

View File

@ -297,7 +297,7 @@ void factor_vm::dump_code_heap()
{ {
cell reloc_size = 0, literal_size = 0; cell reloc_size = 0, literal_size = 0;
heap_block *scan = first_block(&code); heap_block *scan = code->first_block();
while(scan) while(scan)
{ {
@ -326,7 +326,7 @@ void factor_vm::dump_code_heap()
print_cell_hex(scan->size); print_string(" "); print_cell_hex(scan->size); print_string(" ");
print_string(status); print_string("\n"); print_string(status); print_string("\n");
scan = next_block(&code,scan); scan = code->next_block(scan);
} }
print_cell(reloc_size); print_string(" bytes of relocation data\n"); print_cell(reloc_size); print_string(" bytes of relocation data\n");

147
vm/code_gc.cpp → vm/heap.cpp Executable file → Normal file
View File

@ -1,37 +1,36 @@
#include "master.hpp" #include "master.hpp"
/* This malloc-style heap code is reasonably generic. Maybe in the future, it
will be used for the data heap too, if we ever get mark/sweep/compact GC. */
namespace factor namespace factor
{ {
void factor_vm::clear_free_list(heap *heap) void heap::clear_free_list()
{ {
memset(&heap->free,0,sizeof(heap_free_list)); memset(&free,0,sizeof(heap_free_list));
} }
/* This malloc-style heap code is reasonably generic. Maybe in the future, it heap::heap(factor_vm *myvm_, cell size)
will be used for the data heap too, if we ever get incremental
mark/sweep/compact GC. */
void factor_vm::new_heap(heap *heap, cell size)
{ {
heap->seg = alloc_segment(align_page(size)); myvm = myvm_;
if(!heap->seg) seg = myvm->alloc_segment(myvm->align_page(size));
fatal_error("Out of memory in new_heap",size); if(!seg) fatal_error("Out of memory in new_heap",size);
clear_free_list();
clear_free_list(heap);
} }
void factor_vm::add_to_free_list(heap *heap, free_heap_block *block) void heap::add_to_free_list(free_heap_block *block)
{ {
if(block->size < free_list_count * block_size_increment) if(block->size < free_list_count * block_size_increment)
{ {
int index = block->size / block_size_increment; int index = block->size / block_size_increment;
block->next_free = heap->free.small_blocks[index]; block->next_free = free.small_blocks[index];
heap->free.small_blocks[index] = block; free.small_blocks[index] = block;
} }
else else
{ {
block->next_free = heap->free.large_blocks; block->next_free = free.large_blocks;
heap->free.large_blocks = block; free.large_blocks = block;
} }
} }
@ -39,16 +38,16 @@ void factor_vm::add_to_free_list(heap *heap, free_heap_block *block)
In the former case, we must 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 factor_vm::build_free_list(heap *heap, cell size) void heap::build_free_list(cell size)
{ {
heap_block *prev = NULL; heap_block *prev = NULL;
clear_free_list(heap); clear_free_list();
size = (size + block_size_increment - 1) & ~(block_size_increment - 1); size = (size + block_size_increment - 1) & ~(block_size_increment - 1);
heap_block *scan = first_block(heap); heap_block *scan = first_block();
free_heap_block *end = (free_heap_block *)(heap->seg->start + size); free_heap_block *end = (free_heap_block *)(seg->start + size);
/* Add all free blocks to the free list */ /* Add all free blocks to the free list */
while(scan && scan < (heap_block *)end) while(scan && scan < (heap_block *)end)
@ -56,28 +55,28 @@ void factor_vm::build_free_list(heap *heap, cell size)
switch(scan->status) switch(scan->status)
{ {
case B_FREE: case B_FREE:
add_to_free_list(heap,(free_heap_block *)scan); add_to_free_list((free_heap_block *)scan);
break; break;
case B_ALLOCATED: case B_ALLOCATED:
break; break;
default: default:
critical_error("Invalid scan->status",(cell)scan); myvm->critical_error("Invalid scan->status",(cell)scan);
break; break;
} }
prev = scan; prev = scan;
scan = next_block(heap,scan); scan = next_block(scan);
} }
/* If there is room at the end of the heap, add a free block. This /* 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 */ branch is only taken after loading a new image, not after code GC */
if((cell)(end + 1) <= heap->seg->end) if((cell)(end + 1) <= seg->end)
{ {
end->status = B_FREE; end->status = B_FREE;
end->size = heap->seg->end - (cell)end; end->size = seg->end - (cell)end;
/* add final free block */ /* add final free block */
add_to_free_list(heap,end); add_to_free_list(end);
} }
/* This branch is taken if the newly loaded image fits exactly, or /* This branch is taken if the newly loaded image fits exactly, or
after code GC */ after code GC */
@ -86,30 +85,30 @@ void factor_vm::build_free_list(heap *heap, cell size)
/* even if there's no room at the end of the heap for a new /* 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 free block, we might have to jigger it up by a few bytes in
case prev + prev->size */ case prev + prev->size */
if(prev) prev->size = heap->seg->end - (cell)prev; if(prev) prev->size = seg->end - (cell)prev;
} }
} }
void factor_vm::assert_free_block(free_heap_block *block) void heap::assert_free_block(free_heap_block *block)
{ {
if(block->status != B_FREE) if(block->status != B_FREE)
critical_error("Invalid block in free list",(cell)block); myvm->critical_error("Invalid block in free list",(cell)block);
} }
free_heap_block *factor_vm::find_free_block(heap *heap, cell size) free_heap_block *heap::find_free_block(cell size)
{ {
cell attempt = size; cell attempt = size;
while(attempt < free_list_count * block_size_increment) while(attempt < free_list_count * block_size_increment)
{ {
int index = attempt / block_size_increment; int index = attempt / block_size_increment;
free_heap_block *block = heap->free.small_blocks[index]; free_heap_block *block = free.small_blocks[index];
if(block) if(block)
{ {
assert_free_block(block); assert_free_block(block);
heap->free.small_blocks[index] = block->next_free; free.small_blocks[index] = block->next_free;
return block; return block;
} }
@ -117,7 +116,7 @@ free_heap_block *factor_vm::find_free_block(heap *heap, cell size)
} }
free_heap_block *prev = NULL; free_heap_block *prev = NULL;
free_heap_block *block = heap->free.large_blocks; free_heap_block *block = free.large_blocks;
while(block) while(block)
{ {
@ -127,7 +126,7 @@ free_heap_block *factor_vm::find_free_block(heap *heap, cell size)
if(prev) if(prev)
prev->next_free = block->next_free; prev->next_free = block->next_free;
else else
heap->free.large_blocks = block->next_free; free.large_blocks = block->next_free;
return block; return block;
} }
@ -138,7 +137,7 @@ free_heap_block *factor_vm::find_free_block(heap *heap, cell size)
return NULL; return NULL;
} }
free_heap_block *factor_vm::split_free_block(heap *heap, free_heap_block *block, cell size) free_heap_block *heap::split_free_block(free_heap_block *block, cell size)
{ {
if(block->size != size ) if(block->size != size )
{ {
@ -148,21 +147,21 @@ free_heap_block *factor_vm::split_free_block(heap *heap, free_heap_block *block,
split->size = block->size - size; split->size = block->size - size;
split->next_free = block->next_free; split->next_free = block->next_free;
block->size = size; block->size = size;
add_to_free_list(heap,split); add_to_free_list(split);
} }
return block; return block;
} }
/* Allocate a block of memory from the mark and sweep GC heap */ /* Allocate a block of memory from the mark and sweep GC heap */
heap_block *factor_vm::heap_allot(heap *heap, cell size) heap_block *heap::heap_allot(cell size)
{ {
size = (size + block_size_increment - 1) & ~(block_size_increment - 1); size = (size + block_size_increment - 1) & ~(block_size_increment - 1);
free_heap_block *block = find_free_block(heap,size); free_heap_block *block = find_free_block(size);
if(block) if(block)
{ {
block = split_free_block(heap,block,size); block = split_free_block(block,size);
block->status = B_ALLOCATED; block->status = B_ALLOCATED;
return block; return block;
@ -172,13 +171,13 @@ heap_block *factor_vm::heap_allot(heap *heap, cell size)
} }
/* Deallocates a block manually */ /* Deallocates a block manually */
void factor_vm::heap_free(heap *heap, heap_block *block) void heap::heap_free(heap_block *block)
{ {
block->status = B_FREE; block->status = B_FREE;
add_to_free_list(heap,(free_heap_block *)block); add_to_free_list((free_heap_block *)block);
} }
void factor_vm::mark_block(heap_block *block) void heap::mark_block(heap_block *block)
{ {
/* If already marked, do nothing */ /* If already marked, do nothing */
switch(block->status) switch(block->status)
@ -189,41 +188,41 @@ void factor_vm::mark_block(heap_block *block)
block->status = B_MARKED; block->status = B_MARKED;
break; break;
default: default:
critical_error("Marking the wrong block",(cell)block); myvm->critical_error("Marking the wrong block",(cell)block);
break; break;
} }
} }
/* If in the middle of code GC, we have to grow the heap, data GC restarts from /* If in the middle of code GC, we have to grow the heap, data GC restarts from
scratch, so we have to unmark any marked blocks. */ scratch, so we have to unmark any marked blocks. */
void factor_vm::unmark_marked(heap *heap) void heap::unmark_marked()
{ {
heap_block *scan = first_block(heap); heap_block *scan = first_block();
while(scan) while(scan)
{ {
if(scan->status == B_MARKED) if(scan->status == B_MARKED)
scan->status = B_ALLOCATED; scan->status = B_ALLOCATED;
scan = next_block(heap,scan); scan = next_block(scan);
} }
} }
/* After code GC, all referenced code blocks have status set to B_MARKED, so any /* After code GC, all referenced code blocks have status set to B_MARKED, so any
which are allocated and not marked can be reclaimed. */ which are allocated and not marked can be reclaimed. */
void factor_vm::free_unmarked(heap *heap, heap_iterator iter) void heap::free_unmarked(heap_iterator iter)
{ {
clear_free_list(heap); clear_free_list();
heap_block *prev = NULL; heap_block *prev = NULL;
heap_block *scan = first_block(heap); heap_block *scan = first_block();
while(scan) while(scan)
{ {
switch(scan->status) switch(scan->status)
{ {
case B_ALLOCATED: case B_ALLOCATED:
if(secure_gc) if(myvm->secure_gc)
memset(scan + 1,0,scan->size - sizeof(heap_block)); memset(scan + 1,0,scan->size - sizeof(heap_block));
if(prev && prev->status == B_FREE) if(prev && prev->status == B_FREE)
@ -242,30 +241,30 @@ void factor_vm::free_unmarked(heap *heap, heap_iterator iter)
break; break;
case B_MARKED: case B_MARKED:
if(prev && prev->status == B_FREE) if(prev && prev->status == B_FREE)
add_to_free_list(heap,(free_heap_block *)prev); add_to_free_list((free_heap_block *)prev);
scan->status = B_ALLOCATED; scan->status = B_ALLOCATED;
prev = scan; prev = scan;
iter(scan,this); iter(scan,myvm);
break; break;
default: default:
critical_error("Invalid scan->status",(cell)scan); myvm->critical_error("Invalid scan->status",(cell)scan);
} }
scan = next_block(heap,scan); scan = next_block(scan);
} }
if(prev && prev->status == B_FREE) if(prev && prev->status == B_FREE)
add_to_free_list(heap,(free_heap_block *)prev); add_to_free_list((free_heap_block *)prev);
} }
/* Compute total sum of sizes of free blocks, and size of largest free block */ /* Compute total sum of sizes of free blocks, and size of largest free block */
void factor_vm::heap_usage(heap *heap, cell *used, cell *total_free, cell *max_free) void heap::heap_usage(cell *used, cell *total_free, cell *max_free)
{ {
*used = 0; *used = 0;
*total_free = 0; *total_free = 0;
*max_free = 0; *max_free = 0;
heap_block *scan = first_block(heap); heap_block *scan = first_block();
while(scan) while(scan)
{ {
@ -280,34 +279,34 @@ void factor_vm::heap_usage(heap *heap, cell *used, cell *total_free, cell *max_f
*max_free = scan->size; *max_free = scan->size;
break; break;
default: default:
critical_error("Invalid scan->status",(cell)scan); myvm->critical_error("Invalid scan->status",(cell)scan);
} }
scan = next_block(heap,scan); scan = next_block(scan);
} }
} }
/* The size of the heap, not including the last block if it's free */ /* The size of the heap, not including the last block if it's free */
cell factor_vm::heap_size(heap *heap) cell heap::heap_size()
{ {
heap_block *scan = first_block(heap); heap_block *scan = first_block();
while(next_block(heap,scan) != NULL) while(next_block(scan) != NULL)
scan = next_block(heap,scan); scan = next_block(scan);
/* this is the last block in the heap, and it is free */ /* this is the last block in the heap, and it is free */
if(scan->status == B_FREE) if(scan->status == B_FREE)
return (cell)scan - heap->seg->start; return (cell)scan - seg->start;
/* otherwise the last block is allocated */ /* otherwise the last block is allocated */
else else
return heap->seg->size; return seg->size;
} }
/* Compute where each block is going to go, after compaction */ /* Compute where each block is going to go, after compaction */
cell factor_vm::compute_heap_forwarding(heap *heap, unordered_map<heap_block *,char *> &forwarding) cell heap::compute_heap_forwarding(unordered_map<heap_block *,char *> &forwarding)
{ {
heap_block *scan = first_block(heap); heap_block *scan = first_block();
char *address = (char *)first_block(heap); char *address = (char *)first_block();
while(scan) while(scan)
{ {
@ -317,21 +316,21 @@ cell factor_vm::compute_heap_forwarding(heap *heap, unordered_map<heap_block *,c
address += scan->size; address += scan->size;
} }
else if(scan->status == B_MARKED) else if(scan->status == B_MARKED)
critical_error("Why is the block marked?",0); myvm->critical_error("Why is the block marked?",0);
scan = next_block(heap,scan); scan = next_block(scan);
} }
return (cell)address - heap->seg->start; return (cell)address - seg->start;
} }
void factor_vm::compact_heap(heap *heap, unordered_map<heap_block *,char *> &forwarding) void heap::compact_heap(unordered_map<heap_block *,char *> &forwarding)
{ {
heap_block *scan = first_block(heap); heap_block *scan = first_block();
while(scan) while(scan)
{ {
heap_block *next = next_block(heap,scan); heap_block *next = next_block(scan);
if(scan->status == B_ALLOCATED) if(scan->status == B_ALLOCATED)
memmove(forwarding[scan],scan,scan->size); memmove(forwarding[scan],scan,scan->size);

59
vm/heap.hpp Normal file
View File

@ -0,0 +1,59 @@
namespace factor
{
static const cell free_list_count = 16;
static const cell block_size_increment = 32;
struct heap_free_list {
free_heap_block *small_blocks[free_list_count];
free_heap_block *large_blocks;
};
typedef void (*heap_iterator)(heap_block *compiled, factor_vm *vm);
struct heap {
factor_vm *myvm;
segment *seg;
heap_free_list free;
heap(factor_vm *myvm, cell size);
inline heap_block *next_block(heap_block *block)
{
cell next = ((cell)block + block->size);
if(next == seg->end)
return NULL;
else
return (heap_block *)next;
}
inline heap_block *first_block()
{
return (heap_block *)seg->start;
}
inline heap_block *last_block()
{
return (heap_block *)seg->end;
}
void clear_free_list();
void new_heap(cell size);
void add_to_free_list(free_heap_block *block);
void build_free_list(cell size);
void assert_free_block(free_heap_block *block);
free_heap_block *find_free_block(cell size);
free_heap_block *split_free_block(free_heap_block *block, cell size);
heap_block *heap_allot(cell size);
void heap_free(heap_block *block);
void mark_block(heap_block *block);
void unmark_marked();
void free_unmarked(heap_iterator iter);
void heap_usage(cell *used, cell *total_free, cell *max_free);
cell heap_size();
cell compute_heap_forwarding(unordered_map<heap_block *,char *> &forwarding);
void compact_heap(unordered_map<heap_block *,char *> &forwarding);
};
}

View File

@ -56,7 +56,7 @@ void factor_vm::load_code_heap(FILE *file, image_header *h, vm_parameters *p)
if(h->code_size != 0) if(h->code_size != 0)
{ {
size_t bytes_read = fread(first_block(&code),1,h->code_size,file); size_t bytes_read = fread(code->first_block(),1,h->code_size,file);
if(bytes_read != h->code_size) if(bytes_read != h->code_size)
{ {
print_string("truncated image: "); print_string("truncated image: ");
@ -69,7 +69,7 @@ void factor_vm::load_code_heap(FILE *file, image_header *h, vm_parameters *p)
} }
code_relocation_base = h->code_relocation_base; code_relocation_base = h->code_relocation_base;
build_free_list(&code,h->code_size); code->build_free_list(h->code_size);
} }
/* Save the current image to disk */ /* Save the current image to disk */
@ -92,8 +92,8 @@ bool factor_vm::save_image(const vm_char *filename)
h.version = image_version; h.version = image_version;
h.data_relocation_base = tenured->start; h.data_relocation_base = tenured->start;
h.data_size = tenured->here - tenured->start; h.data_size = tenured->here - tenured->start;
h.code_relocation_base = code.seg->start; h.code_relocation_base = code->seg->start;
h.code_size = heap_size(&code); h.code_size = code->heap_size();
h.t = T; h.t = T;
h.bignum_zero = bignum_zero; h.bignum_zero = bignum_zero;
@ -107,7 +107,7 @@ bool factor_vm::save_image(const vm_char *filename)
if(fwrite(&h,sizeof(image_header),1,file) != 1) ok = false; if(fwrite(&h,sizeof(image_header),1,file) != 1) ok = false;
if(fwrite((void*)tenured->start,h.data_size,1,file) != 1) ok = false; if(fwrite((void*)tenured->start,h.data_size,1,file) != 1) ok = false;
if(fwrite(first_block(&code),h.code_size,1,file) != 1) ok = false; if(fwrite(code->first_block(),h.code_size,1,file) != 1) ok = false;
if(fclose(file)) ok = false; if(fclose(file)) ok = false;
if(!ok) if(!ok)
@ -175,7 +175,7 @@ void data_fixup(cell *cell, factor_vm *myvm)
template <typename TYPE> void factor_vm::code_fixup(TYPE **handle) template <typename TYPE> void factor_vm::code_fixup(TYPE **handle)
{ {
TYPE *ptr = *handle; TYPE *ptr = *handle;
TYPE *new_ptr = (TYPE *)(((cell)ptr) + (code.seg->start - code_relocation_base)); TYPE *new_ptr = (TYPE *)(((cell)ptr) + (code->seg->start - code_relocation_base));
*handle = new_ptr; *handle = new_ptr;
} }

View File

@ -24,7 +24,7 @@ void factor_vm::deallocate_inline_cache(cell return_address)
#endif #endif
if(old_type == PIC_TYPE) if(old_type == PIC_TYPE)
heap_free(&code,old_block); code->heap_free(old_block);
} }
/* Figure out what kind of type check the PIC needs based on the methods /* Figure out what kind of type check the PIC needs based on the methods

View File

@ -64,7 +64,7 @@
#include "math.hpp" #include "math.hpp"
#include "float_bits.hpp" #include "float_bits.hpp"
#include "io.hpp" #include "io.hpp"
#include "code_gc.hpp" #include "heap.hpp"
#include "code_heap.hpp" #include "code_heap.hpp"
#include "image.hpp" #include "image.hpp"
#include "callstack.hpp" #include "callstack.hpp"

View File

@ -83,8 +83,8 @@ struct factor_vm_data {
cell bignum_neg_one; cell bignum_neg_one;
//code_heap //code_heap
heap code; heap *code;
unordered_map<heap_block *,char *> forwarding; unordered_map<heap_block *, char *> forwarding;
//image //image
cell code_relocation_base; cell code_relocation_base;

View File

@ -381,24 +381,6 @@ struct factor_vm : factor_vm_data {
inline void primitive_fflush(); inline void primitive_fflush();
inline void primitive_fclose(); inline void primitive_fclose();
//code_gc
void clear_free_list(heap *heap);
void new_heap(heap *heap, cell size);
void add_to_free_list(heap *heap, free_heap_block *block);
void build_free_list(heap *heap, cell size);
void assert_free_block(free_heap_block *block);
free_heap_block *find_free_block(heap *heap, cell size);
free_heap_block *split_free_block(heap *heap, free_heap_block *block, cell size);
heap_block *heap_allot(heap *heap, cell size);
void heap_free(heap *heap, heap_block *block);
void mark_block(heap_block *block);
void unmark_marked(heap *heap);
void free_unmarked(heap *heap, heap_iterator iter);
void heap_usage(heap *heap, cell *used, cell *total_free, cell *max_free);
cell heap_size(heap *heap);
cell compute_heap_forwarding(heap *heap, unordered_map<heap_block *,char *> &forwarding);
void compact_heap(heap *heap, unordered_map<heap_block *,char *> &forwarding);
//code_block //code_block
relocation_type relocation_type_of(relocation_entry r); relocation_type relocation_type_of(relocation_entry r);
relocation_class relocation_class_of(relocation_entry r); relocation_class relocation_class_of(relocation_entry r);