DarkPlaces
Game engine based on the Quake 1 engine by id Software, developed by LadyHavoc
 
prvm_exec.c File Reference
#include "quakedef.h"
#include "progsvm.h"
#include "prvm_execprogram.h"
+ Include dependency graph for prvm_exec.c:

Go to the source code of this file.

Macros

#define ADVANCE_PROFILE_BEFORE_JUMP()
 
#define ADVANCE_PROFILE_BEFORE_JUMP()
 
#define ADVANCE_PROFILE_BEFORE_JUMP()
 
#define ADVANCE_PROFILE_BEFORE_JUMP()
 
#define ADVANCE_PROFILE_BEFORE_JUMP()
 
#define ADVANCE_PROFILE_BEFORE_JUMP()
 
#define ADVANCE_PROFILE_BEFORE_JUMP()
 
#define ADVANCE_PROFILE_BEFORE_JUMP()
 
#define CACHE_CHANGING(DECLARE)
 
#define CACHE_UNCHANGING()
 
#define DISPATCH_OPCODE()
 
#define DISPATCH_OPCODE()
 
#define DISPATCH_OPCODE()
 
#define DISPATCH_OPCODE()
 
#define DISPATCH_OPCODE()
 
#define DISPATCH_OPCODE()
 
#define DISPATCH_OPCODE()
 
#define DISPATCH_OPCODE()
 
#define DO_DECLARE(t)
 
#define HANDLE_OPCODE(opcode)
 
#define HANDLE_OPCODE(opcode)
 
#define HANDLE_OPCODE(opcode)
 
#define HANDLE_OPCODE(opcode)
 
#define HANDLE_OPCODE(opcode)
 
#define HANDLE_OPCODE(opcode)
 
#define HANDLE_OPCODE(opcode)
 
#define HANDLE_OPCODE(opcode)
 
#define NO_DECLARE(t)
 
#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]])
 
#define PRE_ERROR()
 
#define PRE_ERROR()
 
#define PRE_ERROR()
 
#define PRE_ERROR()
 
#define PRE_ERROR()
 
#define PRE_ERROR()
 
#define PRE_ERROR()
 
#define PRE_ERROR()
 
#define PRVM_GLOBALSBASE   0x80000000
 
#define PRVMSLOWINTERPRETER   1
 
#define PRVMSLOWINTERPRETER   1
 
#define PRVMTIMEPROFILING   1
 
#define PRVMTIMEPROFILING   1
 
#define PRVMTIMEPROFILING   1
 
#define PRVMTIMEPROFILING   1
 

Functions

void CLVM_ExecuteProgram (prvm_prog_t *prog, func_t fnum, const char *errormessage)
 
static void PRVM_CallProfile (prvm_prog_t *prog)
 
void PRVM_CallProfile_f (cmd_state_t *cmd)
 
void PRVM_ChildProfile_f (cmd_state_t *cmd)
 
void PRVM_Crash (void)
 
static int PRVM_EnterFunction (prvm_prog_t *prog, mfunction_t *f)
 
void PRVM_ExplicitCoverageEvent (prvm_prog_t *prog, mfunction_t *func, int statement)
 
static void PRVM_FunctionCoverageEvent (prvm_prog_t *prog, mfunction_t *func)
 
void PRVM_Init_Exec (prvm_prog_t *prog)
 
static int PRVM_LeaveFunction (prvm_prog_t *prog)
 
void PRVM_PrintFunction_f (cmd_state_t *cmd)
 
void PRVM_PrintFunctionStatements (prvm_prog_t *prog, const char *name)
 
void PRVM_PrintState (prvm_prog_t *prog, int stack_index)
 
static void PRVM_PrintStatement (prvm_prog_t *prog, mstatement_t *s)
 
void PRVM_Profile (prvm_prog_t *prog, int maxfunctions, double mintime, int sortby)
 
void PRVM_Profile_f (cmd_state_t *cmd)
 
void PRVM_ShortStackTrace (prvm_prog_t *prog, char *buf, size_t bufsize)
 
void PRVM_StackTrace (prvm_prog_t *prog)
 
static void PRVM_StatementCoverageEvent (prvm_prog_t *prog, mfunction_t *func, int statement)
 
static const char * PRVM_WhereAmI (char *buf, size_t bufsize, prvm_prog_t *prog, mfunction_t *func, int statement)
 
void SVVM_ExecuteProgram (prvm_prog_t *prog, func_t fnum, const char *errormessage)
 

Variables

cvar_t prvm_coverage
 
cvar_t prvm_errordump
 
cvar_t prvm_gameplayfix_div0is0
 
static const char * prvm_opnames []
 
qbool prvm_runawaycheck
 
cvar_t prvm_statementprofiling
 
cvar_t prvm_timeprofiling
 
cvar_t prvm_traceqc
 

Macro Definition Documentation

◆ ADVANCE_PROFILE_BEFORE_JUMP [1/8]

#define ADVANCE_PROFILE_BEFORE_JUMP ( )
Value:
prog->xfunction->profile += (st - startst); \
/* All statements from startst+1 to st have been hit. */ \
while (++startst <= st) { \
if (prog->statement_profile[startst - cached_statements]++ == 0 && (prvm_coverage.integer & 4)) \
PRVM_StatementCoverageEvent(prog, prog->xfunction, startst - cached_statements); \
} \
/* Observe: startst now is clobbered (now at st+1)! */ \
}
cvar_t prvm_coverage
Definition prvm_edict.c:39
cvar_t prvm_statementprofiling
Definition prvm_exec.c:947
int integer
Definition cvar.h:73

◆ ADVANCE_PROFILE_BEFORE_JUMP [2/8]

#define ADVANCE_PROFILE_BEFORE_JUMP ( )
Value:
prog->xfunction->profile += (st - startst); \
/* All statements from startst+1 to st have been hit. */ \
while (++startst <= st) { \
if (prog->statement_profile[startst - cached_statements]++ == 0 && (prvm_coverage.integer & 4)) \
PRVM_StatementCoverageEvent(prog, prog->xfunction, startst - cached_statements); \
} \
/* Observe: startst now is clobbered (now at st+1)! */ \
}

◆ ADVANCE_PROFILE_BEFORE_JUMP [3/8]

#define ADVANCE_PROFILE_BEFORE_JUMP ( )
Value:
prog->xfunction->profile += (st - startst); \
/* All statements from startst+1 to st have been hit. */ \
while (++startst <= st) { \
if (prog->statement_profile[startst - cached_statements]++ == 0 && (prvm_coverage.integer & 4)) \
PRVM_StatementCoverageEvent(prog, prog->xfunction, startst - cached_statements); \
} \
/* Observe: startst now is clobbered (now at st+1)! */ \
}

◆ ADVANCE_PROFILE_BEFORE_JUMP [4/8]

#define ADVANCE_PROFILE_BEFORE_JUMP ( )
Value:
prog->xfunction->profile += (st - startst); \
/* All statements from startst+1 to st have been hit. */ \
while (++startst <= st) { \
if (prog->statement_profile[startst - cached_statements]++ == 0 && (prvm_coverage.integer & 4)) \
PRVM_StatementCoverageEvent(prog, prog->xfunction, startst - cached_statements); \
} \
/* Observe: startst now is clobbered (now at st+1)! */ \
}

◆ ADVANCE_PROFILE_BEFORE_JUMP [5/8]

#define ADVANCE_PROFILE_BEFORE_JUMP ( )
Value:
prog->xfunction->profile += (st - startst); \
/* All statements from startst+1 to st have been hit. */ \
while (++startst <= st) { \
if (prog->statement_profile[startst - cached_statements]++ == 0 && (prvm_coverage.integer & 4)) \
PRVM_StatementCoverageEvent(prog, prog->xfunction, startst - cached_statements); \
} \
/* Observe: startst now is clobbered (now at st+1)! */ \
}

◆ ADVANCE_PROFILE_BEFORE_JUMP [6/8]

#define ADVANCE_PROFILE_BEFORE_JUMP ( )
Value:
prog->xfunction->profile += (st - startst); \
/* All statements from startst+1 to st have been hit. */ \
while (++startst <= st) { \
if (prog->statement_profile[startst - cached_statements]++ == 0 && (prvm_coverage.integer & 4)) \
PRVM_StatementCoverageEvent(prog, prog->xfunction, startst - cached_statements); \
} \
/* Observe: startst now is clobbered (now at st+1)! */ \
}

◆ ADVANCE_PROFILE_BEFORE_JUMP [7/8]

#define ADVANCE_PROFILE_BEFORE_JUMP ( )
Value:
prog->xfunction->profile += (st - startst); \
/* All statements from startst+1 to st have been hit. */ \
while (++startst <= st) { \
if (prog->statement_profile[startst - cached_statements]++ == 0 && (prvm_coverage.integer & 4)) \
PRVM_StatementCoverageEvent(prog, prog->xfunction, startst - cached_statements); \
} \
/* Observe: startst now is clobbered (now at st+1)! */ \
}

◆ ADVANCE_PROFILE_BEFORE_JUMP [8/8]

#define ADVANCE_PROFILE_BEFORE_JUMP ( )
Value:
prog->xfunction->profile += (st - startst); \
/* All statements from startst+1 to st have been hit. */ \
while (++startst <= st) { \
if (prog->statement_profile[startst - cached_statements]++ == 0 && (prvm_coverage.integer & 4)) \
PRVM_StatementCoverageEvent(prog, prog->xfunction, startst - cached_statements); \
} \
/* Observe: startst now is clobbered (now at st+1)! */ \
}

