implement Raven's calling convention (rcall: first 2 params in opb and

opc). should give a general speedup to most progs.
This commit is contained in:
Bill Currie 2005-06-12 09:54:01 +00:00
parent be83a5f5c0
commit 762aefc9b1
17 changed files with 125 additions and 10 deletions

View file

@ -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);

View file

@ -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 {

View file

@ -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

View file

@ -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;

View file

@ -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);

View file

@ -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;

View file

@ -822,6 +822,46 @@ opcode_t pr_opcodes[] = {
PROG_ID_VERSION,
"%Ga",
},
{"<RCALL1>", "rcall1", OP_RCALL1, false,
ev_func, ev_void, ev_void,
PROG_ID_VERSION,
"%Ga, %Vb",
},
{"<RCALL2>", "rcall2", OP_RCALL2, false,
ev_func, ev_void, ev_void,
PROG_ID_VERSION,
"%Ga, %Vb, %Vc",
},
{"<RCALL3>", "rcall3", OP_RCALL3, false,
ev_func, ev_void, ev_void,
PROG_ID_VERSION,
"%Ga, %Vb, %Vc",
},
{"<RCALL4>", "rcall4", OP_RCALL4, false,
ev_func, ev_void, ev_void,
PROG_ID_VERSION,
"%Ga, %Vb, %Vc",
},
{"<RCALL5>", "rcall5", OP_RCALL5, false,
ev_func, ev_void, ev_void,
PROG_ID_VERSION,
"%Ga, %Vb, %Vc",
},
{"<RCALL6>", "rcall6", OP_RCALL6, false,
ev_func, ev_void, ev_void,
PROG_ID_VERSION,
"%Ga, %Vb, %Vc",
},
{"<RCALL7>", "rcall7", OP_RCALL7, false,
ev_func, ev_void, ev_void,
PROG_ID_VERSION,
"%Ga, %Vb, %Vc",
},
{"<RCALL8>", "rcall8", OP_RCALL8, false,
ev_func, ev_void, ev_void,
PROG_ID_VERSION,
"%Ga, %Vb, %Vc",
},
{"<STATE>", "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) {

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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);
}

View file

@ -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);

View file

@ -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;

View file

@ -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);

View file

@ -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

View file

@ -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 ("<CALL%d>", 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) {

View file

@ -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);