From 762aefc9b19f68f4cc8870ca5d9986eadee838f0 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sun, 12 Jun 2005 09:54:01 +0000 Subject: [PATCH] implement Raven's calling convention (rcall: first 2 params in opb and opc). should give a general speedup to most progs. --- doc/progs/vm-exec.c | 1 + include/QF/pr_comp.h | 10 ++++++ include/QF/progs.h | 11 +++++++ libs/console/menu.c | 5 +++ libs/gamecode/builtins/bi_gib.c | 1 + libs/gamecode/engine/pr_exec.c | 19 ++++++++++- libs/gamecode/engine/pr_opcode.c | 54 +++++++++++++++++++++++++++++++ libs/gamecode/engine/pr_parse.c | 1 + libs/gamecode/engine/pr_resolve.c | 1 + libs/ruamoko/rua_hash.c | 4 +++ libs/ruamoko/rua_obj.c | 1 + qw/source/sv_ccmds.c | 1 + qw/source/sv_pr_qwe.c | 1 + qw/source/sv_user.c | 3 ++ tools/qfcc/TODO | 2 +- tools/qfcc/source/emit.c | 19 ++++++----- tools/qwaq/main.c | 1 + 17 files changed, 125 insertions(+), 10 deletions(-) diff --git a/doc/progs/vm-exec.c b/doc/progs/vm-exec.c index 91c0d4f6a..0234c2158 100644 --- a/doc/progs/vm-exec.c +++ b/doc/progs/vm-exec.c @@ -20,6 +20,7 @@ call_progs_main (progs_t *pr, int argc, const char **argv) for (i = 0; i < argc; i++) pr_argv[i] = PR_SetTempString (pr, argv[1 + i]); pr_argv[i] = 0; + PR_RESET_PARAMS (pr); P_INT (pr, 0) = argc; P_POINTER (pr, 1) = PR_SetPointer (pr, pr_argv); PR_ExecuteProgram (pr, progs_main); diff --git a/include/QF/pr_comp.h b/include/QF/pr_comp.h index fee066010..363aaf341 100644 --- a/include/QF/pr_comp.h +++ b/include/QF/pr_comp.h @@ -306,6 +306,16 @@ typedef enum { OP_LOADB_Q, OP_LOADBI_Q, OP_ADDRESS_Q, + + OP_RCALL0, + OP_RCALL1, + OP_RCALL2, + OP_RCALL3, + OP_RCALL4, + OP_RCALL5, + OP_RCALL6, + OP_RCALL7, + OP_RCALL8, } pr_opcode_e; typedef struct opcode_s { diff --git a/include/QF/progs.h b/include/QF/progs.h index ae13ca71d..6a1696767 100644 --- a/include/QF/progs.h +++ b/include/QF/progs.h @@ -67,6 +67,16 @@ void PR_RunError (progs_t *pr, const char *error, ...) __attribute__((format(pri */ //@{ +/** Ensure P_* macros point to the right place for passing parameters to progs + functions. + \param pr pointer to progs_t VM struct +*/ +#define PR_RESET_PARAMS(pr) \ + do { \ + (pr)->pr_params[0] = (pr)->pr_real_params[0]; \ + (pr)->pr_params[1] = (pr)->pr_real_params[1]; \ + } while (0) + /** Push an execution frame onto the VM stack. Saves current execution state \param pr pointer to progs_t VM struct */ @@ -1200,6 +1210,7 @@ struct progs_s { pr_type_t *pr_return; pr_type_t *pr_params[MAX_PARMS]; + pr_type_t *pr_real_params[MAX_PARMS]; int pr_param_size; ///< covers both params and return int pr_edict_size; ///< in bytes diff --git a/libs/console/menu.c b/libs/console/menu.c index 47947d872..cddaa1a82 100644 --- a/libs/console/menu.c +++ b/libs/console/menu.c @@ -522,6 +522,7 @@ Menu_Draw (view_t *view) *menu_pr_state.globals.time = *con_data.realtime; if (menu->draw) { + PR_RESET_PARAMS (&menu_pr_state); P_INT (&menu_pr_state, 0) = x; P_INT (&menu_pr_state, 1) = y; PR_ExecuteProgram (&menu_pr_state, menu->draw); @@ -551,6 +552,7 @@ Menu_Draw (view_t *view) return; item = menu->items[menu->cur_item]; if (menu->cursor) { + PR_RESET_PARAMS (&menu_pr_state); P_INT (&menu_pr_state, 0) = x + item->x; P_INT (&menu_pr_state, 1) = y + item->y; PR_ExecuteProgram (&menu_pr_state, menu->cursor); @@ -576,6 +578,7 @@ Menu_KeyEvent (knum_t key, short unicode, qboolean down) if (!menu) return; if (menu->keyevent) { + PR_RESET_PARAMS (&menu_pr_state); P_INT (&menu_pr_state, 0) = key; P_INT (&menu_pr_state, 1) = unicode; P_INT (&menu_pr_state, 2) = down; @@ -586,6 +589,7 @@ Menu_KeyEvent (knum_t key, short unicode, qboolean down) && menu->items[menu->cur_item]->allkeys) { PR_PushFrame (&menu_pr_state); item = menu->items[menu->cur_item]; + PR_RESET_PARAMS (&menu_pr_state); P_STRING (&menu_pr_state, 0) = PR_SetTempString (&menu_pr_state, item->text); P_INT (&menu_pr_state, 1) = key; @@ -613,6 +617,7 @@ Menu_KeyEvent (knum_t key, short unicode, qboolean down) item = menu->items[menu->cur_item]; if (item->func) { PR_PushFrame (&menu_pr_state); + PR_RESET_PARAMS (&menu_pr_state); P_STRING (&menu_pr_state, 0) = PR_SetTempString (&menu_pr_state, item->text); P_INT (&menu_pr_state, 1) = key; diff --git a/libs/gamecode/builtins/bi_gib.c b/libs/gamecode/builtins/bi_gib.c index fcd5bcef2..9bfb54e4d 100644 --- a/libs/gamecode/builtins/bi_gib.c +++ b/libs/gamecode/builtins/bi_gib.c @@ -91,6 +91,7 @@ bi_gib_builtin_f (void) for (i = 0; i < GIB_Argc(); i++) pr_list[i].integer_var = PR_SetTempString (builtin->pr, GIB_Argv(i)); + PR_RESET_PARAMS (builtin->pr); P_INT (builtin->pr, 0) = GIB_Argc(); P_INT (builtin->pr, 1) = PR_SetPointer (builtin->pr, pr_list); PR_ExecuteProgram (builtin->pr, builtin->func); diff --git a/libs/gamecode/engine/pr_exec.c b/libs/gamecode/engine/pr_exec.c index 772240231..8b679515d 100644 --- a/libs/gamecode/engine/pr_exec.c +++ b/libs/gamecode/engine/pr_exec.c @@ -772,6 +772,21 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum) st = pr->pr_statements + pr->pr_xstatement; break; + case OP_RCALL2: + case OP_RCALL3: + case OP_RCALL4: + case OP_RCALL5: + case OP_RCALL6: + case OP_RCALL7: + case OP_RCALL8: + pr->pr_params[1] = &OPC; + goto op_rcall; + case OP_RCALL1: + pr->pr_params[1] = pr->pr_real_params[1]; +op_rcall: + pr->pr_params[0] = &OPB; + pr->pr_argc = st->op - OP_RCALL1 + 1; + goto op_call; case OP_CALL0: case OP_CALL1: case OP_CALL2: @@ -781,9 +796,11 @@ PR_ExecuteProgram (progs_t * pr, func_t fnum) case OP_CALL6: case OP_CALL7: case OP_CALL8: + PR_RESET_PARAMS (pr); + pr->pr_argc = st->op - OP_CALL0; +op_call: pr->pr_xfunction->profile += profile - startprofile; startprofile = profile; - pr->pr_argc = st->op - OP_CALL0; PR_CallFunction (pr, OPA.func_var); st = pr->pr_statements + pr->pr_xstatement; break; diff --git a/libs/gamecode/engine/pr_opcode.c b/libs/gamecode/engine/pr_opcode.c index 7fc07f451..d81d7d455 100644 --- a/libs/gamecode/engine/pr_opcode.c +++ b/libs/gamecode/engine/pr_opcode.c @@ -822,6 +822,46 @@ opcode_t pr_opcodes[] = { PROG_ID_VERSION, "%Ga", }, + {"", "rcall1", OP_RCALL1, false, + ev_func, ev_void, ev_void, + PROG_ID_VERSION, + "%Ga, %Vb", + }, + {"", "rcall2", OP_RCALL2, false, + ev_func, ev_void, ev_void, + PROG_ID_VERSION, + "%Ga, %Vb, %Vc", + }, + {"", "rcall3", OP_RCALL3, false, + ev_func, ev_void, ev_void, + PROG_ID_VERSION, + "%Ga, %Vb, %Vc", + }, + {"", "rcall4", OP_RCALL4, false, + ev_func, ev_void, ev_void, + PROG_ID_VERSION, + "%Ga, %Vb, %Vc", + }, + {"", "rcall5", OP_RCALL5, false, + ev_func, ev_void, ev_void, + PROG_ID_VERSION, + "%Ga, %Vb, %Vc", + }, + {"", "rcall6", OP_RCALL6, false, + ev_func, ev_void, ev_void, + PROG_ID_VERSION, + "%Ga, %Vb, %Vc", + }, + {"", "rcall7", OP_RCALL7, false, + ev_func, ev_void, ev_void, + PROG_ID_VERSION, + "%Ga, %Vb, %Vc", + }, + {"", "rcall8", OP_RCALL8, false, + ev_func, ev_void, ev_void, + PROG_ID_VERSION, + "%Ga, %Vb, %Vc", + }, {"", "state", OP_STATE, false, ev_float, ev_func, ev_void, @@ -1231,6 +1271,20 @@ PR_Check_Opcodes (progs_t *pr) check_global (pr, st, op, ev_void, st->b); check_global (pr, st, op, ev_void, st->c); break; + case OP_RCALL1: + check_global (pr, st, op, ev_void, st->c); + case OP_RCALL2: + case OP_RCALL3: + case OP_RCALL4: + case OP_RCALL5: + case OP_RCALL6: + case OP_RCALL7: + case OP_RCALL8: + if (st->op > OP_RCALL1) + check_global (pr, st, op, ev_integer, st->c); + check_global (pr, st, op, ev_integer, st->b); + check_global (pr, st, op, ev_func, st->a); + break; case OP_STATE: case OP_STATE_F: if (!state_ok) { diff --git a/libs/gamecode/engine/pr_parse.c b/libs/gamecode/engine/pr_parse.c index 5151136d4..7d31edd9b 100644 --- a/libs/gamecode/engine/pr_parse.c +++ b/libs/gamecode/engine/pr_parse.c @@ -487,6 +487,7 @@ ED_LoadFromFile (progs_t *pr, const char *data) if (pr->edict_parse) { PR_PushFrame (pr); + PR_RESET_PARAMS (pr); P_INT (pr, 0) = PR_SetTempString (pr, data); PR_ExecuteProgram (pr, pr->edict_parse); PR_PopFrame (pr); diff --git a/libs/gamecode/engine/pr_resolve.c b/libs/gamecode/engine/pr_resolve.c index 26d3eab9e..7e6768c7a 100644 --- a/libs/gamecode/engine/pr_resolve.c +++ b/libs/gamecode/engine/pr_resolve.c @@ -138,6 +138,7 @@ PR_ResolveGlobals (progs_t *pr) goto error; pr->pr_param_size = G_INT (pr, def->ofs); } + memcpy (pr->pr_real_params, pr->pr_params, sizeof (pr->pr_params)); if (!pr->globals.time) { if ((def = PR_FindGlobal (pr, "time"))) pr->globals.time = &G_FLOAT (pr, def->ofs); diff --git a/libs/ruamoko/rua_hash.c b/libs/ruamoko/rua_hash.c index 21b65df30..07a68499f 100644 --- a/libs/ruamoko/rua_hash.c +++ b/libs/ruamoko/rua_hash.c @@ -98,6 +98,7 @@ static const char * bi_get_key (void *key, void *_ht) { bi_hashtab_t *ht = (bi_hashtab_t *)_ht; + PR_RESET_PARAMS (ht->pr); P_INT (ht->pr, 0) = (long) (key); P_INT (ht->pr, 1) = ht->ud; PR_ExecuteProgram (ht->pr, ht->gk); @@ -108,6 +109,7 @@ static unsigned long bi_get_hash (void *key, void *_ht) { bi_hashtab_t *ht = (bi_hashtab_t *)_ht; + PR_RESET_PARAMS (ht->pr); P_INT (ht->pr, 0) = (long) (key); P_INT (ht->pr, 1) = ht->ud; PR_ExecuteProgram (ht->pr, ht->gh); @@ -118,6 +120,7 @@ static int bi_compare (void *key1, void *key2, void *_ht) { bi_hashtab_t *ht = (bi_hashtab_t *)_ht; + PR_RESET_PARAMS (ht->pr); P_INT (ht->pr, 0) = (long) (key1); P_INT (ht->pr, 1) = (long) (key2); P_INT (ht->pr, 2) = ht->ud; @@ -129,6 +132,7 @@ static void bi_free (void *key, void *_ht) { bi_hashtab_t *ht = (bi_hashtab_t *)_ht; + PR_RESET_PARAMS (ht->pr); P_INT (ht->pr, 0) = (long) (key); P_INT (ht->pr, 1) = ht->ud; PR_ExecuteProgram (ht->pr, ht->f); diff --git a/libs/ruamoko/rua_obj.c b/libs/ruamoko/rua_obj.c index 1f23de8c1..5d7a1095d 100644 --- a/libs/ruamoko/rua_obj.c +++ b/libs/ruamoko/rua_obj.c @@ -1013,6 +1013,7 @@ rua_obj_msgSend_super (progs_t *pr) PR_GetString (pr, object_get_class_name (pr, self)), PR_GetString (pr, pr->selector_names[_cmd->sel_id])); } + pr->pr_params[0] = pr->pr_real_params[0]; P_POINTER (pr, 0) = super->self; PR_CallFunction (pr, imp); } diff --git a/qw/source/sv_ccmds.c b/qw/source/sv_ccmds.c index 08604c2ea..b77d4270b 100644 --- a/qw/source/sv_ccmds.c +++ b/qw/source/sv_ccmds.c @@ -892,6 +892,7 @@ SV_SetLocalinfo (const char *key, const char *value) *sv_globals.time = sv.time; *sv_globals.self = 0; PR_PushFrame (&sv_pr_state); + PR_RESET_PARAMS (&sv_pr_state); P_STRING (&sv_pr_state, 0) = PR_SetTempString (&sv_pr_state, key); P_STRING (&sv_pr_state, 1) = PR_SetTempString (&sv_pr_state, oldvalue); P_STRING (&sv_pr_state, 2) = PR_SetTempString (&sv_pr_state, value); diff --git a/qw/source/sv_pr_qwe.c b/qw/source/sv_pr_qwe.c index d42809d96..1243dce8d 100644 --- a/qw/source/sv_pr_qwe.c +++ b/qw/source/sv_pr_qwe.c @@ -345,6 +345,7 @@ PF_calltimeofday (progs_t * pr) Sys_TimeOfDay (&date); PR_PushFrame (&sv_pr_state); + PR_RESET_PARAMS (pr); P_FLOAT (pr, 0) = (float) date.sec; P_FLOAT (pr, 1) = (float) date.min; P_FLOAT (pr, 2) = (float) date.hour; diff --git a/qw/source/sv_user.c b/qw/source/sv_user.c index 42914610a..a74e50d7f 100644 --- a/qw/source/sv_user.c +++ b/qw/source/sv_user.c @@ -858,6 +858,7 @@ SV_Say (qboolean team) if (sv_funcs.ChatMessage) { PR_PushFrame (&sv_pr_state); + PR_RESET_PARAMS (&sv_pr_state); P_STRING (&sv_pr_state, 0) = PR_SetTempString (&sv_pr_state, p); G_FLOAT (&sv_pr_state, 1) = (float) team; @@ -1176,6 +1177,7 @@ SV_SetUserinfo (client_t *client, const char *key, const char *value) PR_PushFrame (&sv_pr_state); *sv_globals.time = sv.time; *sv_globals.self = EDICT_TO_PROG (&sv_pr_state, client->edict); + PR_RESET_PARAMS (&sv_pr_state); P_STRING (&sv_pr_state, 0) = PR_SetTempString (&sv_pr_state, key); P_STRING (&sv_pr_state, 1) = PR_SetTempString (&sv_pr_state, oldvalue); P_STRING (&sv_pr_state, 2) = PR_SetTempString (&sv_pr_state, value); @@ -1225,6 +1227,7 @@ SV_SetInfo_f (void *unused) if (sv_funcs.UserInfoCallback) { PR_PushFrame (&sv_pr_state); *sv_globals.self = EDICT_TO_PROG (&sv_pr_state, sv_player); + PR_RESET_PARAMS (&sv_pr_state); P_STRING (&sv_pr_state, 0) = PR_SetTempString (&sv_pr_state, key); P_STRING (&sv_pr_state, 1) = PR_SetTempString (&sv_pr_state, value); PR_ExecuteProgram (&sv_pr_state, sv_funcs.UserInfoCallback); diff --git a/tools/qfcc/TODO b/tools/qfcc/TODO index 64b12d8e0..7ae568e5f 100644 --- a/tools/qfcc/TODO +++ b/tools/qfcc/TODO @@ -25,4 +25,4 @@ o CSE optimizations. Hard? o fix local structure used/uninitialized warnings o arrays in entities/structures? o try to reduce memory consumption -? pass the first two parms in call->b and call->c +X pass the first two parms in call->b and call->c diff --git a/tools/qfcc/source/emit.c b/tools/qfcc/source/emit.c index 820fea67e..947377d2b 100644 --- a/tools/qfcc/source/emit.c +++ b/tools/qfcc/source/emit.c @@ -142,12 +142,8 @@ emit_statement (expr_t *e, opcode_t *op, def_t *var_a, def_t *var_b, statement->b = var_b ? var_b->ofs : 0; if (op->type_c == ev_void || op->right_associative) { // ifs, gotos, and assignments don't need vars allocated - if (op->type_c == ev_void) { - var_c = NULL; - statement->c = 0; - } else { + if (var_c) statement->c = var_c->ofs; - } ret = var_a; } else { // allocate result space if (!var_c) { @@ -205,10 +201,12 @@ emit_function_call (expr_t *e, def_t *dest) def_t *ret; def_t *arg; def_t *p; + def_t *a[2] = {0, 0}; expr_t *earg; expr_t *parm; opcode_t *op; int count = 0, ind; + const char *pref = ""; for (earg = e->e.expr.e2; earg; earg = earg->next) count++; @@ -216,6 +214,11 @@ emit_function_call (expr_t *e, def_t *dest) for (earg = e->e.expr.e2; earg; earg = earg->next) { ind--; parm = new_param_expr (get_type (earg), ind); + if (options.code.progsversion != PROG_ID_VERSION && ind < 2) { + pref = "R"; + a[ind] = emit_sub_expr (earg, emit_sub_expr (parm, 0)); + continue; + } if (extract_type (parm) == ev_struct) { expr_t *a = assign_expr (parm, earg); a->line = e->line; @@ -246,9 +249,9 @@ emit_function_call (expr_t *e, def_t *dest) } } } - op = opcode_find (va ("", count), &type_function, &type_void, - &type_void); - emit_statement (e, op, func, 0, 0); + op = opcode_find (va ("<%sCALL%d>", pref, count), + &type_function, &type_void, &type_void); + emit_statement (e, op, func, a[0], a[1]); ret = emit_sub_expr (new_ret_expr (func->type->aux_type), 0); if (dest) { diff --git a/tools/qwaq/main.c b/tools/qwaq/main.c index a844fd118..9460cb81b 100644 --- a/tools/qwaq/main.c +++ b/tools/qwaq/main.c @@ -174,6 +174,7 @@ main (int argc, char **argv) main_func = dfunc - pr.pr_functions; else PR_Undefined (&pr, "function", "main"); + PR_RESET_PARAMS (&pr); P_INT (&pr, 0) = pr_argc; P_POINTER (&pr, 1) = PR_SetPointer (&pr, pr_argv); PR_ExecuteProgram (&pr, main_func);