◆ CACHE_CHANGING

#define CACHE_CHANGING ( DECLARE)
Value:
DECLARE(prvm_vec_t *) cached_edictsfields = prog->edictsfields.fp; \
DECLARE(prvm_vec_t *) cached_edictsfields_entity1 = cached_edictsfields + prog->entityfields; \
DECLARE(unsigned int) cached_entityfieldsarea = prog->entityfieldsarea; \
DECLARE(unsigned int) cached_entityfieldsarea_2 = prog->entityfieldsarea - 2; \
DECLARE(unsigned int) cached_entityfieldsarea_entityfields = prog->entityfieldsarea - prog->entityfields; \
DECLARE(unsigned int) cached_entityfieldsarea_entityfields_2 = prog->entityfieldsarea - prog->entityfields - 2; \
DECLARE(unsigned int) cached_max_edicts = prog->max_edicts
float prvm_vec_t
Definition qtypes.h:55

Definition at line 971 of file prvm_exec.c.

971#define CACHE_CHANGING(DECLARE) \
972 DECLARE(prvm_vec_t *) cached_edictsfields = prog->edictsfields.fp; \
973 DECLARE(prvm_vec_t *) cached_edictsfields_entity1 = cached_edictsfields + prog->entityfields; \
974 DECLARE(unsigned int) cached_entityfieldsarea = prog->entityfieldsarea; \
975 DECLARE(unsigned int) cached_entityfieldsarea_2 = prog->entityfieldsarea - 2; \
976 DECLARE(unsigned int) cached_entityfieldsarea_entityfields = prog->entityfieldsarea - prog->entityfields; \
977 DECLARE(unsigned int) cached_entityfieldsarea_entityfields_2 = prog->entityfieldsarea - prog->entityfields - 2; \
978 DECLARE(unsigned int) cached_max_edicts = prog->max_edicts

Referenced by CLVM_ExecuteProgram(), SVVM_ExecuteProgram(), and while().

◆ CACHE_UNCHANGING

#define CACHE_UNCHANGING ( )
Value:
mstatement_t *cached_statements = prog->statements; \
qbool cached_allowworldwrites = prog->allowworldwrites; \
unsigned int cached_flag = prog->flag; \
unsigned int cached_vmglobals = prog->numglobals; \
unsigned int cached_vmglobals_1 = prog->numglobals - 1; \
unsigned int cached_vmglobals_2 = prog->numglobals - 2; \
unsigned int cached_vmglobals_3 = prog->numglobals - 3; \
unsigned int cached_vmglobal1 = PRVM_GLOBALSBASE + 1; \
unsigned int cached_vmentity0start = PRVM_GLOBALSBASE + prog->numglobals; \
unsigned int cached_vmentity1start = cached_vmentity0start + prog->entityfields; \
unsigned int cached_entityfields = prog->entityfields; \
unsigned int cached_entityfields_2 = prog->entityfields - 2; \
prvm_vec_t *globals = prog->globals.fp; \
prvm_vec_t *global1 = prog->globals.fp + 1
#define PRVM_GLOBALSBASE
Definition prvm_exec.c:951
bool qbool
Definition qtypes.h:9

Definition at line 954 of file prvm_exec.c.

954#define CACHE_UNCHANGING() \
955 mstatement_t *cached_statements = prog->statements; \
956 qbool cached_allowworldwrites = prog->allowworldwrites; \
957 unsigned int cached_flag = prog->flag; \
958 unsigned int cached_vmglobals = prog->numglobals; \
959 unsigned int cached_vmglobals_1 = prog->numglobals - 1; \
960 unsigned int cached_vmglobals_2 = prog->numglobals - 2; \
961 unsigned int cached_vmglobals_3 = prog->numglobals - 3; \
962 unsigned int cached_vmglobal1 = PRVM_GLOBALSBASE + 1; \
963 unsigned int cached_vmentity0start = PRVM_GLOBALSBASE + prog->numglobals; \
964 unsigned int cached_vmentity1start = cached_vmentity0start + prog->entityfields; \
965 unsigned int cached_entityfields = prog->entityfields; \
966 unsigned int cached_entityfields_2 = prog->entityfields - 2; \
967 prvm_vec_t *globals = prog->globals.fp; \
968 prvm_vec_t *global1 = prog->globals.fp + 1

Referenced by CLVM_ExecuteProgram(), and SVVM_ExecuteProgram().

◆ DISPATCH_OPCODE [1/8]

#define DISPATCH_OPCODE ( )
Value:
break

◆ DISPATCH_OPCODE [2/8]

#define DISPATCH_OPCODE ( )
Value:
break

◆ DISPATCH_OPCODE [3/8]

#define DISPATCH_OPCODE ( )
Value:
break

◆ DISPATCH_OPCODE [4/8]

#define DISPATCH_OPCODE ( )
Value:
break

◆ DISPATCH_OPCODE [5/8]

#define DISPATCH_OPCODE ( )
Value:
break

◆ DISPATCH_OPCODE [6/8]

#define DISPATCH_OPCODE ( )
Value:
break

◆ DISPATCH_OPCODE [7/8]

#define DISPATCH_OPCODE ( )
Value:
break

◆ DISPATCH_OPCODE [8/8]

#define DISPATCH_OPCODE ( )
Value:
break

◆ DO_DECLARE

#define DO_DECLARE ( t)
Value:
t

Definition at line 980 of file prvm_exec.c.

Referenced by CLVM_ExecuteProgram(), and SVVM_ExecuteProgram().

◆ HANDLE_OPCODE [1/8]

#define HANDLE_OPCODE ( opcode)
Value:
case opcode

◆ HANDLE_OPCODE [2/8]

#define HANDLE_OPCODE ( opcode)
Value:
case opcode

◆ HANDLE_OPCODE [3/8]

#define HANDLE_OPCODE ( opcode)
Value:
case opcode

◆ HANDLE_OPCODE [4/8]

#define HANDLE_OPCODE ( opcode)
Value:
case opcode

◆ HANDLE_OPCODE [5/8]

#define HANDLE_OPCODE ( opcode)
Value:
case opcode

◆ HANDLE_OPCODE [6/8]

#define HANDLE_OPCODE ( opcode)
Value:
case opcode

◆ HANDLE_OPCODE [7/8]

#define HANDLE_OPCODE ( opcode)
Value:
case opcode

◆ HANDLE_OPCODE [8/8]

#define HANDLE_OPCODE ( opcode)
Value:
case opcode

◆ NO_DECLARE

#define NO_DECLARE ( t)

Definition at line 981 of file prvm_exec.c.

Referenced by while().

◆ OPA

#define OPA   ((prvm_eval_t *)&globals[st->operand[0]])

Definition at line 943 of file prvm_exec.c.

Referenced by while().

◆ OPB

#define OPB   ((prvm_eval_t *)&globals[st->operand[1]])

Definition at line 944 of file prvm_exec.c.

Referenced by while().

◆ OPC

#define OPC   ((prvm_eval_t *)&globals[st->operand[2]])

Definition at line 945 of file prvm_exec.c.

Referenced by while().

◆ PRE_ERROR [1/8]

#define PRE_ERROR ( )
Value:
prog->xstatement = st - cached_statements; \
tm = Sys_DirtyTime(); \
prog->xfunction->tprofile += (tm - starttm >= 0 && tm - starttm < 1800) ? (tm - starttm) : 0; \
startst = st; \
starttm = tm
#define ADVANCE_PROFILE_BEFORE_JUMP()
double Sys_DirtyTime(void)
Definition sys_shared.c:417

◆ PRE_ERROR [2/8]

#define PRE_ERROR ( )
Value:
prog->xstatement = st - cached_statements; \
tm = Sys_DirtyTime(); \
prog->xfunction->tprofile += (tm - starttm >= 0 && tm - starttm < 1800) ? (tm - starttm) : 0; \
startst = st; \
starttm = tm

◆ PRE_ERROR [3/8]

#define PRE_ERROR ( )
Value:
prog->xstatement = st - cached_statements; \
tm = Sys_DirtyTime(); \
prog->xfunction->tprofile += (tm - starttm >= 0 && tm - starttm < 1800) ? (tm - starttm) : 0; \
startst = st; \
starttm = tm

◆ PRE_ERROR [4/8]

#define PRE_ERROR ( )
Value:
prog->xstatement = st - cached_statements; \
tm = Sys_DirtyTime(); \
prog->xfunction->tprofile += (tm - starttm >= 0 && tm - starttm < 1800) ? (tm - starttm) : 0; \
startst = st; \
starttm = tm

◆ PRE_ERROR [5/8]

#define PRE_ERROR ( )
Value:
prog->xstatement = st - cached_statements; \
startst = st

◆ PRE_ERROR [6/8]

#define PRE_ERROR ( )
Value:
prog->xstatement = st - cached_statements; \
startst = st

◆ PRE_ERROR [7/8]

#define PRE_ERROR ( )
Value:
prog->xstatement = st - cached_statements; \
startst = st

◆ PRE_ERROR [8/8]

#define PRE_ERROR ( )
Value:
prog->xstatement = st - cached_statements; \
startst = st

◆ PRVM_GLOBALSBASE

#define PRVM_GLOBALSBASE   0x80000000

Definition at line 951 of file prvm_exec.c.

Referenced by while().

◆ PRVMSLOWINTERPRETER [1/2]

