mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-06 01:03:55 -06:00
tcg: Dynamically allocate TCGOps
With no fixed array allocation, we can't overflow a buffer. This will be important as optimizations related to host vectors may expand the number of ops used. Use QTAILQ to link the ops together. Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
parent
f764718d0c
commit
15fa08f845
12 changed files with 78 additions and 158 deletions
125
tcg/tcg.c
125
tcg/tcg.c
|
@ -862,9 +862,8 @@ void tcg_func_start(TCGContext *s)
|
|||
s->goto_tb_issue_mask = 0;
|
||||
#endif
|
||||
|
||||
s->gen_op_buf[0].next = 1;
|
||||
s->gen_op_buf[0].prev = 0;
|
||||
s->gen_next_op_idx = 1;
|
||||
QTAILQ_INIT(&s->ops);
|
||||
QTAILQ_INIT(&s->free_ops);
|
||||
}
|
||||
|
||||
static inline TCGTemp *tcg_temp_alloc(TCGContext *s)
|
||||
|
@ -1339,7 +1338,6 @@ bool tcg_op_supported(TCGOpcode op)
|
|||
and endian swap in tcg_reg_alloc_call(). */
|
||||
void tcg_gen_callN(void *func, TCGTemp *ret, int nargs, TCGTemp **args)
|
||||
{
|
||||
TCGContext *s = tcg_ctx;
|
||||
int i, real_args, nb_rets, pi;
|
||||
unsigned sizemask, flags;
|
||||
TCGHelperInfo *info;
|
||||
|
@ -1395,17 +1393,7 @@ void tcg_gen_callN(void *func, TCGTemp *ret, int nargs, TCGTemp **args)
|
|||
}
|
||||
#endif /* TCG_TARGET_EXTEND_ARGS */
|
||||
|
||||
i = s->gen_next_op_idx;
|
||||
tcg_debug_assert(i < OPC_BUF_SIZE);
|
||||
s->gen_op_buf[0].prev = i;
|
||||
s->gen_next_op_idx = i + 1;
|
||||
op = &s->gen_op_buf[i];
|
||||
|
||||
/* Set links for sequential allocation during translation. */
|
||||
memset(op, 0, offsetof(TCGOp, args));
|
||||
op->opc = INDEX_op_call;
|
||||
op->prev = i - 1;
|
||||
op->next = i + 1;
|
||||
op = tcg_emit_op(INDEX_op_call);
|
||||
|
||||
pi = 0;
|
||||
if (ret != NULL) {
|
||||
|
@ -1622,20 +1610,18 @@ void tcg_dump_ops(TCGContext *s)
|
|||
{
|
||||
char buf[128];
|
||||
TCGOp *op;
|
||||
int oi;
|
||||
|
||||
for (oi = s->gen_op_buf[0].next; oi != 0; oi = op->next) {
|
||||
QTAILQ_FOREACH(op, &s->ops, link) {
|
||||
int i, k, nb_oargs, nb_iargs, nb_cargs;
|
||||
const TCGOpDef *def;
|
||||
TCGOpcode c;
|
||||
int col = 0;
|
||||
|
||||
op = &s->gen_op_buf[oi];
|
||||
c = op->opc;
|
||||
def = &tcg_op_defs[c];
|
||||
|
||||
if (c == INDEX_op_insn_start) {
|
||||
col += qemu_log("%s ----", oi != s->gen_op_buf[0].next ? "\n" : "");
|
||||
col += qemu_log("\n ----");
|
||||
|
||||
for (i = 0; i < TARGET_INSN_START_WORDS; ++i) {
|
||||
target_ulong a;
|
||||
|
@ -1898,65 +1884,51 @@ static void process_op_defs(TCGContext *s)
|
|||
|
||||
void tcg_op_remove(TCGContext *s, TCGOp *op)
|
||||
{
|
||||
int next = op->next;
|
||||
int prev = op->prev;
|
||||
|
||||
/* We should never attempt to remove the list terminator. */
|
||||
tcg_debug_assert(op != &s->gen_op_buf[0]);
|
||||
|
||||
s->gen_op_buf[next].prev = prev;
|
||||
s->gen_op_buf[prev].next = next;
|
||||
|
||||
memset(op, 0, sizeof(*op));
|
||||
QTAILQ_REMOVE(&s->ops, op, link);
|
||||
QTAILQ_INSERT_TAIL(&s->free_ops, op, link);
|
||||
|
||||
#ifdef CONFIG_PROFILER
|
||||
atomic_set(&s->prof.del_op_count, s->prof.del_op_count + 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
static TCGOp *tcg_op_alloc(TCGOpcode opc)
|
||||
{
|
||||
TCGContext *s = tcg_ctx;
|
||||
TCGOp *op;
|
||||
|
||||
if (likely(QTAILQ_EMPTY(&s->free_ops))) {
|
||||
op = tcg_malloc(sizeof(TCGOp));
|
||||
} else {
|
||||
op = QTAILQ_FIRST(&s->free_ops);
|
||||
QTAILQ_REMOVE(&s->free_ops, op, link);
|
||||
}
|
||||
memset(op, 0, offsetof(TCGOp, link));
|
||||
op->opc = opc;
|
||||
|
||||
return op;
|
||||
}
|
||||
|
||||
TCGOp *tcg_emit_op(TCGOpcode opc)
|
||||
{
|
||||
TCGOp *op = tcg_op_alloc(opc);
|
||||
QTAILQ_INSERT_TAIL(&tcg_ctx->ops, op, link);
|
||||
return op;
|
||||
}
|
||||
|
||||
TCGOp *tcg_op_insert_before(TCGContext *s, TCGOp *old_op,
|
||||
TCGOpcode opc, int nargs)
|
||||
{
|
||||
int oi = s->gen_next_op_idx;
|
||||
int prev = old_op->prev;
|
||||
int next = old_op - s->gen_op_buf;
|
||||
TCGOp *new_op;
|
||||
|
||||
tcg_debug_assert(oi < OPC_BUF_SIZE);
|
||||
s->gen_next_op_idx = oi + 1;
|
||||
|
||||
new_op = &s->gen_op_buf[oi];
|
||||
*new_op = (TCGOp){
|
||||
.opc = opc,
|
||||
.prev = prev,
|
||||
.next = next
|
||||
};
|
||||
s->gen_op_buf[prev].next = oi;
|
||||
old_op->prev = oi;
|
||||
|
||||
TCGOp *new_op = tcg_op_alloc(opc);
|
||||
QTAILQ_INSERT_BEFORE(old_op, new_op, link);
|
||||
return new_op;
|
||||
}
|
||||
|
||||
TCGOp *tcg_op_insert_after(TCGContext *s, TCGOp *old_op,
|
||||
TCGOpcode opc, int nargs)
|
||||
{
|
||||
int oi = s->gen_next_op_idx;
|
||||
int prev = old_op - s->gen_op_buf;
|
||||
int next = old_op->next;
|
||||
TCGOp *new_op;
|
||||
|
||||
tcg_debug_assert(oi < OPC_BUF_SIZE);
|
||||
s->gen_next_op_idx = oi + 1;
|
||||
|
||||
new_op = &s->gen_op_buf[oi];
|
||||
*new_op = (TCGOp){
|
||||
.opc = opc,
|
||||
.prev = prev,
|
||||
.next = next
|
||||
};
|
||||
s->gen_op_buf[next].prev = oi;
|
||||
old_op->next = oi;
|
||||
|
||||
TCGOp *new_op = tcg_op_alloc(opc);
|
||||
QTAILQ_INSERT_AFTER(&s->ops, old_op, new_op, link);
|
||||
return new_op;
|
||||
}
|
||||
|
||||
|
@ -2006,23 +1978,19 @@ static void tcg_la_bb_end(TCGContext *s)
|
|||
static void liveness_pass_1(TCGContext *s)
|
||||
{
|
||||
int nb_globals = s->nb_globals;
|
||||
int oi, oi_prev;
|
||||
TCGOp *op, *op_prev;
|
||||
|
||||
tcg_la_func_end(s);
|
||||
|
||||
for (oi = s->gen_op_buf[0].prev; oi != 0; oi = oi_prev) {
|
||||
QTAILQ_FOREACH_REVERSE_SAFE(op, &s->ops, TCGOpHead, link, op_prev) {
|
||||
int i, nb_iargs, nb_oargs;
|
||||
TCGOpcode opc_new, opc_new2;
|
||||
bool have_opc_new2;
|
||||
TCGLifeData arg_life = 0;
|
||||
TCGTemp *arg_ts;
|
||||
|
||||
TCGOp * const op = &s->gen_op_buf[oi];
|
||||
TCGOpcode opc = op->opc;
|
||||
const TCGOpDef *def = &tcg_op_defs[opc];
|
||||
|
||||
oi_prev = op->prev;
|
||||
|
||||
switch (opc) {
|
||||
case INDEX_op_call:
|
||||
{
|
||||
|
@ -2233,8 +2201,9 @@ static void liveness_pass_1(TCGContext *s)
|
|||
static bool liveness_pass_2(TCGContext *s)
|
||||
{
|
||||
int nb_globals = s->nb_globals;
|
||||
int nb_temps, i, oi, oi_next;
|
||||
int nb_temps, i;
|
||||
bool changes = false;
|
||||
TCGOp *op, *op_next;
|
||||
|
||||
/* Create a temporary for each indirect global. */
|
||||
for (i = 0; i < nb_globals; ++i) {
|
||||
|
@ -2256,16 +2225,13 @@ static bool liveness_pass_2(TCGContext *s)
|
|||
its->state = TS_DEAD;
|
||||
}
|
||||
|
||||
for (oi = s->gen_op_buf[0].next; oi != 0; oi = oi_next) {
|
||||
TCGOp *op = &s->gen_op_buf[oi];
|
||||
QTAILQ_FOREACH_SAFE(op, &s->ops, link, op_next) {
|
||||
TCGOpcode opc = op->opc;
|
||||
const TCGOpDef *def = &tcg_op_defs[opc];
|
||||
TCGLifeData arg_life = op->life;
|
||||
int nb_iargs, nb_oargs, call_flags;
|
||||
TCGTemp *arg_ts, *dir_ts;
|
||||
|
||||
oi_next = op->next;
|
||||
|
||||
if (opc == INDEX_op_call) {
|
||||
nb_oargs = op->callo;
|
||||
nb_iargs = op->calli;
|
||||
|
@ -3168,13 +3134,16 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb)
|
|||
#ifdef CONFIG_PROFILER
|
||||
TCGProfile *prof = &s->prof;
|
||||
#endif
|
||||
int i, oi, oi_next, num_insns;
|
||||
int i, num_insns;
|
||||
TCGOp *op;
|
||||
|
||||
#ifdef CONFIG_PROFILER
|
||||
{
|
||||
int n;
|
||||
|
||||
n = s->gen_op_buf[0].prev + 1;
|
||||
QTAILQ_FOREACH(op, &s->ops, link) {
|
||||
n++;
|
||||
}
|
||||
atomic_set(&prof->op_count, prof->op_count + n);
|
||||
if (n > prof->op_count_max) {
|
||||
atomic_set(&prof->op_count_max, n);
|
||||
|
@ -3260,11 +3229,9 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb)
|
|||
#endif
|
||||
|
||||
num_insns = -1;
|
||||
for (oi = s->gen_op_buf[0].next; oi != 0; oi = oi_next) {
|
||||
TCGOp * const op = &s->gen_op_buf[oi];
|
||||
QTAILQ_FOREACH(op, &s->ops, link) {
|
||||
TCGOpcode opc = op->opc;
|
||||
|
||||
oi_next = op->next;
|
||||
#ifdef CONFIG_PROFILER
|
||||
atomic_set(&prof->table_op_count[opc], prof->table_op_count[opc] + 1);
|
||||
#endif
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue