X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=prvm_edict.c;h=7dcf6daa39b6045760c2a311b153a30438ea920e;hb=f85803e7bc2d0612763bdb8548c7060ddb542afb;hp=12781fdc10da743f51814dc2c34e07d371c45776;hpb=99a143e9c97b009ca04e30a317d01e5b0fa15018;p=xonotic%2Fdarkplaces.git diff --git a/prvm_edict.c b/prvm_edict.c index 12781fdc..7dcf6daa 100644 --- a/prvm_edict.c +++ b/prvm_edict.c @@ -35,8 +35,10 @@ cvar_t prvm_traceqc = {0, "prvm_traceqc", "0", "prints every QuakeC statement as // LordHavoc: counts usage of each QuakeC statement cvar_t prvm_statementprofiling = {0, "prvm_statementprofiling", "0", "counts how many times each QuakeC statement has been executed, these counts are displayed in prvm_printfunction output (if enabled)"}; cvar_t prvm_timeprofiling = {0, "prvm_timeprofiling", "0", "counts how long each function has been executed, these counts are displayed in prvm_profile output (if enabled)"}; +cvar_t prvm_coverage = {0, "prvm_coverage", "0", "report and count coverage events (1: per-function, 2: coverage() builtin, 4: per-statement)"}; cvar_t prvm_backtraceforwarnings = {0, "prvm_backtraceforwarnings", "0", "print a backtrace for warnings too"}; cvar_t prvm_leaktest = {0, "prvm_leaktest", "0", "try to detect memory leaks in strings or entities"}; +cvar_t prvm_leaktest_follow_targetname = {0, "prvm_leaktest_follow_targetname", "0", "if set, target/targetname links are considered when leak testing; this should normally not be required, as entities created during startup - e.g. info_notnull - are never considered leaky"}; cvar_t prvm_leaktest_ignore_classnames = {0, "prvm_leaktest_ignore_classnames", "", "classnames of entities to NOT leak check because they are found by find(world, classname, ...) but are actually spawned by QC code (NOT map entities)"}; cvar_t prvm_errordump = {0, "prvm_errordump", "0", "write a savegame on crash to crash-server.dmp"}; cvar_t prvm_breakpointdump = {0, "prvm_breakpointdump", "0", "write a savegame on breakpoint to breakpoint-server.dmp"}; @@ -188,13 +190,20 @@ prvm_prog_t *PRVM_FriendlyProgFromString(const char *str) ================= PRVM_ED_ClearEdict -Sets everything to NULL +Sets everything to NULL. + +Nota bene: this also marks the entity as allocated if it has been previously +freed and sets the allocation origin. ================= */ void PRVM_ED_ClearEdict(prvm_prog_t *prog, prvm_edict_t *e) { memset(e->fields.fp, 0, prog->entityfields * sizeof(prvm_vec_t)); e->priv.required->free = false; + e->priv.required->freetime = realtime; + if(e->priv.required->allocation_origin) + Mem_Free((char *)e->priv.required->allocation_origin); + e->priv.required->allocation_origin = PRVM_AllocationOrigin(prog); // AK: Let the init_edict function determine if something needs to be initialized prog->init_edict(prog, e); @@ -261,7 +270,6 @@ prvm_edict_t *PRVM_ED_Alloc(prvm_prog_t *prog) if(PRVM_ED_CanAlloc(prog, e)) { PRVM_ED_ClearEdict (prog, e); - e->priv.required->allocation_origin = PRVM_AllocationOrigin(prog); return e; } } @@ -274,10 +282,8 @@ prvm_edict_t *PRVM_ED_Alloc(prvm_prog_t *prog) PRVM_MEM_IncreaseEdicts(prog); e = PRVM_EDICT_NUM(i); - PRVM_ED_ClearEdict(prog, e); - - e->priv.required->allocation_origin = PRVM_AllocationOrigin(prog); + PRVM_ED_ClearEdict(prog, e); return e; } @@ -1316,8 +1322,10 @@ const char *PRVM_ED_ParseEdict (prvm_prog_t *prog, const char *data, prvm_edict_ prog->error_cmd("PRVM_ED_ParseEdict: parse error"); } - if (!init) + if (!init) { ent->priv.required->free = true; + ent->priv.required->freetime = realtime; + } return data; } @@ -1887,7 +1895,14 @@ static void PRVM_LoadLNO( prvm_prog_t *prog, const char *progname ) { (unsigned int)LittleLong( header[ 5 ] ) == (unsigned int)prog->progs_numstatements ) { prog->statement_linenums = (int *)Mem_Alloc(prog->progs_mempool, prog->progs_numstatements * sizeof( int ) ); - memcpy( prog->statement_linenums, (int *) lno + 6, prog->progs_numstatements * sizeof( int ) ); + memcpy( prog->statement_linenums, header + 6, prog->progs_numstatements * sizeof( int ) ); + + /* gmqcc suports columnums */ + if ((unsigned int)filesize > ((6 + 2 * prog->progs_numstatements) * sizeof( int ))) + { + prog->statement_columnnums = (int *)Mem_Alloc(prog->progs_mempool, prog->progs_numstatements * sizeof( int ) ); + memcpy( prog->statement_columnnums, header + 6 + prog->progs_numstatements, prog->progs_numstatements * sizeof( int ) ); + } } Mem_Free( lno ); } @@ -2003,6 +2018,7 @@ void PRVM_Prog_Load(prvm_prog_t *prog, const char * filename, unsigned char * da prog->statements = (mstatement_t *)Mem_Alloc(prog->progs_mempool, prog->progs_numstatements * sizeof(mstatement_t)); // allocate space for profiling statement usage prog->statement_profile = (double *)Mem_Alloc(prog->progs_mempool, prog->progs_numstatements * sizeof(*prog->statement_profile)); + prog->explicit_profile = (double *)Mem_Alloc(prog->progs_mempool, prog->progs_numstatements * sizeof(*prog->statement_profile)); // functions need to be converted to the memory format prog->functions = (mfunction_t *)Mem_Alloc(prog->progs_mempool, sizeof(mfunction_t) * prog->progs_numfunctions); @@ -2208,6 +2224,11 @@ void PRVM_Prog_Load(prvm_prog_t *prog, const char * filename, unsigned char * da break; // 1 global case OP_CALL0: + if ( a < prog->progs_numglobals) + if ( prog->globals.ip[remapglobal(a)] >= 0 ) + if ( prog->globals.ip[remapglobal(a)] < prog->progs_numfunctions ) + if ( prog->functions[prog->globals.ip[remapglobal(a)]].first_statement == -642 ) + ++prog->numexplicitcoveragestatements; case OP_CALL1: case OP_CALL2: case OP_CALL3: @@ -2438,6 +2459,10 @@ fail: // init mempools PRVM_MEM_Alloc(prog); + + // Inittime is at least the time when this function finished. However, + // later events may bump it. + prog->inittime = realtime; } @@ -2894,8 +2919,10 @@ void PRVM_Init (void) Cvar_RegisterVariable (&prvm_traceqc); Cvar_RegisterVariable (&prvm_statementprofiling); Cvar_RegisterVariable (&prvm_timeprofiling); + Cvar_RegisterVariable (&prvm_coverage); Cvar_RegisterVariable (&prvm_backtraceforwarnings); Cvar_RegisterVariable (&prvm_leaktest); + Cvar_RegisterVariable (&prvm_leaktest_follow_targetname); Cvar_RegisterVariable (&prvm_leaktest_ignore_classnames); Cvar_RegisterVariable (&prvm_errordump); Cvar_RegisterVariable (&prvm_breakpointdump); @@ -3072,10 +3099,12 @@ int PRVM_SetTempString(prvm_prog_t *prog, const char *s) { Con_DPrintf("PRVM_SetTempString: enlarging tempstrings buffer (%iKB -> %iKB)\n", old.maxsize/1024, prog->tempstringsbuf.maxsize/1024); prog->tempstringsbuf.data = (unsigned char *) Mem_Alloc(prog->progs_mempool, prog->tempstringsbuf.maxsize); - if (old.cursize) - memcpy(prog->tempstringsbuf.data, old.data, old.cursize); if (old.data) + { + if (old.cursize) + memcpy(prog->tempstringsbuf.data, old.data, old.cursize); Mem_Free(old.data); + } } } t = (char *)prog->tempstringsbuf.data + prog->tempstringsbuf.cursize; @@ -3088,7 +3117,11 @@ int PRVM_AllocString(prvm_prog_t *prog, size_t bufferlength, char **pointer) { int i; if (!bufferlength) + { + if (pointer) + *pointer = NULL; return 0; + } for (i = prog->firstfreeknownstring;i < prog->numknownstrings;i++) if (!prog->knownstrings[i]) break; @@ -3192,6 +3225,8 @@ static qboolean PRVM_IsEdictRelevant(prvm_prog_t *prog, prvm_edict_t *edict) char vabuf2[1024]; if(PRVM_NUM_FOR_EDICT(edict) <= prog->reserved_edicts) return true; // world or clients + if (edict->priv.required->freetime <= prog->inittime) + return true; // created during startup if (prog == SVVM_prog) { if(PRVM_serveredictfloat(edict, solid)) // can block other stuff, or is a trigger? @@ -3242,7 +3277,7 @@ static qboolean PRVM_IsEdictReferenced(prvm_prog_t *prog, prvm_edict_t *edict, i int edictnum = PRVM_NUM_FOR_EDICT(edict); const char *targetname = NULL; - if (prog == SVVM_prog) + if (prog == SVVM_prog && prvm_leaktest_follow_targetname.integer) targetname = PRVM_GetString(prog, PRVM_serveredictstring(edict, targetname)); if(targetname)