TCG: Move translation block variables to new context inside tcg_ctx: tb_ctx
It's worth to clean-up translation blocks variables and move them
into one context as was suggested by Swirl.
Also if we use this context directly inside tcg_ctx, then it
speeds up code generation a bit.
Signed-off-by: Evgeny Voevodin <evgenyvoevodin@gmail.com>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
diff --git a/translate-all.c b/translate-all.c
index d666562..efeb247 100644
--- a/translate-all.c
+++ b/translate-all.c
@@ -72,13 +72,6 @@
#define SMC_BITMAP_USE_THRESHOLD 10
-/* Translation blocks */
-static TranslationBlock *tbs;
-TranslationBlock *tb_phys_hash[CODE_GEN_PHYS_HASH_SIZE];
-static int nb_tbs;
-/* any access to the tbs or the page table must use this lock */
-spinlock_t tb_lock = SPIN_LOCK_UNLOCKED;
-
typedef struct PageDesc {
/* list of TBs intersecting this ram page */
TranslationBlock *first_tb;
@@ -125,10 +118,6 @@
The bottom level has pointers to PageDesc. */
static void *l1_map[V_L1_SIZE];
-/* statistics */
-static int tb_flush_count;
-static int tb_phys_invalidate_count;
-
/* code generation context */
TCGContext tcg_ctx;
@@ -589,7 +578,8 @@
(TCG_MAX_OP_SIZE * OPC_BUF_SIZE);
tcg_ctx.code_gen_max_blocks = tcg_ctx.code_gen_buffer_size /
CODE_GEN_AVG_BLOCK_SIZE;
- tbs = g_malloc(tcg_ctx.code_gen_max_blocks * sizeof(TranslationBlock));
+ tcg_ctx.tb_ctx.tbs =
+ g_malloc(tcg_ctx.code_gen_max_blocks * sizeof(TranslationBlock));
}
/* Must be called before using the QEMU cpus. 'tb_size' is the size
@@ -620,12 +610,12 @@
{
TranslationBlock *tb;
- if (nb_tbs >= tcg_ctx.code_gen_max_blocks ||
+ if (tcg_ctx.tb_ctx.nb_tbs >= tcg_ctx.code_gen_max_blocks ||
(tcg_ctx.code_gen_ptr - tcg_ctx.code_gen_buffer) >=
tcg_ctx.code_gen_buffer_max_size) {
return NULL;
}
- tb = &tbs[nb_tbs++];
+ tb = &tcg_ctx.tb_ctx.tbs[tcg_ctx.tb_ctx.nb_tbs++];
tb->pc = pc;
tb->cflags = 0;
return tb;
@@ -636,9 +626,10 @@
/* In practice this is mostly used for single use temporary TB
Ignore the hard cases and just back up if this TB happens to
be the last one generated. */
- if (nb_tbs > 0 && tb == &tbs[nb_tbs - 1]) {
+ if (tcg_ctx.tb_ctx.nb_tbs > 0 &&
+ tb == &tcg_ctx.tb_ctx.tbs[tcg_ctx.tb_ctx.nb_tbs - 1]) {
tcg_ctx.code_gen_ptr = tb->tc_ptr;
- nb_tbs--;
+ tcg_ctx.tb_ctx.nb_tbs--;
}
}
@@ -693,27 +684,28 @@
#if defined(DEBUG_FLUSH)
printf("qemu: flush code_size=%ld nb_tbs=%d avg_tb_size=%ld\n",
(unsigned long)(tcg_ctx.code_gen_ptr - tcg_ctx.code_gen_buffer),
- nb_tbs, nb_tbs > 0 ?
+ tcg_ctx.tb_ctx.nb_tbs, tcg_ctx.tb_ctx.nb_tbs > 0 ?
((unsigned long)(tcg_ctx.code_gen_ptr - tcg_ctx.code_gen_buffer)) /
- nb_tbs : 0);
+ tcg_ctx.tb_ctx.nb_tbs : 0);
#endif
if ((unsigned long)(tcg_ctx.code_gen_ptr - tcg_ctx.code_gen_buffer)
> tcg_ctx.code_gen_buffer_size) {
cpu_abort(env1, "Internal error: code buffer overflow\n");
}
- nb_tbs = 0;
+ tcg_ctx.tb_ctx.nb_tbs = 0;
for (env = first_cpu; env != NULL; env = env->next_cpu) {
memset(env->tb_jmp_cache, 0, TB_JMP_CACHE_SIZE * sizeof(void *));
}
- memset(tb_phys_hash, 0, CODE_GEN_PHYS_HASH_SIZE * sizeof(void *));
+ memset(tcg_ctx.tb_ctx.tb_phys_hash, 0,
+ CODE_GEN_PHYS_HASH_SIZE * sizeof(void *));
page_flush_tb();
tcg_ctx.code_gen_ptr = tcg_ctx.code_gen_buffer;
/* XXX: flush processor icache at this point if cache flush is
expensive */
- tb_flush_count++;
+ tcg_ctx.tb_ctx.tb_flush_count++;
}
#ifdef DEBUG_TB_CHECK
@@ -725,7 +717,7 @@
address &= TARGET_PAGE_MASK;
for (i = 0; i < CODE_GEN_PHYS_HASH_SIZE; i++) {
- for (tb = tb_phys_hash[i]; tb != NULL; tb = tb->phys_hash_next) {
+ for (tb = tb_ctx.tb_phys_hash[i]; tb != NULL; tb = tb->phys_hash_next) {
if (!(address + TARGET_PAGE_SIZE <= tb->pc ||
address >= tb->pc + tb->size)) {
printf("ERROR invalidate: address=" TARGET_FMT_lx
@@ -743,7 +735,8 @@
int i, flags1, flags2;
for (i = 0; i < CODE_GEN_PHYS_HASH_SIZE; i++) {
- for (tb = tb_phys_hash[i]; tb != NULL; tb = tb->phys_hash_next) {
+ for (tb = tcg_ctx.tb_ctx.tb_phys_hash[i]; tb != NULL;
+ tb = tb->phys_hash_next) {
flags1 = page_get_flags(tb->pc);
flags2 = page_get_flags(tb->pc + tb->size - 1);
if ((flags1 & PAGE_WRITE) || (flags2 & PAGE_WRITE)) {
@@ -835,7 +828,7 @@
/* remove the TB from the hash list */
phys_pc = tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK);
h = tb_phys_hash_func(phys_pc);
- tb_hash_remove(&tb_phys_hash[h], tb);
+ tb_hash_remove(&tcg_ctx.tb_ctx.tb_phys_hash[h], tb);
/* remove the TB from the page list */
if (tb->page_addr[0] != page_addr) {
@@ -849,7 +842,7 @@
invalidate_page_bitmap(p);
}
- tb_invalidated_flag = 1;
+ tcg_ctx.tb_ctx.tb_invalidated_flag = 1;
/* remove the TB from the hash list */
h = tb_jmp_cache_hash_func(tb->pc);
@@ -878,7 +871,7 @@
}
tb->jmp_first = (TranslationBlock *)((uintptr_t)tb | 2); /* fail safe */
- tb_phys_invalidate_count++;
+ tcg_ctx.tb_ctx.tb_phys_invalidate_count++;
}
static inline void set_bits(uint8_t *tab, int start, int len)
@@ -955,7 +948,7 @@
/* cannot fail at this point */
tb = tb_alloc(pc);
/* Don't forget to invalidate previous TB info. */
- tb_invalidated_flag = 1;
+ tcg_ctx.tb_ctx.tb_invalidated_flag = 1;
}
tc_ptr = tcg_ctx.code_gen_ptr;
tb->tc_ptr = tc_ptr;
@@ -1273,7 +1266,7 @@
mmap_lock();
/* add in the physical hash table */
h = tb_phys_hash_func(phys_pc);
- ptb = &tb_phys_hash[h];
+ ptb = &tcg_ctx.tb_ctx.tb_phys_hash[h];
tb->phys_hash_next = *ptb;
*ptb = tb;
@@ -1323,7 +1316,7 @@
uintptr_t v;
TranslationBlock *tb;
- if (nb_tbs <= 0) {
+ if (tcg_ctx.tb_ctx.nb_tbs <= 0) {
return NULL;
}
if (tc_ptr < (uintptr_t)tcg_ctx.code_gen_buffer ||
@@ -1332,10 +1325,10 @@
}
/* binary search (cf Knuth) */
m_min = 0;
- m_max = nb_tbs - 1;
+ m_max = tcg_ctx.tb_ctx.nb_tbs - 1;
while (m_min <= m_max) {
m = (m_min + m_max) >> 1;
- tb = &tbs[m];
+ tb = &tcg_ctx.tb_ctx.tbs[m];
v = (uintptr_t)tb->tc_ptr;
if (v == tc_ptr) {
return tb;
@@ -1345,7 +1338,7 @@
m_min = m + 1;
}
}
- return &tbs[m_max];
+ return &tcg_ctx.tb_ctx.tbs[m_max];
}
static void tb_reset_jump_recursive(TranslationBlock *tb);
@@ -1566,8 +1559,8 @@
cross_page = 0;
direct_jmp_count = 0;
direct_jmp2_count = 0;
- for (i = 0; i < nb_tbs; i++) {
- tb = &tbs[i];
+ for (i = 0; i < tcg_ctx.tb_ctx.nb_tbs; i++) {
+ tb = &tcg_ctx.tb_ctx.tbs[i];
target_code_size += tb->size;
if (tb->size > max_target_code_size) {
max_target_code_size = tb->size;
@@ -1588,27 +1581,32 @@
tcg_ctx.code_gen_ptr - tcg_ctx.code_gen_buffer,
tcg_ctx.code_gen_buffer_max_size);
cpu_fprintf(f, "TB count %d/%d\n",
- nb_tbs, tcg_ctx.code_gen_max_blocks);
+ tcg_ctx.tb_ctx.nb_tbs, tcg_ctx.code_gen_max_blocks);
cpu_fprintf(f, "TB avg target size %d max=%d bytes\n",
- nb_tbs ? target_code_size / nb_tbs : 0,
- max_target_code_size);
+ tcg_ctx.tb_ctx.nb_tbs ? target_code_size /
+ tcg_ctx.tb_ctx.nb_tbs : 0,
+ max_target_code_size);
cpu_fprintf(f, "TB avg host size %td bytes (expansion ratio: %0.1f)\n",
- nb_tbs ? (tcg_ctx.code_gen_ptr - tcg_ctx.code_gen_buffer) /
- nb_tbs : 0,
- target_code_size ?
- (double) (tcg_ctx.code_gen_ptr - tcg_ctx.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);
+ tcg_ctx.tb_ctx.nb_tbs ? (tcg_ctx.code_gen_ptr -
+ tcg_ctx.code_gen_buffer) /
+ tcg_ctx.tb_ctx.nb_tbs : 0,
+ target_code_size ? (double) (tcg_ctx.code_gen_ptr -
+ tcg_ctx.code_gen_buffer) /
+ target_code_size : 0);
+ cpu_fprintf(f, "cross page TB count %d (%d%%)\n", cross_page,
+ tcg_ctx.tb_ctx.nb_tbs ? (cross_page * 100) /
+ tcg_ctx.tb_ctx.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,
+ tcg_ctx.tb_ctx.nb_tbs ? (direct_jmp_count * 100) /
+ tcg_ctx.tb_ctx.nb_tbs : 0,
direct_jmp2_count,
- nb_tbs ? (direct_jmp2_count * 100) / nb_tbs : 0);
+ tcg_ctx.tb_ctx.nb_tbs ? (direct_jmp2_count * 100) /
+ tcg_ctx.tb_ctx.nb_tbs : 0);
cpu_fprintf(f, "\nStatistics:\n");
- 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, "TB flush count %d\n", tcg_ctx.tb_ctx.tb_flush_count);
+ cpu_fprintf(f, "TB invalidate count %d\n",
+ tcg_ctx.tb_ctx.tb_phys_invalidate_count);
cpu_fprintf(f, "TLB flush count %d\n", tlb_flush_count);
tcg_dump_info(f, cpu_fprintf);
}