DarkPlaces
Game engine based on the Quake 1 engine by id Software, developed by LadyHavoc
 
prvm_exec.c
Go to the documentation of this file.
1/*
2Copyright (C) 1996-1997 Id Software, Inc.
3
4This program is free software; you can redistribute it and/or
5modify it under the terms of the GNU General Public License
6as published by the Free Software Foundation; either version 2
7of the License, or (at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13See the GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
17Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19*/
20
21#include "quakedef.h"
22#include "progsvm.h"
23
24// Should only contain the opcodes DP actually implements, so unknown opcodes
25// are more readably marked as such in disassembly. Thus, best keep this in sync
26// with the list in prvm_execprogram.h.
27static const char *prvm_opnames[] =
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};
316
317
318
319//=============================================================================
320
321/*
322=================
323PRVM_PrintStatement
324=================
325*/
326extern cvar_t prvm_coverage;
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}
373
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}
409
410/*
411============
412PRVM_PrintFunction_f
413
414============
415*/
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}
430
431/*
432============
433PRVM_StackTrace
434============
435*/
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}
463
464void PRVM_ShortStackTrace(prvm_prog_t *prog, char *buf, size_t bufsize)
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}
498
499
500static void PRVM_CallProfile (prvm_prog_t *prog)
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}
538
539void PRVM_Profile (prvm_prog_t *prog, int maxfunctions, double mintime, int sortby)
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}
646
647/*
648============
649PRVM_CallProfile_f
650
651============
652*/
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}
667
668/*
669============
670PRVM_Profile_f
671
672============
673*/
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}
699
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}
725
726void PRVM_PrintState(prvm_prog_t *prog, int stack_index)
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}
748
750void PRVM_Crash(void)
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}
783
784/*
785============================================================================
786PRVM_ExecuteProgram
787
788The interpretation main loop
789============================================================================
790*/
791
792/*
793====================
794PRVM_EnterFunction
795
796Returns the new program statement counter
797====================
798*/
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}
839
840/*
841====================
842PRVM_LeaveFunction
843====================
844*/
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}
891
893{
894 // dump the stack
895 prog->depth = 0;
896 prog->localstack_used = 0;
897 // reset the string table
898 // nothing here yet
899}
900
901/*
902==================
903Coverage
904==================
905*/
906// Note: in these two calls, prog->xfunction is assumed to be sane.
907static const char *PRVM_WhereAmI(char *buf, size_t bufsize, prvm_prog_t *prog, mfunction_t *func, int statement)
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}
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}
924void PRVM_ExplicitCoverageEvent(prvm_prog_t *prog, mfunction_t *func, int statement)
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}
930static void PRVM_StatementCoverageEvent(prvm_prog_t *prog, mfunction_t *func, int statement)
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}
936
937#if defined (__GNUC__) || (__clang__) || (__TINYC__)
938# ifndef CONFIG_PEDANTIC
939# define HAVE_COMPUTED_GOTOS 1
940# endif
941#endif
942
943#define OPA ((prvm_eval_t *)&globals[st->operand[0]])
944#define OPB ((prvm_eval_t *)&globals[st->operand[1]])
945#define OPC ((prvm_eval_t *)&globals[st->operand[2]])
946extern cvar_t prvm_traceqc;
950
951#define PRVM_GLOBALSBASE 0x80000000
952
953// These do not change.
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
969
970// These may become out of date when a builtin is called, and are updated accordingly.
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
979
980#define DO_DECLARE(t) t
981#define NO_DECLARE(t)
982
983#ifdef PROFILING
984#ifdef CONFIG_MENU
985/*
986====================
987MVM_ExecuteProgram
988====================
989*/
990void MVM_ExecuteProgram (prvm_prog_t *prog, func_t fnum, const char *errormessage)
991{
992 mstatement_t *st, *startst;
993 mfunction_t *func, *enterfunc;
994 prvm_edict_t *ed;
995 prvm_eval_t *ptr;
996 int jumpcount, cachedpr_trace, exitdepth;
997 int restorevm_tempstringsbuf_cursize;
998 double calltime;
999 double tm, starttm;
1000 prvm_vec_t tempfloat;
1003
1004 calltime = Sys_DirtyTime();
1005
1006 if (!fnum || fnum >= (unsigned int)prog->numfunctions)
1007 {
1010 prog->error_cmd("MVM_ExecuteProgram: %s", errormessage);
1011 }
1012
1013 func = &prog->functions[fnum];
1014
1015 // after executing this function, delete all tempstrings it created
1016 restorevm_tempstringsbuf_cursize = prog->tempstringsbuf.cursize;
1017
1018 prog->trace = prvm_traceqc.integer;
1019
1020 // we know we're done when pr_depth drops to this
1021 exitdepth = prog->depth;
1022
1023// make a stack frame
1024 st = &prog->statements[PRVM_EnterFunction(prog, func)];
1025 // save the starting statement pointer for profiling
1026 // (when the function exits or jumps, the (st - startst) integer value is
1027 // added to the function's profile counter)
1028 startst = st;
1029 starttm = calltime;
1030 // instead of counting instructions, we count jumps
1031 jumpcount = 0;
1032 // add one to the callcount of this function because otherwise engine-called functions aren't counted
1033 if (prog->xfunction->callcount++ == 0 && (prvm_coverage.integer & 1))
1035
1036chooseexecprogram:
1037 cachedpr_trace = prog->trace;
1038 if (prog->trace || prog->watch_global_type != ev_void || prog->watch_field_type != ev_void || prog->break_statement >= 0)
1039 {
1040#define PRVMSLOWINTERPRETER 1
1042 {
1043#define PRVMTIMEPROFILING 1
1044#include "prvm_execprogram.h"
1045#undef PRVMTIMEPROFILING
1046 }
1047 else
1048 {
1049#include "prvm_execprogram.h"
1050 }
1051#undef PRVMSLOWINTERPRETER
1052 }
1053 else
1054 {
1056 {
1057#define PRVMTIMEPROFILING 1
1058#include "prvm_execprogram.h"
1059#undef PRVMTIMEPROFILING
1060 }
1061 else
1062 {
1063#include "prvm_execprogram.h"
1064 }
1065 }
1066
1067cleanup:
1068 if (developer_insane.integer && prog->tempstringsbuf.cursize > restorevm_tempstringsbuf_cursize)
1069 Con_DPrintf("MVM_ExecuteProgram: %s used %i bytes of tempstrings\n", PRVM_GetString(prog, prog->functions[fnum].s_name), prog->tempstringsbuf.cursize - restorevm_tempstringsbuf_cursize);
1070 // delete tempstrings created by this function
1071 prog->tempstringsbuf.cursize = restorevm_tempstringsbuf_cursize;
1072
1073 tm = Sys_DirtyTime() - calltime;if (tm < 0 || tm >= 1800) tm = 0;
1074 func->totaltime += tm;
1075
1076 if (prog == SVVM_prog)
1078}
1079#endif // CONFIG_MENU
1080
1081/*
1082====================
1083CLVM_ExecuteProgram
1084====================
1085*/
1086void CLVM_ExecuteProgram (prvm_prog_t *prog, func_t fnum, const char *errormessage)
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}
1175#endif // PROFILING
1176
1177/*
1178====================
1179SVVM_ExecuteProgram
1180====================
1181*/
1182#ifdef PROFILING
1183void SVVM_ExecuteProgram (prvm_prog_t *prog, func_t fnum, const char *errormessage)
1184#else
1185void PRVM_ExecuteProgram (prvm_prog_t *prog, func_t fnum, const char *errormessage)
1186#endif
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}
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
char * va(char *buf, size_t buflen, const char *format,...)
Definition common.c:972
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
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 dp_strlcpy(dst, src, dsize)
Definition common.h:303
void Con_Print(const char *msg)
Prints to all appropriate console targets, and adds timestamps.
Definition console.c:1504
void Con_DPrintf(const char *fmt,...)
A Con_Printf that only shows up if the "developer" cvar is set.
Definition console.c:1544
void Con_Printf(const char *fmt,...)
Prints to all appropriate console targets.
Definition console.c:1514
entity self
void CSQC_Shutdown()
#define STRING_COLOR_TAG
Definition draw.h:140
static int(ZEXPORT *qz_inflate)(z_stream *strm
GLint GLenum GLsizei GLsizei GLsizei depth
Definition glquake.h:648
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition glquake.h:657
const GLchar * name
Definition glquake.h:601
cvar_t developer_insane
Definition host.c:50
#define max(A, B)
Definition mathlib.h:38
float strlen(string s)
void cmd(string command,...)
unsigned int func_t
Definition pr_comp.h:26
@ OP_IF
Definition pr_comp.h:104
@ OP_GOTO
Definition pr_comp.h:116
@ OP_IFNOT
Definition pr_comp.h:105
@ ev_void
Definition pr_comp.h:29
#define OFS_PARM0
Definition pr_comp.h:34
#define PRVM_clientfunction(funcname)
Definition progsvm.h:194
#define CLVM_prog
Definition progsvm.h:767
@ PRVM_PROG_MAX
Definition progsvm.h:757
mfunction_t * PRVM_ED_FindFunction(prvm_prog_t *prog, const char *name)
Definition prvm_edict.c:425
const char * PRVM_GetString(prvm_prog_t *prog, int num)
void PRVM_Prog_Reset(prvm_prog_t *prog)
#define PRVM_MAX_STACK_DEPTH
Definition progsvm.h:248
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
#define PRVM_PROG_TO_EDICT(n)
Definition progsvm.h:877
char * PRVM_GlobalString(prvm_prog_t *prog, int ofs, char *line, size_t linelength)
Definition prvm_edict.c:602
#define PRVM_LOCALSTACK_SIZE
Definition progsvm.h:249
#define PRVM_serverfunction(funcname)
Definition progsvm.h:182
#define PRVM_GetProg(n)
Definition progsvm.h:764
#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
static void PRVM_StatementCoverageEvent(prvm_prog_t *prog, mfunction_t *func, int statement)
Definition prvm_exec.c:930
cvar_t prvm_coverage
Definition prvm_edict.c:39
cvar_t prvm_gameplayfix_div0is0
Definition prvm_edict.c:57
void PRVM_Crash(void)
Definition prvm_exec.c:750
void PRVM_ChildProfile_f(cmd_state_t *cmd)
Definition prvm_exec.c:700
void PRVM_Init_Exec(prvm_prog_t *prog)
Definition prvm_exec.c:892
#define CACHE_UNCHANGING()
Definition prvm_exec.c:954
cvar_t prvm_timeprofiling
Definition prvm_edict.c:38
static const char * PRVM_WhereAmI(char *buf, size_t bufsize, prvm_prog_t *prog, mfunction_t *func, int statement)
Definition prvm_exec.c:907
#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
void PRVM_PrintFunction_f(cmd_state_t *cmd)
Definition prvm_exec.c:416
void SVVM_ExecuteProgram(prvm_prog_t *prog, func_t fnum, const char *errormessage)
Definition prvm_exec.c:1183
qbool prvm_runawaycheck
Definition prvm_edict.c:60
cvar_t prvm_statementprofiling
Definition prvm_exec.c:947
static int PRVM_EnterFunction(prvm_prog_t *prog, mfunction_t *f)
Definition prvm_exec.c:799
static void PRVM_CallProfile(prvm_prog_t *prog)
Definition prvm_exec.c:500
void PRVM_ExplicitCoverageEvent(prvm_prog_t *prog, mfunction_t *func, int statement)
Definition prvm_exec.c:924
void PRVM_Profile_f(cmd_state_t *cmd)
Definition prvm_exec.c:674
void CLVM_ExecuteProgram(prvm_prog_t *prog, func_t fnum, const char *errormessage)
Definition prvm_exec.c:1086
void PRVM_Profile(prvm_prog_t *prog, int maxfunctions, double mintime, int sortby)
Definition prvm_exec.c:539
void PRVM_PrintFunctionStatements(prvm_prog_t *prog, const char *name)
Definition prvm_exec.c:374
void PRVM_CallProfile_f(cmd_state_t *cmd)
Definition prvm_exec.c:653
#define DO_DECLARE(t)
Definition prvm_exec.c:980
static int PRVM_LeaveFunction(prvm_prog_t *prog)
Definition prvm_exec.c:845
cvar_t prvm_traceqc
Definition prvm_edict.c:35
void PRVM_StackTrace(prvm_prog_t *prog)
Definition prvm_exec.c:436
void PRVM_PrintState(prvm_prog_t *prog, int stack_index)
Definition prvm_exec.c:726
static const char * prvm_opnames[]
Definition prvm_exec.c:27
cvar_t prvm_errordump
Definition prvm_edict.c:44
void PRVM_ShortStackTrace(prvm_prog_t *prog, char *buf, size_t bufsize)
Definition prvm_exec.c:464
static void PRVM_PrintStatement(prvm_prog_t *prog, mstatement_t *s)
Definition prvm_exec.c:329
int i
#define MAX_INPUTLINE
maximum size of console commandline, QuakeC strings, and many other text processing buffers
Definition qdefs.h:94
#define NULL
Definition qtypes.h:12
bool qbool
Definition qtypes.h:9
float prvm_vec_t
Definition qtypes.h:55
void SV_FlushBroadcastMessages(void)
Definition sv_send.c:1371
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
float f
command interpreter state - the tokenizing and execution of commands, as well as pointers to which cv...
Definition cmd.h:127
Definition cvar.h:66
int integer
Definition cvar.h:73
double callcount
Definition pr_comp.h:453
int32_t first_statement
Definition pr_comp.h:444
int32_t s_file
Definition pr_comp.h:461
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
int32_t s_name
Definition pr_comp.h:460
int32_t locals
Definition pr_comp.h:446
double totaltime
Definition pr_comp.h:454
int32_t parm_start
Definition pr_comp.h:445
double profile_total
Definition pr_comp.h:456
opcode_t op
Definition pr_comp.h:470
int operand[3]
Definition pr_comp.h:471
const char * statestring
printed together with backtraces
Definition progsvm.h:717
int * statement_linenums
NULL if not available.
Definition progsvm.h:570
mfunction_t * functions
Definition progsvm.h:541
int statements_covered
Definition progsvm.h:574
const char * name
name of the prog, e.g. "Server", "Client" or "Menu" (used for text output)
Definition progsvm.h:700
void(* error_cmd)(const char *format,...) DP_FUNC_PRINTF(1) DP_FUNC_NORETURN
[INIT]
Definition progsvm.h:747
prvm_int_t * ip
Definition progsvm.h:581
etype_t watch_field_type
Definition progsvm.h:617
int numfunctions
Definition progsvm.h:566
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
int explicit_covered
Definition progsvm.h:576
int break_statement
Definition progsvm.h:610
prvm_int_t localstack[PRVM_LOCALSTACK_SIZE]
Definition progsvm.h:628
double * statement_profile
only incremented if prvm_statementprofiling is on
Definition progsvm.h:573
int functions_covered
Definition progsvm.h:542
etype_t watch_global_type
Definition progsvm.h:613
int numstatements
Definition progsvm.h:563
int xstatement
Definition progsvm.h:621
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
int numexplicitcoveragestatements
Definition progsvm.h:577
mfunction_t * xfunction
Definition progsvm.h:620
union prvm_prog_t::@31 globals
double profiletime
system time when last PRVM_CallProfile was called (or PRVM_Prog_Load initially)
Definition progsvm.h:540
int * statement_columnnums
NULL if not available.
Definition progsvm.h:571
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
int cursize
Definition common.h:54
double Sys_DirtyTime(void)
Definition sys_shared.c:417