From: Rudolf Polzer <divVerent@gmail.com>
Date: Mon, 23 Sep 2024 13:02:27 +0000 (+0200)
Subject: Remove the `jumpabsolute` member from `mstatement_s`.
X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=refs%2Fheads%2FdivVerent%2Fmstatement-smaller;p=xonotic%2Fdarkplaces.git

Remove the `jumpabsolute` member from `mstatement_s`.

This reduces the struct from 20 to 16 bytes, and thus may save some
RAM. It also may improve CPU cache behavior by keeping more QC code in
L1 and L2 cache, and possibly also improve instruction processing inside
the CPU as all statements are aligned the same way.

On `srv04`, this speeds up Xonotic's `serverbench` from 58.92s real,
57.72s user to 57.72s real, 56.59s user (median of 25).
---

diff --git a/pr_comp.h b/pr_comp.h
index f69b6320..7ca0c28a 100644
--- a/pr_comp.h
+++ b/pr_comp.h
@@ -409,8 +409,7 @@ mfunction_t;
 typedef struct mstatement_s
 {
 	opcode_t	op;
-	int			operand[3]; // always a global or -1 for unused
-	int			jumpabsolute; // only used by IF, IFNOT, GOTO
+	int			operand[3]; // always a global, or a relative statement offset ([0] for GOTO, [1] for IF/IFNOT), or -1 for unused
 }
 mstatement_t;
 