#define PRVMSLOWINTERPRETER   1

◆ PRVMSLOWINTERPRETER [2/2]

#define PRVMSLOWINTERPRETER   1

◆ PRVMTIMEPROFILING [1/4]

#define PRVMTIMEPROFILING   1

◆ PRVMTIMEPROFILING [2/4]

#define PRVMTIMEPROFILING   1

◆ PRVMTIMEPROFILING [3/4]

#define PRVMTIMEPROFILING   1

◆ PRVMTIMEPROFILING [4/4]

#define PRVMTIMEPROFILING   1

Function Documentation

◆ CLVM_ExecuteProgram()

void CLVM_ExecuteProgram ( prvm_prog_t * prog,
func_t fnum,
const char * errormessage )

Definition at line 1086 of file prvm_exec.c.

1087{
1088 mstatement_t *st, *startst;
1089 mfunction_t *func, *enterfunc;
1090 prvm_edict_t *ed;
1091 prvm_eval_t *ptr;
1092 int jumpcount, cachedpr_trace, exitdepth;
1093 int restorevm_tempstringsbuf_cursize;
1094 double calltime;
1095 double tm, starttm;
1096 prvm_vec_t tempfloat;
1099
1100 calltime = Sys_DirtyTime();
1101
1102 if (!fnum || fnum >= (unsigned int)prog->numfunctions)
1103 {
1106 prog->error_cmd("CLVM_ExecuteProgram: %s", errormessage);
1107 }
1108
1109 func = &prog->functions[fnum];
1110
1111 // after executing this function, delete all tempstrings it created
1112 restorevm_tempstringsbuf_cursize = prog->tempstringsbuf.cursize;
1113
1114 prog->trace = prvm_traceqc.integer;
1115
1116 // we know we're done when pr_depth drops to this
1117 exitdepth = prog->depth;
1118
1119// make a stack frame
1120 st = &prog->statements[PRVM_EnterFunction(prog, func)];
1121 // save the starting statement pointer for profiling
1122 // (when the function exits or jumps, the (st - startst) integer value is
1123 // added to the function's profile counter)
1124 startst = st;
1125 starttm = calltime;
1126 // instead of counting instructions, we count jumps
1127 jumpcount = 0;
1128 // add one to the callcount of this function because otherwise engine-called functions aren't counted
1129 if (prog->xfunction->callcount++ == 0 && (prvm_coverage.integer & 1))
1131
1132chooseexecprogram:
1133 cachedpr_trace = prog->trace;
1134 if (prog->trace || prog->watch_global_type != ev_void || prog->watch_field_type != ev_void || prog->break_statement >= 0)
1135 {
1136#define PRVMSLOWINTERPRETER 1
1138 {
1139#define PRVMTIMEPROFILING 1
1140#include "prvm_execprogram.h"
1141#undef PRVMTIMEPROFILING
1142 }
1143 else
1144 {
1145#include "prvm_execprogram.h"
1146 }
1147#undef PRVMSLOWINTERPRETER
1148 }
1149 else
1150 {
1152 {
1153#define PRVMTIMEPROFILING 1
1154#include "prvm_execprogram.h"
1155#undef PRVMTIMEPROFILING
1156 }
1157 else
1158 {
1159#include "prvm_execprogram.h"
1160 }
1161 }
1162
1163cleanup:
1164 if (developer_insane.integer && prog->tempstringsbuf.cursize > restorevm_tempstringsbuf_cursize)
1165 Con_DPrintf("CLVM_ExecuteProgram: %s used %i bytes of tempstrings\n", PRVM_GetString(prog, prog->functions[fnum].s_name), prog->tempstringsbuf.cursize - restorevm_tempstringsbuf_cursize);
1166 // delete tempstrings created by this function
1167 prog->tempstringsbuf.cursize = restorevm_tempstringsbuf_cursize;
1168
1169 tm = Sys_DirtyTime() - calltime;if (tm < 0 || tm >= 1800) tm = 0;
1170 func->totaltime += tm;
1171
1172 if (prog == SVVM_prog)
1174}
void Con_DPrintf(const char *fmt,...)
A Con_Printf that only shows up if the "developer" cvar is set.
Definition console.c:1544
entity self
cvar_t developer_insane
Definition host.c:50
@ ev_void
Definition pr_comp.h:29
const char * PRVM_GetString(prvm_prog_t *prog, int num)
#define PRVM_PROG_TO_EDICT(n)
Definition progsvm.h:877
#define PRVM_allglobaledict(fieldname)
Definition progsvm.h:144
void PRVM_ED_Print(prvm_prog_t *prog, prvm_edict_t *ed, const char *wildcard_fieldname)
Definition prvm_edict.c:657
#define SVVM_prog
Definition progsvm.h:766
#define CACHE_UNCHANGING()
Definition prvm_exec.c:954
cvar_t prvm_timeprofiling
Definition prvm_edict.c:38
#define CACHE_CHANGING(DECLARE)
Definition prvm_exec.c:971
static void PRVM_FunctionCoverageEvent(prvm_prog_t *prog, mfunction_t *func)
Definition prvm_exec.c:919
static int PRVM_EnterFunction(prvm_prog_t *prog, mfunction_t *f)
Definition prvm_exec.c:799
#define DO_DECLARE(t)
Definition prvm_exec.c:980
cvar_t prvm_traceqc
Definition prvm_edict.c:35
#define NULL
Definition qtypes.h:12
void SV_FlushBroadcastMessages(void)
Definition sv_send.c:1371
double callcount
Definition pr_comp.h:453
int32_t s_name
Definition pr_comp.h:460
double totaltime
Definition pr_comp.h:454
mfunction_t * functions
Definition progsvm.h:541
void(* error_cmd)(const char *format,...) DP_FUNC_PRINTF(1) DP_FUNC_NORETURN
[INIT]
Definition progsvm.h:747
etype_t watch_field_type
Definition progsvm.h:617
int numfunctions
Definition progsvm.h:566
int break_statement
Definition progsvm.h:610
etype_t watch_global_type
Definition progsvm.h:613
mstatement_t * statements
Definition progsvm.h:547
sizebuf_t tempstringsbuf
buffer for storing all tempstrings created during one invocation of ExecuteProgram
Definition progsvm.h:644
mfunction_t * xfunction
Definition progsvm.h:620
int cursize
Definition common.h:54

References prvm_prog_t::break_statement, CACHE_CHANGING, CACHE_UNCHANGING, mfunction_t::callcount, Con_DPrintf(), sizebuf_t::cursize, prvm_prog_t::depth, developer_insane, DO_DECLARE, prvm_prog_t::error_cmd, ev_void, prvm_prog_t::functions, cvar_t::integer, NULL, prvm_prog_t::numfunctions, PRVM_allglobaledict, prvm_coverage, PRVM_ED_Print(), PRVM_EnterFunction(), PRVM_FunctionCoverageEvent(), PRVM_GetString(), PRVM_PROG_TO_EDICT, prvm_timeprofiling, prvm_traceqc, mfunction_t::s_name, self, prvm_prog_t::statements, SV_FlushBroadcastMessages(), SVVM_prog, Sys_DirtyTime(), prvm_prog_t::tempstringsbuf, mfunction_t::totaltime, prvm_prog_t::trace, prvm_prog_t::watch_field_type, prvm_prog_t::watch_global_type, and prvm_prog_t::xfunction.

Referenced by CL_VM_Init().

◆ PRVM_CallProfile()

static void PRVM_CallProfile ( prvm_prog_t * prog)
static

Definition at line 500 of file prvm_exec.c.

501{
502 mfunction_t *f, *best;
503 int i;
504 double max;
505 double sum;
506 double newprofiletime;
507
508 Con_Printf( "%s Call Profile:\n", prog->name );
509
510 sum = 0;
511 do
512 {
513 max = 0;
514 best = NULL;
515 for (i=0 ; i<prog->numfunctions ; i++)
516 {
517 f = &prog->functions[i];
518 if (max < f->totaltime)
519 {
520 max = f->totaltime;
521 best = f;
522 }
523 }
524 if (best)
525 {
526 sum += best->totaltime;
527 Con_Printf("%9.4f %s\n", best->totaltime, PRVM_GetString(prog, best->s_name));
528 best->totaltime = 0;
529 }
530 } while (best);
531
532 newprofiletime = Sys_DirtyTime();
533 Con_Printf("Total time since last profile reset: %9.4f\n", newprofiletime - prog->profiletime);
534 Con_Printf(" - used by QC code of this VM: %9.4f\n", sum);
535
536 prog->profiletime = newprofiletime;
537}
void Con_Printf(const char *fmt,...)
Prints to all appropriate console targets.
Definition console.c:1514
#define max(A, B)
Definition mathlib.h:38
int i
float f
const char * name
name of the prog, e.g. "Server", "Client" or "Menu" (used for text output)
Definition progsvm.h:700
double profiletime
system time when last PRVM_CallProfile was called (or PRVM_Prog_Load initially)
Definition progsvm.h:540

References Con_Printf(), f, prvm_prog_t::functions, i, max, prvm_prog_t::name, NULL, prvm_prog_t::numfunctions, prvm_prog_t::profiletime, PRVM_GetString(), mfunction_t::s_name, Sys_DirtyTime(), and mfunction_t::totaltime.

Referenced by PRVM_CallProfile_f().

◆ PRVM_CallProfile_f()

void PRVM_CallProfile_f ( cmd_state_t * cmd)

