History

Lua 5.0

Lua Team committed 23 years ago

Commit 488a64b1 parent c2bb718138 files · +16186 −12300Browse files

Showing the changes to src/lcode.c (1 of 138 files). Show all

Unified · Split

src/lcode.c+530−517
@@ -1,66 +1,84 @@
1/*1/*
2** $Id: lcode.c,v 1.51 2000/09/29 12:42:13 roberto Exp $2** $Id: lcode.c,v 1.117 2003/04/03 13:35:34 roberto Exp $
3** Code generator for Lua3** Code generator for Lua
4** See Copyright Notice in lua.h4** See Copyright Notice in lua.h
5*/5*/
6 6
7 7
8#include "stdlib.h"8#include <stdlib.h>
9
10#define lcode_c
9 11
10#include "lua.h"12#include "lua.h"
11 13
12#include "lcode.h"14#include "lcode.h"
15#include "ldebug.h"
13#include "ldo.h"16#include "ldo.h"
14#include "llex.h"17#include "llex.h"
15#include "lmem.h"18#include "lmem.h"
16#include "lobject.h"19#include "lobject.h"
17#include "lopcodes.h"20#include "lopcodes.h"
18#include "lparser.h"21#include "lparser.h"
22#include "ltable.h"
19 23
20 24
21void luaK_error (LexState *ls, const char *msg) {25#define hasjumps(e) ((e)->t != (e)->f)
22 luaX_error(ls, msg, ls->t.token);
23}
24 26
25 27
26/*28void luaK_nil (FuncState *fs, int from, int n) {
27** Returns the the previous instruction, for optimizations.29 Instruction *previous;
28** If there is a jump target between this and the current instruction,30 if (fs->pc > fs->lasttarget && /* no jumps to current position? */
29** returns a dummy instruction to avoid wrong optimizations.31 GET_OPCODE(*(previous = &fs->f->code[fs->pc-1])) == OP_LOADNIL) {
30*/32 int pfrom = GETARG_A(*previous);
31static Instruction previous_instruction (FuncState *fs) {33 int pto = GETARG_B(*previous);
32 if (fs->pc > fs->lasttarget) /* no jumps to current position? */34 if (pfrom <= from && from <= pto+1) { /* can connect both? */
33 return fs->f->code[fs->pc-1]; /* returns previous instruction */35 if (from+n-1 > pto)
34 else36 SETARG_B(*previous, from+n-1);
35 return CREATE_0(OP_END); /* no optimizations after an `END' */37 return;
38 }
39 }
40 luaK_codeABC(fs, OP_LOADNIL, from, from+n-1, 0); /* else no optimization */
36}41}
37 42
38 43
39int luaK_jump (FuncState *fs) {44int luaK_jump (FuncState *fs) {
40 int j = luaK_code1(fs, OP_JMP, NO_JUMP);45 int jpc = fs->jpc; /* save list of jumps to here */
41 if (j == fs->lasttarget) { /* possible jumps to this jump? */46 int j;
42 luaK_concat(fs, &j, fs->jlt); /* keep them on hold */47 fs->jpc = NO_JUMP;
43 fs->jlt = NO_JUMP;48 j = luaK_codeAsBx(fs, OP_JMP, 0, NO_JUMP);
44 }49 luaK_concat(fs, &j, jpc); /* keep them on hold */
45 return j;50 return j;
46}51}
47 52
48 53
54static int luaK_condjump (FuncState *fs, OpCode op, int A, int B, int C) {
55 luaK_codeABC(fs, op, A, B, C);
56 return luaK_jump(fs);
57}
58
59
49static void luaK_fixjump (FuncState *fs, int pc, int dest) {60static void luaK_fixjump (FuncState *fs, int pc, int dest) {
50 Instruction *jmp = &fs->f->code[pc];61 Instruction *jmp = &fs->f->code[pc];
51 if (dest == NO_JUMP)62 int offset = dest-(pc+1);
52 SETARG_S(*jmp, NO_JUMP); /* point to itself to represent end of list */63 lua_assert(dest != NO_JUMP);
53 else { /* jump is relative to position following jump instruction */64 if (abs(offset) > MAXARG_sBx)
54 int offset = dest-(pc+1);65 luaX_syntaxerror(fs->ls, "control structure too long");
55 if (abs(offset) > MAXARG_S)66 SETARG_sBx(*jmp, offset);
56 luaK_error(fs->ls, "control structure too long");67}
57 SETARG_S(*jmp, offset);68
58 }69
70/*
71** returns current `pc' and marks it as a jump target (to avoid wrong
72** optimizations with consecutive instructions not in the same basic block).
73*/
74int luaK_getlabel (FuncState *fs) {
75 fs->lasttarget = fs->pc;
76 return fs->pc;
59}77}
60 78
61 79
62static int luaK_getjump (FuncState *fs, int pc) {80static int luaK_getjump (FuncState *fs, int pc) {
63 int offset = GETARG_S(fs->f->code[pc]);81 int offset = GETARG_sBx(fs->f->code[pc]);
64 if (offset == NO_JUMP) /* point to itself represents end of list */82 if (offset == NO_JUMP) /* point to itself represents end of list */
65 return NO_JUMP; /* end of list */83 return NO_JUMP; /* end of list */
66 else84 else
@@ -68,634 +86,629 @@ static int luaK_getjump (FuncState *fs, int pc) { · 1 unmodified line
68}86}
69 87
70 88
89static Instruction *getjumpcontrol (FuncState *fs, int pc) {
90 Instruction *pi = &fs->f->code[pc];
91 if (pc >= 1 && testOpMode(GET_OPCODE(*(pi-1)), OpModeT))
92 return pi-1;
93 else
94 return pi;
95}
96
97
71/*98/*
72** returns current `pc' and marks it as a jump target (to avoid wrong99** check whether list has any jump that do not produce a value
73** optimizations with consecutive instructions not in the same basic block).100** (or produce an inverted value)
74** discharge list of jumps to last target.
75*/101*/
76int luaK_getlabel (FuncState *fs) {102static int need_value (FuncState *fs, int list, int cond) {
77 if (fs->pc != fs->lasttarget) {103 for (; list != NO_JUMP; list = luaK_getjump(fs, list)) {
78 int lasttarget = fs->lasttarget;104 Instruction i = *getjumpcontrol(fs, list);
79 fs->lasttarget = fs->pc;105 if (GET_OPCODE(i) != OP_TEST || GETARG_C(i) != cond) return 1;
80 luaK_patchlist(fs, fs->jlt, lasttarget); /* discharge old list `jlt' */
81 fs->jlt = NO_JUMP; /* nobody jumps to this new label (yet) */
82 }106 }
83 return fs->pc;107 return 0; /* not found */
84}108}
85 109
86 110
87void luaK_deltastack (FuncState *fs, int delta) {111static void patchtestreg (Instruction *i, int reg) {
88 fs->stacklevel += delta;112 if (reg == NO_REG) reg = GETARG_B(*i);
89 if (fs->stacklevel > fs->f->maxstacksize) {113 SETARG_A(*i, reg);
90 if (fs->stacklevel > MAXSTACK)
91 luaK_error(fs->ls, "function or expression too complex");
92 fs->f->maxstacksize = fs->stacklevel;
93 }
94}114}
95 115
96 116
97void luaK_kstr (LexState *ls, int c) {117static void luaK_patchlistaux (FuncState *fs, int list,
98 luaK_code1(ls->fs, OP_PUSHSTRING, c);118 int ttarget, int treg, int ftarget, int freg, int dtarget) {
119 while (list != NO_JUMP) {
120 int next = luaK_getjump(fs, list);
121 Instruction *i = getjumpcontrol(fs, list);
122 if (GET_OPCODE(*i) != OP_TEST) {
123 lua_assert(dtarget != NO_JUMP);
124 luaK_fixjump(fs, list, dtarget); /* jump to default target */
125 }
126 else {
127 if (GETARG_C(*i)) {
128 lua_assert(ttarget != NO_JUMP);
129 patchtestreg(i, treg);
130 luaK_fixjump(fs, list, ttarget);
131 }
132 else {
133 lua_assert(ftarget != NO_JUMP);
134 patchtestreg(i, freg);
135 luaK_fixjump(fs, list, ftarget);
136 }
137 }
138 list = next;
139 }
99}140}
100 141
101 142
102static int number_constant (FuncState *fs, Number r) {143static void luaK_dischargejpc (FuncState *fs) {
103 /* check whether `r' has appeared within the last LOOKBACKNUMS entries */144 luaK_patchlistaux(fs, fs->jpc, fs->pc, NO_REG, fs->pc, NO_REG, fs->pc);
104 Proto *f = fs->f;145 fs->jpc = NO_JUMP;
105 int c = f->nknum;
106 int lim = c < LOOKBACKNUMS ? 0 : c-LOOKBACKNUMS;
107 while (--c >= lim)
108 if (f->knum[c] == r) return c;
109 /* not found; create a new entry */
110 luaM_growvector(fs->L, f->knum, f->nknum, 1, Number,
111 "constant table overflow", MAXARG_U);
112 c = f->nknum++;
113 f->knum[c] = r;
114 return c;
115}
116
117
118void luaK_number (FuncState *fs, Number f) {
119 if (f <= (Number)MAXARG_S && (Number)(int)f == f)
120 luaK_code1(fs, OP_PUSHINT, (int)f); /* f has a short integer value */
121 else
122 luaK_code1(fs, OP_PUSHNUM, number_constant(fs, f));
123}146}
124 147
125 148
126void luaK_adjuststack (FuncState *fs, int n) {149void luaK_patchlist (FuncState *fs, int list, int target) {
127 if (n > 0)150 if (target == fs->pc)
128 luaK_code1(fs, OP_POP, n);151 luaK_patchtohere(fs, list);
129 else152 else {
130 luaK_code1(fs, OP_PUSHNIL, -n);153 lua_assert(target < fs->pc);
154 luaK_patchlistaux(fs, list, target, NO_REG, target, NO_REG, target);
155 }
131}156}
132 157
133 158
134int luaK_lastisopen (FuncState *fs) {159void luaK_patchtohere (FuncState *fs, int list) {
135 /* check whether last instruction is an open function call */160 luaK_getlabel(fs);
136 Instruction i = previous_instruction(fs);161 luaK_concat(fs, &fs->jpc, list);
137 if (GET_OPCODE(i) == OP_CALL && GETARG_B(i) == MULT_RET)
138 return 1;
139 else return 0;
140}162}
141 163
142 164
143void luaK_setcallreturns (FuncState *fs, int nresults) {165void luaK_concat (FuncState *fs, int *l1, int l2) {
144 if (luaK_lastisopen(fs)) { /* expression is an open function call? */166 if (l2 == NO_JUMP) return;
145 SETARG_B(fs->f->code[fs->pc-1], nresults); /* set number of results */167 else if (*l1 == NO_JUMP)
146 luaK_deltastack(fs, nresults); /* push results */168 *l1 = l2;
169 else {
170 int list = *l1;
171 int next;
172 while ((next = luaK_getjump(fs, list)) != NO_JUMP) /* find last element */
173 list = next;
174 luaK_fixjump(fs, list, l2);
147 }175 }
148}176}
149 177
150 178
151static int discharge (FuncState *fs, expdesc *var) {179void luaK_checkstack (FuncState *fs, int n) {
152 switch (var->k) {180 int newstack = fs->freereg + n;
153 case VLOCAL:181 if (newstack > fs->f->maxstacksize) {
154 luaK_code1(fs, OP_GETLOCAL, var->u.index);182 if (newstack >= MAXSTACK)
155 break;183 luaX_syntaxerror(fs->ls, "function or expression too complex");
156 case VGLOBAL:184 fs->f->maxstacksize = cast(lu_byte, newstack);
157 luaK_code1(fs, OP_GETGLOBAL, var->u.index);
158 break;
159 case VINDEXED:
160 luaK_code0(fs, OP_GETTABLE);
161 break;
162 case VEXP:
163 return 0; /* nothing to do */
164 }185 }
165 var->k = VEXP;
166 var->u.l.t = var->u.l.f = NO_JUMP;
167 return 1;
168}186}
169 187
170 188
171static void discharge1 (FuncState *fs, expdesc *var) {189void luaK_reserveregs (FuncState *fs, int n) {
172 discharge(fs, var);190 luaK_checkstack(fs, n);
173 /* if it has jumps then it is already discharged */191 fs->freereg += n;
174 if (var->u.l.t == NO_JUMP && var->u.l.f == NO_JUMP)
175 luaK_setcallreturns(fs, 1); /* call must return 1 value */
176}192}
177 193
178 194
179void luaK_storevar (LexState *ls, const expdesc *var) {195static void freereg (FuncState *fs, int reg) {
180 FuncState *fs = ls->fs;196 if (reg >= fs->nactvar && reg < MAXSTACK) {
181 switch (var->k) {197 fs->freereg--;
182 case VLOCAL:198 lua_assert(reg == fs->freereg);
183 luaK_code1(fs, OP_SETLOCAL, var->u.index);
184 break;
185 case VGLOBAL:
186 luaK_code1(fs, OP_SETGLOBAL, var->u.index);
187 break;
188 case VINDEXED: /* table is at top-3; pop 3 elements after operation */
189 luaK_code2(fs, OP_SETTABLE, 3, 3);
190 break;
191 default:
192 LUA_INTERNALERROR("invalid var kind to store");
193 }199 }
194}200}
195 201
196 202
197static OpCode invertjump (OpCode op) {203static void freeexp (FuncState *fs, expdesc *e) {
198 switch (op) {204 if (e->k == VNONRELOC)
199 case OP_JMPNE: return OP_JMPEQ;205 freereg(fs, e->info);
200 case OP_JMPEQ: return OP_JMPNE;
201 case OP_JMPLT: return OP_JMPGE;
202 case OP_JMPLE: return OP_JMPGT;
203 case OP_JMPGT: return OP_JMPLE;
204 case OP_JMPGE: return OP_JMPLT;
205 case OP_JMPT: case OP_JMPONT: return OP_JMPF;
206 case OP_JMPF: case OP_JMPONF: return OP_JMPT;
207 default:
208 LUA_INTERNALERROR("invalid jump instruction");
209 return OP_END; /* to avoid warnings */
210 }
211}206}
212 207
213 208
214static void luaK_patchlistaux (FuncState *fs, int list, int target,209static int addk (FuncState *fs, TObject *k, TObject *v) {
215 OpCode special, int special_target) {210 const TObject *idx = luaH_get(fs->h, k);
216 Instruction *code = fs->f->code;211 if (ttisnumber(idx)) {
217 while (list != NO_JUMP) {212 lua_assert(luaO_rawequalObj(&fs->f->k[cast(int, nvalue(idx))], v));
218 int next = luaK_getjump(fs, list);213 return cast(int, nvalue(idx));
219 Instruction *i = &code[list];214 }
220 OpCode op = GET_OPCODE(*i);215 else { /* constant not found; create a new entry */
221 if (op == special) /* this `op' already has a value */216 Proto *f = fs->f;
222 luaK_fixjump(fs, list, special_target);217 luaM_growvector(fs->L, f->k, fs->nk, f->sizek, TObject,
223 else {218 MAXARG_Bx, "constant table overflow");
224 luaK_fixjump(fs, list, target); /* do the patch */219 setobj2n(&f->k[fs->nk], v);
225 if (op == OP_JMPONT) /* remove eventual values */220 setnvalue(luaH_set(fs->L, fs->h, k), cast(lua_Number, fs->nk));
226 SET_OPCODE(*i, OP_JMPT);221 return fs->nk++;
227 else if (op == OP_JMPONF)
228 SET_OPCODE(*i, OP_JMPF);
229 }
230 list = next;
231 }222 }
232}223}
233 224
234 225
235void luaK_patchlist (FuncState *fs, int list, int target) {226int luaK_stringK (FuncState *fs, TString *s) {
236 if (target == fs->lasttarget) /* same target that list `jlt'? */227 TObject o;
237 luaK_concat(fs, &fs->jlt, list); /* delay fixing */228 setsvalue(&o, s);
238 else229 return addk(fs, &o, &o);
239 luaK_patchlistaux(fs, list, target, OP_END, 0);
240}230}
241 231
242 232
243static int need_value (FuncState *fs, int list, OpCode hasvalue) {233int luaK_numberK (FuncState *fs, lua_Number r) {
244 /* check whether list has a jump without a value */234 TObject o;
245 for (; list != NO_JUMP; list = luaK_getjump(fs, list))235 setnvalue(&o, r);
246 if (GET_OPCODE(fs->f->code[list]) != hasvalue) return 1;236 return addk(fs, &o, &o);
247 return 0; /* not found */
248}237}
249 238
250 239
251void luaK_concat (FuncState *fs, int *l1, int l2) {240static int nil_constant (FuncState *fs) {
252 if (*l1 == NO_JUMP)241 TObject k, v;
253 *l1 = l2;242 setnilvalue(&v);
254 else {243 sethvalue(&k, fs->h); /* cannot use nil as key; instead use table itself */
255 int list = *l1;244 return addk(fs, &k, &v);
256 for (;;) { /* traverse `l1' */
257 int next = luaK_getjump(fs, list);
258 if (next == NO_JUMP) { /* end of list? */
259 luaK_fixjump(fs, list, l2);
260 return;
261 }
262 list = next;
263 }
264 }
265}245}
266 246
267 247
268static void luaK_testgo (FuncState *fs, expdesc *v, int invert, OpCode jump) {248void luaK_setcallreturns (FuncState *fs, expdesc *e, int nresults) {
269 int prevpos; /* position of last instruction */249 if (e->k == VCALL) { /* expression is an open function call? */
270 Instruction *previous;250 SETARG_C(getcode(fs, e), nresults+1);
271 int *golist, *exitlist;251 if (nresults == 1) { /* `regular' expression? */
272 if (!invert) {252 e->k = VNONRELOC;
273 golist = &v->u.l.f; /* go if false */253 e->info = GETARG_A(getcode(fs, e));
274 exitlist = &v->u.l.t; /* exit if true */254 }
275 }
276 else {
277 golist = &v->u.l.t; /* go if true */
278 exitlist = &v->u.l.f; /* exit if false */
279 }
280 discharge1(fs, v);
281 prevpos = fs->pc-1;
282 previous = &fs->f->code[prevpos];
283 LUA_ASSERT(*previous==previous_instruction(fs), "no jump allowed here");
284 if (!ISJUMP(GET_OPCODE(*previous)))
285 prevpos = luaK_code1(fs, jump, NO_JUMP);
286 else { /* last instruction is already a jump */
287 if (invert)
288 SET_OPCODE(*previous, invertjump(GET_OPCODE(*previous)));
289 }255 }
290 luaK_concat(fs, exitlist, prevpos); /* insert last jump in `exitlist' */
291 luaK_patchlist(fs, *golist, luaK_getlabel(fs));
292 *golist = NO_JUMP;
293}256}
294 257
295 258
296void luaK_goiftrue (FuncState *fs, expdesc *v, int keepvalue) {259void luaK_dischargevars (FuncState *fs, expdesc *e) {
297 luaK_testgo(fs, v, 1, keepvalue ? OP_JMPONF : OP_JMPF);260 switch (e->k) {
261 case VLOCAL: {
262 e->k = VNONRELOC;
263 break;
264 }
265 case VUPVAL: {
266 e->info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->info, 0);
267 e->k = VRELOCABLE;
268 break;
269 }
270 case VGLOBAL: {
271 e->info = luaK_codeABx(fs, OP_GETGLOBAL, 0, e->info);
272 e->k = VRELOCABLE;
273 break;
274 }
275 case VINDEXED: {
276 freereg(fs, e->aux);
277 freereg(fs, e->info);
278 e->info = luaK_codeABC(fs, OP_GETTABLE, 0, e->info, e->aux);
279 e->k = VRELOCABLE;
280 break;
281 }
282 case VCALL: {
283 luaK_setcallreturns(fs, e, 1);
284 break;
285 }
286 default: break; /* there is one value available (somewhere) */
287 }
298}288}
299 289
300 290
301static void luaK_goiffalse (FuncState *fs, expdesc *v, int keepvalue) {291static int code_label (FuncState *fs, int A, int b, int jump) {
302 luaK_testgo(fs, v, 0, keepvalue ? OP_JMPONT : OP_JMPT);292 luaK_getlabel(fs); /* those instructions may be jump targets */
293 return luaK_codeABC(fs, OP_LOADBOOL, A, b, jump);
303}294}
304 295
305 296
306static int code_label (FuncState *fs, OpCode op, int arg) {297static void discharge2reg (FuncState *fs, expdesc *e, int reg) {
307 luaK_getlabel(fs); /* those instructions may be jump targets */298 luaK_dischargevars(fs, e);
308 return luaK_code1(fs, op, arg);299 switch (e->k) {
309}300 case VNIL: {
310 301 luaK_nil(fs, reg, 1);
311 302 break;
312void luaK_tostack (LexState *ls, expdesc *v, int onlyone) {303 }
313 FuncState *fs = ls->fs;304 case VFALSE: case VTRUE: {
314 if (!discharge(fs, v)) { /* `v' is an expression? */305 luaK_codeABC(fs, OP_LOADBOOL, reg, e->k == VTRUE, 0);
315 OpCode previous = GET_OPCODE(fs->f->code[fs->pc-1]);306 break;
316 if (!ISJUMP(previous) && v->u.l.f == NO_JUMP && v->u.l.t == NO_JUMP) {307 }
317 /* expression has no jumps */308 case VK: {
318 if (onlyone)309 luaK_codeABx(fs, OP_LOADK, reg, e->info);
319 luaK_setcallreturns(fs, 1); /* call must return 1 value */310 break;
320 }311 }
321 else { /* expression has jumps */312 case VRELOCABLE: {
322 int final; /* position after whole expression */313 Instruction *pc = &getcode(fs, e);
323 int j = NO_JUMP; /* eventual jump over values */314 SETARG_A(*pc, reg);
324 int p_nil = NO_JUMP; /* position of an eventual PUSHNIL */315 break;
325 int p_1 = NO_JUMP; /* position of an eventual PUSHINT */316 }
326 if (ISJUMP(previous) || need_value(fs, v->u.l.f, OP_JMPONF)317 case VNONRELOC: {
327 || need_value(fs, v->u.l.t, OP_JMPONT)) {318 if (reg != e->info)
328 /* expression needs values */319 luaK_codeABC(fs, OP_MOVE, reg, e->info, 0);
329 if (ISJUMP(previous))320 break;
330 luaK_concat(fs, &v->u.l.t, fs->pc-1); /* put `previous' in t. list */321 }
331 else {322 default: {
332 j = code_label(fs, OP_JMP, NO_JUMP); /* to jump over both pushes */323 lua_assert(e->k == VVOID || e->k == VJMP);
333 /* correct stack for compiler and symbolic execution */324 return; /* nothing to do... */
334 luaK_adjuststack(fs, 1);
335 }
336 p_nil = code_label(fs, OP_PUSHNILJMP, 0);
337 p_1 = code_label(fs, OP_PUSHINT, 1);
338 luaK_patchlist(fs, j, luaK_getlabel(fs));
339 }
340 final = luaK_getlabel(fs);
341 luaK_patchlistaux(fs, v->u.l.f, p_nil, OP_JMPONF, final);
342 luaK_patchlistaux(fs, v->u.l.t, p_1, OP_JMPONT, final);
343 v->u.l.f = v->u.l.t = NO_JUMP;
344 }325 }
345 }326 }
327 e->info = reg;
328 e->k = VNONRELOC;
346}329}
347 330
348 331
349void luaK_prefix (LexState *ls, UnOpr op, expdesc *v) {332static void discharge2anyreg (FuncState *fs, expdesc *e) {
350 FuncState *fs = ls->fs;333 if (e->k != VNONRELOC) {
351 if (op == OPR_MINUS) {334 luaK_reserveregs(fs, 1);
352 luaK_tostack(ls, v, 1);335 discharge2reg(fs, e, fs->freereg-1);
353 luaK_code0(fs, OP_MINUS);
354 }336 }
355 else { /* op == NOT */337}
356 Instruction *previous;338
357 discharge1(fs, v);339
358 previous = &fs->f->code[fs->pc-1];340static void luaK_exp2reg (FuncState *fs, expdesc *e, int reg) {
359 if (ISJUMP(GET_OPCODE(*previous)))341 discharge2reg(fs, e, reg);
360 SET_OPCODE(*previous, invertjump(GET_OPCODE(*previous)));342 if (e->k == VJMP)
361 else343 luaK_concat(fs, &e->t, e->info); /* put this jump in `t' list */
362 luaK_code0(fs, OP_NOT);344 if (hasjumps(e)) {
363 /* interchange true and false lists */345 int final; /* position after whole expression */
364 { int temp = v->u.l.f; v->u.l.f = v->u.l.t; v->u.l.t = temp; }346 int p_f = NO_JUMP; /* position of an eventual LOAD false */
347 int p_t = NO_JUMP; /* position of an eventual LOAD true */
348 if (need_value(fs, e->t, 1) || need_value(fs, e->f, 0)) {
349 int fj = NO_JUMP; /* first jump (over LOAD ops.) */
350 if (e->k != VJMP)
351 fj = luaK_jump(fs);
352 p_f = code_label(fs, reg, 0, 1);
353 p_t = code_label(fs, reg, 1, 0);
354 luaK_patchtohere(fs, fj);
355 }
356 final = luaK_getlabel(fs);
357 luaK_patchlistaux(fs, e->f, p_f, NO_REG, final, reg, p_f);
358 luaK_patchlistaux(fs, e->t, final, reg, p_t, NO_REG, p_t);
365 }359 }
360 e->f = e->t = NO_JUMP;
361 e->info = reg;
362 e->k = VNONRELOC;
366}363}
367 364
368 365
369void luaK_infix (LexState *ls, BinOpr op, expdesc *v) {366void luaK_exp2nextreg (FuncState *fs, expdesc *e) {
370 FuncState *fs = ls->fs;367 luaK_dischargevars(fs, e);
371 switch (op) {368 freeexp(fs, e);
372 case OPR_AND:369 luaK_reserveregs(fs, 1);
373 luaK_goiftrue(fs, v, 1);370 luaK_exp2reg(fs, e, fs->freereg - 1);
374 break;371}
375 case OPR_OR:372
376 luaK_goiffalse(fs, v, 1);373
377 break;374int luaK_exp2anyreg (FuncState *fs, expdesc *e) {
378 default:375 luaK_dischargevars(fs, e);
379 luaK_tostack(ls, v, 1); /* all other binary operators need a value */376 if (e->k == VNONRELOC) {
377 if (!hasjumps(e)) return e->info; /* exp is already in a register */
378 if (e->info >= fs->nactvar) { /* reg. is not a local? */
379 luaK_exp2reg(fs, e, e->info); /* put value on it */
380 return e->info;
381 }
380 }382 }
383 luaK_exp2nextreg(fs, e); /* default */
384 return e->info;
381}385}
382 386
383 387
388void luaK_exp2val (FuncState *fs, expdesc *e) {
389 if (hasjumps(e))
390 luaK_exp2anyreg(fs, e);
391 else
392 luaK_dischargevars(fs, e);
393}
384 394
385static const struct {
386 OpCode opcode; /* opcode for each binary operator */
387 int arg; /* default argument for the opcode */
388} codes[] = { /* ORDER OPR */
389 {OP_ADD, 0}, {OP_SUB, 0}, {OP_MULT, 0}, {OP_DIV, 0},
390 {OP_POW, 0}, {OP_CONCAT, 2},
391 {OP_JMPNE, NO_JUMP}, {OP_JMPEQ, NO_JUMP},
392 {OP_JMPLT, NO_JUMP}, {OP_JMPLE, NO_JUMP},
393 {OP_JMPGT, NO_JUMP}, {OP_JMPGE, NO_JUMP}
394};
395 395
396int luaK_exp2RK (FuncState *fs, expdesc *e) {
397 luaK_exp2val(fs, e);
398 switch (e->k) {
399 case VNIL: {
400 if (fs->nk + MAXSTACK <= MAXARG_C) { /* constant fit in argC? */
401 e->info = nil_constant(fs);
402 e->k = VK;
403 return e->info + MAXSTACK;
404 }
405 else break;
406 }
407 case VK: {
408 if (e->info + MAXSTACK <= MAXARG_C) /* constant fit in argC? */
409 return e->info + MAXSTACK;
410 else break;
411 }
412 default: break;
413 }
414 /* not a constant in the right range: put it in a register */
415 return luaK_exp2anyreg(fs, e);
416}
396 417
397void luaK_posfix (LexState *ls, BinOpr op, expdesc *v1, expdesc *v2) {418
398 FuncState *fs = ls->fs;419void luaK_storevar (FuncState *fs, expdesc *var, expdesc *exp) {
399 switch (op) {420 switch (var->k) {
400 case OPR_AND: {421 case VLOCAL: {
401 LUA_ASSERT(v1->u.l.t == NO_JUMP, "list must be closed");422 freeexp(fs, exp);
402 discharge1(fs, v2);423 luaK_exp2reg(fs, exp, var->info);
403 v1->u.l.t = v2->u.l.t;424 return;
404 luaK_concat(fs, &v1->u.l.f, v2->u.l.f);425 }
426 case VUPVAL: {
427 int e = luaK_exp2anyreg(fs, exp);
428 luaK_codeABC(fs, OP_SETUPVAL, e, var->info, 0);
405 break;429 break;
406 }430 }
407 case OPR_OR: {431 case VGLOBAL: {
408 LUA_ASSERT(v1->u.l.f == NO_JUMP, "list must be closed");432 int e = luaK_exp2anyreg(fs, exp);
409 discharge1(fs, v2);433 luaK_codeABx(fs, OP_SETGLOBAL, e, var->info);
410 v1->u.l.f = v2->u.l.f;434 break;
411 luaK_concat(fs, &v1->u.l.t, v2->u.l.t);435 }
436 case VINDEXED: {
437 int e = luaK_exp2RK(fs, exp);
438 luaK_codeABC(fs, OP_SETTABLE, var->info, var->aux, e);
412 break;439 break;
413 }440 }
414 default: {441 default: {
415 luaK_tostack(ls, v2, 1); /* `v2' must be a value */442 lua_assert(0); /* invalid var kind to store */
416 luaK_code1(fs, codes[op].opcode, codes[op].arg);443 break;
417 }444 }
418 }445 }
446 freeexp(fs, exp);
419}447}
420 448
421 449
422static void codelineinfo (FuncState *fs) {450void luaK_self (FuncState *fs, expdesc *e, expdesc *key) {
423 Proto *f = fs->f;451 int func;
424 LexState *ls = fs->ls;452 luaK_exp2anyreg(fs, e);
425 if (ls->lastline > fs->lastline) {453 freeexp(fs, e);
426 luaM_growvector(fs->L, f->lineinfo, f->nlineinfo, 2, int,454 func = fs->freereg;
427 "line info overflow", MAX_INT);455 luaK_reserveregs(fs, 2);
428 if (ls->lastline > fs->lastline+1)456 luaK_codeABC(fs, OP_SELF, func, e->info, luaK_exp2RK(fs, key));
429 f->lineinfo[f->nlineinfo++] = -(ls->lastline - (fs->lastline+1));457 freeexp(fs, key);
430 f->lineinfo[f->nlineinfo++] = fs->pc;458 e->info = func;
431 fs->lastline = ls->lastline;459 e->k = VNONRELOC;
432 }
433}460}
434 461
435 462
436int luaK_code0 (FuncState *fs, OpCode o) {463static void invertjump (FuncState *fs, expdesc *e) {
437 return luaK_code2(fs, o, 0, 0);464 Instruction *pc = getjumpcontrol(fs, e->info);
465 lua_assert(testOpMode(GET_OPCODE(*pc), OpModeT) &&
466 GET_OPCODE(*pc) != OP_TEST);
467 SETARG_A(*pc, !(GETARG_A(*pc)));
438}468}
439 469
440 470
441int luaK_code1 (FuncState *fs, OpCode o, int arg1) {471static int jumponcond (FuncState *fs, expdesc *e, int cond) {
442 return luaK_code2(fs, o, arg1, 0);472 if (e->k == VRELOCABLE) {
473 Instruction ie = getcode(fs, e);
474 if (GET_OPCODE(ie) == OP_NOT) {
475 fs->pc--; /* remove previous OP_NOT */
476 return luaK_condjump(fs, OP_TEST, NO_REG, GETARG_B(ie), !cond);
477 }
478 /* else go through */
479 }
480 discharge2anyreg(fs, e);
481 freeexp(fs, e);
482 return luaK_condjump(fs, OP_TEST, NO_REG, e->info, cond);
443}483}
444 484
445 485
446int luaK_code2 (FuncState *fs, OpCode o, int arg1, int arg2) {486void luaK_goiftrue (FuncState *fs, expdesc *e) {
447 Instruction i = previous_instruction(fs);487 int pc; /* pc of last jump */
448 int delta = luaK_opproperties[o].push - luaK_opproperties[o].pop;488 luaK_dischargevars(fs, e);
449 int optm = 0; /* 1 when there is an optimization */489 switch (e->k) {
450 switch (o) {490 case VK: case VTRUE: {
451 case OP_CLOSURE: {491 pc = NO_JUMP; /* always true; do nothing */
452 delta = -arg2+1;
453 break;492 break;
454 }493 }
455 case OP_SETTABLE: {494 case VFALSE: {
456 delta = -arg2;495 pc = luaK_jump(fs); /* always jump */
457 break;496 break;
458 }497 }
459 case OP_SETLIST: {498 case VJMP: {
460 if (arg2 == 0) return NO_JUMP; /* nothing to do */499 invertjump(fs, e);
461 delta = -arg2;500 pc = e->info;
462 break;501 break;
463 }502 }
464 case OP_SETMAP: {503 default: {
465 if (arg1 == 0) return NO_JUMP; /* nothing to do */504 pc = jumponcond(fs, e, 0);
466 delta = -2*arg1;
467 break;505 break;
468 }506 }
469 case OP_RETURN: {507 }
470 if (GET_OPCODE(i) == OP_CALL && GETARG_B(i) == MULT_RET) {508 luaK_concat(fs, &e->f, pc); /* insert last jump in `f' list */
471 SET_OPCODE(i, OP_TAILCALL);509}
472 SETARG_B(i, arg1);510
473 optm = 1;511
474 }512void luaK_goiffalse (FuncState *fs, expdesc *e) {
513 int pc; /* pc of last jump */
514 luaK_dischargevars(fs, e);
515 switch (e->k) {
516 case VNIL: case VFALSE: {
517 pc = NO_JUMP; /* always false; do nothing */
475 break;518 break;
476 }519 }
477 case OP_PUSHNIL: {520 case VTRUE: {
478 if (arg1 == 0) return NO_JUMP; /* nothing to do */521 pc = luaK_jump(fs); /* always jump */
479 delta = arg1;
480 switch(GET_OPCODE(i)) {
481 case OP_PUSHNIL: SETARG_U(i, GETARG_U(i)+arg1); optm = 1; break;
482 default: break;
483 }
484 break;522 break;
485 }523 }
486 case OP_POP: {524 case VJMP: {
487 if (arg1 == 0) return NO_JUMP; /* nothing to do */525 pc = e->info;
488 delta = -arg1;
489 switch(GET_OPCODE(i)) {
490 case OP_SETTABLE: SETARG_B(i, GETARG_B(i)+arg1); optm = 1; break;
491 default: break;
492 }
493 break;526 break;
494 }527 }
495 case OP_GETTABLE: {528 default: {
496 switch(GET_OPCODE(i)) {529 pc = jumponcond(fs, e, 1);
497 case OP_PUSHSTRING: /* `t.x' */
498 SET_OPCODE(i, OP_GETDOTTED);
499 optm = 1;
500 break;
501 case OP_GETLOCAL: /* `t[i]' */
502 SET_OPCODE(i, OP_GETINDEXED);
503 optm = 1;
504 break;
505 default: break;
506 }
507 break;530 break;
508 }531 }
509 case OP_ADD: {532 }
510 switch(GET_OPCODE(i)) {533 luaK_concat(fs, &e->t, pc); /* insert last jump in `t' list */
511 case OP_PUSHINT: SET_OPCODE(i, OP_ADDI); optm = 1; break; /* `a+k' */534}
512 default: break;535
513 }536
537static void codenot (FuncState *fs, expdesc *e) {
538 luaK_dischargevars(fs, e);
539 switch (e->k) {
540 case VNIL: case VFALSE: {
541 e->k = VTRUE;
514 break;542 break;
515 }543 }
516 case OP_SUB: {544 case VK: case VTRUE: {
517 switch(GET_OPCODE(i)) {545 e->k = VFALSE;
518 case OP_PUSHINT: /* `a-k' */
519 i = CREATE_S(OP_ADDI, -GETARG_S(i));
520 optm = 1;
521 break;
522 default: break;
523 }
524 break;546 break;
525 }547 }
526 case OP_CONCAT: {548 case VJMP: {
527 delta = -arg1+1;549 invertjump(fs, e);
528 switch(GET_OPCODE(i)) {
529 case OP_CONCAT: /* `a..b..c' */
530 SETARG_U(i, GETARG_U(i)+1);
531 optm = 1;
532 break;
533 default: break;
534 }
535 break;550 break;
536 }551 }
537 case OP_MINUS: {552 case VRELOCABLE:
538 switch(GET_OPCODE(i)) {553 case VNONRELOC: {
539 case OP_PUSHINT: /* `-k' */554 discharge2anyreg(fs, e);
540 SETARG_S(i, -GETARG_S(i));555 freeexp(fs, e);
541 optm = 1;556 e->info = luaK_codeABC(fs, OP_NOT, 0, e->info, 0);
542 break;557 e->k = VRELOCABLE;
543 case OP_PUSHNUM: /* `-k' */
544 SET_OPCODE(i, OP_PUSHNEGNUM);
545 optm = 1;
546 break;
547 default: break;
548 }
549 break;558 break;
550 }559 }
551 case OP_JMPNE: {560 default: {
552 if (i == CREATE_U(OP_PUSHNIL, 1)) { /* `a~=nil' */561 lua_assert(0); /* cannot happen */
553 i = CREATE_S(OP_JMPT, NO_JUMP);
554 optm = 1;
555 }
556 break;562 break;
557 }563 }
558 case OP_JMPEQ: {564 }
559 if (i == CREATE_U(OP_PUSHNIL, 1)) { /* `a==nil' */565 /* interchange true and false lists */
560 i = CREATE_0(OP_NOT);566 { int temp = e->f; e->f = e->t; e->t = temp; }
561 delta = -1; /* just undo effect of previous PUSHNIL */567}
562 optm = 1;568
563 }569
564 break;570void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) {
571 t->aux = luaK_exp2RK(fs, k);
572 t->k = VINDEXED;
573}
574
575
576void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) {
577 if (op == OPR_MINUS) {
578 luaK_exp2val(fs, e);
579 if (e->k == VK && ttisnumber(&fs->f->k[e->info]))
580 e->info = luaK_numberK(fs, -nvalue(&fs->f->k[e->info]));
581 else {
582 luaK_exp2anyreg(fs, e);
583 freeexp(fs, e);
584 e->info = luaK_codeABC(fs, OP_UNM, 0, e->info, 0);
585 e->k = VRELOCABLE;
565 }586 }
566 case OP_JMPT:587 }
567 case OP_JMPONT: {588 else /* op == NOT */
568 switch (GET_OPCODE(i)) {589 codenot(fs, e);
569 case OP_NOT: {590}
570 i = CREATE_S(OP_JMPF, NO_JUMP);591
571 optm = 1;592
572 break;593void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) {
573 }594 switch (op) {
574 case OP_PUSHINT: {595 case OPR_AND: {
575 if (o == OP_JMPT) { /* JMPONT must keep original integer value */596 luaK_goiftrue(fs, v);
576 i = CREATE_S(OP_JMP, NO_JUMP);597 luaK_patchtohere(fs, v->t);
577 optm = 1;598 v->t = NO_JUMP;
578 }
579 break;
580 }
581 case OP_PUSHNIL: {
582 if (GETARG_U(i) == 1) {
583 fs->pc--; /* erase previous instruction */
584 luaK_deltastack(fs, -1); /* correct stack */
585 return NO_JUMP;
586 }
587 break;
588 }
589 default: break;
590 }
591 break;599 break;
592 }600 }
593 case OP_JMPF:601 case OPR_OR: {
594 case OP_JMPONF: {602 luaK_goiffalse(fs, v);
595 switch (GET_OPCODE(i)) {603 luaK_patchtohere(fs, v->f);
596 case OP_NOT: {604 v->f = NO_JUMP;
597 i = CREATE_S(OP_JMPT, NO_JUMP);
598 optm = 1;
599 break;
600 }
601 case OP_PUSHINT: { /* `while 1 do ...' */
602 fs->pc--; /* erase previous instruction */
603 luaK_deltastack(fs, -1); /* correct stack */
604 return NO_JUMP;
605 }
606 case OP_PUSHNIL: { /* `repeat ... until nil' */
607 if (GETARG_U(i) == 1) {
608 i = CREATE_S(OP_JMP, NO_JUMP);
609 optm = 1;
610 }
611 break;
612 }
613 default: break;
614 }
615 break;605 break;
616 }606 }
617 case OP_GETDOTTED:607 case OPR_CONCAT: {
618 case OP_GETINDEXED:608 luaK_exp2nextreg(fs, v); /* operand must be on the `stack' */
619 case OP_TAILCALL:
620 case OP_ADDI: {
621 LUA_INTERNALERROR("instruction used only for optimizations");
622 break;609 break;
623 }610 }
624 default: {611 default: {
625 LUA_ASSERT(delta != VD, "invalid delta");612 luaK_exp2RK(fs, v);
626 break;613 break;
627 }614 }
628 }615 }
629 luaK_deltastack(fs, delta);616}
630 if (optm) { /* optimize: put instruction in place of last one */617
631 fs->f->code[fs->pc-1] = i; /* change previous instruction */618
632 return fs->pc-1; /* do not generate new instruction */619static void codebinop (FuncState *fs, expdesc *res, BinOpr op,
620 int o1, int o2) {
621 if (op <= OPR_POW) { /* arithmetic operator? */
622 OpCode opc = cast(OpCode, (op - OPR_ADD) + OP_ADD); /* ORDER OP */
623 res->info = luaK_codeABC(fs, opc, 0, o1, o2);
624 res->k = VRELOCABLE;
633 }625 }
634 /* else build new instruction */626 else { /* test operator */
635 switch ((enum Mode)luaK_opproperties[o].mode) {627 static const OpCode ops[] = {OP_EQ, OP_EQ, OP_LT, OP_LE, OP_LT, OP_LE};
636 case iO: i = CREATE_0(o); break;628 int cond = 1;
637 case iU: i = CREATE_U(o, arg1); break;629 if (op >= OPR_GT) { /* `>' or `>='? */
638 case iS: i = CREATE_S(o, arg1); break;630 int temp; /* exchange args and replace by `<' or `<=' */
639 case iAB: i = CREATE_AB(o, arg1, arg2); break;631 temp = o1; o1 = o2; o2 = temp; /* o1 <==> o2 */
632 }
633 else if (op == OPR_NE) cond = 0;
634 res->info = luaK_condjump(fs, ops[op - OPR_NE], cond, o1, o2);
635 res->k = VJMP;
640 }636 }
641 codelineinfo(fs);637}
638
639
640void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) {
641 switch (op) {
642 case OPR_AND: {
643 lua_assert(e1->t == NO_JUMP); /* list must be closed */
644 luaK_dischargevars(fs, e2);
645 luaK_concat(fs, &e1->f, e2->f);
646 e1->k = e2->k; e1->info = e2->info; e1->aux = e2->aux; e1->t = e2->t;
647 break;
648 }
649 case OPR_OR: {
650 lua_assert(e1->f == NO_JUMP); /* list must be closed */
651 luaK_dischargevars(fs, e2);
652 luaK_concat(fs, &e1->t, e2->t);
653 e1->k = e2->k; e1->info = e2->info; e1->aux = e2->aux; e1->f = e2->f;
654 break;
655 }
656 case OPR_CONCAT: {
657 luaK_exp2val(fs, e2);
658 if (e2->k == VRELOCABLE && GET_OPCODE(getcode(fs, e2)) == OP_CONCAT) {
659 lua_assert(e1->info == GETARG_B(getcode(fs, e2))-1);
660 freeexp(fs, e1);
661 SETARG_B(getcode(fs, e2), e1->info);
662 e1->k = e2->k; e1->info = e2->info;
663 }
664 else {
665 luaK_exp2nextreg(fs, e2);
666 freeexp(fs, e2);
667 freeexp(fs, e1);
668 e1->info = luaK_codeABC(fs, OP_CONCAT, 0, e1->info, e2->info);
669 e1->k = VRELOCABLE;
670 }
671 break;
672 }
673 default: {
674 int o1 = luaK_exp2RK(fs, e1);
675 int o2 = luaK_exp2RK(fs, e2);
676 freeexp(fs, e2);
677 freeexp(fs, e1);
678 codebinop(fs, e1, op, o1, o2);
679 }
680 }
681}
682
683
684void luaK_fixline (FuncState *fs, int line) {
685 fs->f->lineinfo[fs->pc - 1] = line;
686}
687
688
689int luaK_code (FuncState *fs, Instruction i, int line) {
690 Proto *f = fs->f;
691 luaK_dischargejpc(fs); /* `pc' will change */
642 /* put new instruction in code array */692 /* put new instruction in code array */
643 luaM_growvector(fs->L, fs->f->code, fs->pc, 1, Instruction,693 luaM_growvector(fs->L, f->code, fs->pc, f->sizecode, Instruction,
644 "code size overflow", MAX_INT);694 MAX_INT, "code size overflow");
645 fs->f->code[fs->pc] = i;695 f->code[fs->pc] = i;
696 /* save corresponding line information */
697 luaM_growvector(fs->L, f->lineinfo, fs->pc, f->sizelineinfo, int,
698 MAX_INT, "code size overflow");
699 f->lineinfo[fs->pc] = line;
646 return fs->pc++;700 return fs->pc++;
647}701}
648 702
649 703
650const struct OpProperties luaK_opproperties[NUM_OPCODES] = {704int luaK_codeABC (FuncState *fs, OpCode o, int a, int b, int c) {
651 {iO, 0, 0}, /* OP_END */705 lua_assert(getOpMode(o) == iABC);
652 {iU, 0, 0}, /* OP_RETURN */706 return luaK_code(fs, CREATE_ABC(o, a, b, c), fs->ls->lastline);
653 {iAB, 0, 0}, /* OP_CALL */707}
654 {iAB, 0, 0}, /* OP_TAILCALL */708
655 {iU, VD, 0}, /* OP_PUSHNIL */709
656 {iU, VD, 0}, /* OP_POP */710int luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) {
657 {iS, 1, 0}, /* OP_PUSHINT */711 lua_assert(getOpMode(o) == iABx || getOpMode(o) == iAsBx);
658 {iU, 1, 0}, /* OP_PUSHSTRING */712 return luaK_code(fs, CREATE_ABx(o, a, bc), fs->ls->lastline);
659 {iU, 1, 0}, /* OP_PUSHNUM */713}
660 {iU, 1, 0}, /* OP_PUSHNEGNUM */
661 {iU, 1, 0}, /* OP_PUSHUPVALUE */
662 {iU, 1, 0}, /* OP_GETLOCAL */
663 {iU, 1, 0}, /* OP_GETGLOBAL */
664 {iO, 1, 2}, /* OP_GETTABLE */
665 {iU, 1, 1}, /* OP_GETDOTTED */
666 {iU, 1, 1}, /* OP_GETINDEXED */
667 {iU, 2, 1}, /* OP_PUSHSELF */
668 {iU, 1, 0}, /* OP_CREATETABLE */
669 {iU, 0, 1}, /* OP_SETLOCAL */
670 {iU, 0, 1}, /* OP_SETGLOBAL */
671 {iAB, VD, 0}, /* OP_SETTABLE */
672 {iAB, VD, 0}, /* OP_SETLIST */
673 {iU, VD, 0}, /* OP_SETMAP */
674 {iO, 1, 2}, /* OP_ADD */
675 {iS, 1, 1}, /* OP_ADDI */
676 {iO, 1, 2}, /* OP_SUB */
677 {iO, 1, 2}, /* OP_MULT */
678 {iO, 1, 2}, /* OP_DIV */
679 {iO, 1, 2}, /* OP_POW */
680 {iU, VD, 0}, /* OP_CONCAT */
681 {iO, 1, 1}, /* OP_MINUS */
682 {iO, 1, 1}, /* OP_NOT */
683 {iS, 0, 2}, /* OP_JMPNE */
684 {iS, 0, 2}, /* OP_JMPEQ */
685 {iS, 0, 2}, /* OP_JMPLT */
686 {iS, 0, 2}, /* OP_JMPLE */
687 {iS, 0, 2}, /* OP_JMPGT */
688 {iS, 0, 2}, /* OP_JMPGE */
689 {iS, 0, 1}, /* OP_JMPT */
690 {iS, 0, 1}, /* OP_JMPF */
691 {iS, 0, 1}, /* OP_JMPONT */
692 {iS, 0, 1}, /* OP_JMPONF */
693 {iS, 0, 0}, /* OP_JMP */
694 {iO, 0, 0}, /* OP_PUSHNILJMP */
695 {iS, 0, 0}, /* OP_FORPREP */
696 {iS, 0, 3}, /* OP_FORLOOP */
697 {iS, 2, 0}, /* OP_LFORPREP */
698 {iS, 0, 3}, /* OP_LFORLOOP */
699 {iAB, VD, 0} /* OP_CLOSURE */
700};
701 714