X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=prvm_execprogram.h;h=a6c45c98c47379dbada45e3111ef193b43626aa7;hb=1afcf4f1345700afbfe8fa77d8b02477a744bad3;hp=b87cfcf91b3fb0e74cb822addd1122754391194b;hpb=66c17456052bcd458a64c76802d04618bd464d05;p=xonotic%2Fdarkplaces.git diff --git a/prvm_execprogram.h b/prvm_execprogram.h index b87cfcf9..a6c45c98 100644 --- a/prvm_execprogram.h +++ b/prvm_execprogram.h @@ -1,6 +1,15 @@ -// NEED to reset startst after calling this! +extern cvar_t prvm_garbagecollection_enable; +// NEED to reset startst after calling this! startst may or may not be clobbered! #define ADVANCE_PROFILE_BEFORE_JUMP() \ - prog->xfunction->profile += (st - startst) + prog->xfunction->profile += (st - startst); \ + if (prvm_statementprofiling.integer || (prvm_coverage.integer & 4)) { \ + /* 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)! */ \ + } #ifdef PRVMTIMEPROFILING #define PRE_ERROR() \ @@ -117,15 +126,15 @@ { if (prog->watch_global_type != ev_void) { - prvm_eval_t *f = PRVM_GLOBALFIELDVALUE(prog->watch_global); + prvm_eval_t *g = PRVM_GLOBALFIELDVALUE(prog->watch_global); prog->xstatement = st + 1 - cached_statements; - PRVM_Watchpoint(prog, 1, "Global watchpoint hit by engine", prog->watch_global_type, &prog->watch_global_value, f); + PRVM_Watchpoint(prog, 1, "Global watchpoint hit by engine", prog->watch_global_type, &prog->watch_global_value, g); } if (prog->watch_field_type != ev_void && prog->watch_edict < prog->max_edicts) { - prvm_eval_t *f = PRVM_EDICTFIELDVALUE(prog->edicts + prog->watch_edict, prog->watch_field); + prvm_eval_t *g = PRVM_EDICTFIELDVALUE(prog->edicts + prog->watch_edict, prog->watch_field); prog->xstatement = st + 1 - cached_statements; - PRVM_Watchpoint(prog, 1, "Entityfield watchpoint hit by engine", prog->watch_field_type, &prog->watch_edictfield_value, f); + PRVM_Watchpoint(prog, 1, "Entityfield watchpoint hit by engine", prog->watch_field_type, &prog->watch_edictfield_value, g); } } #endif @@ -140,8 +149,6 @@ #if PRVMSLOWINTERPRETER if (prog->trace) PRVM_PrintStatement(prog, st); - if (prog->statement_profile[st - cached_statements]++ == 0 && (prvm_coverage.integer & 4)) - PRVM_StatementCoverageEvent(prog, prog->xfunction, st - cached_statements); if (prog->break_statement >= 0) if ((st - cached_statements) == prog->break_statement) { @@ -275,10 +282,18 @@ HANDLE_OPCODE(OP_STORE_F): HANDLE_OPCODE(OP_STORE_ENT): HANDLE_OPCODE(OP_STORE_FLD): // integers - HANDLE_OPCODE(OP_STORE_S): HANDLE_OPCODE(OP_STORE_FNC): // pointers OPB->_int = OPA->_int; DISPATCH_OPCODE(); + HANDLE_OPCODE(OP_STORE_S): + // refresh the garbage collection on the string - this guards + // against a certain sort of repeated migration to earlier + // points in the scan that could otherwise result in the string + // being freed for being unused + if(prvm_garbagecollection_enable.integer) + PRVM_GetString(prog, OPA->_int); + OPB->_int = OPA->_int; + DISPATCH_OPCODE(); HANDLE_OPCODE(OP_STORE_V): OPB->ivector[0] = OPA->ivector[0]; OPB->ivector[1] = OPA->ivector[1]; @@ -288,7 +303,6 @@ HANDLE_OPCODE(OP_STOREP_F): HANDLE_OPCODE(OP_STOREP_ENT): HANDLE_OPCODE(OP_STOREP_FLD): // integers - HANDLE_OPCODE(OP_STOREP_S): HANDLE_OPCODE(OP_STOREP_FNC): // pointers if ((prvm_uint_t)OPB->_int - cached_entityfields >= cached_entityfieldsarea_entityfields) { @@ -307,6 +321,30 @@ ptr = (prvm_eval_t *)(cached_edictsfields + OPB->_int); ptr->_int = OPA->_int; DISPATCH_OPCODE(); + HANDLE_OPCODE(OP_STOREP_S): + if ((prvm_uint_t)OPB->_int - cached_entityfields >= cached_entityfieldsarea_entityfields) + { + if ((prvm_uint_t)OPB->_int >= cached_entityfieldsarea) + { + PRE_ERROR(); + prog->error_cmd("%s attempted to write to an out of bounds edict (%i)", prog->name, (int)OPB->_int); + goto cleanup; + } + if ((prvm_uint_t)OPB->_int < cached_entityfields && !cached_allowworldwrites) + { + PRE_ERROR(); + VM_Warning(prog, "assignment to world.%s (field %i) in %s\n", PRVM_GetString(prog, PRVM_ED_FieldAtOfs(prog, OPB->_int)->s_name), (int)OPB->_int, prog->name); + } + } + // refresh the garbage collection on the string - this guards + // against a certain sort of repeated migration to earlier + // points in the scan that could otherwise result in the string + // being freed for being unused + if(prvm_garbagecollection_enable.integer) + PRVM_GetString(prog, OPA->_int); + ptr = (prvm_eval_t *)(cached_edictsfields + OPB->_int); + ptr->_int = OPA->_int; + DISPATCH_OPCODE(); HANDLE_OPCODE(OP_STOREP_V): if ((prvm_uint_t)OPB->_int - cached_entityfields > (prvm_uint_t)cached_entityfieldsarea_entityfields_3) { @@ -355,7 +393,6 @@ HANDLE_OPCODE(OP_LOAD_F): HANDLE_OPCODE(OP_LOAD_FLD): HANDLE_OPCODE(OP_LOAD_ENT): - HANDLE_OPCODE(OP_LOAD_S): HANDLE_OPCODE(OP_LOAD_FNC): if ((prvm_uint_t)OPA->edict >= cached_max_edicts) { @@ -372,6 +409,27 @@ ed = PRVM_PROG_TO_EDICT(OPA->edict); OPC->_int = ((prvm_eval_t *)(ed->fields.ip + OPB->_int))->_int; DISPATCH_OPCODE(); + HANDLE_OPCODE(OP_LOAD_S): + if ((prvm_uint_t)OPA->edict >= cached_max_edicts) + { + PRE_ERROR(); + prog->error_cmd("%s Progs attempted to read an out of bounds edict number", prog->name); + goto cleanup; + } + if ((prvm_uint_t)OPB->_int >= cached_entityfields) + { + PRE_ERROR(); + prog->error_cmd("%s attempted to read an invalid field in an edict (%i)", prog->name, (int)OPB->_int); + goto cleanup; + } + ed = PRVM_PROG_TO_EDICT(OPA->edict); + OPC->_int = ((prvm_eval_t *)(ed->fields.ip + OPB->_int))->_int; + // refresh the garbage collection on the string - this guards + // against a certain sort of repeated migration to earlier + // points in the scan that could otherwise result in the string + // being freed for being unused + PRVM_GetString(prog, OPC->_int); + DISPATCH_OPCODE(); HANDLE_OPCODE(OP_LOAD_V): if ((prvm_uint_t)OPA->edict >= cached_max_edicts) @@ -476,26 +534,26 @@ goto cleanup; } - newf = &prog->functions[OPA->function]; - if (newf->callcount++ == 0 && (prvm_coverage.integer & 1)) - PRVM_FunctionCoverageEvent(prog, newf); + enterfunc = &prog->functions[OPA->function]; + if (enterfunc->callcount++ == 0 && (prvm_coverage.integer & 1)) + PRVM_FunctionCoverageEvent(prog, enterfunc); - if (newf->first_statement < 0) + if (enterfunc->first_statement < 0) { // negative first_statement values are built in functions - int builtinnumber = -newf->first_statement; + int builtinnumber = -enterfunc->first_statement; prog->xfunction->builtinsprofile++; if (builtinnumber < prog->numbuiltins && prog->builtins[builtinnumber]) { prog->builtins[builtinnumber](prog); #ifdef PRVMTIMEPROFILING tm = Sys_DirtyTime(); - newf->tprofile += (tm - starttm >= 0 && tm - starttm < 1800) ? (tm - starttm) : 0; + enterfunc->tprofile += (tm - starttm >= 0 && tm - starttm < 1800) ? (tm - starttm) : 0; prog->xfunction->tbprofile += (tm - starttm >= 0 && tm - starttm < 1800) ? (tm - starttm) : 0; starttm = tm; #endif // builtins may cause ED_Alloc() to be called, update cached variables - cached_edictsfields = prog->edictsfields; + cached_edictsfields = prog->edictsfields.fp; cached_entityfields = prog->entityfields; cached_entityfields_3 = prog->entityfields - 3; cached_entityfieldsarea = prog->entityfieldsarea; @@ -515,7 +573,7 @@ prog->error_cmd("No such builtin #%i in %s; most likely cause: outdated engine build. Try updating!", builtinnumber, prog->name); } else - st = cached_statements + PRVM_EnterFunction(prog, newf); + st = cached_statements + PRVM_EnterFunction(prog, enterfunc); startst = st; DISPATCH_OPCODE(); @@ -555,7 +613,7 @@ } DISPATCH_OPCODE(); -// LordHavoc: to be enabled when Progs version 7 (or whatever it will be numbered) is finalized +// LadyHavoc: to be enabled when Progs version 7 (or whatever it will be numbered) is finalized /* HANDLE_OPCODE(OP_ADD_I): OPC->_int = OPA->_int + OPB->_int; @@ -834,15 +892,15 @@ { if (prog->watch_global_type != ev_void) { - prvm_eval_t *f = PRVM_GLOBALFIELDVALUE(prog->watch_global); + prvm_eval_t *g = PRVM_GLOBALFIELDVALUE(prog->watch_global); prog->xstatement = st - cached_statements; - PRVM_Watchpoint(prog, 0, "Global watchpoint hit", prog->watch_global_type, &prog->watch_global_value, f); + PRVM_Watchpoint(prog, 0, "Global watchpoint hit", prog->watch_global_type, &prog->watch_global_value, g); } if (prog->watch_field_type != ev_void && prog->watch_edict < prog->max_edicts) { - prvm_eval_t *f = PRVM_EDICTFIELDVALUE(prog->edicts + prog->watch_edict, prog->watch_field); + prvm_eval_t *g = PRVM_EDICTFIELDVALUE(prog->edicts + prog->watch_edict, prog->watch_field); prog->xstatement = st - cached_statements; - PRVM_Watchpoint(prog, 0, "Entityfield watchpoint hit", prog->watch_field_type, &prog->watch_edictfield_value, f); + PRVM_Watchpoint(prog, 0, "Entityfield watchpoint hit", prog->watch_field_type, &prog->watch_edictfield_value, g); } } #endif