summary refs log tree commit diff stats
path: root/tcg/tcg.c
diff options
context:
space:
mode:
authorRichard Henderson <rth@twiddle.net>2015-09-22 13:01:15 -0700
committerRichard Henderson <rth@twiddle.net>2015-10-07 20:36:53 +1100
commitb125f9dc7bd68cd4c57189db4da83b0620b28a72 (patch)
tree8d2b7a06e64121738343a3abebb5070b64f4ff21 /tcg/tcg.c
parentf293709c6af7a65a9bcec09cdba7a60183657a3e (diff)
downloadfocaccia-qemu-b125f9dc7bd68cd4c57189db4da83b0620b28a72.tar.gz
focaccia-qemu-b125f9dc7bd68cd4c57189db4da83b0620b28a72.zip
tcg: Check for overflow via highwater mark
We currently pre-compute an worst case code size for any TB, which
works out to be 122kB.  Since the average TB size is near 1kB, this
wastes quite a lot of storage.

Instead, check for overflow in between generating code for each opcode.
The overhead of the check isn't measurable and wastage is minimized.

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <rth@twiddle.net>
Diffstat (limited to 'tcg/tcg.c')
-rw-r--r--tcg/tcg.c14
1 files changed, 11 insertions, 3 deletions
diff --git a/tcg/tcg.c b/tcg/tcg.c
index 56091087a4..682af8a7c6 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -385,9 +385,10 @@ void tcg_prologue_init(TCGContext *s)
     total_size = s->code_gen_buffer_size - prologue_size;
     s->code_gen_buffer_size = total_size;
 
-    /* Compute a high-water mark, at which we voluntarily flush the
-       buffer and start over.  */
-    s->code_gen_buffer_max_size = total_size - TCG_MAX_OP_SIZE * OPC_BUF_SIZE;
+    /* Compute a high-water mark, at which we voluntarily flush the buffer
+       and start over.  The size here is arbitrary, significantly larger
+       than we expect the code generation for any one opcode to require.  */
+    s->code_gen_highwater = s->code_gen_buffer + (total_size - 1024);
 
     tcg_register_jit(s->code_gen_buffer, total_size);
 
@@ -2438,6 +2439,13 @@ int tcg_gen_code(TCGContext *s, tcg_insn_unit *gen_code_buf)
 #ifndef NDEBUG
         check_regs(s);
 #endif
+        /* Test for (pending) buffer overflow.  The assumption is that any
+           one operation beginning below the high water mark cannot overrun
+           the buffer completely.  Thus we can test for overflow after
+           generating code without having to check during generation.  */
+        if (unlikely(s->code_gen_ptr > s->code_gen_highwater)) {
+            return -1;
+        }
     }
     tcg_debug_assert(num_insns >= 0);
     s->gen_insn_end_off[num_insns] = tcg_current_code_size(s);