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); 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 */ /* Look up an external library symbol referenced by a compiled code block */

View File

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

View File

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

View File

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

View File

@ -9,6 +9,14 @@ struct zone {
cell here; cell here;
cell size; cell size;
cell end; cell end;
cell init_zone(cell size_, cell start_)
{
size = size_;
start = here = start_;
end = start_ + size_;
return end;
}
}; };
struct data_heap { struct data_heap {
@ -23,14 +31,14 @@ struct data_heap {
zone *generations; zone *generations;
zone *semispaces; zone *semispaces;
cell *allot_markers; char *allot_markers;
cell *allot_markers_end; char *allot_markers_end;
cell *cards; char *cards;
cell *cards_end; char *cards_end;
cell *decks; char *decks;
cell *decks_end; char *decks_end;
/* the 0th generation is where new objects are allocated. */ /* the 0th generation is where new objects are allocated. */
cell nursery() { return 0; } cell nursery() { return 0; }
@ -42,6 +50,9 @@ struct data_heap {
cell tenured() { return gen_count - 1; } cell tenured() { return gen_count - 1; }
bool have_aging_p() { return gen_count > 2; } 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; 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; 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(data_room);
PRIMITIVE(size); PRIMITIVE(size);

View File

@ -14,7 +14,7 @@ void heap::clear_free_list()
heap::heap(factor_vm *myvm_, cell size) heap::heap(factor_vm *myvm_, cell size)
{ {
myvm = myvm_; 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); if(!seg) fatal_error("Out of memory in new_heap",size);
clear_free_list(); 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 // 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 // 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 // write_barrier.hpp
inline card *factor_vm::addr_to_card(cell a) inline card *factor_vm::addr_to_card(cell a)

View File

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

View File

@ -3,10 +3,10 @@
namespace factor 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() 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); int size = readlink("/proc/self/exe", path, PATH_MAX);
if (size < 0) if (size < 0)

View File

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

View File

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

View File

@ -1,10 +1,23 @@
namespace factor 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 { struct segment {
factor_vm *myvm;
cell start; cell start;
cell size; cell size;
cell end; cell end;
segment(factor_vm *myvm, cell size);
~segment();
}; };
} }

View File

@ -5,9 +5,6 @@ namespace factor
struct factor_vm : factor_vm_data { struct factor_vm : factor_vm_data {
// segments
inline cell align_page(cell a);
// contexts // contexts
void reset_datastack(); void reset_datastack();
void reset_retainstack(); 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); bignum *digit_stream_to_bignum(unsigned int n_digits, unsigned int (*producer)(unsigned int, factor_vm *), unsigned int radix, int negative_p);
//data_heap //data_heap
cell init_zone(zone *z, cell size, cell start);
void init_card_decks(); 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); 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_cards(cell from, cell to);
void clear_decks(cell from, cell to); void clear_decks(cell from, cell to);
void clear_allot_markers(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_dlopen(dll *dll);
void *ffi_dlsym(dll *dll, symbol_char *symbol); void *ffi_dlsym(dll *dll, symbol_char *symbol);
void ffi_dlclose(dll *dll); void ffi_dlclose(dll *dll);
segment *alloc_segment(cell size);
void c_to_factor_toplevel(cell quot); void c_to_factor_toplevel(cell quot);
// os-windows // os-windows
#if defined(WINDOWS) #if defined(WINDOWS)
void sleep_micros(u64 usec); void sleep_micros(u64 usec);
long getpagesize(); long getpagesize();
void dealloc_segment(segment *block);
const vm_char *vm_executable_path(); const vm_char *vm_executable_path();
const vm_char *default_image_path(); const vm_char *default_image_path();
void windows_image_path(vm_char *full_path, vm_char *temp_path, unsigned int length); void windows_image_path(vm_char *full_path, vm_char *temp_path, unsigned int length);