mirror of https://github.com/xemu-project/xemu.git
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 Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
parent
8b86d6d258
commit
6e6c4efed9
|
@ -1722,6 +1722,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
|
||||||
tb->cflags = cflags;
|
tb->cflags = cflags;
|
||||||
tb->trace_vcpu_dstate = *cpu->trace_dstate;
|
tb->trace_vcpu_dstate = *cpu->trace_dstate;
|
||||||
tcg_ctx->tb_cflags = cflags;
|
tcg_ctx->tb_cflags = cflags;
|
||||||
|
tb_overflow:
|
||||||
|
|
||||||
#ifdef CONFIG_PROFILER
|
#ifdef CONFIG_PROFILER
|
||||||
/* includes aborted translations because of exceptions */
|
/* includes aborted translations because of exceptions */
|
||||||
|
@ -1755,14 +1756,39 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
|
||||||
ti = profile_getclock();
|
ti = profile_getclock();
|
||||||
#endif
|
#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);
|
gen_code_size = tcg_gen_code(tcg_ctx, tb);
|
||||||
if (unlikely(gen_code_size < 0)) {
|
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(tb, (void *)gen_code_buf + gen_code_size);
|
search_size = encode_search(tb, (void *)gen_code_buf + gen_code_size);
|
||||||
if (unlikely(search_size < 0)) {
|
if (unlikely(search_size < 0)) {
|
||||||
|
|
|
@ -3996,6 +3996,10 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb)
|
||||||
if (unlikely((void *)s->code_ptr > s->code_gen_highwater)) {
|
if (unlikely((void *)s->code_ptr > s->code_gen_highwater)) {
|
||||||
return -1;
|
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);
|
tcg_debug_assert(num_insns >= 0);
|
||||||
s->gen_insn_end_off[num_insns] = tcg_current_code_size(s);
|
s->gen_insn_end_off[num_insns] = tcg_current_code_size(s);
|
||||||
|
|
Loading…
Reference in New Issue