Make segment, context, data_heap, zone more object-oriented, and fix crash when calling undefined symbols

db4
Slava Pestov 2009-09-25 21:17:20 -05:00
parent c046ff4b23
commit f81c8549f4
13 changed files with 103 additions and 119 deletions

View File

@ -93,9 +93,9 @@ void factor_vm::undefined_symbol()
general_error(ERROR_UNDEFINED_SYMBOL,F,F,NULL);
}
void undefined_symbol(factor_vm *myvm)
void undefined_symbol()
{
return myvm->undefined_symbol();
return SIGNAL_VM_PTR()->undefined_symbol();
}
/* Look up an external library symbol referenced by a compiled code block */

View File

@ -43,9 +43,9 @@ context *factor_vm::alloc_context()
}
else
{
new_context = (context *)safe_malloc(sizeof(context));
new_context->datastack_region = alloc_segment(ds_size);
new_context->retainstack_region = alloc_segment(rs_size);
new_context = new context;
new_context->datastack_region = new segment(this,ds_size);
new_context->retainstack_region = new segment(this,rs_size);
}
return new_context;

View File

@ -455,7 +455,7 @@ void factor_vm::end_gc(cell gc_elapsed)
if(growing_data_heap)
{
dealloc_data_heap(old_data_heap);
delete old_data_heap;
old_data_heap = NULL;
growing_data_heap = false;
}

View File