Definition at line 653 of file prvm_exec.c.

654{
655 prvm_prog_t *prog;
656 if (Cmd_Argc(cmd) != 2)
657 {
658 Con_Print("prvm_callprofile <program name>\n");
659 return;
660 }
661
662 if (!(prog = PRVM_FriendlyProgFromString(Cmd_Argv(cmd, 1))))
663 return;
664
665 PRVM_CallProfile(prog);
666}
static int Cmd_Argc(cmd_state_t *cmd)
Definition cmd.h:249
static const char * Cmd_Argv(cmd_state_t *cmd, int arg)
Cmd_Argv(cmd, ) will return an empty string (not a NULL) if arg > argc, so string operations are alwa...
Definition cmd.h:254
void Con_Print(const char *msg)
Prints to all appropriate console targets, and adds timestamps.
Definition console.c:1504
void cmd(string command,...)
prvm_prog_t * PRVM_FriendlyProgFromString(const char *str)
for console commands (prints error if name unknown and returns NULL, prints error if prog not loaded ...
Definition prvm_edict.c:184
static void PRVM_CallProfile(prvm_prog_t *prog)
Definition prvm_exec.c:500

References cmd(), Cmd_Argc(), Cmd_Argv(), Con_Print(), PRVM_CallProfile(), and PRVM_FriendlyProgFromString().

◆ PRVM_ChildProfile_f()

void PRVM_ChildProfile_f ( cmd_state_t * cmd)

Definition at line 700 of file prvm_exec.c.

701{
702 prvm_prog_t *prog;
703 int howmany;
704
705 if (prvm_coverage.integer & 1)
706 {
707 Con_Printf("Collecting function coverage, cannot profile - sorry!\n");
708 return;
709 }
710
711 howmany = 1<<30;
712 if (Cmd_Argc(cmd) == 3)
713 howmany = atoi(Cmd_Argv(cmd, 2));
714 else if (Cmd_Argc(cmd) != 2)
715 {
716 Con_Print("prvm_childprofile <program name>\n");
717 return;
718 }
719
720 if (!(prog = PRVM_FriendlyProgFromString(Cmd_Argv(cmd, 1))))
721 return;
722
723 PRVM_Profile(prog, howmany, 0, 1);
724}
void PRVM_Profile(prvm_prog_t *prog, int maxfunctions, double mintime, int sortby)
Definition prvm_exec.c:539

References cmd(), Cmd_Argc(), Cmd_Argv(), Con_Print(), Con_Printf(), cvar_t::integer, prvm_coverage, PRVM_FriendlyProgFromString(), and PRVM_Profile().

◆ PRVM_Crash()

void PRVM_Crash ( void )

Definition at line 750 of file prvm_exec.c.

751{
752 prvm_prog_t *prog;
753 char vabuf[1024];
754 int i;
755
756 // determine which program crashed
757 for (i = 0; i < PRVM_PROG_MAX; ++i)
758 if (PRVM_GetProg(i)->loaded && PRVM_GetProg(i)->depth > 0)
759 break;
760 if (i >= PRVM_PROG_MAX)
761 return; // none of them crashed
762 prog = PRVM_GetProg(i);
763
764 Con_Printf("QuakeC crash report for %s:\n", prog->name);
765 PRVM_PrintState(prog, 0);
766
767 // don't call graceful shutdown on crash
768 if (prog == SVVM_prog)
770 else if (prog == CLVM_prog)
772
773 if(prvm_errordump.integer && (prog == SVVM_prog || prog == CLVM_prog))
774 {
775 // make a savegame
776 SV_Savegame_to(prog, va(vabuf, sizeof(vabuf), "crash-%s.dmp", prog->name));
777 }
778
779 // dump the stack so host_error can shutdown functions
780 // and free memory, unset prog->loaded, etc
781 PRVM_Prog_Reset(prog);
782}
char * va(char *buf, size_t buflen, const char *format,...)
Definition common.c:972
void CSQC_Shutdown()
GLint GLenum GLsizei GLsizei GLsizei depth
Definition glquake.h:648
#define PRVM_clientfunction(funcname)
Definition progsvm.h:194
#define CLVM_prog
Definition progsvm.h:767
@ PRVM_PROG_MAX
Definition progsvm.h:757
void PRVM_Prog_Reset(prvm_prog_t *prog)
#define PRVM_serverfunction(funcname)
Definition progsvm.h:182
#define PRVM_GetProg(n)
Definition progsvm.h:764
void PRVM_PrintState(prvm_prog_t *prog, int stack_index)
Definition prvm_exec.c:726
cvar_t prvm_errordump
Definition prvm_edict.c:44
void SV_Savegame_to(prvm_prog_t *prog, const char *name)
Definition sv_save.c:35
void SV_Shutdown(void)
Definition sv_main.c:2128

References CLVM_prog, Con_Printf(), CSQC_Shutdown(), depth, i, cvar_t::integer, prvm_prog_t::name, PRVM_clientfunction, prvm_errordump, PRVM_GetProg, PRVM_PrintState(), PRVM_PROG_MAX, PRVM_Prog_Reset(), PRVM_serverfunction, SV_Savegame_to(), SV_Shutdown(), SVVM_prog, and va().

Referenced by Host_Error(), and MVM_error_cmd().

◆ PRVM_EnterFunction()

static int PRVM_EnterFunction ( prvm_prog_t * prog,
mfunction_t * f )
static

Definition at line 799 of file prvm_exec.c.

800{
801 int i, j, c, o;
802
803 if (!f)
804 prog->error_cmd("PRVM_EnterFunction: NULL function in %s", prog->name);
805
806 prog->stack[prog->depth].s = prog->xstatement;
807 prog->stack[prog->depth].f = prog->xfunction;
808 prog->stack[prog->depth].profile_acc = -f->profile;
809 prog->stack[prog->depth].tprofile_acc = -f->tprofile + -f->tbprofile;
810 prog->stack[prog->depth].builtinsprofile_acc = -f->builtinsprofile;
811 prog->depth++;
812 if (prog->depth >=PRVM_MAX_STACK_DEPTH)
813 prog->error_cmd("stack overflow");
814
815// save off any locals that the new function steps on
816 c = f->locals;
818 prog->error_cmd("PRVM_ExecuteProgram: locals stack overflow in %s", prog->name);
819
820 for (i=0 ; i < c ; i++)
821 prog->localstack[prog->localstack_used+i] = prog->globals.ip[f->parm_start + i];
822 prog->localstack_used += c;
823
824// copy parameters
825 o = f->parm_start;
826 for (i=0 ; i<f->numparms ; i++)
827 {
828 for (j=0 ; j<f->parm_size[i] ; j++)
829 {
830 prog->globals.ip[o] = prog->globals.ip[OFS_PARM0+i*3+j];
831 o++;
832 }
833 }
834
835 ++f->recursion;
836 prog->xfunction = f;
837 return f->first_statement - 1; // offset the s++
838}
#define OFS_PARM0
Definition pr_comp.h:34
#define PRVM_MAX_STACK_DEPTH
Definition progsvm.h:248
#define PRVM_LOCALSTACK_SIZE
Definition progsvm.h:249
prvm_int_t * ip
Definition progsvm.h:581
int localstack_used
Definition progsvm.h:629
prvm_stack_t stack[PRVM_MAX_STACK_DEPTH+1]
stacktrace writes into stack[MAX_STACK_DEPTH] thus increase the array, so depth wont be overwritten
Definition progsvm.h:625
prvm_int_t localstack[PRVM_LOCALSTACK_SIZE]
Definition progsvm.h:628
int xstatement
Definition progsvm.h:621
union prvm_prog_t::@31 globals
double tprofile_acc
Definition progsvm.h:54
mfunction_t * f
Definition progsvm.h:53
double profile_acc
Definition progsvm.h:55
double builtinsprofile_acc
Definition progsvm.h:56

References prvm_stack_t::builtinsprofile_acc, prvm_prog_t::depth, prvm_prog_t::error_cmd, f, prvm_stack_t::f, prvm_prog_t::globals, i, prvm_prog_t::ip, prvm_prog_t::localstack, prvm_prog_t::localstack_used, prvm_prog_t::name, OFS_PARM0, prvm_stack_t::profile_acc, PRVM_LOCALSTACK_SIZE, PRVM_MAX_STACK_DEPTH, prvm_stack_t::s, prvm_prog_t::stack, prvm_stack_t::tprofile_acc, prvm_prog_t::xfunction, and prvm_prog_t::xstatement.

Referenced by CLVM_ExecuteProgram(), SVVM_ExecuteProgram(), and while().

◆ PRVM_ExplicitCoverageEvent()

void PRVM_ExplicitCoverageEvent ( prvm_prog_t * prog,
mfunction_t * func,
int statement )

Definition at line 924 of file prvm_exec.c.

925{
926 char vabuf[128];
927 ++prog->explicit_covered;
928 Con_Printf("prvm_coverage: %s just executed a coverage() statement at %s for the first time. Coverage: %.2f%%.\n", prog->name, PRVM_WhereAmI(vabuf, sizeof(vabuf), prog, func, statement), prog->explicit_covered * 100.0 / prog->numexplicitcoveragestatements);
929}
static const char * PRVM_WhereAmI(char *buf, size_t bufsize, prvm_prog_t *prog, mfunction_t *func, int statement)
Definition prvm_exec.c:907
int explicit_covered
Definition progsvm.h:576
int numexplicitcoveragestatements
Definition progsvm.h:577

References Con_Printf(), prvm_prog_t::explicit_covered, prvm_prog_t::name, prvm_prog_t::numexplicitcoveragestatements, and PRVM_WhereAmI().

Referenced by VM_coverage().

◆ PRVM_FunctionCoverageEvent()

static void PRVM_FunctionCoverageEvent ( prvm_prog_t * prog,
mfunction_t * func )
static

Definition at line 919 of file prvm_exec.c.

920{
921 ++prog->functions_covered;
922 Con_Printf("prvm_coverage: %s just called %s for the first time. Coverage: %.2f%%.\n", prog->name, PRVM_GetString(prog, func->s_name), prog->functions_covered * 100.0 / prog->numfunctions);
923}
int functions_covered
Definition progsvm.h:542

References Con_Printf(), prvm_prog_t::functions_covered, prvm_prog_t::name, prvm_prog_t::numfunctions, PRVM_GetString(), and mfunction_t::s_name.

Referenced by CLVM_ExecuteProgram(), SVVM_ExecuteProgram(), and while().

◆ PRVM_Init_Exec()

void PRVM_Init_Exec ( prvm_prog_t * prog)

Definition at line 892 of file prvm_exec.c.

893{
894 // dump the stack
895 prog->depth = 0;
896 prog->localstack_used = 0;
897 // reset the string table
898 // nothing here yet
899}

References prvm_prog_t::depth, and prvm_prog_t::localstack_used.

Referenced by PRVM_Prog_Load().

◆ PRVM_LeaveFunction()

static int PRVM_LeaveFunction ( prvm_prog_t * prog)
static

Definition at line 845 of file prvm_exec.c.

846{
847 int i, c;
848 mfunction_t *f;
849
850 if (prog->depth <= 0)
851 prog->error_cmd("prog stack underflow in %s", prog->name);
852
853 if (!prog->xfunction)
854 prog->error_cmd("PR_LeaveFunction: NULL function in %s", prog->name);
855// restore locals from the stack
856 c = prog->xfunction->locals;
857 prog->localstack_used -= c;
858 if (prog->localstack_used < 0)
859 prog->error_cmd("PRVM_ExecuteProgram: locals stack underflow in %s", prog->name);
860
861 for (i=0 ; i < c ; i++)
862 prog->globals.ip[prog->xfunction->parm_start + i] = prog->localstack[prog->localstack_used+i];
863
864// up stack
865 prog->depth--;
866 f = prog->xfunction;
867 --f->recursion;
868 prog->xfunction = prog->stack[prog->depth].f;
869 prog->stack[prog->depth].profile_acc += f->profile;
870 prog->stack[prog->depth].tprofile_acc += f->tprofile + f->tbprofile;
871 prog->stack[prog->depth].builtinsprofile_acc += f->builtinsprofile;
872 if(prog->depth > 0)
873 {
874 prog->stack[prog->depth-1].profile_acc += prog->stack[prog->depth].profile_acc;
875 prog->stack[prog->depth-1].tprofile_acc += prog->stack[prog->depth].tprofile_acc;
876 prog->stack[prog->depth-1].builtinsprofile_acc += prog->stack[prog->depth].builtinsprofile_acc;
877 }
878 if(!f->recursion)
879 {
880 // if f is already on the call stack...
881 // we cannot add this profile data to it now
882 // or we would add it more than once
883 // so, let's only add to the function's profile if it is the outermost call
884 f->profile_total += prog->stack[prog->depth].profile_acc;
885 f->tprofile_total += prog->stack[prog->depth].tprofile_acc;
886 f->builtinsprofile_total += prog->stack[prog->depth].builtinsprofile_acc;
887 }
888
889 return prog->stack[prog->depth].s;
890}
int32_t locals
Definition pr_comp.h:446
int32_t parm_start
Definition pr_comp.h:445

References prvm_stack_t::builtinsprofile_acc, prvm_prog_t::depth, prvm_prog_t::error_cmd, f, prvm_stack_t::f, prvm_prog_t::globals, i, prvm_prog_t::ip, mfunction_t::locals, prvm_prog_t::localstack, prvm_prog_t::localstack_used, prvm_prog_t::name, mfunction_t::parm_start, prvm_stack_t::profile_acc, prvm_stack_t::s, prvm_prog_t::stack, prvm_stack_t::tprofile_acc, and prvm_prog_t::xfunction.

Referenced by while().

◆ PRVM_PrintFunction_f()

void PRVM_PrintFunction_f ( cmd_state_t * cmd)

Definition at line 416 of file prvm_exec.c.

417{
418 prvm_prog_t *prog;
419 if (Cmd_Argc(cmd) != 3)
420 {
421 Con_Printf("usage: prvm_printfunction <program name> <function name>\n");
422 return;
423 }
424
425 if (!(prog = PRVM_FriendlyProgFromString(Cmd_Argv(cmd, 1))))
426 return;
427
429}
void PRVM_PrintFunctionStatements(prvm_prog_t *prog, const char *name)
Definition prvm_exec.c:374

References cmd(), Cmd_Argc(), Cmd_Argv(), Con_Printf(), PRVM_FriendlyProgFromString(), and PRVM_PrintFunctionStatements().

◆ PRVM_PrintFunctionStatements()

void PRVM_PrintFunctionStatements ( prvm_prog_t * prog,
const char * name )

Definition at line 374 of file prvm_exec.c.

375{
376 int i, firststatement, endstatement;
377 mfunction_t *func;
378 func = PRVM_ED_FindFunction (prog, name);
379 if (!func)
380 {
381 Con_Printf("%s progs: no function named %s\n", prog->name, name);
382 return;
383 }
384 firststatement = func->first_statement;
385 if (firststatement < 0)
386 {
387 Con_Printf("%s progs: function %s is builtin #%i\n", prog->name, name, -firststatement);
388 return;
389 }
390
391 // find the end statement
392 endstatement = prog->numstatements;
393 for (i = 0;i < prog->numfunctions;i++)
394 if (endstatement > prog->functions[i].first_statement && firststatement < prog->functions[i].first_statement)
395 endstatement = prog->functions[i].first_statement;
396
397 // now print the range of statements
398 Con_Printf("%s progs: disassembly of function %s (statements %i-%i, locals %i-%i):\n", prog->name, name, firststatement, endstatement, func->parm_start, func->parm_start + func->locals - 1);
399 prog->xfunction = func;
400 for (i = firststatement;i < endstatement;i++)
401 {
402 PRVM_PrintStatement(prog, prog->statements + i);
403 if (!(prvm_coverage.integer & 4))
404 prog->statement_profile[i] = 0;
405 }
406 if (prvm_coverage.integer & 4)
407 Con_Printf("Collecting statement coverage, not flushing statement profile.\n");
408}
const GLchar * name
Definition glquake.h:601
mfunction_t * PRVM_ED_FindFunction(prvm_prog_t *prog, const char *name)
Definition prvm_edict.c:425
static void PRVM_PrintStatement(prvm_prog_t *prog, mstatement_t *s)
Definition prvm_exec.c:329
int32_t first_statement
Definition pr_comp.h:444
double * statement_profile
only incremented if prvm_statementprofiling is on
Definition progsvm.h:573
int numstatements
Definition progsvm.h:563

References Con_Printf(), mfunction_t::first_statement, prvm_prog_t::functions, i, cvar_t::integer, mfunction_t::locals, name, prvm_prog_t::name, prvm_prog_t::numfunctions, prvm_prog_t::numstatements, mfunction_t::parm_start, prvm_coverage, PRVM_ED_FindFunction(), PRVM_PrintStatement(), prvm_prog_t::statement_profile, prvm_prog_t::statements, and prvm_prog_t::xfunction.

Referenced by PRVM_PrintFunction_f().

◆ PRVM_PrintState()

void PRVM_PrintState ( prvm_prog_t * prog,
int stack_index )

Definition at line 726 of file prvm_exec.c.

727{
728 int i;
729 mfunction_t *func = prog->xfunction;
730 int st = prog->xstatement;
731 if (stack_index > 0 && stack_index <= prog->depth)
732 {
733 func = prog->stack[prog->depth - stack_index].f;
734 st = prog->stack[prog->depth - stack_index].s;
735 }
736 if (prog->statestring)
737 {
738 Con_Printf("Caller-provided information: %s\n", prog->statestring);
739 }
740 if (func)
741 {
742 for (i = -7; i <= 0;i++)
743 if (st + i >= func->first_statement)
744 PRVM_PrintStatement(prog, prog->statements + st + i);
745 }
746 PRVM_StackTrace(prog);
747}
void PRVM_StackTrace(prvm_prog_t *prog)
Definition prvm_exec.c:436
const char * statestring
printed together with backtraces
Definition progsvm.h:717

References Con_Printf(), depth, prvm_prog_t::depth, prvm_stack_t::f, mfunction_t::first_statement, i, PRVM_PrintStatement(), PRVM_StackTrace(), prvm_stack_t::s, prvm_prog_t::stack, prvm_prog_t::statements, prvm_prog_t::statestring, prvm_prog_t::xfunction, and prvm_prog_t::xstatement.

Referenced by PRVM_Breakpoint(), PRVM_Crash(), and VM_Warning().

◆ PRVM_PrintStatement()

static void PRVM_PrintStatement ( prvm_prog_t * prog,
mstatement_t * s )
static

Definition at line 329 of file prvm_exec.c.

330{
331 size_t i;
332 int opnum = (int)(s - prog->statements);
333 char valuebuf[MAX_INPUTLINE];
334 const char *opname;
335
336 Con_Printf("s%i: ", opnum);
337 if( prog->statement_linenums )
338 {
339 if ( prog->statement_columnnums )
340 Con_Printf( "%s:%i:%i: ", PRVM_GetString( prog, prog->xfunction->s_file ), prog->statement_linenums[ opnum ], prog->statement_columnnums[ opnum ] );
341 else
342 Con_Printf( "%s:%i: ", PRVM_GetString( prog, prog->xfunction->s_file ), prog->statement_linenums[ opnum ] );
343 }
344
346 Con_Printf("%7.0f ", prog->statement_profile[s - prog->statements]);
347
348 if ( (unsigned)s->op < sizeof(prvm_opnames)/sizeof(prvm_opnames[0]) && prvm_opnames[s->op])
349 opname = prvm_opnames[s->op];
350 else
351 opname = valuebuf, dpsnprintf(valuebuf, sizeof(valuebuf), "OPCODE_%u", (unsigned)s->op);
352 Con_Printf("%s ", opname);
353 i = strlen(opname);
354 // don't count a preceding color tag when padding the name
355 if (opname[0] == STRING_COLOR_TAG)
356 i -= 2;
357 for ( ; i<10 ; i++)
358 Con_Print(" ");
359
360 if (s->op == OP_GOTO) {
361 Con_Printf("statement %i", (int)(s - prog->statements) + s->operand[0]);
362 } else {
363 if (s->operand[0] >= 0) Con_Printf( "%s", PRVM_GlobalString(prog, s->operand[0], valuebuf, sizeof(valuebuf)));
364 }
365 if (s->op == OP_IF || s->op == OP_IFNOT) {
366 Con_Printf(", statement %i", (int)(s - prog->statements) + s->operand[1]);
367 } else {
368 if (s->operand[1] >= 0) Con_Printf(", %s", PRVM_GlobalString(prog, s->operand[1], valuebuf, sizeof(valuebuf)));
369 }
370 if (s->operand[2] >= 0) Con_Printf(", %s", PRVM_GlobalString(prog, s->operand[2], valuebuf, sizeof(valuebuf)));
371 Con_Print("\n");
372}
int dpsnprintf(char *buffer, size_t buffersize, const char *format,...)
Returns the number of printed characters, excluding the final '\0' or returns -1 if the buffer isn't ...
Definition common.c:997
#define STRING_COLOR_TAG
Definition draw.h:140
static int(ZEXPORT *qz_inflate)(z_stream *strm
float strlen(string s)
@ OP_IF
Definition pr_comp.h:104
@ OP_GOTO
Definition pr_comp.h:116
@ OP_IFNOT
Definition pr_comp.h:105
char * PRVM_GlobalString(prvm_prog_t *prog, int ofs, char *line, size_t linelength)
Definition prvm_edict.c:602
static const char * prvm_opnames[]
Definition prvm_exec.c:27
#define MAX_INPUTLINE
maximum size of console commandline, QuakeC strings, and many other text processing buffers
Definition qdefs.h:94
int32_t s_file
Definition pr_comp.h:461
opcode_t op
Definition pr_comp.h:470
int operand[3]
Definition pr_comp.h:471
int * statement_linenums
NULL if not available.
Definition progsvm.h:570
int * statement_columnnums
NULL if not available.
Definition progsvm.h:571

References Con_Print(), Con_Printf(), dpsnprintf(), i, int(), cvar_t::integer, MAX_INPUTLINE, mstatement_t::op, OP_GOTO, OP_IF, OP_IFNOT, mstatement_t::operand, PRVM_GetString(), PRVM_GlobalString(), prvm_opnames, prvm_statementprofiling, mfunction_t::s_file, prvm_prog_t::statement_columnnums, prvm_prog_t::statement_linenums, prvm_prog_t::statement_profile, prvm_prog_t::statements, STRING_COLOR_TAG, strlen(), and prvm_prog_t::xfunction.

Referenced by PRVM_PrintFunctionStatements(), PRVM_PrintState(), and while().

◆ PRVM_Profile()

void PRVM_Profile ( prvm_prog_t * prog,
int maxfunctions,
double mintime,
int sortby )

Definition at line 539 of file prvm_exec.c.

540{
541 mfunction_t *f, *best;
542 int i, num;
543 double max;
544
546 mintime *= 10000000; // count each statement as about 0.1µs
547
549 Con_Printf( "%s Profile:\n[CallCount] [Time] [BuiltinTm] [Statement] [BuiltinCt] [TimeTotal] [StmtTotal] [BltnTotal] [self]\n", prog->name );
550 // 12345678901 12345678901 12345678901 12345678901 12345678901 12345678901 12345678901 123.45%
551 else
552 Con_Printf( "%s Profile:\n[CallCount] [Statement] [BuiltinCt] [StmtTotal] [BltnTotal] [self]\n", prog->name );
553 // 12345678901 12345678901 12345678901 12345678901 12345678901 123.45%
554
555 num = 0;
556 do
557 {
558 max = 0;
559 best = NULL;
560 for (i=0 ; i<prog->numfunctions ; i++)
561 {
562 f = &prog->functions[i];
564 {
565 if(sortby)
566 {
567 if(f->first_statement < 0)
568 {
569 if (max < f->tprofile)
570 {
571 max = f->tprofile;
572 best = f;
573 }
574 }
575 else
576 {
577 if (max < f->tprofile_total)
578 {
579 max = f->tprofile_total;
580 best = f;
581 }
582 }
583 }
584 else
585 {
586 if (max < f->tprofile + f->tbprofile)
587 {
588 max = f->tprofile + f->tbprofile;
589 best = f;
590 }
591 }
592 }
593 else
594 {
595 if(sortby)
596 {
597 if (max < f->profile_total + f->builtinsprofile_total + f->callcount)
598 {
599 max = f->profile_total + f->builtinsprofile_total + f->callcount;
600 best = f;
601 }
602 }
603 else
604 {
605 if (max < f->profile + f->builtinsprofile + f->callcount)
606 {
607 max = f->profile + f->builtinsprofile + f->callcount;
608 best = f;
609 }
610 }
611 }
612 }
613 if (best)
614 {
615 if (num < maxfunctions && max > mintime)
616 {
618 {
619 if (best->first_statement < 0)
620 Con_Printf("%11.0f %11.6f ------------- builtin ------------- %11.6f ----------- builtin ----------- %s\n", best->callcount, best->tprofile, best->tprofile, PRVM_GetString(prog, best->s_name));
621 // %11.6f 12345678901 12345678901 12345678901 %11.6f 12345678901 12345678901 123.45%
622 else
623 Con_Printf("%11.0f %11.6f %11.6f %11.0f %11.0f %11.6f %11.0f %11.0f %6.2f%% %s\n", best->callcount, best->tprofile, best->tbprofile, best->profile, best->builtinsprofile, best->tprofile_total, best->profile_total, best->builtinsprofile_total, (best->tprofile_total > 0) ? ((best->tprofile) * 100.0 / (best->tprofile_total)) : -99.99, PRVM_GetString(prog, best->s_name));
624 }
625 else
626 {
627 if (best->first_statement < 0)
628 Con_Printf("%11.0f ----------------------- builtin ----------------------- %s\n", best->callcount, PRVM_GetString(prog, best->s_name));
629 // 12345678901 12345678901 12345678901 12345678901 123.45%
630 else
631 Con_Printf("%11.0f %11.0f %11.0f %11.0f %11.0f %6.2f%% %s\n", best->callcount, best->profile, best->builtinsprofile, best->profile_total, best->builtinsprofile_total, (best->profile + best->builtinsprofile) * 100.0 / (best->profile_total + best->builtinsprofile_total), PRVM_GetString(prog, best->s_name));
632 }
633 }
634 num++;
635 best->profile = 0;
636 best->tprofile = 0;
637 best->tbprofile = 0;
638 best->builtinsprofile = 0;
639 best->profile_total = 0;
640 best->tprofile_total = 0;
641 best->builtinsprofile_total = 0;
642 best->callcount = 0;
643 }
644 } while (best);
645}
double tbprofile
Definition pr_comp.h:450
double builtinsprofile
Definition pr_comp.h:452
double profile
Definition pr_comp.h:451
double builtinsprofile_total
Definition pr_comp.h:457
double tprofile_total
Definition pr_comp.h:455
double tprofile
Definition pr_comp.h:449
double profile_total
Definition pr_comp.h:456

References mfunction_t::builtinsprofile, mfunction_t::builtinsprofile_total, mfunction_t::callcount, Con_Printf(), f, mfunction_t::first_statement, prvm_prog_t::functions, i, cvar_t::integer, max, prvm_prog_t::name, NULL, prvm_prog_t::numfunctions, mfunction_t::profile, mfunction_t::profile_total, PRVM_GetString(), prvm_timeprofiling, mfunction_t::s_name, mfunction_t::tbprofile, mfunction_t::tprofile, and mfunction_t::tprofile_total.

Referenced by PRVM_ChildProfile_f(), PRVM_Profile_f(), and while().

◆ PRVM_Profile_f()

void PRVM_Profile_f ( cmd_state_t * cmd)

Definition at line 674 of file prvm_exec.c.

675{
676 prvm_prog_t *prog;
677 int howmany;
678
679 if (prvm_coverage.integer & 1)
680 {
681 Con_Printf("Collecting function coverage, cannot profile - sorry!\n");
682 return;
683 }
684
685 howmany = 1<<30;
686 if (Cmd_Argc(cmd) == 3)
687 howmany = atoi(Cmd_Argv(cmd, 2));
688 else if (Cmd_Argc(cmd) != 2)
689 {
690 Con_Print("prvm_profile <program name>\n");
691 return;
692 }
693
694 if (!(prog = PRVM_FriendlyProgFromString(Cmd_Argv(cmd, 1))))
695 return;
696
697 PRVM_Profile(prog, howmany, 0, 0);
698}

References cmd(), Cmd_Argc(), Cmd_Argv(), Con_Print(), Con_Printf(), cvar_t::integer, prvm_coverage, PRVM_FriendlyProgFromString(), and PRVM_Profile().

◆ PRVM_ShortStackTrace()

void PRVM_ShortStackTrace ( prvm_prog_t * prog,
char * buf,
size_t bufsize )

Definition at line 464 of file prvm_exec.c.

465{
466 mfunction_t *f;
467 int i;
468 char vabuf[1024];
469 char *p;
470
471 if(prog)
472 {
473 i = dpsnprintf(buf, bufsize, "(%s) ", prog->name);
474 p = buf + max(0, i);
475 }
476 else
477 {
478 dp_strlcpy(buf, "<NO PROG>", bufsize);
479 return;
480 }
481
482 prog->stack[prog->depth].s = prog->xstatement;
483 prog->stack[prog->depth].f = prog->xfunction;
484 for (i = prog->depth;i > 0;i--)
485 {
486 f = prog->stack[i].f;
487 p = dp_stpecpy(
488 p,
489 buf + bufsize,
490 f
491 ? 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)
492 : "<NULL> "
493 );
494 if (p == buf + bufsize)
495 break;
496 }
497}
char * dp_stpecpy(char *dst, char *end, const char *src)
Chain-copies a string with truncation and efficiency (compared to strlcat()).
Definition common.c:1373
#define dp_strlcpy(dst, src, dsize)
Definition common.h:303
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition glquake.h:657

References buf, prvm_prog_t::depth, dp_stpecpy(), dp_strlcpy, dpsnprintf(), f, prvm_stack_t::f, i, max, prvm_prog_t::name, PRVM_GetString(), prvm_stack_t::s, prvm_prog_t::stack, va(), prvm_prog_t::xfunction, and prvm_prog_t::xstatement.

Referenced by PRVM_AllocationOrigin().

◆ PRVM_StackTrace()

void PRVM_StackTrace ( prvm_prog_t * prog)

Definition at line 436 of file prvm_exec.c.

437{
438 mfunction_t *f;
439 int i;
440
441 prog->stack[prog->depth].s = prog->xstatement;
442 prog->stack[prog->depth].f = prog->xfunction;
443 for (i = prog->depth;i > 0;i--)
444 {
445 f = prog->stack[i].f;
446
447 if (!f)
448 Con_Print("<NULL FUNCTION>\n");
449 else
450 {
451 if (prog->statement_linenums)
452 {
453 if (prog->statement_columnnums)
454 Con_Printf("%12s:%i:%i : %s : statement %i\n", PRVM_GetString(prog, f->s_file), prog->statement_linenums[prog->stack[i].s], prog->statement_columnnums[prog->stack[i].s], PRVM_GetString(prog, f->s_name), prog->stack[i].s - f->first_statement);
455 else
456 Con_Printf("%12s:%i : %s : statement %i\n", PRVM_GetString(prog, f->s_file), prog->statement_linenums[prog->stack[i].s], PRVM_GetString(prog, f->s_name), prog->stack[i].s - f->first_statement);
457 }
458 else
459 Con_Printf("%12s : %s : statement %i\n", PRVM_GetString(prog, f->s_file), PRVM_GetString(prog, f->s_name), prog->stack[i].s - f->first_statement);
460 }
461 }
462}

References Con_Print(), Con_Printf(), prvm_prog_t::depth, f, prvm_stack_t::f, i, PRVM_GetString(), prvm_stack_t::s, prvm_prog_t::stack, prvm_prog_t::statement_columnnums, prvm_prog_t::statement_linenums, prvm_prog_t::xfunction, and prvm_prog_t::xstatement.

Referenced by PRVM_PrintState(), and VM_stackdump().

◆ PRVM_StatementCoverageEvent()

static void PRVM_StatementCoverageEvent ( prvm_prog_t * prog,
mfunction_t * func,
int statement )
static

Definition at line 930 of file prvm_exec.c.

931{
932 char vabuf[128];
933 ++prog->statements_covered;
934 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);
935}
int statements_covered
Definition progsvm.h:574

