mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-02-25 12:26:53 +00:00
tcg: Restart after TB code generation overflow
If a TB generates too much code, try again with fewer insns. Fixes: https://bugs.launchpad.net/bugs/1824853 Backports commit 6e6c4efed995d9eca6ae0cfdb2252df830262f50 from qemu
This commit is contained in:
parent
bca82cde84
commit
434b3ab9ec
|
@ -1360,6 +1360,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
|
|||
tb->cs_base = cs_base;
|
||||
tb->flags = flags;
|
||||
tb->cflags = cflags;
|
||||
tb_overflow:
|
||||
|
||||
#ifdef CONFIG_PROFILER
|
||||
tcg_ctx->tb_count1++; /* includes aborted translations because of
|
||||
|
@ -1406,14 +1407,39 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
|
|||
tcg_ctx->code_time -= profile_getclock();
|
||||
#endif
|
||||
|
||||
/* ??? Overflow could be handled better here. In particular, we
|
||||
don't need to re-do gen_intermediate_code, nor should we re-do
|
||||
the tcg optimization currently hidden inside tcg_gen_code. All
|
||||
that should be required is to flush the TBs, allocate a new TB,
|
||||
re-initialize it per above, and re-do the actual code generation. */
|
||||
gen_code_size = tcg_gen_code(tcg_ctx, tb);
|
||||
if (unlikely(gen_code_size < 0)) {
|
||||
goto buffer_overflow;
|
||||
switch (gen_code_size) {
|
||||
case -1:
|
||||
/*
|
||||
* Overflow of code_gen_buffer, or the current slice of it.
|
||||
*
|
||||
* TODO: We don't need to re-do gen_intermediate_code, nor
|
||||
* should we re-do the tcg optimization currently hidden
|
||||
* inside tcg_gen_code. All that should be required is to
|
||||
* flush the TBs, allocate a new TB, re-initialize it per
|
||||
* above, and re-do the actual code generation.
|
||||
*/
|
||||
goto buffer_overflow;
|
||||
|
||||
case -2:
|
||||
/*
|
||||
* The code generated for the TranslationBlock is too large.
|
||||
* The maximum size allowed by the unwind info is 64k.
|
||||
* There may be stricter constraints from relocations
|
||||
* in the tcg backend.
|
||||
*
|
||||
* Try again with half as many insns as we attempted this time.
|
||||
* If a single insn overflows, there's a bug somewhere...
|
||||
*/
|
||||
max_insns = tb->icount;
|
||||
assert(max_insns > 1);
|
||||
max_insns /= 2;
|
||||
goto tb_overflow;
|
||||
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
}
|
||||
search_size = encode_search(tcg_ctx, tb, (unsigned char *)gen_code_buf + gen_code_size);
|
||||
if (unlikely(search_size < 0)) {
|
||||
|
|
|
@ -3366,6 +3366,10 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb)
|
|||
if (unlikely((void *)s->code_ptr > s->code_gen_highwater)) {
|
||||
return -1;
|
||||
}
|
||||
/* Test for TB overflow, as seen by gen_insn_end_off. */
|
||||
if (unlikely(tcg_current_code_size(s) > UINT16_MAX)) {
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
tcg_debug_assert(num_insns >= 0);
|
||||
s->gen_insn_end_off[num_insns] = tcg_current_code_size(s);
|
||||
|
|
Loading…
Reference in a new issue