vm: use C++ exceptions instead of longjmp(), to make Windows crash more

release
Slava Pestov 2010-04-02 14:10:55 -04:00
parent d24ce84dde
commit b740a1fe5d
4 changed files with 49 additions and 42 deletions

View File

@ -1,6 +1,8 @@
namespace factor namespace factor
{ {
struct must_start_gc_again {};
template<typename TargetGeneration, typename Policy> struct data_workhorse { template<typename TargetGeneration, typename Policy> struct data_workhorse {
factor_vm *parent; factor_vm *parent;
TargetGeneration *target; TargetGeneration *target;
@ -27,8 +29,7 @@ template<typename TargetGeneration, typename Policy> struct data_workhorse {
{ {
cell size = untagged->size(); cell size = untagged->size();
object *newpointer = target->allot(size); object *newpointer = target->allot(size);
/* XXX not exception-safe */ if(!newpointer) throw must_start_gc_again();
if(!newpointer) longjmp(parent->current_gc->gc_unwind,1);
memcpy(newpointer,untagged,size); memcpy(newpointer,untagged,size);
untagged->forward_to(newpointer); untagged->forward_to(newpointer);

View File

@ -135,49 +135,57 @@ void factor_vm::gc(gc_op op, cell requested_bytes, bool trace_contexts_p)
/* Keep trying to GC higher and higher generations until we don't run out /* Keep trying to GC higher and higher generations until we don't run out
of space */ of space */
if(setjmp(current_gc->gc_unwind)) for(;;)
{ {
/* We come back here if a generation is full */ try
start_gc_again();
}
current_gc->event->op = current_gc->op;
switch(current_gc->op)
{
case collect_nursery_op:
collect_nursery();
break;
case collect_aging_op:
collect_aging();
if(data->high_fragmentation_p())
{ {
current_gc->op = collect_full_op; current_gc->event->op = current_gc->op;
current_gc->event->op = collect_full_op;
collect_full(trace_contexts_p); switch(current_gc->op)
{
case collect_nursery_op:
collect_nursery();
break;
case collect_aging_op:
collect_aging();
if(data->high_fragmentation_p())
{
current_gc->op = collect_full_op;
current_gc->event->op = collect_full_op;
collect_full(trace_contexts_p);
}
break;
case collect_to_tenured_op:
collect_to_tenured();
if(data->high_fragmentation_p())
{
current_gc->op = collect_full_op;
current_gc->event->op = collect_full_op;
collect_full(trace_contexts_p);
}
break;
case collect_full_op:
collect_full(trace_contexts_p);
break;
case collect_compact_op:
collect_compact(trace_contexts_p);
break;
case collect_growing_heap_op:
collect_growing_heap(requested_bytes,trace_contexts_p);
break;
default:
critical_error("Bad GC op",current_gc->op);
break;
}
break;
} }
break; catch(const must_start_gc_again e)
case collect_to_tenured_op:
collect_to_tenured();
if(data->high_fragmentation_p())
{ {
current_gc->op = collect_full_op; /* We come back here if a generation is full */
current_gc->event->op = collect_full_op; start_gc_again();
collect_full(trace_contexts_p); continue;
} }
break;
case collect_full_op:
collect_full(trace_contexts_p);
break;
case collect_compact_op:
collect_compact(trace_contexts_p);
break;
case collect_growing_heap_op:
collect_growing_heap(requested_bytes,trace_contexts_p);
break;
default:
critical_error("Bad GC op",current_gc->op);
break;
} }
end_gc(); end_gc();

View File

@ -45,7 +45,6 @@ struct gc_event {
struct gc_state { struct gc_state {
gc_op op; gc_op op;
u64 start_time; u64 start_time;
jmp_buf gc_unwind;
gc_event *event; gc_event *event;
explicit gc_state(gc_op op_, factor_vm *parent); explicit gc_state(gc_op op_, factor_vm *parent);

View File

@ -16,7 +16,6 @@
#include <fcntl.h> #include <fcntl.h>
#include <limits.h> #include <limits.h>
#include <math.h> #include <math.h>
#include <setjmp.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>