References Con_Printf(), prvm_prog_t::name, prvm_prog_t::numstatements, PRVM_WhereAmI(), and prvm_prog_t::statements_covered.

◆ PRVM_WhereAmI()

static const char * PRVM_WhereAmI ( char * buf,
size_t bufsize,
prvm_prog_t * prog,
mfunction_t * func,
int statement )
static

Definition at line 907 of file prvm_exec.c.

908{
909 if (prog->statement_linenums)
910 {
911 if (prog->statement_columnnums)
912 return va(buf, bufsize, "%s:%i:%i(%s, %i)", PRVM_GetString(prog, func->s_file), prog->statement_linenums[statement], prog->statement_columnnums[statement], PRVM_GetString(prog, func->s_name), statement - func->first_statement);
913 else
914 return va(buf, bufsize, "%s:%i(%s, %i)", PRVM_GetString(prog, func->s_file), prog->statement_linenums[statement], PRVM_GetString(prog, func->s_name), statement - func->first_statement);
915 }
916 else
917 return va(buf, bufsize, "%s(%s, %i)", PRVM_GetString(prog, func->s_file), PRVM_GetString(prog, func->s_name), statement - func->first_statement);
918}

References buf, mfunction_t::first_statement, PRVM_GetString(), mfunction_t::s_file, mfunction_t::s_name, prvm_prog_t::statement_columnnums, prvm_prog_t::statement_linenums, and va().

