diff --git a/lcode.c b/lcode.c index f94afb0b..5ca597eb 100644 --- a/lcode.c +++ b/lcode.c @@ -1,5 +1,5 @@ /* -** $Id: lcode.c,v 2.129 2017/10/04 15:49:24 roberto Exp roberto $ +** $Id: lcode.c,v 2.130 2017/10/04 21:56:32 roberto Exp roberto $ ** Code generator for Lua ** See Copyright Notice in lua.h */ @@ -37,6 +37,9 @@ #define hasjumps(e) ((e)->t != (e)->f) +static int codesJ (FuncState *fs, OpCode o, int sj, int k); + + /* ** If expression is a numeric constant, fills 'v' with its value ** and returns 1. Otherwise, returns 0. @@ -89,7 +92,7 @@ void luaK_nil (FuncState *fs, int from, int n) { ** a list of jumps. */ static int getjump (FuncState *fs, int pc) { - int offset = GETARG_sBx(fs->f->code[pc]); + int offset = GETARG_sJ(fs->f->code[pc]); if (offset == NO_JUMP) /* point to itself represents end of list */ return NO_JUMP; /* end of list */ else @@ -105,9 +108,10 @@ static void fixjump (FuncState *fs, int pc, int dest) { Instruction *jmp = &fs->f->code[pc]; int offset = dest - (pc + 1); lua_assert(dest != NO_JUMP); - if (abs(offset) > MAXARG_sBx) + if (abs(offset) > MAXARG_sJ) luaX_syntaxerror(fs->ls, "control structure too long"); - SETARG_sBx(*jmp, offset); + lua_assert(GET_OPCODE(*jmp) == OP_JMP); + SETARG_sJ(*jmp, offset); } @@ -138,7 +142,7 @@ int luaK_jump (FuncState *fs) { int jpc = fs->jpc; /* save list of jumps to here */ int j; fs->jpc = NO_JUMP; /* no more jumps to here */ - j = luaK_codeAsBx(fs, OP_JMP, 0, NO_JUMP); + j = codesJ(fs, OP_JMP, NO_JUMP, 0); luaK_concat(fs, &j, jpc); /* keep them on hold */ return j; } @@ -286,16 +290,16 @@ int luaK_needclose (FuncState *fs, int list) { /* ** Correct a jump list to jump to 'target'. If 'hasclose' is true, ** 'target' contains an OP_CLOSE instruction (see first assert). -** Only jumps with the A arg true need that close; other jumps +** Only jumps with the 'k' arg true need that close; other jumps ** avoid it jumping to the next instruction. */ void luaK_patchgoto (FuncState *fs, int list, int target, int hasclose) { lua_assert(!hasclose || GET_OPCODE(fs->f->code[target]) == OP_CLOSE); while (list != NO_JUMP) { int next = getjump(fs, list); - lua_assert(!GETARG_A(fs->f->code[list]) || hasclose); + lua_assert(!GETARG_k(fs->f->code[list]) || hasclose); patchtestreg(fs, list, NO_REG); /* do not generate values */ - if (!hasclose || GETARG_A(fs->f->code[list])) + if (!hasclose || GETARG_k(fs->f->code[list])) fixjump(fs, list, target); else /* there is a CLOSE instruction but jump does not need it */ fixjump(fs, list, target + 1); /* avoid CLOSE instruction */ @@ -305,14 +309,14 @@ void luaK_patchgoto (FuncState *fs, int list, int target, int hasclose) { /* -** Mark (using the A arg) all jumps in 'list' to close upvalues. Mark +** Mark (using the 'k' arg) all jumps in 'list' to close upvalues. Mark ** will instruct 'luaK_patchgoto' to make these jumps go to OP_CLOSE ** instructions. */ void luaK_patchclose (FuncState *fs, int list) { for (; list != NO_JUMP; list = getjump(fs, list)) { lua_assert(GET_OPCODE(fs->f->code[list]) == OP_JMP); - SETARG_A(fs->f->code[list], 1); + SETARG_k(fs->f->code[list], 1); } } @@ -398,6 +402,17 @@ int luaK_codeAsBx (FuncState *fs, OpCode o, int a, int bc) { } +/* +** Format and emit an 'isJ' instruction. +*/ +static int codesJ (FuncState *fs, OpCode o, int sj, int k) { + unsigned int j = sj + MAXARG_sJ; + lua_assert(getOpMode(o) == isJ); + lua_assert(j <= MAXARG_sJ && (k & ~1) == 0); + return luaK_code(fs, CREATE_sJ(o, j, k)); +} + + /* ** Emit an "extra argument" instruction (format 'iAx') */ diff --git a/ldebug.c b/ldebug.c index 83ddde72..e1f9c015 100644 --- a/ldebug.c +++ b/ldebug.c @@ -1,5 +1,5 @@ /* -** $Id: ldebug.c,v 2.135 2017/11/02 11:28:56 roberto Exp $ +** $Id: ldebug.c,v 2.140 2017/11/07 13:25:26 roberto Exp roberto $ ** Debug Interface ** See Copyright Notice in lua.h */ @@ -442,7 +442,7 @@ static int findsetreg (Proto *p, int lastpc, int reg) { break; } case OP_JMP: { /* doesn't change registers, but changes 'jmptarget' */ - int b = GETARG_sBx(i); + int b = GETARG_sJ(i); int dest = pc + 1 + b; /* jump does not skip 'lastpc' and is larger than current one? */ if (dest <= lastpc && dest > jmptarget) diff --git a/lopcodes.c b/lopcodes.c index 42ce73d9..6ea54d09 100644 --- a/lopcodes.c +++ b/lopcodes.c @@ -1,5 +1,5 @@ /* -** $Id: lopcodes.c,v 1.65 2017/09/28 16:53:29 roberto Exp roberto $ +** $Id: lopcodes.c,v 1.66 2017/10/04 15:49:24 roberto Exp roberto $ ** Opcodes for Lua virtual machine ** See Copyright Notice in lua.h */ @@ -129,7 +129,7 @@ LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = { ,opmode(0, 1, iABC) /* OP_LEN */ ,opmode(0, 1, iABC) /* OP_CONCAT */ ,opmode(0, 0, iABC) /* OP_CLOSE */ - ,opmode(0, 0, iAsBx) /* OP_JMP */ + ,opmode(0, 0, isJ) /* OP_JMP */ ,opmode(1, 0, iABC) /* OP_EQ */ ,opmode(1, 0, iABC) /* OP_LT */ ,opmode(1, 0, iABC) /* OP_LE */ diff --git a/lopcodes.h b/lopcodes.h index de0c5cc1..bc8d722f 100644 --- a/lopcodes.h +++ b/lopcodes.h @@ -1,5 +1,5 @@ /* -** $Id: lopcodes.h,v 1.165 2017/10/04 15:49:24 roberto Exp roberto $ +** $Id: lopcodes.h,v 1.166 2017/10/04 21:56:32 roberto Exp roberto $ ** Opcodes for Lua virtual machine ** See Copyright Notice in lua.h */ @@ -21,6 +21,7 @@ iABC |k| C(8) | | B(8) | | A(8) | | Op(7) | iABx | Bx(17) | | A(8) | | Op(7) | iAsBx | sBx (signed)(17) | | A(8) | | Op(7) | iAx | Ax(25) | | Op(7) | +iksJ |k| sJ(24) | | Op(7) | A signed argument is represented in excess K: the represented value is the written unsigned value minus K, where K is half the maximum for the @@ -28,7 +29,7 @@ iAx | Ax(25) | | Op(7) | ===========================================================================*/ -enum OpMode {iABC, iABx, iAsBx, iAx}; /* basic instruction format */ +enum OpMode {iABC, iABx, iAsBx, iAx, isJ}; /* basic instruction formats */ /* @@ -40,6 +41,8 @@ enum OpMode {iABC, iABx, iAsBx, iAx}; /* basic instruction format */ #define SIZE_Bx (SIZE_Cx + SIZE_B) #define SIZE_A 8 #define SIZE_Ax (SIZE_Cx + SIZE_B + SIZE_A) +#define SIZE_sJ (SIZE_C + SIZE_B + SIZE_A) + #define SIZE_OP 7 @@ -50,6 +53,7 @@ enum OpMode {iABC, iABx, iAsBx, iAx}; /* basic instruction format */ #define POS_k (POS_C + SIZE_C) #define POS_Bx POS_B #define POS_Ax POS_A +#define POS_sJ POS_A /* @@ -71,6 +75,12 @@ enum OpMode {iABC, iABx, iAsBx, iAx}; /* basic instruction format */ #define MAXARG_Ax MAX_INT #endif +#if SIZE_sJ < LUAI_BITSINT-1 +#define MAXARG_sJ ((1 << (SIZE_sJ - 1)) - 1) +#else +#define MAXARG_sJ MAX_INT +#endif + #define MAXARG_A ((1<= R(A) */ -OP_JMP,/* sBx pc+=sBx */ +OP_JMP,/* k sJ pc += sJ (k is used in code generation) */ OP_EQ,/* A B C if ((R(B) == R(C)) ~= A) then pc++ */ OP_LT,/* A B C if ((R(B) < R(C)) ~= A) then pc++ */ OP_LE,/* A B C if ((R(B) <= R(C)) ~= A) then pc++ */ diff --git a/ltests.c b/ltests.c index bee734f3..5f7b4064 100644 --- a/ltests.c +++ b/ltests.c @@ -1,5 +1,5 @@ /* -** $Id: ltests.c,v 2.227 2017/11/02 11:28:56 roberto Exp $ +** $Id: ltests.c,v 2.230 2017/11/07 13:25:26 roberto Exp roberto $ ** Internal Module for Debugging of the Lua Implementation ** See Copyright Notice in lua.h */ @@ -543,14 +543,20 @@ static char *buildop (Proto *p, int pc, char *buff) { GETARG_k(i) ? " (k)" : ""); break; case iABx: - sprintf(buff+strlen(buff), "%-12s%4d %4d", name, GETARG_A(i), GETARG_Bx(i)); + sprintf(buff+strlen(buff), "%-12s%4d %4d", name, GETARG_A(i), + GETARG_Bx(i)); break; case iAsBx: - sprintf(buff+strlen(buff), "%-12s%4d %4d", name, GETARG_A(i), GETARG_sBx(i)); + sprintf(buff+strlen(buff), "%-12s%4d %4d", name, GETARG_A(i), + GETARG_sBx(i)); break; case iAx: sprintf(buff+strlen(buff), "%-12s%4d", name, GETARG_Ax(i)); break; + case isJ: + sprintf(buff+strlen(buff), "%-12s%4d (%1d)", name, GETARG_sJ(i), + !!GETARG_k(i)); + break; } return buff; } diff --git a/lvm.c b/lvm.c index b5e1c813..009dfc57 100644 --- a/lvm.c +++ b/lvm.c @@ -1,5 +1,5 @@ /* -** $Id: lvm.c,v 2.301 2017/11/01 18:20:48 roberto Exp $ +** $Id: lvm.c,v 2.306 2017/11/07 13:25:26 roberto Exp roberto $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -753,7 +753,7 @@ void luaV_finishOp (lua_State *L) { ** Execute a jump instruction. The 'updatemask' allows signals to stop ** tight loops. (Without it, the local copy of 'mask' could never change.) */ -#define dojump(ci,i,e) { pc += GETARG_sBx(i) + e; updatemask(L); } +#define dojump(ci,i,e) { pc += GETARG_sJ(i) + e; updatemask(L); } /* for test instructions, execute the jump instruction that follows it */