vm: use C++ exceptions instead of longjmp(), to make Windows crash more
parent
d24ce84dde
commit
b740a1fe5d
|
@ -1,6 +1,8 @@
|
|||
namespace factor
|
||||
{
|
||||
|
||||
struct must_start_gc_again {};
|
||||
|
||||
template<typename TargetGeneration, typename Policy> struct data_workhorse {
|
||||
factor_vm *parent;
|
||||
TargetGeneration *target;
|
||||
|
@ -27,8 +29,7 @@ template<typename TargetGeneration, typename Policy> struct data_workhorse {
|
|||
{
|
||||
cell size = untagged->size();
|
||||
object *newpointer = target->allot(size);
|
||||
/* XXX not exception-safe */
|
||||
if(!newpointer) longjmp(parent->current_gc->gc_unwind,1);
|
||||
if(!newpointer) throw must_start_gc_again();
|
||||
|
||||
memcpy(newpointer,untagged,size);
|
||||
untagged->forward_to(newpointer);
|
||||
|
|
84
vm/gc.cpp
84
vm/gc.cpp
|
@ -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
|
||||
of space */
|
||||
if(setjmp(current_gc->gc_unwind))
|
||||
for(;;)
|
||||
{
|
||||
/* We come back here if a generation is full */
|
||||
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())
|
||||
try
|
||||
{
|
||||
current_gc->op = collect_full_op;
|
||||
current_gc->event->op = collect_full_op;
|
||||
collect_full(trace_contexts_p);
|
||||
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 = 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;
|
||||
case collect_to_tenured_op:
|
||||
collect_to_tenured();
|
||||
if(data->high_fragmentation_p())
|
||||
catch(const must_start_gc_again e)
|
||||
{
|
||||
current_gc->op = collect_full_op;
|
||||
current_gc->event->op = collect_full_op;
|
||||
collect_full(trace_contexts_p);
|
||||
/* We come back here if a generation is full */
|
||||
start_gc_again();
|
||||
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();
|
||||
|
|
|
@ -45,7 +45,6 @@ struct gc_event {
|
|||
struct gc_state {
|
||||
gc_op op;
|
||||
u64 start_time;
|
||||
jmp_buf gc_unwind;
|
||||
gc_event *event;
|
||||
|
||||
explicit gc_state(gc_op op_, factor_vm *parent);
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
#include <setjmp.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
|
Loading…
Reference in New Issue