Referenced by PRVM_ExplicitCoverageEvent(), and PRVM_StatementCoverageEvent().

◆ SVVM_ExecuteProgram()

void SVVM_ExecuteProgram ( prvm_prog_t * prog,
func_t fnum,
const char * errormessage )

Definition at line 1183 of file prvm_exec.c.

1187{
1188 mstatement_t *st, *startst;
1189 mfunction_t *func, *enterfunc;
1190 prvm_edict_t *ed;
1191 prvm_eval_t *ptr;
1192 int jumpcount, cachedpr_trace, exitdepth;
1193 int restorevm_tempstringsbuf_cursize;
1194 double calltime;
1195 double tm, starttm;
1196 prvm_vec_t tempfloat;
1199
1200 calltime = Sys_DirtyTime();
1201
1202 if (!fnum || fnum >= (unsigned int)prog->numfunctions)
1203 {
1206 prog->error_cmd("SVVM_ExecuteProgram: %s", errormessage);
1207 }
1208
1209 func = &prog->functions[fnum];
1210
1211 // after executing this function, delete all tempstrings it created
1212 restorevm_tempstringsbuf_cursize = prog->tempstringsbuf.cursize;
1213
1214 prog->trace = prvm_traceqc.integer;
1215
1216 // we know we're done when pr_depth drops to this
1217 exitdepth = prog->depth;
1218
1219// make a stack frame
1220 st = &prog->statements[PRVM_EnterFunction(prog, func)];
1221 // save the starting statement pointer for profiling
1222 // (when the function exits or jumps, the (st - startst) integer value is
1223 // added to the function's profile counter)
1224 startst = st;
1225 starttm = calltime;
1226 // instead of counting instructions, we count jumps
1227 jumpcount = 0;
1228 // add one to the callcount of this function because otherwise engine-called functions aren't counted
1229 if (prog->xfunction->callcount++ == 0 && (prvm_coverage.integer & 1))
1231
1232chooseexecprogram:
1233 cachedpr_trace = prog->trace;
1234 if (prog->trace || prog->watch_global_type != ev_void || prog->watch_field_type != ev_void || prog->break_statement >= 0)
1235 {
1236#define PRVMSLOWINTERPRETER 1
1238 {
1239#define PRVMTIMEPROFILING 1
1240#include "prvm_execprogram.h"
1241#undef PRVMTIMEPROFILING
1242 }
1243 else
1244 {
1245#include "prvm_execprogram.h"
1246 }
1247#undef PRVMSLOWINTERPRETER
1248 }
1249 else
1250 {
1252 {
1253#define PRVMTIMEPROFILING 1
1254#include "prvm_execprogram.h"
1255#undef PRVMTIMEPROFILING
1256 }
1257 else
1258 {
1259#include "prvm_execprogram.h"
1260 }
1261 }
1262
1263cleanup:
1264 if (developer_insane.integer && prog->tempstringsbuf.cursize > restorevm_tempstringsbuf_cursize)
1265 Con_DPrintf("SVVM_ExecuteProgram: %s used %i bytes of tempstrings\n", PRVM_GetString(prog, prog->functions[fnum].s_name), prog->tempstringsbuf.cursize - restorevm_tempstringsbuf_cursize);
1266 // delete tempstrings created by this function
1267 prog->tempstringsbuf.cursize = restorevm_tempstringsbuf_cursize;
1268
1269 tm = Sys_DirtyTime() - calltime;if (tm < 0 || tm >= 1800) tm = 0;
1270 func->totaltime += tm;
1271
1272 if (prog == SVVM_prog)
1274}

