From 6c0ecf631ac9685aabefe2182203fad0811da96f Mon Sep 17 00:00:00 2001 From: Joe Groff Date: Thu, 17 Nov 2011 17:13:59 -0800 Subject: [PATCH] vm: charge samples collected in prolog to parent Fixes #379 --- vm/errors.cpp | 6 +++--- vm/mach_signal.cpp | 1 + vm/os-unix.cpp | 1 + vm/safepoints.cpp | 10 ++++++++-- vm/safepoints.hpp | 2 +- vm/sampling_profiler.cpp | 33 ++++++++++++++++++++++++--------- vm/sampling_profiler.hpp | 3 ++- vm/vm.hpp | 7 ++++--- 8 files changed, 44 insertions(+), 19 deletions(-) diff --git a/vm/errors.cpp b/vm/errors.cpp index 99c21b60d6..b7fd4488a8 100755 --- a/vm/errors.cpp +++ b/vm/errors.cpp @@ -115,10 +115,10 @@ void factor_vm::verify_memory_protection_error(cell 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)) - safepoint.handle_safepoint(this); + safepoint.handle_safepoint(this, pc); else if(ctx->datastack_seg->underflow_p(addr)) general_error(ERROR_DATASTACK_UNDERFLOW,false_object,false_object); else if(ctx->datastack_seg->overflow_p(addr)) @@ -158,7 +158,7 @@ void factor_vm::primitive_unimplemented() 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) { /* In theory we should only get here if the callstack overflowed during a diff --git a/vm/mach_signal.cpp b/vm/mach_signal.cpp index 52148676c5..718937577c 100755 --- a/vm/mach_signal.cpp +++ b/vm/mach_signal.cpp @@ -40,6 +40,7 @@ void factor_vm::call_fault_handler( if(exception == EXC_BAD_ACCESS) { 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); handler = (cell)factor::memory_signal_handler_impl; } diff --git a/vm/os-unix.cpp b/vm/os-unix.cpp index d7f4bb5ebf..cc53edea25 100755 --- a/vm/os-unix.cpp +++ b/vm/os-unix.cpp @@ -167,6 +167,7 @@ void memory_signal_handler(int signal, siginfo_t *siginfo, void *uap) factor_vm *vm = current_vm(); vm->verify_memory_protection_error((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); } diff --git a/vm/safepoints.cpp b/vm/safepoints.cpp index 2353157cab..12c63bffb3 100644 --- a/vm/safepoints.cpp +++ b/vm/safepoints.cpp @@ -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->faulting_p = false; @@ -49,7 +49,13 @@ void safepoint_state::handle_safepoint(factor_vm *parent) volatile atomic::store(&fep_p, false); } 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); + } } } diff --git a/vm/safepoints.hpp b/vm/safepoints.hpp index 782de47be7..c30afd5fcf 100644 --- a/vm/safepoints.hpp +++ b/vm/safepoints.hpp @@ -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_samples(factor_vm *parent, cell samples, cell pc, bool foreign_thread_p) volatile; diff --git a/vm/sampling_profiler.cpp b/vm/sampling_profiler.cpp index 7c1dc837dc..8b567408ae 100644 --- a/vm/sampling_profiler.cpp +++ b/vm/sampling_profiler.cpp @@ -31,31 +31,46 @@ void profiling_sample_count::clear() volatile } profiling_sample::profiling_sample(factor_vm *vm, + bool prolog_p, profiling_sample_count const &counts, cell thread) : counts(counts), 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(); if (!counts.empty()) - samples.push_back(profiling_sample(this, + samples.push_back(profiling_sample(this, prolog_p, 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(); stack_frame *frame = ctx->bottom_frame(); - - while (frame >= ctx->callstack_top) { - sample_callstacks.push_back(frame_code(frame)->owner); - frame = frame_successor(frame); + if (prolog_p) + { + 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); + frame = frame_successor(frame); + } } *end = sample_callstacks.size(); @@ -98,7 +113,7 @@ void factor_vm::end_sampling_profiler() { atomic::store(&sampling_profiler_p, false); end_sampling_profiler_timer(); - record_sample(); + record_sample(false); } void factor_vm::primitive_sampling_profiler() diff --git a/vm/sampling_profiler.hpp b/vm/sampling_profiler.hpp index 11319615cf..5f0558fe04 100644 --- a/vm/sampling_profiler.hpp +++ b/vm/sampling_profiler.hpp @@ -31,7 +31,7 @@ struct profiling_sample_count jit_sample_count(jit_sample_count), foreign_sample_count(foreign_sample_count), foreign_thread_sample_count(foreign_thread_sample_count) {} - + bool empty() const { return sample_count @@ -56,6 +56,7 @@ struct profiling_sample cell callstack_begin, callstack_end; profiling_sample(factor_vm *vm, + bool prolog_p, profiling_sample_count const &counts, cell thread); }; diff --git a/vm/vm.hpp b/vm/vm.hpp index 016bd5b7b4..0889a254f6 100755 --- a/vm/vm.hpp +++ b/vm/vm.hpp @@ -75,6 +75,7 @@ struct factor_vm bool signal_resumable; cell signal_number; cell signal_fault_addr; + cell signal_fault_pc; unsigned int signal_fpu_status; /* Pipe used to notify Factor multiplexer of signals */ @@ -204,8 +205,8 @@ struct factor_vm // sampling_profiler void clear_samples(); - void record_sample(); - void record_callstack_sample(cell *begin, cell *end); + void record_sample(bool prolog_p); + void record_callstack_sample(cell *begin, cell *end, bool prolog_p); void start_sampling_profiler(fixnum rate); void end_sampling_profiler(); void set_sampling_profiler(fixnum rate); @@ -218,7 +219,7 @@ struct factor_vm void type_error(cell type, cell tagged); void not_implemented_error(); 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 divide_by_zero_error(); void fp_trap_error(unsigned int fpu_status);