diff --git a/cpu-all.h b/cpu-all.h index 303fab0c1b..d395c0038b 100644 --- a/cpu-all.h +++ b/cpu-all.h @@ -742,4 +742,7 @@ static inline void cpu_physical_memory_set_dirty(target_ulong addr) void cpu_physical_memory_reset_dirty(target_ulong start, target_ulong end); +void dump_exec_info(FILE *f, + int (*cpu_fprintf)(FILE *f, const char *fmt, ...)); + #endif /* CPU_ALL_H */ diff --git a/exec.c b/exec.c index 3057750feb..40bd60a9f0 100644 --- a/exec.c +++ b/exec.c @@ -128,6 +128,11 @@ char *logfilename = "/tmp/qemu.log"; FILE *logfile; int loglevel; +/* statistics */ +static int tlb_flush_count; +static int tb_flush_count; +static int tb_phys_invalidate_count; + static void page_init(void) { /* NOTE: we can always suppose that qemu_host_page_size >= @@ -336,6 +341,7 @@ void tb_flush(CPUState *env) code_gen_ptr = code_gen_buffer; /* XXX: flush processor icache at this point if cache flush is expensive */ + tb_flush_count++; } #ifdef DEBUG_TB_CHECK @@ -530,6 +536,7 @@ static inline void tb_phys_invalidate(TranslationBlock *tb, unsigned int page_ad } tb_invalidate(tb); + tb_phys_invalidate_count++; } static inline void set_bits(uint8_t *tab, int start, int len) @@ -1298,6 +1305,7 @@ void tlb_flush(CPUState *env, int flush_global) #if !defined(CONFIG_SOFTMMU) munmap((void *)MMAP_AREA_START, MMAP_AREA_END - MMAP_AREA_START); #endif + tlb_flush_count++; } static inline void tlb_flush_entry(CPUTLBEntry *tlb_entry, target_ulong addr) @@ -2137,6 +2145,53 @@ int cpu_memory_rw_debug(CPUState *env, target_ulong addr, return 0; } +void dump_exec_info(FILE *f, + int (*cpu_fprintf)(FILE *f, const char *fmt, ...)) +{ + int i, target_code_size, max_target_code_size; + int direct_jmp_count, direct_jmp2_count, cross_page; + TranslationBlock *tb; + + target_code_size = 0; + max_target_code_size = 0; + cross_page = 0; + direct_jmp_count = 0; + direct_jmp2_count = 0; + for(i = 0; i < nb_tbs; i++) { + tb = &tbs[i]; + target_code_size += tb->size; + if (tb->size > max_target_code_size) + max_target_code_size = tb->size; + if (tb->page_addr[1] != -1) + cross_page++; + if (tb->tb_next_offset[0] != 0xffff) { + direct_jmp_count++; + if (tb->tb_next_offset[1] != 0xffff) { + direct_jmp2_count++; + } + } + } + /* XXX: avoid using doubles ? */ + cpu_fprintf(f, "TB count %d\n", nb_tbs); + cpu_fprintf(f, "TB avg target size %d max=%d bytes\n", + nb_tbs ? target_code_size / nb_tbs : 0, + max_target_code_size); + cpu_fprintf(f, "TB avg host size %d bytes (expansion ratio: %0.1f)\n", + nb_tbs ? (code_gen_ptr - code_gen_buffer) / nb_tbs : 0, + target_code_size ? (double) (code_gen_ptr - code_gen_buffer) / target_code_size : 0); + cpu_fprintf(f, "cross page TB count %d (%d%%)\n", + cross_page, + nb_tbs ? (cross_page * 100) / nb_tbs : 0); + cpu_fprintf(f, "direct jump count %d (%d%%) (2 jumps=%d %d%%)\n", + direct_jmp_count, + nb_tbs ? (direct_jmp_count * 100) / nb_tbs : 0, + direct_jmp2_count, + nb_tbs ? (direct_jmp2_count * 100) / nb_tbs : 0); + cpu_fprintf(f, "TB flush count %d\n", tb_flush_count); + cpu_fprintf(f, "TB invalidate count %d\n", tb_phys_invalidate_count); + cpu_fprintf(f, "TLB flush count %d\n", tlb_flush_count); +} + #if !defined(CONFIG_USER_ONLY) #define MMUSUFFIX _cmmu diff --git a/monitor.c b/monitor.c index cfb9c49755..ae1ce8792f 100644 --- a/monitor.c +++ b/monitor.c @@ -220,14 +220,19 @@ static void do_info_block(void) static void do_info_registers(void) { #ifdef TARGET_I386 - cpu_dump_state(cpu_single_env, stdout, monitor_fprintf, + cpu_dump_state(cpu_single_env, NULL, monitor_fprintf, X86_DUMP_FPU | X86_DUMP_CCOP); #else - cpu_dump_state(cpu_single_env, stdout, monitor_fprintf, + cpu_dump_state(cpu_single_env, NULL, monitor_fprintf, 0); #endif } +static void do_info_jit(void) +{ + dump_exec_info(NULL, monitor_fprintf); +} + static void do_info_history (void) { int i; @@ -893,6 +898,8 @@ static term_cmd_t info_cmds[] = { { "mem", "", mem_info, "", "show the active virtual memory mappings", }, #endif + { "jit", "", do_info_jit, + "", "show dynamic compiler info", }, { NULL, NULL, }, };