diff options
-rw-r--r-- | lcode.c | 91 | ||||
-rw-r--r-- | lcode.h | 3 | ||||
-rw-r--r-- | lparser.c | 4 | ||||
-rw-r--r-- | lparser.h | 3 | ||||
-rw-r--r-- | lvm.c | 10 |
5 files changed, 63 insertions, 48 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lcode.c,v 2.138 2017/11/28 15:26:15 roberto Exp roberto $ | 2 | ** $Id: lcode.c,v 2.140 2017/11/30 13:17:06 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 | */ |
@@ -134,17 +134,10 @@ void luaK_concat (FuncState *fs, int *l1, int l2) { | |||
134 | 134 | ||
135 | /* | 135 | /* |
136 | ** Create a jump instruction and return its position, so its destination | 136 | ** Create a jump instruction and return its position, so its destination |
137 | ** can be fixed later (with 'fixjump'). If there are jumps to | 137 | ** can be fixed later (with 'fixjump'). |
138 | ** this position (kept in 'jpc'), link them all together so that | ||
139 | ** 'patchlistaux' will fix all them directly to the final destination. | ||
140 | */ | 138 | */ |
141 | int luaK_jump (FuncState *fs) { | 139 | int luaK_jump (FuncState *fs) { |
142 | int jpc = fs->jpc; /* save list of jumps to here */ | 140 | return codesJ(fs, OP_JMP, NO_JUMP, 0); |
143 | int j; | ||
144 | fs->jpc = NO_JUMP; /* no more jumps to here */ | ||
145 | j = codesJ(fs, OP_JMP, NO_JUMP, 0); | ||
146 | luaK_concat(fs, &j, jpc); /* keep them on hold */ | ||
147 | return j; | ||
148 | } | 141 | } |
149 | 142 | ||
150 | 143 | ||
@@ -250,38 +243,19 @@ static void patchlistaux (FuncState *fs, int list, int vtarget, int reg, | |||
250 | 243 | ||
251 | 244 | ||
252 | /* | 245 | /* |
253 | ** Ensure all pending jumps to current position are fixed (jumping | ||
254 | ** to current position with no values) and reset list of pending | ||
255 | ** jumps | ||
256 | */ | ||
257 | static void dischargejpc (FuncState *fs) { | ||
258 | patchlistaux(fs, fs->jpc, fs->pc, NO_REG, fs->pc); | ||
259 | fs->jpc = NO_JUMP; | ||
260 | } | ||
261 | |||
262 | |||
263 | /* | ||
264 | ** Add elements in 'list' to list of pending jumps to "here" | ||
265 | ** (current position) | ||
266 | */ | ||
267 | void luaK_patchtohere (FuncState *fs, int list) { | ||
268 | luaK_getlabel(fs); /* mark "here" as a jump target */ | ||
269 | luaK_concat(fs, &fs->jpc, list); | ||
270 | } | ||
271 | |||
272 | |||
273 | /* | ||
274 | ** Path all jumps in 'list' to jump to 'target'. | 246 | ** Path all jumps in 'list' to jump to 'target'. |
275 | ** (The assert means that we cannot fix a jump to a forward address | 247 | ** (The assert means that we cannot fix a jump to a forward address |
276 | ** because we only know addresses once code is generated.) | 248 | ** because we only know addresses once code is generated.) |
277 | */ | 249 | */ |
278 | void luaK_patchlist (FuncState *fs, int list, int target) { | 250 | void luaK_patchlist (FuncState *fs, int list, int target) { |
279 | if (target == fs->pc) /* 'target' is current position? */ | 251 | lua_assert(target <= fs->pc); |
280 | luaK_patchtohere(fs, list); /* add list to pending jumps */ | 252 | patchlistaux(fs, list, target, NO_REG, target); |
281 | else { | 253 | } |
282 | lua_assert(target < fs->pc); | 254 | |
283 | patchlistaux(fs, list, target, NO_REG, target); | 255 | |
284 | } | 256 | void luaK_patchtohere (FuncState *fs, int list) { |
257 | int hr = luaK_getlabel(fs); /* mark "here" as a jump target */ | ||
258 | luaK_patchlist(fs, list, hr); | ||
285 | } | 259 | } |
286 | 260 | ||
287 | 261 | ||
@@ -365,7 +339,6 @@ static void savelineinfo (FuncState *fs, Proto *f, int pc, int line) { | |||
365 | */ | 339 | */ |
366 | static int luaK_code (FuncState *fs, Instruction i) { | 340 | static int luaK_code (FuncState *fs, Instruction i) { |
367 | Proto *f = fs->f; | 341 | Proto *f = fs->f; |
368 | dischargejpc(fs); /* 'pc' will change */ | ||
369 | /* put new instruction in code array */ | 342 | /* put new instruction in code array */ |
370 | luaM_growvector(fs->ls->L, f->code, fs->pc, f->sizecode, Instruction, | 343 | luaM_growvector(fs->ls->L, f->code, fs->pc, f->sizecode, Instruction, |
371 | MAX_INT, "opcodes"); | 344 | MAX_INT, "opcodes"); |
@@ -1537,3 +1510,45 @@ void luaK_setlist (FuncState *fs, int base, int nelems, int tostore) { | |||
1537 | fs->freereg = base + 1; /* free registers with list values */ | 1510 | fs->freereg = base + 1; /* free registers with list values */ |
1538 | } | 1511 | } |
1539 | 1512 | ||
1513 | |||
1514 | /* | ||
1515 | ** return the final target of a jump (skipping jumps to jumps) | ||
1516 | */ | ||
1517 | static int finaltarget (Instruction *code, int i) { | ||
1518 | int count; | ||
1519 | for (count = 0; count < 100; count++) { /* avoid infinite loops */ | ||
1520 | Instruction pc = code[i]; | ||
1521 | if (GET_OPCODE(pc) != OP_JMP) | ||
1522 | break; | ||
1523 | else | ||
1524 | i += GETARG_sJ(pc) + 1; | ||
1525 | } | ||
1526 | return i; | ||
1527 | } | ||
1528 | |||
1529 | |||
1530 | /* | ||
1531 | ** Do a final pass over the code of a function, doing small peephole | ||
1532 | ** optimizations and adjustments. | ||
1533 | */ | ||
1534 | void luaK_finish (FuncState *fs) { | ||
1535 | int i; | ||
1536 | Proto *p = fs->f; | ||
1537 | for (i = 0; i < fs->pc; i++) { | ||
1538 | Instruction *pc = &p->code[i]; | ||
1539 | switch (GET_OPCODE(*pc)) { | ||
1540 | case OP_RETURN: case OP_RETURN0: case OP_RETURN1: | ||
1541 | case OP_TAILCALL: { | ||
1542 | if (p->sizep > 0) | ||
1543 | SETARG_k(*pc, 1); /* signal that they must close upvalues */ | ||
1544 | break; | ||
1545 | } | ||
1546 | case OP_JMP: { | ||
1547 | int target = finaltarget(p->code, i); | ||
1548 | fixjump(fs, i, target); | ||
1549 | break; | ||
1550 | } | ||
1551 | default: break; | ||
1552 | } | ||
1553 | } | ||
1554 | } | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lcode.h,v 1.67 2017/09/28 16:53:29 roberto Exp roberto $ | 2 | ** $Id: lcode.h,v 1.68 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 | */ |
@@ -88,6 +88,7 @@ LUAI_FUNC void luaK_infix (FuncState *fs, BinOpr op, expdesc *v); | |||
88 | LUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1, | 88 | LUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1, |
89 | expdesc *v2, int line); | 89 | expdesc *v2, int line); |
90 | LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore); | 90 | LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore); |
91 | LUAI_FUNC void luaK_finish (FuncState *fs); | ||
91 | 92 | ||
92 | 93 | ||
93 | #endif | 94 | #endif |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lparser.c,v 2.167 2017/10/04 21:53:03 roberto Exp roberto $ | 2 | ** $Id: lparser.c,v 2.168 2017/11/23 16:35:54 roberto Exp roberto $ |
3 | ** Lua Parser | 3 | ** Lua Parser |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -547,7 +547,6 @@ static void open_func (LexState *ls, FuncState *fs, BlockCnt *bl) { | |||
547 | fs->previousline = f->linedefined; | 547 | fs->previousline = f->linedefined; |
548 | fs->iwthabs = 0; | 548 | fs->iwthabs = 0; |
549 | fs->lasttarget = 0; | 549 | fs->lasttarget = 0; |
550 | fs->jpc = NO_JUMP; | ||
551 | fs->freereg = 0; | 550 | fs->freereg = 0; |
552 | fs->nk = 0; | 551 | fs->nk = 0; |
553 | fs->nabslineinfo = 0; | 552 | fs->nabslineinfo = 0; |
@@ -569,6 +568,7 @@ static void close_func (LexState *ls) { | |||
569 | Proto *f = fs->f; | 568 | Proto *f = fs->f; |
570 | luaK_ret(fs, 0, 0); /* final return */ | 569 | luaK_ret(fs, 0, 0); /* final return */ |
571 | leaveblock(fs); | 570 | leaveblock(fs); |
571 | luaK_finish(fs); | ||
572 | luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction); | 572 | luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction); |
573 | f->sizecode = fs->pc; | 573 | f->sizecode = fs->pc; |
574 | luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->pc, ls_byte); | 574 | luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->pc, ls_byte); |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lparser.h,v 1.77 2017/04/28 20:57:45 roberto Exp roberto $ | 2 | ** $Id: lparser.h,v 1.78 2017/06/27 11:35:31 roberto Exp roberto $ |
3 | ** Lua Parser | 3 | ** Lua Parser |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -124,7 +124,6 @@ typedef struct FuncState { | |||
124 | int pc; /* next position to code (equivalent to 'ncode') */ | 124 | int pc; /* next position to code (equivalent to 'ncode') */ |
125 | int lasttarget; /* 'label' of last 'jump label' */ | 125 | int lasttarget; /* 'label' of last 'jump label' */ |
126 | int previousline; /* last line that was saved in 'lineinfo' */ | 126 | int previousline; /* last line that was saved in 'lineinfo' */ |
127 | int jpc; /* list of pending jumps to 'pc' */ | ||
128 | int nk; /* number of elements in 'k' */ | 127 | int nk; /* number of elements in 'k' */ |
129 | int np; /* number of elements in 'p' */ | 128 | int np; /* number of elements in 'p' */ |
130 | int nabslineinfo; /* number of elements in 'abslineinfo' */ | 129 | int nabslineinfo; /* number of elements in 'abslineinfo' */ |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lvm.c,v 2.321 2017/11/29 13:02:17 roberto Exp roberto $ | 2 | ** $Id: lvm.c,v 2.322 2017/11/29 16:57:36 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 | */ |
@@ -1453,7 +1453,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
1453 | /* next instruction will do the return */ | 1453 | /* next instruction will do the return */ |
1454 | } | 1454 | } |
1455 | else { /* tail call */ | 1455 | else { /* tail call */ |
1456 | if (cl->p->sizep > 0) /* close upvalues from previous call */ | 1456 | if (TESTARG_k(i)) /* close upvalues from previous call */ |
1457 | luaF_close(L, ci->func + 1); | 1457 | luaF_close(L, ci->func + 1); |
1458 | luaD_pretailcall(L, ci, ra, b); /* prepare call frame */ | 1458 | luaD_pretailcall(L, ci, ra, b); /* prepare call frame */ |
1459 | goto tailcall; | 1459 | goto tailcall; |
@@ -1462,7 +1462,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
1462 | } | 1462 | } |
1463 | vmcase(OP_RETURN) { | 1463 | vmcase(OP_RETURN) { |
1464 | int b = GETARG_B(i); | 1464 | int b = GETARG_B(i); |
1465 | if (cl->p->sizep > 0) | 1465 | if (TESTARG_k(i)) |
1466 | luaF_close(L, base); | 1466 | luaF_close(L, base); |
1467 | halfProtect( | 1467 | halfProtect( |
1468 | luaD_poscall(L, ci, ra, (b != 0 ? b - 1 : cast_int(L->top - ra))) | 1468 | luaD_poscall(L, ci, ra, (b != 0 ? b - 1 : cast_int(L->top - ra))) |
@@ -1470,7 +1470,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
1470 | return; | 1470 | return; |
1471 | } | 1471 | } |
1472 | vmcase(OP_RETURN0) { | 1472 | vmcase(OP_RETURN0) { |
1473 | if (cl->p->sizep > 0) | 1473 | if (TESTARG_k(i)) |
1474 | luaF_close(L, base); | 1474 | luaF_close(L, base); |
1475 | if (L->hookmask) | 1475 | if (L->hookmask) |
1476 | halfProtect(luaD_poscall(L, ci, ra, 0)); /* no hurry... */ | 1476 | halfProtect(luaD_poscall(L, ci, ra, 0)); /* no hurry... */ |
@@ -1484,7 +1484,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) { | |||
1484 | return; | 1484 | return; |
1485 | } | 1485 | } |
1486 | vmcase(OP_RETURN1) { | 1486 | vmcase(OP_RETURN1) { |
1487 | if (cl->p->sizep > 0) | 1487 | if (TESTARG_k(i)) |
1488 | luaF_close(L, base); | 1488 | luaF_close(L, base); |
1489 | if (L->hookmask) | 1489 | if (L->hookmask) |
1490 | halfProtect(luaD_poscall(L, ci, ra, 1)); /* no hurry... */ | 1490 | halfProtect(luaD_poscall(L, ci, ra, 1)); /* no hurry... */ |