References prvm_prog_t::break_statement, CACHE_CHANGING, CACHE_UNCHANGING, mfunction_t::callcount, Con_DPrintf(), sizebuf_t::cursize, prvm_prog_t::depth, developer_insane, DO_DECLARE, prvm_prog_t::error_cmd, ev_void, prvm_prog_t::functions, cvar_t::integer, NULL, prvm_prog_t::numfunctions, PRVM_allglobaledict, prvm_coverage, PRVM_ED_Print(), PRVM_EnterFunction(), PRVM_FunctionCoverageEvent(), PRVM_GetString(), PRVM_PROG_TO_EDICT, prvm_timeprofiling, prvm_traceqc, mfunction_t::s_name, self, prvm_prog_t::statements, SV_FlushBroadcastMessages(), SVVM_prog, Sys_DirtyTime(), prvm_prog_t::tempstringsbuf, mfunction_t::totaltime, prvm_prog_t::trace, prvm_prog_t::watch_field_type, prvm_prog_t::watch_global_type, and prvm_prog_t::xfunction.

Referenced by SV_VM_Setup().

Variable Documentation

◆ prvm_coverage

cvar_t prvm_coverage
extern

Definition at line 39 of file prvm_edict.c.

39{CF_CLIENT | CF_SERVER, "prvm_coverage", "0", "report and count coverage events (1: per-function, 2: coverage() builtin, 4: per-statement)"};
#define CF_SERVER
cvar/command that only the server can change/execute
Definition cmd.h:49
#define CF_CLIENT
cvar/command that only the client can change/execute
Definition cmd.h:48