@ -3,14 +3,6 @@
namespace factor
{
cell factor_vm::init_zone(zone *z, cell size, cell start)
{
z->size = size;
z->start = z->here = start;
z->end = start + size;
return z->end;
}
void factor_vm::init_card_decks()
{
cell start = align(data->seg->start,deck_size);
@ -19,89 +11,86 @@ void factor_vm::init_card_decks()
decks_offset = (cell)data->decks - (start >> deck_bits);
}
data_heap *factor_vm::alloc_data_heap(cell gens, cell young_size,cell aging_size,cell tenured_size)
data_heap::data_heap(factor_vm *myvm, cell gen_count_, cell young_size_, cell aging_size_, cell tenured_size_)
{
young_size = align(young_size,deck_size);
aging_size = align(aging_size,deck_size);
tenured_size = align(tenured_size,deck_size);
young_size_ = align(young_size_,deck_size);
aging_size_ = align(aging_size_,deck_size);
tenured_size_ = align(tenured_size_,deck_size);
data_heap *data = (data_heap *)safe_malloc(sizeof(data_heap));
data->young_size = young_size;
data->aging_size = aging_size;
data->tenured_size = tenured_size;
data->gen_count = gens;
young_size = young_size_;
aging_size = aging_size_;
tenured_size = tenured_size_;
gen_count = gen_count_;
cell total_size;
if(data->gen_count == 2)
if(gen_count == 2)
total_size = young_size + 2 * tenured_size;
else if(data->gen_count == 3)
else if(gen_count == 3)
total_size = young_size + 2 * aging_size + 2 * tenured_size;
else
{
fatal_error("Invalid number of generations",data->gen_count);
return NULL; /* can't happen */
total_size = 0;
fatal_error("Invalid number of generations",gen_count);
}
total_size += deck_size;
data->seg = alloc_segment(total_size);
seg = new segment(myvm,total_size);
data->generations = (zone *)safe_malloc(sizeof(zone) * data->gen_count);
data->semispaces = (zone *)safe_malloc(sizeof(zone) * data->gen_count);
generations = new zone[gen_count];
semispaces = new zone[gen_count];
cell cards_size = total_size >> card_bits;
data->allot_markers = (cell *)safe_malloc(cards_size);
data->allot_markers_end = data->allot_markers + cards_size;
allot_markers = new char[cards_size];
allot_markers_end = allot_markers + cards_size;
data->cards = (cell *)safe_malloc(cards_size);
data->cards_end = data->cards + cards_size;
cards = new char[cards_size];
cards_end = cards + cards_size;
cell decks_size = total_size >> deck_bits;
data->decks = (cell *)safe_malloc(decks_size);
data->decks_end = data->decks + decks_size;
decks = new char[decks_size];
decks_end = decks + decks_size;
cell alloter = align(data->seg->start,deck_size);
cell alloter = align(seg->start,deck_size);
alloter = init_zone(&data->generations[data->tenured()],tenured_size,alloter);
alloter = init_zone(&data->semispaces[data->tenured()],tenured_size,alloter);
alloter = generations[tenured()].init_zone(tenured_size,alloter);
alloter = semispaces[tenured()].init_zone(tenured_size,alloter);
if(data->gen_count == 3)
if(gen_count == 3)
{
alloter = init_zone(&data->generations[data->aging()],aging_size,alloter);
alloter = init_zone(&data->semispaces[data->aging()],aging_size,alloter);
alloter = generations[aging()].init_zone(aging_size,alloter);
alloter = semispaces[aging()].init_zone(aging_size,alloter);
}
if(data->gen_count >= 2)
if(gen_count >= 2)
{
alloter = init_zone(&data->generations[data->nursery()],young_size,alloter);
alloter = init_zone(&data->semispaces[data->nursery()],0,alloter);
alloter = generations[nursery()].init_zone(young_size,alloter);
alloter = semispaces[nursery()].init_zone(0,alloter);
}
if(data->seg->end - alloter > deck_size)
critical_error("Bug in alloc_data_heap",alloter);
return data;
if(seg->end - alloter > deck_size)
myvm->critical_error("Bug in alloc_data_heap",alloter);
}
data_heap *factor_vm::grow_data_heap(data_heap *data, cell requested_bytes)
{
cell new_tenured_size = (data->tenured_size * 2) + requested_bytes;
return alloc_data_heap(data->gen_count,
return new data_heap(this,
data->gen_count,
data->young_size,
data->aging_size,
new_tenured_size);
}
void factor_vm::dealloc_data_heap(data_heap *data)
data_heap::~data_heap()
{
dealloc_segment(data->seg);
free(data->generations);
free(data->semispaces);
free(data->allot_markers);
free(data->cards);
free(data->decks);
free(data);
delete seg;
delete[] generations;
delete[] semispaces;
delete[] allot_markers;
delete[] cards;
delete[] decks;
}
void factor_vm::clear_cards(cell from, cell to)
@ -162,7 +151,7 @@ void factor_vm::set_data_heap(data_heap *data_)
void factor_vm::init_data_heap(cell gens,cell young_size,cell aging_size,cell tenured_size,bool secure_gc_)
{
set_data_heap(alloc_data_heap(gens,young_size,aging_size,tenured_size));
set_data_heap(new data_heap(this,gens,young_size,aging_size,tenured_size));
secure_gc = secure_gc_;
init_data_gc();
}

View File

@ -9,6 +9,14 @@ struct zone {
cell here;
cell size;
cell end;
cell init_zone(cell size_, cell start_)
{
size = size_;
start = here = start_;
end = start_ + size_;
return end;
}
};
struct data_heap {
@ -23,14 +31,14 @@ struct data_heap {
zone *generations;
zone *semispaces;
cell *allot_markers;
cell *allot_markers_end;
char *allot_markers;
char *allot_markers_end;
cell *cards;
cell *cards_end;
char *cards;
char *cards_end;
cell *decks;
cell *decks_end;
char *decks;
char *decks_end;
/* the 0th generation is where new objects are allocated. */
cell nursery() { return 0; }
@ -42,6 +50,9 @@ struct data_heap {
cell tenured() { return gen_count - 1; }
bool have_aging_p() { return gen_count > 2; }
data_heap(factor_vm *myvm, cell gen_count, cell young_size, cell aging_size, cell tenured_size);
~data_heap();
};
static const cell max_gen_count = 3;
@ -51,11 +62,6 @@ inline static bool in_zone(zone *z, object *pointer)
return (cell)pointer >= z->start && (cell)pointer < z->end;
}
/* set up guard pages to check for under/overflow.
size must be a multiple of the page size */
segment *alloc_segment(cell size); // defined in OS-*.cpp files PD
void dealloc_segment(segment *block);
PRIMITIVE(data_room);
PRIMITIVE(size);

View File

@ -14,7 +14,7 @@ void heap::clear_free_list()
heap::heap(factor_vm *myvm_, cell size)
{
myvm = myvm_;
seg = myvm->alloc_segment(myvm->align_page(size));
seg = new segment(myvm,align_page(size));
if(!seg) fatal_error("Out of memory in new_heap",size);
clear_free_list();
}

View File

@ -4,13 +4,6 @@ namespace factor
// I've had to copy inline implementations here to make dependencies work. Am hoping to move this code back into include files
// once the rest of the reentrant changes are done. -PD
// segments.hpp
inline cell factor_vm::align_page(cell a)
{
return align(a,getpagesize());
}
// write_barrier.hpp
inline card *factor_vm::addr_to_card(cell a)

View File

@ -18,6 +18,7 @@ void early_init() { }
#define SUFFIX ".image"
#define SUFFIX_LEN 6
/* You must delete[] the result yourself. */
const char *default_image_path()
{
const char *path = vm_executable_path();
@ -31,7 +32,7 @@ const char *default_image_path()
const char *iter = path;
while(*iter) { len++; iter++; }
char *new_path = (char *)safe_malloc(PATH_MAX + SUFFIX_LEN + 1);
char *new_path = new char[PATH_MAX + SUFFIX_LEN + 1];
memcpy(new_path,path,len + 1);
memcpy(new_path + len,SUFFIX,SUFFIX_LEN + 1);
return new_path;

View File

@ -3,10 +3,10 @@
namespace factor
{
/* Snarfed from SBCL linux-so.c. You must free() this yourself. */
/* Snarfed from SBCL linux-so.c. You must delete[] the result yourself. */
const char *vm_executable_path()
{
char *path = (char *)safe_malloc(PATH_MAX + 1);
char *path = new char[PATH_MAX + 1];
int size = readlink("/proc/self/exe", path, PATH_MAX);
if (size < 0)

View File

@ -83,8 +83,11 @@ inline void factor_vm::primitive_existsp()
PRIMITIVE_FORWARD(existsp)
segment *factor_vm::alloc_segment(cell size)
segment::segment(factor_vm *myvm_, cell size_)
{
myvm = myvm_;
size = size_;
int pagesize = getpagesize();
char *array = (char *)mmap(NULL,pagesize + size + pagesize,
@ -92,7 +95,7 @@ segment *factor_vm::alloc_segment(cell size)
MAP_ANON | MAP_PRIVATE,-1,0);
if(array == (char*)-1)
out_of_memory();
myvm->out_of_memory();
if(mprotect(array,pagesize,PROT_NONE) == -1)
fatal_error("Cannot protect low guard page",(cell)array);
@ -100,26 +103,16 @@ segment *factor_vm::alloc_segment(cell size)
if(mprotect(array + pagesize + size,pagesize,PROT_NONE) == -1)
fatal_error("Cannot protect high guard page",(cell)array);
segment *retval = (segment *)safe_malloc(sizeof(segment));
retval->start = (cell)(array + pagesize);
retval->size = size;
retval->end = retval->start + size;
return retval;
start = (cell)(array + pagesize);
end = start + size;
}
void dealloc_segment(segment *block)
segment::~segment()
{
int pagesize = getpagesize();
int retval = munmap((void*)(block->start - pagesize),
pagesize + block->size + pagesize);
int retval = munmap((void*)(start - pagesize),pagesize + size + pagesize);
if(retval)
fatal_error("dealloc_segment failed",0);
free(block);
fatal_error("Segment deallocation failed",0);
}
stack_frame *factor_vm::uap_stack_pointer(void *uap)

View File

@ -98,14 +98,17 @@ inline void factor_vm::primitive_existsp()
PRIMITIVE_FORWARD(existsp)
segment *factor_vm::alloc_segment(cell size)
segment::segment(factor_vm *myvm_, cell size_)
{
myvm = myvm_;
size = size_;
char *mem;
DWORD ignore;
if((mem = (char *)VirtualAlloc(NULL, getpagesize() * 2 + size,
MEM_COMMIT, PAGE_EXECUTE_READWRITE)) == 0)
out_of_memory();
myvm->out_of_memory();
if (!VirtualProtect(mem, getpagesize(), PAGE_NOACCESS, &ignore))
fatal_error("Cannot allocate low guard page", (cell)mem);
@ -114,22 +117,16 @@ segment *factor_vm::alloc_segment(cell size)
getpagesize(), PAGE_NOACCESS, &ignore))
fatal_error("Cannot allocate high guard page", (cell)mem);
segment *block = (segment *)safe_malloc(sizeof(segment));
block->start = (cell)mem + getpagesize();
block->size = size;
block->end = block->start + size;
return block;
start = (cell)mem + getpagesize();
end = start + size;
}
void factor_vm::dealloc_segment(segment *block)
segment::~segment()
{
SYSTEM_INFO si;
GetSystemInfo(&si);
if(!VirtualFree((void*)(block->start - si.dwPageSize), 0, MEM_RELEASE))
fatal_error("dealloc_segment failed",0);
free(block);
if(!VirtualFree((void*)(start - si.dwPageSize), 0, MEM_RELEASE))
myvm->fatal_error("Segment deallocation failed",0);
}
long factor_vm::getpagesize()

View File

@ -1,10 +1,23 @@
namespace factor
{
struct factor_vm;
inline cell align_page(cell a)
{
return align(a,getpagesize());
}
/* segments set up guard pages to check for under/overflow.
size must be a multiple of the page size */
struct segment {
factor_vm *myvm;
cell start;
cell size;
cell end;
segment(factor_vm *myvm, cell size);
~segment();
};
}

View File

@ -5,9 +5,6 @@ namespace factor
struct factor_vm : factor_vm_data {
// segments
inline cell align_page(cell a);
// contexts
void reset_datastack();
void reset_retainstack();
@ -127,11 +124,8 @@ struct factor_vm : factor_vm_data {
bignum *digit_stream_to_bignum(unsigned int n_digits, unsigned int (*producer)(unsigned int, factor_vm *), unsigned int radix, int negative_p);
//data_heap
cell init_zone(zone *z, cell size, cell start);
void init_card_decks();
data_heap *alloc_data_heap(cell gens, cell young_size,cell aging_size,cell tenured_size);
data_heap *grow_data_heap(data_heap *data, cell requested_bytes);
void dealloc_data_heap(data_heap *data);
void clear_cards(cell from, cell to);
void clear_decks(cell from, cell to);
void clear_allot_markers(cell from, cell to);
@ -560,14 +554,12 @@ struct factor_vm : factor_vm_data {
void ffi_dlopen(dll *dll);
void *ffi_dlsym(dll *dll, symbol_char *symbol);
void ffi_dlclose(dll *dll);
segment *alloc_segment(cell size);
void c_to_factor_toplevel(cell quot);
// os-windows
#if defined(WINDOWS)
void sleep_micros(u64 usec);
long getpagesize();
void dealloc_segment(segment *block);
const vm_char *vm_executable_path();
const vm_char *default_image_path();
void windows_image_path(vm_char *full_path, vm_char *temp_path, unsigned int length);