|
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 | 3 | ** Code generator for Lua |
4 | 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 | 136 | ** Create a jump instruction and return its position, so its destination |
137 | | -** can be fixed later (with 'fixjump'). If there are jumps to |
138 | | -** this position (kept in 'jpc'), link them all together so that |
139 | | -** 'patchlistaux' will fix all them directly to the final destination. |
| 137 | +** can be fixed later (with 'fixjump'). |
140 | 138 | */ |
141 | 139 | int luaK_jump (FuncState *fs) { |
142 | | - int jpc = fs->jpc; /* save list of jumps to here */ |
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; |
| 140 | + return codesJ(fs, OP_JMP, NO_JUMP, 0); |
148 | 141 | } |
149 | 142 |
|
150 | 143 |
|
@@ -249,39 +242,20 @@ static void patchlistaux (FuncState *fs, int list, int vtarget, int reg, |
249 | 242 | } |
250 | 243 |
|
251 | 244 |
|
252 | | -/* |
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 | 245 | /* |
274 | 246 | ** Path all jumps in 'list' to jump to 'target'. |
275 | 247 | ** (The assert means that we cannot fix a jump to a forward address |
276 | 248 | ** because we only know addresses once code is generated.) |
277 | 249 | */ |
278 | 250 | void luaK_patchlist (FuncState *fs, int list, int target) { |
279 | | - if (target == fs->pc) /* 'target' is current position? */ |
280 | | - luaK_patchtohere(fs, list); /* add list to pending jumps */ |
281 | | - else { |
282 | | - lua_assert(target < fs->pc); |
283 | | - patchlistaux(fs, list, target, NO_REG, target); |
284 | | - } |
| 251 | + lua_assert(target <= fs->pc); |
| 252 | + patchlistaux(fs, list, target, NO_REG, target); |
| 253 | +} |
| 254 | + |
| 255 | + |
| 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 | 340 | static int luaK_code (FuncState *fs, Instruction i) { |
367 | 341 | Proto *f = fs->f; |
368 | | - dischargejpc(fs); /* 'pc' will change */ |
369 | 342 | /* put new instruction in code array */ |
370 | 343 | luaM_growvector(fs->ls->L, f->code, fs->pc, f->sizecode, Instruction, |
371 | 344 | MAX_INT, "opcodes"); |
@@ -1537,3 +1510,45 @@ void luaK_setlist (FuncState *fs, int base, int nelems, int tostore) { |
1537 | 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 | +} |
0 commit comments