I think that most sampling profilers like oprofile (http://oprofile.sourceforge.net/news/) or perf (https://perf.wiki.kernel.org/index.php/Main_Page) will give you CPU-level profiling and performance counters. The UI of those tools isn't super-friendly; if you're on OS X the "Instruments" app gives the same information with a far superior UI.
I have written a JIT that uses LuaJIT's dynamic assembly language engine DynASM (http://luajit.org/dynasm.html). DynASM is an incredibly piece of engineering, it lets you write really readable code for generating machine code at runtime, and is extremely small and low-overhead.
I keep meaning to write an article that demonstrates how to use LuaJIT for a small but interesting JIT. I just never quite get around to it. I always wish that I could use to implement the Universal Machine from ICFP 2008 (http://www.boundvariable.org/task.shtml), which is absolutely the most delightful problem ever, but as I recall it makes extensive use of self-modifying code which makes JIT-ting much more difficult and less effective.
I have written a JIT that uses LuaJIT's dynamic assembly language engine DynASM (http://luajit.org/dynasm.html). DynASM is an incredibly piece of engineering, it lets you write really readable code for generating machine code at runtime, and is extremely small and low-overhead.
I keep meaning to write an article that demonstrates how to use LuaJIT for a small but interesting JIT. I just never quite get around to it. I always wish that I could use to implement the Universal Machine from ICFP 2008 (http://www.boundvariable.org/task.shtml), which is absolutely the most delightful problem ever, but as I recall it makes extensive use of self-modifying code which makes JIT-ting much more difficult and less effective.