aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2017-11-07 15:20:42 -0200
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2017-11-07 15:20:42 -0200
commitc3e5946fb2b7b5781d9bca9d303967abe6263482 (patch)
tree012bee6184675f1559e994eba42dda7c38381283
parentad0704e40cc7b3135fedc6d40a522addb039e090 (diff)
downloadlua-c3e5946fb2b7b5781d9bca9d303967abe6263482.tar.gz
lua-c3e5946fb2b7b5781d9bca9d303967abe6263482.tar.bz2
lua-c3e5946fb2b7b5781d9bca9d303967abe6263482.zip
new format for JUMP instructions (to allow larger offsets)
-rw-r--r--lcode.c35
-rw-r--r--ldebug.c4
-rw-r--r--lopcodes.c4
-rw-r--r--lopcodes.h30
-rw-r--r--ltests.c12
-rw-r--r--lvm.c4
6 files changed, 65 insertions, 24 deletions
diff --git a/lcode.c b/lcode.c
index f94afb0b..5ca597eb 100644
--- a/lcode.c
+++ b/lcode.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lcode.c,v 2.129 2017/10/04 15:49:24 roberto Exp roberto $ 2** $Id: lcode.c,v 2.130 2017/10/04 21:56:32 roberto Exp roberto $
3** Code generator for Lua 3** Code generator for Lua
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -37,6 +37,9 @@
37#define hasjumps(e) ((e)->t != (e)->f) 37#define hasjumps(e) ((e)->t != (e)->f)
38 38
39 39
40static int codesJ (FuncState *fs, OpCode o, int sj, int k);
41
42
40/* 43/*
41** If expression is a numeric constant, fills 'v' with its value 44** If expression is a numeric constant, fills 'v' with its value
42** and returns 1. Otherwise, returns 0. 45** and returns 1. Otherwise, returns 0.
@@ -89,7 +92,7 @@ void luaK_nil (FuncState *fs, int from, int n) {
89** a list of jumps. 92** a list of jumps.
90*/ 93*/
91static int getjump (FuncState *fs, int pc) { 94static int getjump (FuncState *fs, int pc) {
92 int offset = GETARG_sBx(fs->f->code[pc]); 95 int offset = GETARG_sJ(fs->f->code[pc]);
93 if (offset == NO_JUMP) /* point to itself represents end of list */ 96 if (offset == NO_JUMP) /* point to itself represents end of list */
94 return NO_JUMP; /* end of list */ 97 return NO_JUMP; /* end of list */
95 else 98 else
@@ -105,9 +108,10 @@ static void fixjump (FuncState *fs, int pc, int dest) {
105 Instruction *jmp = &fs->f->code[pc]; 108 Instruction *jmp = &fs->f->code[pc];
106 int offset = dest - (pc + 1); 109 int offset = dest - (pc + 1);
107 lua_assert(dest != NO_JUMP); 110 lua_assert(dest != NO_JUMP);
108 if (abs(offset) > MAXARG_sBx) 111 if (abs(offset) > MAXARG_sJ)
109 luaX_syntaxerror(fs->ls, "control structure too long"); 112 luaX_syntaxerror(fs->ls, "control structure too long");
110 SETARG_sBx(*jmp, offset); 113 lua_assert(GET_OPCODE(*jmp) == OP_JMP);
114 SETARG_sJ(*jmp, offset);
111} 115}
112 116
113 117
@@ -138,7 +142,7 @@ int luaK_jump (FuncState *fs) {
138 int jpc = fs->jpc; /* save list of jumps to here */ 142 int jpc = fs->jpc; /* save list of jumps to here */
139 int j; 143 int j;
140 fs->jpc = NO_JUMP; /* no more jumps to here */ 144 fs->jpc = NO_JUMP; /* no more jumps to here */
141 j = luaK_codeAsBx(fs, OP_JMP, 0, NO_JUMP); 145 j = codesJ(fs, OP_JMP, NO_JUMP, 0);
142 luaK_concat(fs, &j, jpc); /* keep them on hold */ 146 luaK_concat(fs, &j, jpc); /* keep them on hold */
143 return j; 147 return j;
144} 148}
@@ -286,16 +290,16 @@ int luaK_needclose (FuncState *fs, int list) {
286/* 290/*
287** Correct a jump list to jump to 'target'. If 'hasclose' is true, 291** Correct a jump list to jump to 'target'. If 'hasclose' is true,
288** 'target' contains an OP_CLOSE instruction (see first assert). 292** 'target' contains an OP_CLOSE instruction (see first assert).
289** Only jumps with the A arg true need that close; other jumps 293** Only jumps with the 'k' arg true need that close; other jumps
290** avoid it jumping to the next instruction. 294** avoid it jumping to the next instruction.
291*/ 295*/
292void luaK_patchgoto (FuncState *fs, int list, int target, int hasclose) { 296void luaK_patchgoto (FuncState *fs, int list, int target, int hasclose) {
293 lua_assert(!hasclose || GET_OPCODE(fs->f->code[target]) == OP_CLOSE); 297 lua_assert(!hasclose || GET_OPCODE(fs->f->code[target]) == OP_CLOSE);
294 while (list != NO_JUMP) { 298 while (list != NO_JUMP) {
295 int next = getjump(fs, list); 299 int next = getjump(fs, list);
296 lua_assert(!GETARG_A(fs->f->code[list]) || hasclose); 300 lua_assert(!GETARG_k(fs->f->code[list]) || hasclose);
297 patchtestreg(fs, list, NO_REG); /* do not generate values */ 301 patchtestreg(fs, list, NO_REG); /* do not generate values */
298 if (!hasclose || GETARG_A(fs->f->code[list])) 302 if (!hasclose || GETARG_k(fs->f->code[list]))
299 fixjump(fs, list, target); 303 fixjump(fs, list, target);
300 else /* there is a CLOSE instruction but jump does not need it */ 304 else /* there is a CLOSE instruction but jump does not need it */
301 fixjump(fs, list, target + 1); /* avoid CLOSE instruction */ 305 fixjump(fs, list, target + 1); /* avoid CLOSE instruction */
@@ -305,14 +309,14 @@ void luaK_patchgoto (FuncState *fs, int list, int target, int hasclose) {
305 309
306 310
307/* 311/*
308** Mark (using the A arg) all jumps in 'list' to close upvalues. Mark 312** Mark (using the 'k' arg) all jumps in 'list' to close upvalues. Mark
309** will instruct 'luaK_patchgoto' to make these jumps go to OP_CLOSE 313** will instruct 'luaK_patchgoto' to make these jumps go to OP_CLOSE
310** instructions. 314** instructions.
311*/ 315*/
312void luaK_patchclose (FuncState *fs, int list) { 316void luaK_patchclose (FuncState *fs, int list) {
313 for (; list != NO_JUMP; list = getjump(fs, list)) { 317 for (; list != NO_JUMP; list = getjump(fs, list)) {
314 lua_assert(GET_OPCODE(fs->f->code[list]) == OP_JMP); 318 lua_assert(GET_OPCODE(fs->f->code[list]) == OP_JMP);
315 SETARG_A(fs->f->code[list], 1); 319 SETARG_k(fs->f->code[list], 1);
316 } 320 }
317} 321}
318 322
@@ -399,6 +403,17 @@ int luaK_codeAsBx (FuncState *fs, OpCode o, int a, int bc) {
399 403
400 404
401/* 405/*
406** Format and emit an 'isJ' instruction.
407*/
408static int codesJ (FuncState *fs, OpCode o, int sj, int k) {
409 unsigned int j = sj + MAXARG_sJ;
410 lua_assert(getOpMode(o) == isJ);
411 lua_assert(j <= MAXARG_sJ && (k & ~1) == 0);
412 return luaK_code(fs, CREATE_sJ(o, j, k));
413}
414
415
416/*
402** Emit an "extra argument" instruction (format 'iAx') 417** Emit an "extra argument" instruction (format 'iAx')
403*/ 418*/
404static int codeextraarg (FuncState *fs, int a) { 419static int codeextraarg (FuncState *fs, int a) {
diff --git a/ldebug.c b/ldebug.c
index 83ddde72..e1f9c015 100644
--- a/ldebug.c
+++ b/ldebug.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ldebug.c,v 2.135 2017/11/02 11:28:56 roberto Exp $ 2** $Id: ldebug.c,v 2.140 2017/11/07 13:25:26 roberto Exp roberto $
3** Debug Interface 3** Debug Interface
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -442,7 +442,7 @@ static int findsetreg (Proto *p, int lastpc, int reg) {
442 break; 442 break;
443 } 443 }
444 case OP_JMP: { /* doesn't change registers, but changes 'jmptarget' */ 444 case OP_JMP: { /* doesn't change registers, but changes 'jmptarget' */
445 int b = GETARG_sBx(i); 445 int b = GETARG_sJ(i);
446 int dest = pc + 1 + b; 446 int dest = pc + 1 + b;
447 /* jump does not skip 'lastpc' and is larger than current one? */ 447 /* jump does not skip 'lastpc' and is larger than current one? */
448 if (dest <= lastpc && dest > jmptarget) 448 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 @@
1/* 1/*
2** $Id: lopcodes.c,v 1.65 2017/09/28 16:53:29 roberto Exp roberto $ 2** $Id: lopcodes.c,v 1.66 2017/10/04 15:49:24 roberto Exp roberto $
3** Opcodes for Lua virtual machine 3** Opcodes for Lua virtual machine
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -129,7 +129,7 @@ LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = {
129 ,opmode(0, 1, iABC) /* OP_LEN */ 129 ,opmode(0, 1, iABC) /* OP_LEN */
130 ,opmode(0, 1, iABC) /* OP_CONCAT */ 130 ,opmode(0, 1, iABC) /* OP_CONCAT */
131 ,opmode(0, 0, iABC) /* OP_CLOSE */ 131 ,opmode(0, 0, iABC) /* OP_CLOSE */
132 ,opmode(0, 0, iAsBx) /* OP_JMP */ 132 ,opmode(0, 0, isJ) /* OP_JMP */
133 ,opmode(1, 0, iABC) /* OP_EQ */ 133 ,opmode(1, 0, iABC) /* OP_EQ */
134 ,opmode(1, 0, iABC) /* OP_LT */ 134 ,opmode(1, 0, iABC) /* OP_LT */
135 ,opmode(1, 0, iABC) /* OP_LE */ 135 ,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 @@
1/* 1/*
2** $Id: lopcodes.h,v 1.165 2017/10/04 15:49:24 roberto Exp roberto $ 2** $Id: lopcodes.h,v 1.166 2017/10/04 21:56:32 roberto Exp roberto $
3** Opcodes for Lua virtual machine 3** Opcodes for Lua virtual machine
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -21,6 +21,7 @@ iABC |k| C(8) | | B(8) | | A(8) | | Op(7) |
21iABx | Bx(17) | | A(8) | | Op(7) | 21iABx | Bx(17) | | A(8) | | Op(7) |
22iAsBx | sBx (signed)(17) | | A(8) | | Op(7) | 22iAsBx | sBx (signed)(17) | | A(8) | | Op(7) |
23iAx | Ax(25) | | Op(7) | 23iAx | Ax(25) | | Op(7) |
24iksJ |k| sJ(24) | | Op(7) |
24 25
25 A signed argument is represented in excess K: the represented value is 26 A signed argument is represented in excess K: the represented value is
26 the written unsigned value minus K, where K is half the maximum for the 27 the written unsigned value minus K, where K is half the maximum for the
@@ -28,7 +29,7 @@ iAx | Ax(25) | | Op(7) |
28===========================================================================*/ 29===========================================================================*/
29 30
30 31
31enum OpMode {iABC, iABx, iAsBx, iAx}; /* basic instruction format */ 32enum OpMode {iABC, iABx, iAsBx, iAx, isJ}; /* basic instruction formats */
32 33
33 34
34/* 35/*
@@ -40,6 +41,8 @@ enum OpMode {iABC, iABx, iAsBx, iAx}; /* basic instruction format */
40#define SIZE_Bx (SIZE_Cx + SIZE_B) 41#define SIZE_Bx (SIZE_Cx + SIZE_B)
41#define SIZE_A 8 42#define SIZE_A 8
42#define SIZE_Ax (SIZE_Cx + SIZE_B + SIZE_A) 43#define SIZE_Ax (SIZE_Cx + SIZE_B + SIZE_A)
44#define SIZE_sJ (SIZE_C + SIZE_B + SIZE_A)
45
43 46
44#define SIZE_OP 7 47#define SIZE_OP 7
45 48
@@ -50,6 +53,7 @@ enum OpMode {iABC, iABx, iAsBx, iAx}; /* basic instruction format */
50#define POS_k (POS_C + SIZE_C) 53#define POS_k (POS_C + SIZE_C)
51#define POS_Bx POS_B 54#define POS_Bx POS_B
52#define POS_Ax POS_A 55#define POS_Ax POS_A
56#define POS_sJ POS_A
53 57
54 58
55/* 59/*
@@ -71,6 +75,12 @@ enum OpMode {iABC, iABx, iAsBx, iAx}; /* basic instruction format */
71#define MAXARG_Ax MAX_INT 75#define MAXARG_Ax MAX_INT
72#endif 76#endif
73 77
78#if SIZE_sJ < LUAI_BITSINT-1
79#define MAXARG_sJ ((1 << (SIZE_sJ - 1)) - 1)
80#else
81#define MAXARG_sJ MAX_INT
82#endif
83
74 84
75#define MAXARG_A ((1<<SIZE_A)-1) 85#define MAXARG_A ((1<<SIZE_A)-1)
76#define MAXARG_B ((1<<SIZE_B)-1) 86#define MAXARG_B ((1<<SIZE_B)-1)
@@ -111,6 +121,7 @@ enum OpMode {iABC, iABx, iAsBx, iAx}; /* basic instruction format */
111#define SETARG_C(i,v) setarg(i, v, POS_C, SIZE_C) 121#define SETARG_C(i,v) setarg(i, v, POS_C, SIZE_C)
112 122
113#define GETARG_k(i) (cast(int, ((i) & (1 << POS_k)))) 123#define GETARG_k(i) (cast(int, ((i) & (1 << POS_k))))
124#define SETARG_k(i,v) setarg(i, v, POS_k, 1)
114 125
115#define GETARG_Bx(i) check_exp(checkopm(i, iABx), getarg(i, POS_Bx, SIZE_Bx)) 126#define GETARG_Bx(i) check_exp(checkopm(i, iABx), getarg(i, POS_Bx, SIZE_Bx))
116#define SETARG_Bx(i,v) setarg(i, v, POS_Bx, SIZE_Bx) 127#define SETARG_Bx(i,v) setarg(i, v, POS_Bx, SIZE_Bx)
@@ -122,12 +133,17 @@ enum OpMode {iABC, iABx, iAsBx, iAx}; /* basic instruction format */
122 check_exp(checkopm(i, iAsBx), getarg(i, POS_Bx, SIZE_Bx) - MAXARG_sBx) 133 check_exp(checkopm(i, iAsBx), getarg(i, POS_Bx, SIZE_Bx) - MAXARG_sBx)
123#define SETARG_sBx(i,b) SETARG_Bx((i),cast(unsigned int, (b)+MAXARG_sBx)) 134#define SETARG_sBx(i,b) SETARG_Bx((i),cast(unsigned int, (b)+MAXARG_sBx))
124 135
136#define GETARG_sJ(i) \
137 check_exp(checkopm(i, isJ), getarg(i, POS_sJ, SIZE_sJ) - MAXARG_sJ)
138#define SETARG_sJ(i,j) \
139 setarg(i, cast(unsigned int, (j)+MAXARG_sJ), POS_sJ, SIZE_sJ)
140
125 141
126#define CREATE_ABCk(o,a,b,c,k) ((cast(Instruction, o)<<POS_OP) \ 142#define CREATE_ABCk(o,a,b,c,k) ((cast(Instruction, o)<<POS_OP) \
127 | (cast(Instruction, a)<<POS_A) \ 143 | (cast(Instruction, a)<<POS_A) \
128 | (cast(Instruction, b)<<POS_B) \ 144 | (cast(Instruction, b)<<POS_B) \
129 | (cast(Instruction, c)<<POS_C)) \ 145 | (cast(Instruction, c)<<POS_C) \
130 | (cast(Instruction, k)<<POS_k) 146 | (cast(Instruction, k)<<POS_k))
131 147
132#define CREATE_ABx(o,a,bc) ((cast(Instruction, o)<<POS_OP) \ 148#define CREATE_ABx(o,a,bc) ((cast(Instruction, o)<<POS_OP) \
133 | (cast(Instruction, a)<<POS_A) \ 149 | (cast(Instruction, a)<<POS_A) \
@@ -136,6 +152,10 @@ enum OpMode {iABC, iABx, iAsBx, iAx}; /* basic instruction format */
136#define CREATE_Ax(o,a) ((cast(Instruction, o)<<POS_OP) \ 152#define CREATE_Ax(o,a) ((cast(Instruction, o)<<POS_OP) \
137 | (cast(Instruction, a)<<POS_Ax)) 153 | (cast(Instruction, a)<<POS_Ax))
138 154
155#define CREATE_sJ(o,j,k) ((cast(Instruction, o) << POS_OP) \
156 | (cast(Instruction, j) << POS_sJ) \
157 | (cast(Instruction, k) << POS_k))
158
139 159
140#if !defined(MAXINDEXRK) /* (for debugging only) */ 160#if !defined(MAXINDEXRK) /* (for debugging only) */
141#define MAXINDEXRK MAXARG_B 161#define MAXINDEXRK MAXARG_B
@@ -215,7 +235,7 @@ OP_LEN,/* A B R(A) := length of R(B) */
215OP_CONCAT,/* A B C R(A) := R(B).. ... ..R(C) */ 235OP_CONCAT,/* A B C R(A) := R(B).. ... ..R(C) */
216 236
217OP_CLOSE,/* A close all upvalues >= R(A) */ 237OP_CLOSE,/* A close all upvalues >= R(A) */
218OP_JMP,/* sBx pc+=sBx */ 238OP_JMP,/* k sJ pc += sJ (k is used in code generation) */
219OP_EQ,/* A B C if ((R(B) == R(C)) ~= A) then pc++ */ 239OP_EQ,/* A B C if ((R(B) == R(C)) ~= A) then pc++ */
220OP_LT,/* A B C if ((R(B) < R(C)) ~= A) then pc++ */ 240OP_LT,/* A B C if ((R(B) < R(C)) ~= A) then pc++ */
221OP_LE,/* A B C if ((R(B) <= R(C)) ~= A) then pc++ */ 241OP_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 @@
1/* 1/*
2** $Id: ltests.c,v 2.227 2017/11/02 11:28:56 roberto Exp $ 2** $Id: ltests.c,v 2.230 2017/11/07 13:25:26 roberto Exp roberto $
3** Internal Module for Debugging of the Lua Implementation 3** Internal Module for Debugging of the Lua Implementation
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -543,14 +543,20 @@ static char *buildop (Proto *p, int pc, char *buff) {
543 GETARG_k(i) ? " (k)" : ""); 543 GETARG_k(i) ? " (k)" : "");
544 break; 544 break;
545 case iABx: 545 case iABx:
546 sprintf(buff+strlen(buff), "%-12s%4d %4d", name, GETARG_A(i), GETARG_Bx(i)); 546 sprintf(buff+strlen(buff), "%-12s%4d %4d", name, GETARG_A(i),
547 GETARG_Bx(i));
547 break; 548 break;
548 case iAsBx: 549 case iAsBx:
549 sprintf(buff+strlen(buff), "%-12s%4d %4d", name, GETARG_A(i), GETARG_sBx(i)); 550 sprintf(buff+strlen(buff), "%-12s%4d %4d", name, GETARG_A(i),
551 GETARG_sBx(i));
550 break; 552 break;
551 case iAx: 553 case iAx:
552 sprintf(buff+strlen(buff), "%-12s%4d", name, GETARG_Ax(i)); 554 sprintf(buff+strlen(buff), "%-12s%4d", name, GETARG_Ax(i));
553 break; 555 break;
556 case isJ:
557 sprintf(buff+strlen(buff), "%-12s%4d (%1d)", name, GETARG_sJ(i),
558 !!GETARG_k(i));
559 break;
554 } 560 }
555 return buff; 561 return buff;
556} 562}
diff --git a/lvm.c b/lvm.c
index b5e1c813..009dfc57 100644
--- a/lvm.c
+++ b/lvm.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lvm.c,v 2.301 2017/11/01 18:20:48 roberto Exp $ 2** $Id: lvm.c,v 2.306 2017/11/07 13:25:26 roberto Exp roberto $
3** Lua virtual machine 3** Lua virtual machine
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -753,7 +753,7 @@ void luaV_finishOp (lua_State *L) {
753** Execute a jump instruction. The 'updatemask' allows signals to stop 753** Execute a jump instruction. The 'updatemask' allows signals to stop
754** tight loops. (Without it, the local copy of 'mask' could never change.) 754** tight loops. (Without it, the local copy of 'mask' could never change.)
755*/ 755*/
756#define dojump(ci,i,e) { pc += GETARG_sBx(i) + e; updatemask(L); } 756#define dojump(ci,i,e) { pc += GETARG_sJ(i) + e; updatemask(L); }
757 757
758 758
759/* for test instructions, execute the jump instruction that follows it */ 759/* for test instructions, execute the jump instruction that follows it */