: signal-handler-save-regs ( -- regs ) volatile-regs R12 suffix ;
:: jit-signal-handler-prolog ( -- frame-size )
- ! do we also need to save XMM?
signal-handler-save-regs :> save-regs
save-regs length bootstrap-cells 16 align stack-frame-size + :> frame-size
RSP frame-size bootstrap-cell - SUB ! minus a cell for return address
code = new code_heap(size);
}
-bool factor_vm::in_code_heap_p(cell ptr)
-{
- return (ptr >= code->seg->start && ptr <= code->seg->end);
-}
-
struct word_updater {
factor_vm *parent;
bool reset_inline_caches;
{
if (!code->seg->in_segment_p(*pc) || *sp < ctx->callstack_seg->start + stack_reserved)
{
- /* Fault came from foreign code, a callstack overflow, or we would probably
- overflow if we tried the resumable handler. We can't resume, so cut the
+ /* Fault came from foreign code or a callstack overflow, or we don't
+ have enough callstack room to try the resumable handler. Cut the
callstack down to the shallowest Factor stack frame that leaves room for
- the signal handler to do its thing and launch the handler without going
+ the signal handler to do its thing, and launch the handler without going
through the resumable subprimitive. */
signal_resumable = false;
stack_frame *frame = ctx->callstack_bottom - 1;
handler_word = tagged<word>(special_objects[LEAF_SIGNAL_HANDLER_WORD]);
}
else
- {
- fatal_error("Invalid stack frame during signal handler", *sp);
- }
+ assert(false);
*pc = (cell)handler_word->code->entry_point();
}
void factor_vm::print_datastack()
{
- std::cout << "==== DATA STACK:\n";
+ std::cout << "==== DATA STACK:" << std::endl;
print_objects((cell *)ctx->datastack_seg->start,(cell *)ctx->datastack);
}
void factor_vm::print_retainstack()
{
- std::cout << "==== RETAIN STACK:\n";
+ std::cout << "==== RETAIN STACK:" << std::endl;
print_objects((cell *)ctx->retainstack_seg->start,(cell *)ctx->retainstack);
}
void factor_vm::print_callstack()
{
- std::cout << "==== CALL STACK:\n";
+ std::cout << "==== CALL STACK:" << std::endl;
stack_frame_printer printer(this);
iterate_callstack(ctx,printer);
}
{
code_block_printer printer(this);
code->allocator->iterate(printer);
- std::cout << printer.reloc_size << " bytes used by relocation tables\n";
- std::cout << printer.parameter_size << " bytes used by parameter tables\n";
+ std::cout << printer.reloc_size << " bytes used by relocation tables" << std::endl;
+ std::cout << printer.parameter_size << " bytes used by parameter tables" << std::endl;
}
void factor_vm::factorbug()
{
if(fep_disabled)
{
- std::cout << "Low level debugger disabled\n";
+ std::cout << "Low level debugger disabled" << std::endl;
exit(1);
}
fep_p = true;
- std::cout << "Starting low level debugger...\n";
- std::cout << "Basic commands:\n";
- std::cout << " q ^D -- quit Factor\n";
- std::cout << " c -- continue executing Factor - NOT SAFE\n";
- std::cout << " t -- throw exception in Factor - NOT SAFE\n";
- std::cout << " .s .r .c -- print data, retain, call stacks\n";
- std::cout << "Advanced commands:\n";
- std::cout << " e -- dump environment\n";
- std::cout << " d <addr> <count> -- dump memory\n";
- std::cout << " u <addr> -- dump object at tagged <addr>\n";
- std::cout << " . <addr> -- print object at tagged <addr>\n";
- std::cout << " g -- dump generations\n";
- std::cout << " ds dr -- dump data, retain stacks\n";
- std::cout << " trim -- toggle output trimming\n";
- std::cout << " data -- data heap dump\n";
- std::cout << " words -- words dump\n";
- std::cout << " tuples -- tuples dump\n";
- std::cout << " refs <addr> -- find data heap references to object\n";
- std::cout << " push <addr> -- push object on data stack - NOT SAFE\n";
- std::cout << " gc -- trigger full GC - NOT SAFE\n";
- std::cout << " code -- code heap dump\n";
+ std::cout << "Starting low level debugger..." << std::endl;
+ std::cout << "Basic commands:" << std::endl;
+ std::cout << " q ^D -- quit Factor" << std::endl;
+ std::cout << " c -- continue executing Factor - NOT SAFE" << std::endl;
+ std::cout << " t -- throw exception in Factor - NOT SAFE" << std::endl;
+ std::cout << " .s .r .c -- print data, retain, call stacks" << std::endl;
+ std::cout << "Advanced commands:" << std::endl;
+ std::cout << " e -- dump environment" << std::endl;
+ std::cout << " d <addr> <count> -- dump memory" << std::endl;
+ std::cout << " u <addr> -- dump object at tagged <addr>" << std::endl;
+ std::cout << " . <addr> -- print object at tagged <addr>" << std::endl;
+ std::cout << " g -- dump generations" << std::endl;
+ std::cout << " ds dr -- dump data, retain stacks" << std::endl;
+ std::cout << " trim -- toggle output trimming" << std::endl;
+ std::cout << " data -- data heap dump" << std::endl;
+ std::cout << " words -- words dump" << std::endl;
+ std::cout << " tuples -- tuples dump" << std::endl;
+ std::cout << " refs <addr> -- find data heap references to object" << std::endl;
+ std::cout << " push <addr> -- push object on data stack - NOT SAFE" << std::endl;
+ std::cout << " gc -- trigger full GC - NOT SAFE" << std::endl;
+ std::cout << " code -- code heap dump" << std::endl;
bool seen_command = false;
{
char cmd[1024];
- std::cout << "READY\n";
+ std::cout << "READY" << std::endl;
std::cout.flush();
std::cin >> std::setw(1024) >> cmd >> std::setw(0);
else if(strcmp(cmd,"refs") == 0)
{
cell addr = read_cell_hex();
- std::cout << "Data heap references:\n";
+ std::cout << "Data heap references:" << std::endl;
find_data_references(addr);
std::cout << std::endl;
}
else if(strcmp(cmd,"gc") == 0)
primitive_full_gc();
else
- std::cout << "unknown command\n";
+ std::cout << "unknown command" << std::endl;
}
}
void factor_vm::primitive_die()
{
- std::cout << "The die word was called by the library. Unless you called it yourself,\n";
- std::cout << "you have triggered a bug in Factor. Please report.\n";
+ std::cout << "The die word was called by the library. Unless you called it yourself," << std::endl;
+ std::cout << "you have triggered a bug in Factor. Please report." << std::endl;
factorbug();
}
void factor_vm::enqueue_safepoint_sample()
{
- if (!sampling_p)
- fatal_error("Received sampling signal while not sampling!", 0);
- ++safepoint_sample_count;
+ if (sampling_profiler_p)
+ ++safepoint_sample_count;
}
void factor_vm::handle_safepoint()
{
code->unguard_safepoint();
- if (safepoint_fep) {
+ if (safepoint_fep)
+ {
std::cout << "Interrupted\n";
factorbug();
safepoint_fep = false;
vm->signal_number = signal;
vm->dispatch_signal(uap,factor::synchronous_signal_handler_impl);
} else
- fatal_error("Foreign thread received signal ", signal);
+ fatal_error("Foreign thread received signal", signal);
}
void enqueue_signal_handler(int signal, siginfo_t *siginfo, void *uap)
if (vm)
vm->enqueue_safepoint_signal(signal);
else
- fatal_error("Foreign thread received signal ", signal);
+ fatal_error("Foreign thread received signal", signal);
}
void fep_signal_handler(int signal, siginfo_t *siginfo, void *uap)
if (vm)
vm->enqueue_safepoint_fep();
else
- fatal_error("Foreign thread received signal ", signal);
+ fatal_error("Foreign thread received signal", signal);
}
void sample_signal_handler(int signal, siginfo_t *siginfo, void *uap)
if (vm)
vm->enqueue_safepoint_sample();
else
- fatal_error("Foreign thread received signal ", signal);
+ fatal_error("Foreign thread received signal", signal);
}
void ignore_signal_handler(int signal, siginfo_t *siginfo, void *uap)
return vm->exception_handler(e,frame,c,dispatch);
else
{
- fatal_error("Foreign thread received exception ", e->ExceptionCode);
+ fatal_error("Foreign thread received exception", e->ExceptionCode);
return 0; // to placate MSVC
}
}
switch (dwCtrlType) {
case CTRL_C_EVENT:
case CTRL_BREAK_EVENT:
- {
+ {
/* The CtrlHandler runs in its own thread without stopping the main thread.
Since in practice nobody uses the multi-VM stuff yet, we just grab the first
VM we can get. This will not be a good idea when we actually support native
factor_vm *vm = thread_vms.begin()->second;
vm->enqueue_safepoint_fep();
return TRUE;
- }
+ }
default:
return FALSE;
}
void factor_vm::init_profiler()
{
- profiling_p = false;
+ counting_profiler_p = false;
}
/* Allocates memory */
/* Allocates memory */
void factor_vm::set_profiling(bool profiling)
{
- if(profiling == profiling_p)
+ if(profiling == counting_profiler_p)
return;
/* Push everything to tenured space so that we can heap scan
data_root<array> words(find_all_words(),this);
- profiling_p = profiling;
+ counting_profiler_p = profiling;
cell length = array_capacity(words.untagged());
for(cell i = 0; i < length; i++)
nursery(0,0),
callback_id(0),
c_to_factor_func(NULL),
- profiling_p(false),
- sampling_p(false),
+ counting_profiler_p(false),
+ sampling_profiler_p(false),
safepoint_fep(false),
safepoint_sample_count(0),
gc_off(false),
c_to_factor_func_type c_to_factor_func;
/* Is call counting enabled? */
- bool profiling_p;
+ bool counting_profiler_p;
/* Is sampling profiler enabled? */
- bool sampling_p;
+ bool sampling_profiler_p;
/* Global variables used to pass fault handler state from signal handler
to VM */
return (Type *)allot_object(Type::type_number,size);
}
- inline bool in_data_heap_p(cell pointer)
- {
- return (pointer >= data->seg->start && pointer < data->seg->end);
- }
-
inline void check_data_pointer(object *pointer)
{
#ifdef FACTOR_DEBUG
if(!(current_gc && current_gc->op == collect_growing_heap_op))
- assert(in_data_heap_p((cell)pointer));
+ assert(data->seg->in_segment_p((cell)pointer));
#endif
}
}
void init_code_heap(cell size);
- bool in_code_heap_p(cell ptr);
void update_code_heap_words(bool reset_inline_caches);
void initialize_code_blocks();
void primitive_modify_code_heap();
new_word->code = NULL;
jit_compile_word(new_word.value(),new_word->def,true);
- if(profiling_p)
+ if(counting_profiler_p)
{
code_block *profiling_block = compile_profiling_stub(new_word.value());
new_word->profiling = profiling_block;
data_root<word> w(ctx->pop(),this);
w.untag_check(this);
- if(profiling_p)
+ if(counting_profiler_p)
{
ctx->push(from_unsigned_cell((cell)w->profiling->entry_point()));
ctx->push(from_unsigned_cell((cell)w->profiling + w->profiling->size()));
void factor_vm::update_word_entry_point(word *w)
{
- if(profiling_p && w->profiling)
+ if(counting_profiler_p && w->profiling)
w->entry_point = w->profiling->entry_point();
else
w->entry_point = w->code->entry_point();