diff --git a/prvm_edict.c b/prvm_edict.c
index cc318e99..3d510187 100644
--- a/prvm_edict.c
+++ b/prvm_edict.c
@@ -2294,19 +2294,17 @@ void PRVM_Prog_Load(prvm_prog_t *prog, const char *filename, unsigned char *data
 				prog->error_cmd("%s: out of bounds IF/IFNOT (statement %d) in %s", __func__, i, prog->name);
 			prog->statements[i].op = op;
 			prog->statements[i].operand[0] = remapglobal(a);
-			prog->statements[i].operand[1] = -1;
+			prog->statements[i].operand[1] = b;
 			prog->statements[i].operand[2] = -1;
-			prog->statements[i].jumpabsolute = i + b;
 			break;
 		case OP_GOTO:
 			a = (short)a;
 			if (a + i < 0 || a + i >= prog->progs_numstatements)
 				prog->error_cmd("%s: out of bounds GOTO (statement %d) in %s", __func__, i, prog->name);
 			prog->statements[i].op = op;
-			prog->statements[i].operand[0] = -1;
+			prog->statements[i].operand[0] = a;
 			prog->statements[i].operand[1] = -1;
 			prog->statements[i].operand[2] = -1;
-			prog->statements[i].jumpabsolute = i + a;
 			break;
 		default:
 			Con_DPrintf("%s: unknown opcode %d at statement %d in %s\n", __func__, (int)op, i, prog->name);
@@ -2316,7 +2314,6 @@ void PRVM_Prog_Load(prvm_prog_t *prog, const char *filename, unsigned char *data
 			prog->statements[i].operand[0] = 0;
 			prog->statements[i].operand[1] =
 			prog->statements[i].operand[2] = op;
-			prog->statements[i].jumpabsolute = -1;
 			break;
 		case OP_STORE_I:
 		case OP_ADD_I:
@@ -2427,7 +2424,6 @@ void PRVM_Prog_Load(prvm_prog_t *prog, const char *filename, unsigned char *data
 			prog->statements[i].operand[0] = remapglobal(a);
 			prog->statements[i].operand[1] = remapglobal(b);
 			prog->statements[i].operand[2] = remapglobal(c);
-			prog->statements[i].jumpabsolute = -1;
 			break;
 		// global none global
 		case OP_NOT_F:
@@ -2441,7 +2437,6 @@ void PRVM_Prog_Load(prvm_prog_t *prog, const char *filename, unsigned char *data
 			prog->statements[i].operand[0] = remapglobal(a);
 			prog->statements[i].operand[1] = -1;
 			prog->statements[i].operand[2] = remapglobal(c);
-			prog->statements[i].jumpabsolute = -1;
 			break;
 		// 2 globals
 		case OP_STOREP_F:
@@ -2466,7 +2461,6 @@ void PRVM_Prog_Load(prvm_prog_t *prog, const char *filename, unsigned char *data
 			prog->statements[i].operand[0] = remapglobal(a);
 			prog->statements[i].operand[1] = remapglobal(b);
 			prog->statements[i].operand[2] = -1;
-			prog->statements[i].jumpabsolute = -1;
 			break;
 		// 1 global
 		case OP_CALL0:
@@ -2493,7 +2487,6 @@ void PRVM_Prog_Load(prvm_prog_t *prog, const char *filename, unsigned char *data
 			prog->statements[i].operand[0] = remapglobal(a);
 			prog->statements[i].operand[1] = -1;
 			prog->statements[i].operand[2] = -1;
-			prog->statements[i].jumpabsolute = -1;
 			break;
 		}
 	}
diff --git a/prvm_exec.c b/prvm_exec.c
index 3c68f6d1..e7f54680 100644
--- a/prvm_exec.c
+++ b/prvm_exec.c
@@ -332,10 +332,17 @@ static void PRVM_PrintStatement(prvm_prog_t *prog, mstatement_t *s)
 	for ( ; i<10 ; i++)
 		Con_Print(" ");
 
-	if (s->operand[0] >= 0) Con_Printf(  "%s", PRVM_GlobalString(prog, s->operand[0], valuebuf, sizeof(valuebuf)));
-	if (s->operand[1] >= 0) Con_Printf(", %s", PRVM_GlobalString(prog, s->operand[1], valuebuf, sizeof(valuebuf)));
+	if (s->op == OP_GOTO) {
+		Con_Printf("statement %i", (int)(s - prog->statements) + s->operand[0]);
+	} else {
+		if (s->operand[0] >= 0) Con_Printf(  "%s", PRVM_GlobalString(prog, s->operand[0], valuebuf, sizeof(valuebuf)));
+	}
+	if (s->op == OP_IF || s->op == OP_IFNOT) {
+		Con_Printf(", statement %i", (int)(s - prog->statements) + s->operand[1]);
+	} else {
+		if (s->operand[1] >= 0) Con_Printf(", %s", PRVM_GlobalString(prog, s->operand[1], valuebuf, sizeof(valuebuf)));
+	}
 	if (s->operand[2] >= 0) Con_Printf(", %s", PRVM_GlobalString(prog, s->operand[2], valuebuf, sizeof(valuebuf)));
-	if (s->jumpabsolute >= 0) Con_Printf(", statement %i", s->jumpabsolute);
 	Con_Print("\n");
 }
 
diff --git a/prvm_execprogram.h b/prvm_execprogram.h
index 2a70bfc8..34dd8d29 100644
--- a/prvm_execprogram.h
+++ b/prvm_execprogram.h
@@ -637,7 +637,7 @@ int i;
 				// and entity, string, field values can never have that value
 				{
 					ADVANCE_PROFILE_BEFORE_JUMP();
-					st = cached_statements + st->jumpabsolute - 1;	// offset the st++
+					st += st->operand[1] - 1;	// offset the st++
 					startst = st;
 					// no bounds check needed, it is done when loading progs
 					if (++jumpcount == 10000000 && prvm_runawaycheck)
@@ -657,7 +657,7 @@ int i;
 				// and entity, string, field values can never have that value
 				{
 					ADVANCE_PROFILE_BEFORE_JUMP();
-					st = cached_statements + st->jumpabsolute - 1;	// offset the st++
+					st += st->operand[1] - 1;	// offset the st++
 					startst = st;
 					// no bounds check needed, it is done when loading progs
 					if (++jumpcount == 10000000 && prvm_runawaycheck)
@@ -671,7 +671,7 @@ int i;
 
 			HANDLE_OPCODE(OP_GOTO):
 				ADVANCE_PROFILE_BEFORE_JUMP();
-				st = cached_statements + st->jumpabsolute - 1;	// offset the st++
+				st += st->operand[0] - 1;	// offset the st++
 				startst = st;
 				// no bounds check needed, it is done when loading progs
 				if (++jumpcount == 10000000 && prvm_runawaycheck)