X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=prvm_exec.c;h=37daaaa252f19ccf84039862a5c2cd5c9d305c40;hb=HEAD;hp=65ee31b2328a7175f9284c0699a7bb8f5393a6d8;hpb=91efd4d4260983eae86f644ff1813cc391d3c27e;p=xonotic%2Fdarkplaces.git diff --git a/prvm_exec.c b/prvm_exec.c index 65ee31b2..d29aa7f5 100644 --- a/prvm_exec.c +++ b/prvm_exec.c @@ -21,7 +21,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "quakedef.h" #include "progsvm.h" -const char *prvm_opnames[] = +static const char *prvm_opnames[] = { "^5DONE", @@ -107,7 +107,186 @@ const char *prvm_opnames[] = "^2OR", "BITAND", -"BITOR" +"BITOR", + + + + +NULL, +NULL, +NULL, +NULL, +NULL, +NULL, +NULL, +NULL, +NULL, +NULL, +NULL, +NULL, +NULL, +NULL, +NULL, +NULL, +NULL, +NULL, +NULL, +NULL, +NULL, +NULL, +NULL, +NULL, +NULL, +NULL, +NULL, +NULL, +NULL, +NULL, +NULL, +NULL, +NULL, +NULL, +NULL, +NULL, +NULL, +NULL, +NULL, +NULL, +NULL, +NULL, +NULL, +NULL, +NULL, +NULL, +NULL, + +"STORE_I", + +NULL, +NULL, + +"ADD_I", +"ADD_FI", +"ADD_IF", + +"SUB_I", +"SUB_FI", +"SUB_IF", +"CONV_IF", +"CONV_FI", + +NULL, +NULL, + +"LOAD_I", +"STOREP_I", + +NULL, +NULL, + +"BITAND_I", +"BITOR_I", + +"MUL_I", +"DIV_I", +"EQ_I", +"NE_I", + +NULL, +NULL, + +"NOT_I", + +"DIV_VF", + +NULL, +NULL, +NULL, +NULL, +NULL, +NULL, +NULL, +NULL, +NULL, +NULL, +NULL, +NULL, + +"STORE_P", + +NULL, +NULL, +NULL, +NULL, +NULL, +NULL, +NULL, +NULL, + +"LE_I", +"GE_I", +"LT_I", +"GT_I", + +"LE_IF", +"GE_IF", +"LT_IF", +"GT_IF", + +"LE_FI", +"GE_FI", +"LT_FI", +"GT_FI", + +"EQ_IF", +"EQ_FI", + +NULL, +NULL, +NULL, +NULL, + +"MUL_IF", +"MUL_FI", +"MUL_VI", + +NULL, + +"DIV_IF", +"DIV_FI", +"BITAND_IF", +"BITOR_IF", +"BITAND_FI", +"BITOR_FI", +"AND_I", +"OR_I", +"AND_IF", +"OR_IF", +"AND_FI", +"OR_FI", +"NE_IF", +"NE_FI", + +"GSTOREP_I", +"GSTOREP_F", +"GSTOREP_ENT", +"GSTOREP_FLD", +"GSTOREP_S", +"GSTOREP_FNC", +"GSTOREP_V", +"GADDRESS", +"GLOAD_I", +"GLOAD_F", +"GLOAD_FLD", +"GLOAD_ENT", +"GLOAD_S", +"GLOAD_FNC", +"BOUNDCHECK", +NULL, +NULL, +NULL, +NULL, +"GLOAD_V", }; @@ -127,6 +306,7 @@ static void PRVM_PrintStatement(prvm_prog_t *prog, mstatement_t *s) size_t i; int opnum = (int)(s - prog->statements); char valuebuf[MAX_INPUTLINE]; + const char *opname; Con_Printf("s%i: ", opnum); if( prog->statement_linenums ) @@ -140,16 +320,18 @@ static void PRVM_PrintStatement(prvm_prog_t *prog, mstatement_t *s) if (prvm_statementprofiling.integer) Con_Printf("%7.0f ", prog->statement_profile[s - prog->statements]); - if ( (unsigned)s->op < sizeof(prvm_opnames)/sizeof(prvm_opnames[0])) - { - Con_Printf("%s ", prvm_opnames[s->op]); - i = strlen(prvm_opnames[s->op]); - // don't count a preceding color tag when padding the name - if (prvm_opnames[s->op][0] == STRING_COLOR_TAG) - i -= 2; - for ( ; i<10 ; i++) - Con_Print(" "); - } + if ( (unsigned)s->op < sizeof(prvm_opnames)/sizeof(prvm_opnames[0]) && prvm_opnames[s->op]) + opname = prvm_opnames[s->op]; + else + opname = valuebuf, dpsnprintf(valuebuf, sizeof(valuebuf), "OPCODE_%u", (unsigned)s->op); + Con_Printf("%s ", opname); + i = strlen(opname); + // don't count a preceding color tag when padding the name + if (opname[0] == STRING_COLOR_TAG) + i -= 2; + for ( ; i<10 ; i++) + Con_Print(" "); + if (s->operand[0] >= 0) Con_Printf( "%s", PRVM_GlobalString(prog, s->operand[0], valuebuf, sizeof(valuebuf))); if (s->operand[1] >= 0) Con_Printf(", %s", PRVM_GlobalString(prog, s->operand[1], valuebuf, sizeof(valuebuf))); if (s->operand[2] >= 0) Con_Printf(", %s", PRVM_GlobalString(prog, s->operand[2], valuebuf, sizeof(valuebuf))); @@ -199,19 +381,19 @@ PRVM_PrintFunction_f ============ */ -void PRVM_PrintFunction_f (void) +void PRVM_PrintFunction_f(cmd_state_t *cmd) { prvm_prog_t *prog; - if (Cmd_Argc() != 3) + if (Cmd_Argc(cmd) != 3) { Con_Printf("usage: prvm_printfunction \n"); return; } - if (!(prog = PRVM_FriendlyProgFromString(Cmd_Argv(1)))) + if (!(prog = PRVM_FriendlyProgFromString(Cmd_Argv(cmd, 1)))) return; - PRVM_PrintFunctionStatements(prog, Cmd_Argv(2)); + PRVM_PrintFunctionStatements(prog, Cmd_Argv(cmd, 2)); } /* @@ -249,17 +431,19 @@ void PRVM_StackTrace (prvm_prog_t *prog) void PRVM_ShortStackTrace(prvm_prog_t *prog, char *buf, size_t bufsize) { - mfunction_t *f; - int i; + mfunction_t *f; + int i; char vabuf[1024]; + char *p; if(prog) { - dpsnprintf(buf, bufsize, "(%s) ", prog->name); + i = dpsnprintf(buf, bufsize, "(%s) ", prog->name); + p = buf + max(0, i); } else { - strlcpy(buf, "", bufsize); + dp_strlcpy(buf, "", bufsize); return; } @@ -268,13 +452,14 @@ void PRVM_ShortStackTrace(prvm_prog_t *prog, char *buf, size_t bufsize) for (i = prog->depth;i > 0;i--) { f = prog->stack[i].f; - - if(strlcat(buf, + p = dp_stpecpy( + p, + buf + bufsize, f ? va(vabuf, sizeof(vabuf), "%s:%s(%i) ", PRVM_GetString(prog, f->s_file), PRVM_GetString(prog, f->s_name), prog->stack[i].s - f->first_statement) - : " ", - bufsize - ) >= bufsize) + : " " + ); + if (p == buf + bufsize) break; } } @@ -433,16 +618,16 @@ PRVM_CallProfile_f ============ */ -void PRVM_CallProfile_f (void) +void PRVM_CallProfile_f(cmd_state_t *cmd) { prvm_prog_t *prog; - if (Cmd_Argc() != 2) + if (Cmd_Argc(cmd) != 2) { Con_Print("prvm_callprofile \n"); return; } - if (!(prog = PRVM_FriendlyProgFromString(Cmd_Argv(1)))) + if (!(prog = PRVM_FriendlyProgFromString(Cmd_Argv(cmd, 1)))) return; PRVM_CallProfile(prog); @@ -454,7 +639,7 @@ PRVM_Profile_f ============ */ -void PRVM_Profile_f (void) +void PRVM_Profile_f(cmd_state_t *cmd) { prvm_prog_t *prog; int howmany; @@ -466,21 +651,21 @@ void PRVM_Profile_f (void) } howmany = 1<<30; - if (Cmd_Argc() == 3) - howmany = atoi(Cmd_Argv(2)); - else if (Cmd_Argc() != 2) + if (Cmd_Argc(cmd) == 3) + howmany = atoi(Cmd_Argv(cmd, 2)); + else if (Cmd_Argc(cmd) != 2) { Con_Print("prvm_profile \n"); return; } - if (!(prog = PRVM_FriendlyProgFromString(Cmd_Argv(1)))) + if (!(prog = PRVM_FriendlyProgFromString(Cmd_Argv(cmd, 1)))) return; PRVM_Profile(prog, howmany, 0, 0); } -void PRVM_ChildProfile_f (void) +void PRVM_ChildProfile_f(cmd_state_t *cmd) { prvm_prog_t *prog; int howmany; @@ -492,15 +677,15 @@ void PRVM_ChildProfile_f (void) } howmany = 1<<30; - if (Cmd_Argc() == 3) - howmany = atoi(Cmd_Argv(2)); - else if (Cmd_Argc() != 2) + if (Cmd_Argc(cmd) == 3) + howmany = atoi(Cmd_Argv(cmd, 2)); + else if (Cmd_Argc(cmd) != 2) { Con_Print("prvm_childprofile \n"); return; } - if (!(prog = PRVM_FriendlyProgFromString(Cmd_Argv(1)))) + if (!(prog = PRVM_FriendlyProgFromString(Cmd_Argv(cmd, 1)))) return; PRVM_Profile(prog, howmany, 0, 1); @@ -530,37 +715,38 @@ void PRVM_PrintState(prvm_prog_t *prog, int stack_index) } extern cvar_t prvm_errordump; -void PRVM_Crash(prvm_prog_t *prog) +void PRVM_Crash(void) { + prvm_prog_t *prog; char vabuf[1024]; - if (prog == NULL) - return; - if (!prog->loaded) - return; + int i; - PRVM_serverfunction(SV_Shutdown) = 0; // don't call SV_Shutdown on crash + // determine which program crashed + for (i = 0; i < PRVM_PROG_MAX; ++i) + if (PRVM_GetProg(i)->loaded && PRVM_GetProg(i)->depth > 0) + break; + if (i >= PRVM_PROG_MAX) + return; // none of them crashed + prog = PRVM_GetProg(i); - if( prog->depth > 0 ) - { - Con_Printf("QuakeC crash report for %s:\n", prog->name); - PRVM_PrintState(prog, 0); - } + Con_Printf("QuakeC crash report for %s:\n", prog->name); + PRVM_PrintState(prog, 0); - if(prvm_errordump.integer) + // don't call graceful shutdown on crash + if (prog == SVVM_prog) + PRVM_serverfunction(SV_Shutdown) = 0; + else if (prog == CLVM_prog) + PRVM_clientfunction(CSQC_Shutdown) = 0; + + if(prvm_errordump.integer && (prog == SVVM_prog || prog == CLVM_prog)) { // make a savegame - Host_Savegame_to(prog, va(vabuf, sizeof(vabuf), "crash-%s.dmp", prog->name)); + SV_Savegame_to(prog, va(vabuf, sizeof(vabuf), "crash-%s.dmp", prog->name)); } // dump the stack so host_error can shutdown functions prog->depth = 0; prog->localstack_used = 0; - - // delete all tempstrings (FIXME: is this safe in VM->engine->VM recursion?) - prog->tempstringsbuf.cursize = 0; - - // reset the prog pointer - prog = NULL; } /* @@ -716,16 +902,18 @@ static void PRVM_StatementCoverageEvent(prvm_prog_t *prog, mfunction_t *func, in Con_Printf("prvm_coverage: %s just executed a statement at %s for the first time. Coverage: %.2f%%.\n", prog->name, PRVM_WhereAmI(vabuf, sizeof(vabuf), prog, func, statement), prog->statements_covered * 100.0 / prog->numstatements); } -#ifdef __GNUC__ -#define HAVE_COMPUTED_GOTOS 1 +#if defined (__GNUC__) || (__clang__) || (__TINYC__) +# ifndef CONFIG_PEDANTIC +# define HAVE_COMPUTED_GOTOS 1 +# endif #endif -#define OPA ((prvm_eval_t *)&prog->globals.fp[st->operand[0]]) -#define OPB ((prvm_eval_t *)&prog->globals.fp[st->operand[1]]) -#define OPC ((prvm_eval_t *)&prog->globals.fp[st->operand[2]]) +#define OPA ((prvm_eval_t *)&globals[st->operand[0]]) +#define OPB ((prvm_eval_t *)&globals[st->operand[1]]) +#define OPC ((prvm_eval_t *)&globals[st->operand[2]]) extern cvar_t prvm_traceqc; extern cvar_t prvm_statementprofiling; -extern qboolean prvm_runawaycheck; +extern qbool prvm_runawaycheck; #ifdef PROFILING #ifdef CONFIG_MENU @@ -737,7 +925,7 @@ MVM_ExecuteProgram void MVM_ExecuteProgram (prvm_prog_t *prog, func_t fnum, const char *errormessage) { mstatement_t *st, *startst; - mfunction_t *f, *newf; + mfunction_t *func, *enterfunc; prvm_edict_t *ed; prvm_eval_t *ptr; int jumpcount, cachedpr_trace, exitdepth; @@ -746,7 +934,7 @@ void MVM_ExecuteProgram (prvm_prog_t *prog, func_t fnum, const char *errormessag double tm, starttm; prvm_vec_t tempfloat; // these may become out of date when a builtin is called, and are updated accordingly - prvm_vec_t *cached_edictsfields = prog->edictsfields; + prvm_vec_t *cached_edictsfields = prog->edictsfields.fp; unsigned int cached_entityfields = prog->entityfields; unsigned int cached_entityfields_3 = prog->entityfields - 3; unsigned int cached_entityfieldsarea = prog->entityfieldsarea; @@ -756,9 +944,11 @@ void MVM_ExecuteProgram (prvm_prog_t *prog, func_t fnum, const char *errormessag unsigned int cached_max_edicts = prog->max_edicts; // these do not change mstatement_t *cached_statements = prog->statements; - qboolean cached_allowworldwrites = prog->allowworldwrites; + qbool cached_allowworldwrites = prog->allowworldwrites; unsigned int cached_flag = prog->flag; + prvm_vec_t *globals = prog->globals.fp; + calltime = Sys_DirtyTime(); if (!fnum || fnum >= (unsigned int)prog->numfunctions) @@ -768,7 +958,7 @@ void MVM_ExecuteProgram (prvm_prog_t *prog, func_t fnum, const char *errormessag prog->error_cmd("MVM_ExecuteProgram: %s", errormessage); } - f = &prog->functions[fnum]; + func = &prog->functions[fnum]; // after executing this function, delete all tempstrings it created restorevm_tempstringsbuf_cursize = prog->tempstringsbuf.cursize; @@ -779,7 +969,7 @@ void MVM_ExecuteProgram (prvm_prog_t *prog, func_t fnum, const char *errormessag exitdepth = prog->depth; // make a stack frame - st = &prog->statements[PRVM_EnterFunction(prog, f)]; + st = &prog->statements[PRVM_EnterFunction(prog, func)]; // save the starting statement pointer for profiling // (when the function exits or jumps, the (st - startst) integer value is // added to the function's profile counter) @@ -793,7 +983,7 @@ void MVM_ExecuteProgram (prvm_prog_t *prog, func_t fnum, const char *errormessag chooseexecprogram: cachedpr_trace = prog->trace; - if (prvm_statementprofiling.integer || prog->trace || prog->watch_global_type != ev_void || prog->watch_field_type != ev_void || prog->break_statement >= 0 || (prvm_coverage.integer & 4)) + if (prog->trace || prog->watch_global_type != ev_void || prog->watch_field_type != ev_void || prog->break_statement >= 0) { #define PRVMSLOWINTERPRETER 1 if (prvm_timeprofiling.integer) @@ -829,12 +1019,12 @@ cleanup: prog->tempstringsbuf.cursize = restorevm_tempstringsbuf_cursize; tm = Sys_DirtyTime() - calltime;if (tm < 0 || tm >= 1800) tm = 0; - f->totaltime += tm; + func->totaltime += tm; if (prog == SVVM_prog) SV_FlushBroadcastMessages(); } -#endif +#endif // CONFIG_MENU /* ==================== @@ -844,7 +1034,7 @@ CLVM_ExecuteProgram void CLVM_ExecuteProgram (prvm_prog_t *prog, func_t fnum, const char *errormessage) { mstatement_t *st, *startst; - mfunction_t *f, *newf; + mfunction_t *func, *enterfunc; prvm_edict_t *ed; prvm_eval_t *ptr; int jumpcount, cachedpr_trace, exitdepth; @@ -853,7 +1043,7 @@ void CLVM_ExecuteProgram (prvm_prog_t *prog, func_t fnum, const char *errormessa double tm, starttm; prvm_vec_t tempfloat; // these may become out of date when a builtin is called, and are updated accordingly - prvm_vec_t *cached_edictsfields = prog->edictsfields; + prvm_vec_t *cached_edictsfields = prog->edictsfields.fp; unsigned int cached_entityfields = prog->entityfields; unsigned int cached_entityfields_3 = prog->entityfields - 3; unsigned int cached_entityfieldsarea = prog->entityfieldsarea; @@ -863,9 +1053,11 @@ void CLVM_ExecuteProgram (prvm_prog_t *prog, func_t fnum, const char *errormessa unsigned int cached_max_edicts = prog->max_edicts; // these do not change mstatement_t *cached_statements = prog->statements; - qboolean cached_allowworldwrites = prog->allowworldwrites; + qbool cached_allowworldwrites = prog->allowworldwrites; unsigned int cached_flag = prog->flag; + prvm_vec_t *globals = prog->globals.fp; + calltime = Sys_DirtyTime(); if (!fnum || fnum >= (unsigned int)prog->numfunctions) @@ -875,7 +1067,7 @@ void CLVM_ExecuteProgram (prvm_prog_t *prog, func_t fnum, const char *errormessa prog->error_cmd("CLVM_ExecuteProgram: %s", errormessage); } - f = &prog->functions[fnum]; + func = &prog->functions[fnum]; // after executing this function, delete all tempstrings it created restorevm_tempstringsbuf_cursize = prog->tempstringsbuf.cursize; @@ -886,7 +1078,7 @@ void CLVM_ExecuteProgram (prvm_prog_t *prog, func_t fnum, const char *errormessa exitdepth = prog->depth; // make a stack frame - st = &prog->statements[PRVM_EnterFunction(prog, f)]; + st = &prog->statements[PRVM_EnterFunction(prog, func)]; // save the starting statement pointer for profiling // (when the function exits or jumps, the (st - startst) integer value is // added to the function's profile counter) @@ -900,7 +1092,7 @@ void CLVM_ExecuteProgram (prvm_prog_t *prog, func_t fnum, const char *errormessa chooseexecprogram: cachedpr_trace = prog->trace; - if (prvm_statementprofiling.integer || prog->trace || prog->watch_global_type != ev_void || prog->watch_field_type != ev_void || prog->break_statement >= 0 || (prvm_coverage.integer & 4)) + if (prog->trace || prog->watch_global_type != ev_void || prog->watch_field_type != ev_void || prog->break_statement >= 0) { #define PRVMSLOWINTERPRETER 1 if (prvm_timeprofiling.integer) @@ -936,12 +1128,12 @@ cleanup: prog->tempstringsbuf.cursize = restorevm_tempstringsbuf_cursize; tm = Sys_DirtyTime() - calltime;if (tm < 0 || tm >= 1800) tm = 0; - f->totaltime += tm; + func->totaltime += tm; if (prog == SVVM_prog) SV_FlushBroadcastMessages(); } -#endif +#endif // PROFILING /* ==================== @@ -955,7 +1147,7 @@ void PRVM_ExecuteProgram (prvm_prog_t *prog, func_t fnum, const char *errormessa #endif { mstatement_t *st, *startst; - mfunction_t *f, *newf; + mfunction_t *func, *enterfunc; prvm_edict_t *ed; prvm_eval_t *ptr; int jumpcount, cachedpr_trace, exitdepth; @@ -964,7 +1156,7 @@ void PRVM_ExecuteProgram (prvm_prog_t *prog, func_t fnum, const char *errormessa double tm, starttm; prvm_vec_t tempfloat; // these may become out of date when a builtin is called, and are updated accordingly - prvm_vec_t *cached_edictsfields = prog->edictsfields; + prvm_vec_t *cached_edictsfields = prog->edictsfields.fp; unsigned int cached_entityfields = prog->entityfields; unsigned int cached_entityfields_3 = prog->entityfields - 3; unsigned int cached_entityfieldsarea = prog->entityfieldsarea; @@ -974,9 +1166,11 @@ void PRVM_ExecuteProgram (prvm_prog_t *prog, func_t fnum, const char *errormessa unsigned int cached_max_edicts = prog->max_edicts; // these do not change mstatement_t *cached_statements = prog->statements; - qboolean cached_allowworldwrites = prog->allowworldwrites; + qbool cached_allowworldwrites = prog->allowworldwrites; unsigned int cached_flag = prog->flag; + prvm_vec_t *globals = prog->globals.fp; + calltime = Sys_DirtyTime(); if (!fnum || fnum >= (unsigned int)prog->numfunctions) @@ -986,7 +1180,7 @@ void PRVM_ExecuteProgram (prvm_prog_t *prog, func_t fnum, const char *errormessa prog->error_cmd("SVVM_ExecuteProgram: %s", errormessage); } - f = &prog->functions[fnum]; + func = &prog->functions[fnum]; // after executing this function, delete all tempstrings it created restorevm_tempstringsbuf_cursize = prog->tempstringsbuf.cursize; @@ -997,7 +1191,7 @@ void PRVM_ExecuteProgram (prvm_prog_t *prog, func_t fnum, const char *errormessa exitdepth = prog->depth; // make a stack frame - st = &prog->statements[PRVM_EnterFunction(prog, f)]; + st = &prog->statements[PRVM_EnterFunction(prog, func)]; // save the starting statement pointer for profiling // (when the function exits or jumps, the (st - startst) integer value is // added to the function's profile counter) @@ -1011,7 +1205,7 @@ void PRVM_ExecuteProgram (prvm_prog_t *prog, func_t fnum, const char *errormessa chooseexecprogram: cachedpr_trace = prog->trace; - if (prvm_statementprofiling.integer || prog->trace || prog->watch_global_type != ev_void || prog->watch_field_type != ev_void || prog->break_statement >= 0 || (prvm_coverage.integer & 4)) + if (prog->trace || prog->watch_global_type != ev_void || prog->watch_field_type != ev_void || prog->break_statement >= 0) { #define PRVMSLOWINTERPRETER 1 if (prvm_timeprofiling.integer) @@ -1047,7 +1241,7 @@ cleanup: prog->tempstringsbuf.cursize = restorevm_tempstringsbuf_cursize; tm = Sys_DirtyTime() - calltime;if (tm < 0 || tm >= 1800) tm = 0; - f->totaltime += tm; + func->totaltime += tm; if (prog == SVVM_prog) SV_FlushBroadcastMessages();