diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2017-11-07 15:20:42 -0200 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2017-11-07 15:20:42 -0200 |
| commit | c3e5946fb2b7b5781d9bca9d303967abe6263482 (patch) | |
| tree | 012bee6184675f1559e994eba42dda7c38381283 /lcode.c | |
| parent | ad0704e40cc7b3135fedc6d40a522addb039e090 (diff) | |
| download | lua-c3e5946fb2b7b5781d9bca9d303967abe6263482.tar.gz lua-c3e5946fb2b7b5781d9bca9d303967abe6263482.tar.bz2 lua-c3e5946fb2b7b5781d9bca9d303967abe6263482.zip | |
new format for JUMP instructions (to allow larger offsets)
Diffstat (limited to '')
| -rw-r--r-- | lcode.c | 35 |
1 files changed, 25 insertions, 10 deletions
| @@ -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 | ||
| 40 | static 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 | */ |
| 91 | static int getjump (FuncState *fs, int pc) { | 94 | static 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 | */ |
| 292 | void luaK_patchgoto (FuncState *fs, int list, int target, int hasclose) { | 296 | void 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 | */ |
| 312 | void luaK_patchclose (FuncState *fs, int list) { | 316 | void 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 | */ | ||
| 408 | static 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 | */ |
| 404 | static int codeextraarg (FuncState *fs, int a) { | 419 | static int codeextraarg (FuncState *fs, int a) { |
