From e5ef25591d98322cb56c99e54158535fa6bbfbc6 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Sat, 17 Oct 2009 00:33:23 +0000 Subject: [PATCH] - Use a union, rather than pointer aliasing, to access the parts of a VM instruction. SVN r1922 (scripting) --- src/autostart.cpp | 10 ++-- src/info.cpp | 4 +- src/thingdef/thingdef.cpp | 2 +- src/zscript/vm.h | 46 +++++++++++++++--- src/zscript/vmbuilder.cpp | 50 +++++++++----------- src/zscript/vmbuilder.h | 2 +- src/zscript/vmdisasm.cpp | 98 +++++++++++++++++++-------------------- src/zscript/vmexec.cpp | 32 ++++++------- src/zscript/vmexec.h | 72 ++++++++++++++-------------- src/zscript/vmframe.cpp | 9 ++-- 10 files changed, 171 insertions(+), 154 deletions(-) diff --git a/src/autostart.cpp b/src/autostart.cpp index 3822bafc1..7babed907 100644 --- a/src/autostart.cpp +++ b/src/autostart.cpp @@ -98,11 +98,11 @@ __declspec(allocate(".yreg$a")) void *const YRegHead = 0; // (There are linker scripts, but that apparently involves extracting the // default script from ld and then modifying it.) -void *ARegHead const __attribute__((section(SECTION_AREG))) = 0; -void *CRegHead const __attribute__((section(SECTION_CREG))) = 0; -void *GRegHead const __attribute__((section(SECTION_GREG))) = 0; -void *MRegHead const __attribute__((section(SECTION_MREG))) = 0; -void *YRegHead const __attribute__((section(SECTION_YREG))) = 0; +void *const ARegHead __attribute__((section(SECTION_AREG))) = 0; +void *const CRegHead __attribute__((section(SECTION_CREG))) = 0; +void *const GRegHead __attribute__((section(SECTION_GREG))) = 0; +void *const MRegHead __attribute__((section(SECTION_MREG))) = 0; +void *const YRegHead __attribute__((section(SECTION_YREG))) = 0; #else diff --git a/src/info.cpp b/src/info.cpp index 8f36ffac4..4d56875e3 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -94,11 +94,11 @@ void FState::SetAction(PSymbolActionFunction *func, bool setdefaultparams) // Create a function for this state. VMScriptFunction *vmfunc = new VMScriptFunction; - VM_UBYTE *code = vmfunc->AllocCode(sizeof(codetemplate)/VM_OPSIZE); + VMOP *code = vmfunc->AllocCode(sizeof(codetemplate)/sizeof(VMOP)); memcpy(code, codetemplate, sizeof(codetemplate)); FVoidObj *konsta = vmfunc->AllocKonstA(2); VM_ATAG *atag = vmfunc->KonstATags(); - konsta[0].v = func->Function; + konsta[0].v = (void *)func->Function; konsta[1].o = callfunc; atag[0] = ATAG_GENERIC; atag[1] = ATAG_OBJECT; diff --git a/src/thingdef/thingdef.cpp b/src/thingdef/thingdef.cpp index 29e23a039..605f161e5 100644 --- a/src/thingdef/thingdef.cpp +++ b/src/thingdef/thingdef.cpp @@ -316,7 +316,7 @@ static void FinishThingdef() func->NumRegD, func->NumRegF, func->NumRegA, func->NumRegS, func->MaxParam); VMDumpConstants(dump, func); fprintf(dump, "\nDisassembly:\n"); - VMDisasm(dump, func->Code, func->NumCodeBytes / 4, func); + VMDisasm(dump, func->Code, func->CodeSize, func); #endif //if(i==6) I_Error("Poop"); } diff --git a/src/zscript/vm.h b/src/zscript/vm.h index 95c32dd5c..16987ed72 100644 --- a/src/zscript/vm.h +++ b/src/zscript/vm.h @@ -17,7 +17,41 @@ typedef signed int VM_SWORD; typedef VM_UBYTE VM_ATAG; #define VM_EPSILON (1/1024.0) -#define VM_OPSIZE 4 // Number of bytes used by one opcode + +union VMOP +{ + struct + { + VM_UBYTE op, a, b, c; + }; + struct + { + VM_SBYTE pad0, as, bs, cs; + }; + struct + { + VM_SWORD pad1:8, i24:24; + }; + struct + { + VM_SWORD pad2:16, i16:16; + }; + struct + { + VM_UHALF pad3, i16u; + }; + VM_UWORD word; + + // Interesting fact: VC++ produces better code for i16 when it's defined + // as a bitfield than when it's defined as two discrete units. + // Compare: + // mov eax,dword ptr [op] ; As two discrete units + // shr eax,10h + // movsx eax,ax + // versus: + // mov eax,dword ptr [op] ; As a bitfield + // sar eax,10h +}; enum { @@ -685,7 +719,7 @@ public: VMScriptFunction(); ~VMScriptFunction(); size_t PropagateMark(); - VM_UBYTE *AllocCode(int numops); + VMOP *AllocCode(int numops); int *AllocKonstD(int numkonst); double *AllocKonstF(int numkonst); FString *AllocKonstS(int numkonst); @@ -694,13 +728,13 @@ public: VM_ATAG *KonstATags() { return (VM_UBYTE *)(KonstA + NumKonstA); } const VM_ATAG *KonstATags() const { return (VM_UBYTE *)(KonstA + NumKonstA); } - VM_UBYTE *Code; + VMOP *Code; int *KonstD; double *KonstF; FString *KonstS; FVoidObj *KonstA; int ExtraSpace; - int NumCodeBytes; + int CodeSize; // Size of code in instructions (not bytes) VM_UBYTE NumRegD; VM_UBYTE NumRegF; VM_UBYTE NumRegS; @@ -809,10 +843,10 @@ enum EVMEngine }; void VMSelectEngine(EVMEngine engine); -extern int (*VMExec)(VMFrameStack *stack, const VM_UBYTE *pc, VMReturn *ret, int numret); +extern int (*VMExec)(VMFrameStack *stack, const VMOP *pc, VMReturn *ret, int numret); void VMFillParams(VMValue *params, VMFrame *callee, int numparam); void VMDumpConstants(FILE *out, const VMScriptFunction *func); -void VMDisasm(FILE *out, const VM_UBYTE *code, int codesize, const VMScriptFunction *func); +void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction *func); #endif diff --git a/src/zscript/vmbuilder.cpp b/src/zscript/vmbuilder.cpp index 450190ddf..b681c3d66 100644 --- a/src/zscript/vmbuilder.cpp +++ b/src/zscript/vmbuilder.cpp @@ -39,7 +39,7 @@ VMScriptFunction *VMFunctionBuilder::MakeFunction() VMScriptFunction *func = new VMScriptFunction; // Copy code block. - memcpy(func->AllocCode(Code.Size()), &Code[0], Code.Size()); + memcpy(func->AllocCode(Code.Size()), &Code[0], Code.Size() * sizeof(VMOP)); // Create constant tables. if (NumIntConstants > 0) @@ -425,12 +425,6 @@ size_t VMFunctionBuilder::Emit(int opcode, int opa, int opb, int opc) assert(opa >= 0 && opa <= 255); assert(opb >= 0 && opb <= 255); assert(opc >= 0 && opc <= 255); - size_t loc = Code.Reserve(4); - VM_UBYTE *code = &Code[loc]; - code[0] = opcode; - code[1] = opa; - code[2] = opb; - code[3] = opc; if (opcode == OP_PARAM) { ParamChange(1); @@ -439,7 +433,12 @@ size_t VMFunctionBuilder::Emit(int opcode, int opa, int opb, int opc) { ParamChange(-opb); } - return loc / 4; + VMOP op; + op.op = opcode; + op.a = opa; + op.b = opb; + op.c = opc; + return Code.Push(op); } size_t VMFunctionBuilder::Emit(int opcode, int opa, VM_SHALF opbc) @@ -447,29 +446,25 @@ size_t VMFunctionBuilder::Emit(int opcode, int opa, VM_SHALF opbc) assert(opcode >= 0 && opcode < NUM_OPS); assert(opa >= 0 && opa <= 255); assert(opbc >= -32768 && opbc <= 32767); - size_t loc = Code.Reserve(4); - VM_UBYTE *code = &Code[loc]; - code[0] = opcode; - code[1] = opa; - *(VM_SHALF *)&code[2] = opbc; - return loc / 4; + VMOP op; + op.op = opcode; + op.a = opa; + op.i16 = opbc; + return Code.Push(op); } size_t VMFunctionBuilder::Emit(int opcode, int opabc) { assert(opcode >= 0 && opcode < NUM_OPS); assert(opabc >= -(1 << 23) && opabc <= (1 << 24) - 1); - size_t loc = Code.Reserve(4); -#ifdef __BIG_ENDIAN__ - *(VM_UWORD *)&Code[loc] = (opabc & 0xFFFFFF) | (opcode << 24); -#else - *(VM_UWORD *)&Code[loc] = opcode | (opabc << 8); -#endif if (opcode == OP_PARAMI) { ParamChange(1); } - return loc / 4; + VMOP op; + op.op = opcode; + op.i24 = opabc; + return Code.Push(op); } //========================================================================== @@ -504,14 +499,11 @@ size_t VMFunctionBuilder::EmitLoadInt(int regnum, int value) void VMFunctionBuilder::Backpatch(size_t loc, size_t target) { - assert(loc < Code.Size() / 4); + assert(loc < Code.Size()); int offset = int(target - loc - 1); - assert(offset >= -(1 << 24) && offset <= (1 << 24) - 1); -#ifdef __BIG_ENDIAN__ - *(VM_UWORD *)&Code[loc * 4] = (offset & 0xFFFFFF) | (OP_JMP << 24); -#else - *(VM_UWORD *)&Code[loc * 4] = OP_JMP | (offset << 8); -#endif + assert(((offset << 8) >> 8) == offset); + Code[loc].op = OP_JMP; + Code[loc].i24 = offset; } //========================================================================== @@ -525,5 +517,5 @@ void VMFunctionBuilder::Backpatch(size_t loc, size_t target) void VMFunctionBuilder::BackpatchToHere(size_t loc) { - Backpatch(loc, Code.Size() / 4); + Backpatch(loc, Code.Size()); } diff --git a/src/zscript/vmbuilder.h b/src/zscript/vmbuilder.h index 328377f67..2399411f6 100644 --- a/src/zscript/vmbuilder.h +++ b/src/zscript/vmbuilder.h @@ -70,7 +70,7 @@ private: int MaxParam; int ActiveParam; - TArray Code; + TArray Code; // PARAM increases ActiveParam; CALL decreases it. void ParamChange(int delta); diff --git a/src/zscript/vmdisasm.cpp b/src/zscript/vmdisasm.cpp index 0864e881b..e8217815d 100644 --- a/src/zscript/vmdisasm.cpp +++ b/src/zscript/vmdisasm.cpp @@ -94,14 +94,6 @@ const VMOpInfo OpInfo[NUM_OPS] = #include "vmops.h" }; -#ifdef WORDS_BIGENDIAN -#define ABCs(x) ((*(VM_SWORD *)(x) << 8) >> 8) -#define JMPOFS(x) ((*(VM_SWORD *)(x) << 8) >> 6) -#else -#define ABCs(x) (*(VM_SWORD *)(x) >> 8) -#define JMPOFS(x) ((*(VM_SWORD *)(x) >> 6) & ~3) -#endif - static int print_reg(FILE *out, int col, int arg, int mode, int immshift, const VMScriptFunction *func); static int printf_wrapper(FILE *f, const char *fmt, ...) @@ -179,21 +171,21 @@ void VMDumpConstants(FILE *out, const VMScriptFunction *func) } } -void VMDisasm(FILE *out, const VM_UBYTE *code, int codesize, const VMScriptFunction *func) +void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction *func) { const char *name; int col; int mode; int a; - for (int i = 0; i < codesize; i += 4) + for (int i = 0; i < codesize; ++i) { - name = OpInfo[code[i]].Name; - mode = OpInfo[code[i]].Mode; - a = code[i+1]; + name = OpInfo[code[i].op].Name; + mode = OpInfo[code[i].op].Mode; + a = code[i].a; // String comparison encodes everything in a single instruction. - if (code[i] == OP_CMPS) + if (code[i].op == OP_CMPS) { switch (a & CMP_METHOD_MASK) { @@ -207,31 +199,31 @@ void VMDisasm(FILE *out, const VM_UBYTE *code, int codesize, const VMScriptFunct a &= CMP_CHECK | CMP_APPROX; } - printf_wrapper(out, "%08x: %02x%02x%02x%02x %-8s", i, code[i], code[i+1], code[i+2], code[i+3], name); + printf_wrapper(out, "%08x: %02x%02x%02x%02x %-8s", i << 2, code[i].op, code[i].a, code[i].b, code[i].c, name); col = 0; - switch (code[i]) + switch (code[i].op) { case OP_JMP: case OP_TRY: - col = printf_wrapper(out, "%08x", i + 4 + JMPOFS(&code[i])); + col = printf_wrapper(out, "%08x", i + 4 + (code[i].i24 << 2)); break; case OP_PARAMI: - col = printf_wrapper(out, "%d", ABCs(&code[i])); + col = printf_wrapper(out, "%d", code[i].i24); break; case OP_RET: - if (code[i+2] != REGT_NIL) + if (code[i].b != REGT_NIL) { - if ((code[i+2] & REGT_FINAL) && a == 0) + if ((code[i].b & REGT_FINAL) && a == 0) { - col = print_reg(out, 0, *(VM_UHALF *)&code[i+2], MODE_PARAM, 16, func); + col = print_reg(out, 0, code[i].i16u, MODE_PARAM, 16, func); } else { col = print_reg(out, 0, a, (mode & MODE_ATYPE) >> MODE_ASHIFT, 24, func); - col += print_reg(out, col, *(VM_UHALF *)&code[i+2], MODE_PARAM, 16, func); - if (code[i+2] & REGT_FINAL) + col += print_reg(out, col, code[i].i16u, MODE_PARAM, 16, func); + if (code[i].b & REGT_FINAL) { col += printf_wrapper(out, " [final]"); } @@ -242,7 +234,7 @@ void VMDisasm(FILE *out, const VM_UBYTE *code, int codesize, const VMScriptFunct default: if ((mode & MODE_BCTYPE) == MODE_BCCAST) { - switch (code[i+3]) + switch (code[i].c) { case CAST_I2F: mode = MODE_AF | MODE_BI | MODE_CUNUSED; @@ -273,11 +265,11 @@ void VMDisasm(FILE *out, const VM_UBYTE *code, int codesize, const VMScriptFunct col = print_reg(out, 0, a, (mode & MODE_ATYPE) >> MODE_ASHIFT, 24, func); if ((mode & MODE_BCTYPE) == MODE_BCTHROW) { - mode = (code[i+1] == 0) ? (MODE_BP | MODE_CUNUSED) : (MODE_BKP | MODE_CUNUSED); + mode = (code[i].a == 0) ? (MODE_BP | MODE_CUNUSED) : (MODE_BKP | MODE_CUNUSED); } else if ((mode & MODE_BCTYPE) == MODE_BCCATCH) { - switch (code[i+1]) + switch (code[i].a) { case 0: mode = MODE_BUNUSED | MODE_CUNUSED; @@ -298,12 +290,12 @@ void VMDisasm(FILE *out, const VM_UBYTE *code, int codesize, const VMScriptFunct } if ((mode & (MODE_BTYPE | MODE_CTYPE)) == MODE_BCJOINT) { - col += print_reg(out, col, *(VM_UHALF *)&code[i+2], (mode & MODE_BCTYPE) >> MODE_BCSHIFT, 16, func); + col += print_reg(out, col, code[i].i16u, (mode & MODE_BCTYPE) >> MODE_BCSHIFT, 16, func); } else { - col += print_reg(out, col, code[i+2], (mode & MODE_BTYPE) >> MODE_BSHIFT, 24, func); - col += print_reg(out, col, code[i+3], (mode & MODE_CTYPE) >> MODE_CSHIFT, 24, func); + col += print_reg(out, col, code[i].b, (mode & MODE_BTYPE) >> MODE_BSHIFT, 24, func); + col += print_reg(out, col, code[i].c, (mode & MODE_CTYPE) >> MODE_CSHIFT, 24, func); } break; } @@ -312,13 +304,13 @@ void VMDisasm(FILE *out, const VM_UBYTE *code, int codesize, const VMScriptFunct col = 30; } printf_wrapper(out, "%*c", 30 - col, ';'); - if (code[i] == OP_JMP || code[i] == OP_TRY) + if (code[i].op == OP_JMP || code[i].op == OP_TRY || code[i].op == OP_PARAMI) { - printf_wrapper(out, "%d\n", JMPOFS(&code[i]) >> 2); + printf_wrapper(out, "%d\n", code[i].i24); } else { - printf_wrapper(out, "%d,%d,%d\n", code[i+1], code[i+2], code[i+3]); + printf_wrapper(out, "%d,%d,%d\n", code[i].a, code[i].b, code[i].c); } } } @@ -385,40 +377,46 @@ static int print_reg(FILE *out, int col, int arg, int mode, int immshift, const case MODE_PARAM: { - union { VM_UHALF Together; struct { VM_UBYTE RegType, RegNum; }; } p; - p.Together = arg; - switch (p.RegType & (REGT_TYPE | REGT_KONST | REGT_MULTIREG)) + int regtype, regnum; +#ifdef __BIG_ENDIAN__ + regtype = (arg >> 8) & 255; + regnum = arg & 255; +#else + regtype = arg & 255; + regnum = (arg >> 8) & 255; +#endif + switch (regtype & (REGT_TYPE | REGT_KONST | REGT_MULTIREG)) { case REGT_INT: - return col+printf_wrapper(out, "d%d", p.RegNum); + return col+printf_wrapper(out, "d%d", regnum); case REGT_FLOAT: - return col+printf_wrapper(out, "f%d", p.RegNum); + return col+printf_wrapper(out, "f%d", regnum); case REGT_STRING: - return col+printf_wrapper(out, "s%d", p.RegNum); + return col+printf_wrapper(out, "s%d", regnum); case REGT_POINTER: - return col+printf_wrapper(out, "a%d", p.RegNum); + return col+printf_wrapper(out, "a%d", regnum); case REGT_FLOAT | REGT_MULTIREG: - return col+printf_wrapper(out, "v%d", p.RegNum); + return col+printf_wrapper(out, "v%d", regnum); case REGT_INT | REGT_KONST: - return col+print_reg(out, 0, p.RegNum, MODE_KI, 0, func); + return col+print_reg(out, 0, regnum, MODE_KI, 0, func); case REGT_FLOAT | REGT_KONST: - return col+print_reg(out, 0, p.RegNum, MODE_KF, 0, func); + return col+print_reg(out, 0, regnum, MODE_KF, 0, func); case REGT_STRING | REGT_KONST: - return col+print_reg(out, 0, p.RegNum, MODE_KS, 0, func); + return col+print_reg(out, 0, regnum, MODE_KS, 0, func); case REGT_POINTER | REGT_KONST: - return col+print_reg(out, 0, p.RegNum, MODE_KP, 0, func); + return col+print_reg(out, 0, regnum, MODE_KP, 0, func); case REGT_FLOAT | REGT_MULTIREG | REGT_KONST: - return col+print_reg(out, 0, p.RegNum, MODE_KV, 0, func); + return col+print_reg(out, 0, regnum, MODE_KV, 0, func); default: - if (p.RegType == REGT_NIL) + if (regtype == REGT_NIL) { return col+printf_wrapper(out, "nil"); } return col+printf_wrapper(out, "param[t=%d,%c,%c,n=%d]", - p.RegType & REGT_TYPE, - p.RegType & REGT_KONST ? 'k' : 'r', - p.RegType & REGT_MULTIREG ? 'm' : 's', - p.RegNum); + regtype & REGT_TYPE, + regtype & REGT_KONST ? 'k' : 'r', + regtype & REGT_MULTIREG ? 'm' : 's', + regnum); } } diff --git a/src/zscript/vmexec.cpp b/src/zscript/vmexec.cpp index 6ef11c29b..c05ebca92 100644 --- a/src/zscript/vmexec.cpp +++ b/src/zscript/vmexec.cpp @@ -9,7 +9,7 @@ #if COMPGOTO #define OP(x) x -#define NEXTOP do { unsigned op = *pc; a = pc[1]; pc += 4; goto *ops[op]; } while(0) +#define NEXTOP do { unsigned op = pc->op; a = pc->a; pc++; goto *ops[op]; } while(0) #else #define OP(x) case OP_##x #define NEXTOP break @@ -17,20 +17,14 @@ #define luai_nummod(a,b) ((a) - floor((a)/(b))*(b)) -#define A (*(pc - 3)) -#define B (*(pc - 2)) -#define C ( *(pc - 1)) -#define Cs (*(VM_SBYTE *)(pc - 1)) -#define BC (*(VM_UHALF *)(pc - 2)) -#define BCs (*(VM_SHALF *)(pc - 2)) - -#ifdef WORDS_BIGENDIAN -#define ABCs ((*(VM_SWORD *)(pc - 4) << 8) >> 8) -#define JMPOFS(x) ((*(VM_SWORD *)(x) << 8) >> 6) -#else -#define ABCs (*(VM_SWORD *)(pc - 4) >> 8) -#define JMPOFS(x) ((*(VM_SWORD *)(x) >> 6) & ~3) -#endif +#define A (pc[-1].a) +#define B (pc[-1].b) +#define C (pc[-1].c) +#define Cs (pc[-1].cs) +#define BC (pc[-1].i16u) +#define BCs (pc[-1].i16) +#define ABCs (pc[-1].i24) +#define JMPOFS(x) ((x)->i24) #define KC (konstd[C]) #define RC (reg.d[C]) @@ -52,10 +46,10 @@ #define CMPJMP(test) \ if ((test) == (a & CMP_CHECK)) { \ - assert(*pc == OP_JMP); \ - pc += 4 + JMPOFS(pc); \ + assert(pc->op == OP_JMP); \ + pc += 1 + JMPOFS(pc); \ } else { \ - pc += 4; \ + pc += 1; \ } enum @@ -112,7 +106,7 @@ struct VMExec_Unchecked #undef assert #include -int (*VMExec)(VMFrameStack *stack, const VM_UBYTE *pc, VMReturn *ret, int numret) = +int (*VMExec)(VMFrameStack *stack, const VMOP *pc, VMReturn *ret, int numret) = #ifdef NDEBUG VMExec_Unchecked::Exec #else diff --git a/src/zscript/vmexec.h b/src/zscript/vmexec.h index f8da2f291..07809909b 100644 --- a/src/zscript/vmexec.h +++ b/src/zscript/vmexec.h @@ -3,7 +3,7 @@ #endif -static int Exec(VMFrameStack *stack, const VM_UBYTE *pc, VMReturn *ret, int numret) +static int Exec(VMFrameStack *stack, const VMOP *pc, VMReturn *ret, int numret) { #if COMPGOTO static const void * const ops[256] = @@ -12,7 +12,7 @@ static int Exec(VMFrameStack *stack, const VM_UBYTE *pc, VMReturn *ret, int numr #include "vmops.h" }; #endif - const VM_UBYTE *exception_frames[MAX_TRY_DEPTH]; + const VMOP *exception_frames[MAX_TRY_DEPTH]; int try_depth = 0; VMFrame *f = stack->TopFrame(); VMScriptFunction *sfunc; @@ -52,7 +52,7 @@ begin: { #if !COMPGOTO VM_UBYTE op; - for(;;) switch(op = pc[0], a = pc[1], pc += 4, op) + for(;;) switch(op = pc->op, a = pc->a, pc++, op) #else NEXTOP; #endif @@ -383,17 +383,17 @@ begin: ASSERTD(a); if (reg.d[a] != BC) { - pc += 4; + pc++; } NEXTOP; OP(JMP): - pc += JMPOFS(pc - 4); + pc += JMPOFS(pc - 1); NEXTOP; OP(IJMP): ASSERTD(a); - pc += (BCs + reg.d[a]) << 2; - assert(*pc == OP_JMP); - pc += (1 + *((VM_SHALF *)pc + 1)) << 2; + pc += (BCs + reg.d[a]); + assert(pc->op == OP_JMP); + pc += 1 + JMPOFS(pc); NEXTOP; OP(PARAMI): assert(f->NumParam < sfunc->MaxParam); @@ -536,7 +536,7 @@ begin: { reg.param[--f->NumParam].~VMValue(); } - pc += C * 4; // Skip RESULTs + pc += C; // Skip RESULTs } NEXTOP; OP(RET): @@ -567,8 +567,8 @@ begin: { THROW(X_TOO_MANY_TRIES); } - assert(*(pc + JMPOFS(pc - 4)) == OP_CATCH); - exception_frames[try_depth++] = pc + JMPOFS(pc - 4); + assert((pc + JMPOFS(pc - 1))->op == OP_CATCH); + exception_frames[try_depth++] = pc + JMPOFS(pc - 1); NEXTOP; OP(UNTRY): assert(a <= try_depth); @@ -664,12 +664,12 @@ begin: } if (cmp == (a & CMP_CHECK)) { - assert(*pc == OP_JMP); - pc += 4 + JMPOFS(pc); + assert(pc->op == OP_JMP); + pc += 1 + JMPOFS(pc); } else { - pc += 4; + pc += 1; } } NEXTOP; @@ -1255,48 +1255,48 @@ begin: while(--try_depth >= 0) { pc = exception_frames[try_depth]; - assert(pc[0] == OP_CATCH); - while (pc[1] > 1) + assert(pc->op == OP_CATCH); + while (pc->a > 1) { // CATCH must be followed by JMP if it doesn't terminate a catch chain. - assert(pc[4] == OP_JMP); + assert(pc[1].op == OP_JMP); PClass *type; - int b = pc[2]; + int b = pc->b; - if (pc[1] == 2) + if (pc->a == 2) { ASSERTA(b); type = (PClass *)reg.a[b]; } else { - assert(pc[1] == 3); + assert(pc->a == 3); ASSERTKA(b); assert(konstatag[b] == ATAG_OBJECT); type = (PClass *)konsta[b].o; } - ASSERTA(pc[3]); + ASSERTA(pc->c); if (type == extype) { // Found a handler. Store the exception in pC, skip the JMP, // and begin executing its code. - reg.a[pc[3]] = exception; - reg.atag[pc[3]] = ATAG_OBJECT; - pc += 8; + reg.a[pc->c] = exception; + reg.atag[pc->c] = ATAG_OBJECT; + pc += 2; goto begin; } // This catch didn't handle it. Try the next one. - pc += 4 + JMPOFS(pc + 4); - assert(pc[0] == OP_CATCH); + pc += 1 + JMPOFS(pc + 1); + assert(pc->op == OP_CATCH); } - if (pc[1] == 1) + if (pc->a == 1) { // Catch any type of VMException. This terminates the chain. - ASSERTA(pc[3]); - reg.a[pc[3]] = exception; - reg.atag[pc[3]] = ATAG_OBJECT; - pc += 4; + ASSERTA(pc->c); + reg.a[pc->c] = exception; + reg.atag[pc->c] = ATAG_OBJECT; + pc += 1; goto begin; } // This frame failed. Try the next one out. @@ -1382,18 +1382,18 @@ static void DoCast(const VMRegisters ®, const VMFrame *f, int a, int b, int c // //=========================================================================== -static void FillReturns(const VMRegisters ®, VMFrame *frame, VMReturn *returns, const VM_UBYTE *retval, int numret) +static void FillReturns(const VMRegisters ®, VMFrame *frame, VMReturn *returns, const VMOP *retval, int numret) { int i, type, num; VMReturn *ret; assert(REGT_INT == 0 && REGT_FLOAT == 1 && REGT_STRING == 2 && REGT_POINTER == 3); - for (i = 0, ret = returns; i < numret; ++i, ++ret, retval += 4) + for (i = 0, ret = returns; i < numret; ++i, ++ret, ++retval) { - assert(retval[0] == OP_RESULT); // opcode - ret->RegType = type = retval[2]; - ret->RegNum = num = retval[3]; + assert(retval->op == OP_RESULT); // opcode + ret->RegType = type = retval->b; + ret->RegNum = num = retval->c; assert(!(type & REGT_KONST)); type &= REGT_TYPE; if (type < REGT_STRING) diff --git a/src/zscript/vmframe.cpp b/src/zscript/vmframe.cpp index 80766762b..0dce412c2 100644 --- a/src/zscript/vmframe.cpp +++ b/src/zscript/vmframe.cpp @@ -15,7 +15,7 @@ VMScriptFunction::VMScriptFunction() KonstS = NULL; KonstA = NULL; ExtraSpace = 0; - NumCodeBytes = 0; + CodeSize = 0; NumRegD = 0; NumRegF = 0; NumRegS = 0; @@ -37,12 +37,11 @@ VMScriptFunction::~VMScriptFunction() if (KonstA != NULL) M_Free(KonstA); } -VM_UBYTE *VMScriptFunction::AllocCode(int numops) +VMOP *VMScriptFunction::AllocCode(int numops) { assert(Code == NULL && numops > 0); - numops *= VM_OPSIZE; - NumCodeBytes = numops; - return Code = (VM_UBYTE *)M_Malloc(numops); + CodeSize = numops; + return Code = (VMOP *)M_Malloc(numops * sizeof(VMOP)); } int *VMScriptFunction::AllocKonstD(int numkonst)