Referenced by CLVM_ExecuteProgram(), PRVM_ChildProfile_f(), PRVM_Init(), PRVM_PrintFunctionStatements(), PRVM_Profile_f(), and SVVM_ExecuteProgram().

◆ prvm_errordump

cvar_t prvm_errordump
extern

Definition at line 44 of file prvm_edict.c.

44{CF_CLIENT | CF_SERVER, "prvm_errordump", "0", "write a savegame on crash to crash-server.dmp"};

Referenced by PRVM_Crash(), and PRVM_Init().

◆ prvm_gameplayfix_div0is0

cvar_t prvm_gameplayfix_div0is0
extern

Definition at line 57 of file prvm_edict.c.

57{CF_SERVER, "prvm_gameplayfix_div0is0", "0", "When set to 1, floating point division by 0 will return zero instead of returning the IEEE standardized result (likely nan or inf). Other ways of getting non-finite values are not affected, and the warning will still print."};

Referenced by PRVM_Init(), and while().

◆ prvm_opnames

const char* prvm_opnames[]
static

Definition at line 27 of file prvm_exec.c.

28{
29"^5DONE",
30"MUL_F",
31"MUL_V",
32"MUL_FV",
33"MUL_VF",
34"DIV_F",
35"ADD_F",
36"ADD_V",
37"SUB_F",
38"SUB_V",
39
40"^2EQ_F",
41"^2EQ_V",
42"^2EQ_S",
43"^2EQ_E",
44"^2EQ_FNC",
45
46"^2NE_F",
47"^2NE_V",
48"^2NE_S",
49"^2NE_E",
50"^2NE_FNC",
51
52"^2LE_F",
53"^2GE_F",
54"^2LT_F",
55"^2GT_F",
56
57"^6LOAD_F",
58"^6LOAD_V",
59"^6LOAD_S",
60"^6LOAD_ENT",
61"^6LOAD_FLD",
62"^6LOAD_FNC",
63
64"^1ADDRESS",
65
66"STORE_F",
67"STORE_V",
68"STORE_S",
69"STORE_ENT",
70"STORE_FLD",
71"STORE_FNC",
72
73"^1STOREP_F",
74"^1STOREP_V",
75"^1STOREP_S",
76"^1STOREP_ENT",
77"^1STOREP_FLD",
78"^1STOREP_FNC",
79
80"^5RETURN",
81"^2NOT_F",
82"^2NOT_V",
83"^2NOT_S",
84"^2NOT_ENT",
85"^2NOT_FNC",
86"^5IF",
87"^5IFNOT",
88"^3CALL0",
89"^3CALL1",
90"^3CALL2",
91"^3CALL3",
92"^3CALL4",
93"^3CALL5",
94"^3CALL6",
95"^3CALL7",
96"^3CALL8",
97"^1STATE",
98"^5GOTO",
99"^2AND_F",
100"^2OR_F",
101
102"BITAND_F",
103"BITOR_F",
104
105
106
107NULL,
108NULL,
109NULL,
110NULL,
111
112NULL,
113NULL,
114
115NULL,
116NULL,
117NULL,
118NULL,
119
120NULL,
121NULL,
122NULL,
123NULL,
124
125NULL,
126NULL,
127NULL,
128NULL,
129NULL,
130
131NULL,
132NULL,
133
134NULL,
135
136NULL,
137NULL,
138NULL,
139NULL,
140
141NULL,
142NULL,
143NULL,
144NULL,
145NULL,
146NULL,
147
148NULL,
149NULL,
150NULL,
151NULL,
152NULL,
153
154NULL,
155NULL,
156
157
158NULL,
159NULL,
160NULL,
161NULL,
162NULL,
163NULL,
164NULL,
165NULL,
166
167"STORE_I",
168NULL,
169NULL,
170
171"ADD_I",
172"ADD_FI",
173"ADD_IF",
174
175"SUB_I",
176"SUB_FI",
177"SUB_IF",
178
179"CONV_ITOF",
180"CONV_FTOI",
181
182NULL,
183NULL,
184
185"^6LOAD_I",
186
187"^1STOREP_I",
188NULL,
189NULL,
190
191"BITAND_I",
192"BITOR_I",
193
194"MUL_I",
195"DIV_I",
196"EQ_I",
197"NE_I",
198
199NULL,
200
201NULL,
202
203"NOT_I",
204
205"DIV_VF",
206
207NULL,
208"RSHIFT_I",
209"LSHIFT_I",
210
211"GLOBALADDRESS",
212"ADD_PIW",
213
214"LOADA_F",
215"LOADA_V",
216"LOADA_S",
217"LOADA_ENT",
218"LOADA_FLD",
219"LOADA_FNC",
220"LOADA_I",
221
222"STORE_P",
223"^6FIELD_P",
224
225"LOADP_F",
226"LOADP_V",
227"LOADP_S",
228"LOADP_ENT",
229"LOADP_FLD",
230"LOADP_FNC",
231"LOADP_I",
232
233"LE_I",
234"GE_I",
235"LT_I",
236"GT_I",
237
238"LE_IF",
239"GE_IF",
240"LT_IF",
241"GT_IF",
242
243"LE_FI",
244"GE_FI",
245"LT_FI",
246"GT_FI",
247
248"EQ_IF",
249"EQ_FI",
250
251NULL,
252NULL,
253NULL,
254NULL,
255
256"MUL_IF",
257"MUL_FI",
258"MUL_VI",
259NULL,
260"DIV_IF",
261"DIV_FI",
262"BITAND_IF",
263"BITOR_IF",
264"BITAND_FI",
265"BITOR_FI",
266"AND_I",
267"OR_I",
268"AND_IF",
269"OR_IF",
270"AND_FI",
271"OR_FI",
272"NE_IF",
273"NE_FI",
274
275"GSTOREP_I",
276"GSTOREP_F",
277"GSTOREP_ENT",
278"GSTOREP_FLD",
279"GSTOREP_S",
280"GSTOREP_FNC",
281"GSTOREP_V",
282"GADDRESS",
283"GLOAD_I",
284"GLOAD_F",
285"GLOAD_FLD",
286"GLOAD_ENT",
287"GLOAD_S",
288"GLOAD_FNC",
289"BOUNDCHECK",
290
291NULL,
292NULL,
293NULL,
294NULL,
295
296"GLOAD_V",
297
298NULL,
299NULL,
300
301NULL,
302NULL,
303NULL,
304NULL,
305
306
307NULL,
308NULL,
309
310
311"^2LE_U",
312"^2LT_U",
313"DIV_U",
314"RSHIFT_U",
315};

Referenced by PRVM_PrintStatement().

◆ prvm_runawaycheck

qbool prvm_runawaycheck
extern

Definition at line 60 of file prvm_edict.c.

Referenced by PRVM_Init().

◆ prvm_statementprofiling

cvar_t prvm_statementprofiling
extern

Definition at line 947 of file prvm_exec.c.

Referenced by PRVM_Init(), and PRVM_PrintStatement().

◆ prvm_timeprofiling

cvar_t prvm_timeprofiling
extern

Definition at line 38 of file prvm_edict.c.

38{CF_CLIENT | CF_SERVER, "prvm_timeprofiling", "0", "counts how long each function has been executed, these counts are displayed in prvm_profile output (if enabled)"};

Referenced by CLVM_ExecuteProgram(), PRVM_Init(), PRVM_Profile(), and SVVM_ExecuteProgram().

◆ prvm_traceqc

cvar_t prvm_traceqc
extern

Definition at line 35 of file prvm_edict.c.

35{CF_CLIENT | CF_SERVER, "prvm_traceqc", "0", "prints every QuakeC statement as it is executed (only for really thorough debugging!)"};

Referenced by CLVM_ExecuteProgram(), PRVM_Init(), and SVVM_ExecuteProgram().