- Use a union, rather than pointer aliasing, to access the parts of a VM instruction.

SVN r1922 (scripting)
This commit is contained in:
Randy Heit 2009-10-17 00:33:23 +00:00
parent c424c61ffc
commit e5ef25591d
10 changed files with 171 additions and 154 deletions

View file

@ -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

View file

@ -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;

View file

@ -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");
}

View file

@ -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

View file

@ -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());
}

View file

@ -70,7 +70,7 @@ private:
int MaxParam;
int ActiveParam;
TArray<VM_UBYTE> Code;
TArray<VMOP> Code;
// PARAM increases ActiveParam; CALL decreases it.
void ParamChange(int delta);

View file

@ -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);
}
}

View file

@ -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 <assert.h>
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

View file

@ -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 &reg, const VMFrame *f, int a, int b, int c
//
//===========================================================================
static void FillReturns(const VMRegisters &reg, VMFrame *frame, VMReturn *returns, const VM_UBYTE *retval, int numret)
static void FillReturns(const VMRegisters &reg, 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)

View file

@ -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)