aboutsummaryrefslogtreecommitdiff
path: root/exec.c
diff options
context:
space:
mode:
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2005-01-26 22:00:47 +0000
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2005-01-26 22:00:47 +0000
commite3db7226b411d767b9a3ac8e0d88f5cbd5782349 (patch)
treedbc6a91f0c538c2736a9c9d3acab3300125dd11e /exec.c
parentd79284e07aae8d702c1d3f9d83590480fa06f5d7 (diff)
JIT statistics
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1244 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'exec.c')
-rw-r--r--exec.c55
1 files changed, 55 insertions, 0 deletions
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