vm: charge samples collected in prolog to parent

Fixes #379
db4
Joe Groff 2011-11-17 17:13:59 -08:00
parent 81911b9f87
commit 6c0ecf631a
8 changed files with 44 additions and 19 deletions

View File

@ -115,10 +115,10 @@ void factor_vm::verify_memory_protection_error(cell addr)
fatal_error("Memory protection fault during gc", addr); fatal_error("Memory protection fault during gc", addr);
} }
void factor_vm::memory_protection_error(cell addr) void factor_vm::memory_protection_error(cell pc, cell addr)
{ {
if(code->safepoint_p(addr)) if(code->safepoint_p(addr))
safepoint.handle_safepoint(this); safepoint.handle_safepoint(this, pc);
else if(ctx->datastack_seg->underflow_p(addr)) else if(ctx->datastack_seg->underflow_p(addr))
general_error(ERROR_DATASTACK_UNDERFLOW,false_object,false_object); general_error(ERROR_DATASTACK_UNDERFLOW,false_object,false_object);
else if(ctx->datastack_seg->overflow_p(addr)) else if(ctx->datastack_seg->overflow_p(addr))
@ -158,7 +158,7 @@ void factor_vm::primitive_unimplemented()
void factor_vm::memory_signal_handler_impl() void factor_vm::memory_signal_handler_impl()
{ {
memory_protection_error(signal_fault_addr); memory_protection_error(signal_fault_pc, signal_fault_addr);
if (!signal_resumable) if (!signal_resumable)
{ {
/* In theory we should only get here if the callstack overflowed during a /* In theory we should only get here if the callstack overflowed during a

View File

@ -40,6 +40,7 @@ void factor_vm::call_fault_handler(
if(exception == EXC_BAD_ACCESS) if(exception == EXC_BAD_ACCESS)
{ {
signal_fault_addr = MACH_EXC_STATE_FAULT(exc_state); signal_fault_addr = MACH_EXC_STATE_FAULT(exc_state);
signal_fault_pc = (cell)MACH_PROGRAM_COUNTER(thread_state);
verify_memory_protection_error(signal_fault_addr); verify_memory_protection_error(signal_fault_addr);
handler = (cell)factor::memory_signal_handler_impl; handler = (cell)factor::memory_signal_handler_impl;
} }

View File

@ -167,6 +167,7 @@ void memory_signal_handler(int signal, siginfo_t *siginfo, void *uap)
factor_vm *vm = current_vm(); factor_vm *vm = current_vm();
vm->verify_memory_protection_error((cell)siginfo->si_addr); vm->verify_memory_protection_error((cell)siginfo->si_addr);
vm->signal_fault_addr = (cell)siginfo->si_addr; vm->signal_fault_addr = (cell)siginfo->si_addr;
vm->signal_fault_pc = (cell)UAP_PROGRAM_COUNTER(uap);
vm->dispatch_signal(uap,factor::memory_signal_handler_impl); vm->dispatch_signal(uap,factor::memory_signal_handler_impl);
} }

View File

@ -35,7 +35,7 @@ void safepoint_state::enqueue_samples(factor_vm *parent, cell samples, cell pc,
} }
} }
void safepoint_state::handle_safepoint(factor_vm *parent) volatile void safepoint_state::handle_safepoint(factor_vm *parent, cell pc) volatile
{ {
parent->code->unguard_safepoint(); parent->code->unguard_safepoint();
parent->faulting_p = false; parent->faulting_p = false;
@ -49,7 +49,13 @@ void safepoint_state::handle_safepoint(factor_vm *parent) volatile
atomic::store(&fep_p, false); atomic::store(&fep_p, false);
} }
else if (atomic::load(&parent->sampling_profiler_p)) else if (atomic::load(&parent->sampling_profiler_p))
parent->record_sample(); {
assert(parent->code->seg->in_segment_p(pc));
code_block *block = parent->code->code_block_for_address(pc);
bool prolog_p = (cell)block->entry_point() == pc;
parent->record_sample(prolog_p);
}
} }
} }

View File

@ -12,7 +12,7 @@ struct safepoint_state
{ {
} }
void handle_safepoint(factor_vm *parent) volatile; void handle_safepoint(factor_vm *parent, cell pc) volatile;
void enqueue_safepoint(factor_vm *parent) volatile; void enqueue_safepoint(factor_vm *parent) volatile;
void enqueue_samples(factor_vm *parent, cell samples, cell pc, bool foreign_thread_p) volatile; void enqueue_samples(factor_vm *parent, cell samples, cell pc, bool foreign_thread_p) volatile;

View File

@ -31,32 +31,47 @@ void profiling_sample_count::clear() volatile
} }
profiling_sample::profiling_sample(factor_vm *vm, profiling_sample::profiling_sample(factor_vm *vm,
bool prolog_p,
profiling_sample_count const &counts, profiling_sample_count const &counts,
cell thread) cell thread)
: :
counts(counts), counts(counts),
thread(thread) thread(thread)
{ {
vm->record_callstack_sample(&callstack_begin, &callstack_end); vm->record_callstack_sample(&callstack_begin, &callstack_end, prolog_p);
} }
void factor_vm::record_sample() void factor_vm::record_sample(bool prolog_p)
{ {
profiling_sample_count counts = safepoint.sample_counts.record_counts(); profiling_sample_count counts = safepoint.sample_counts.record_counts();
if (!counts.empty()) if (!counts.empty())
samples.push_back(profiling_sample(this, samples.push_back(profiling_sample(this, prolog_p,
counts, special_objects[OBJ_CURRENT_THREAD])); counts, special_objects[OBJ_CURRENT_THREAD]));
} }
void factor_vm::record_callstack_sample(cell *begin, cell *end) void factor_vm::record_callstack_sample(cell *begin, cell *end, bool prolog_p)
{ {
*begin = sample_callstacks.size(); *begin = sample_callstacks.size();
stack_frame *frame = ctx->bottom_frame(); stack_frame *frame = ctx->bottom_frame();
if (prolog_p)
while (frame >= ctx->callstack_top) { {
assert(frame >= ctx->callstack_top);
stack_frame *next_frame = frame_successor(frame);
while (next_frame >= ctx->callstack_top)
{
sample_callstacks.push_back(frame_code(frame)->owner);
frame = next_frame;
next_frame = frame_successor(next_frame);
}
}
else
{
while (frame >= ctx->callstack_top)
{
sample_callstacks.push_back(frame_code(frame)->owner); sample_callstacks.push_back(frame_code(frame)->owner);
frame = frame_successor(frame); frame = frame_successor(frame);
} }
}
*end = sample_callstacks.size(); *end = sample_callstacks.size();
} }
@ -98,7 +113,7 @@ void factor_vm::end_sampling_profiler()
{ {
atomic::store(&sampling_profiler_p, false); atomic::store(&sampling_profiler_p, false);
end_sampling_profiler_timer(); end_sampling_profiler_timer();
record_sample(); record_sample(false);
} }
void factor_vm::primitive_sampling_profiler() void factor_vm::primitive_sampling_profiler()

View File

@ -56,6 +56,7 @@ struct profiling_sample
cell callstack_begin, callstack_end; cell callstack_begin, callstack_end;
profiling_sample(factor_vm *vm, profiling_sample(factor_vm *vm,
bool prolog_p,
profiling_sample_count const &counts, profiling_sample_count const &counts,
cell thread); cell thread);
}; };

View File

@ -75,6 +75,7 @@ struct factor_vm
bool signal_resumable; bool signal_resumable;
cell signal_number; cell signal_number;
cell signal_fault_addr; cell signal_fault_addr;
cell signal_fault_pc;
unsigned int signal_fpu_status; unsigned int signal_fpu_status;
/* Pipe used to notify Factor multiplexer of signals */ /* Pipe used to notify Factor multiplexer of signals */
@ -204,8 +205,8 @@ struct factor_vm
// sampling_profiler // sampling_profiler
void clear_samples(); void clear_samples();
void record_sample(); void record_sample(bool prolog_p);
void record_callstack_sample(cell *begin, cell *end); void record_callstack_sample(cell *begin, cell *end, bool prolog_p);
void start_sampling_profiler(fixnum rate); void start_sampling_profiler(fixnum rate);
void end_sampling_profiler(); void end_sampling_profiler();
void set_sampling_profiler(fixnum rate); void set_sampling_profiler(fixnum rate);
@ -218,7 +219,7 @@ struct factor_vm
void type_error(cell type, cell tagged); void type_error(cell type, cell tagged);
void not_implemented_error(); void not_implemented_error();
void verify_memory_protection_error(cell addr); void verify_memory_protection_error(cell addr);
void memory_protection_error(cell addr); void memory_protection_error(cell pc, cell addr);
void signal_error(cell signal); void signal_error(cell signal);
void divide_by_zero_error(); void divide_by_zero_error();
void fp_trap_error(unsigned int fpu_status); void fp_trap_error(unsigned int fpu_status);