fb1f9a1ea74deccd6356fccf695e2ef38362c7b8
[openwrt/svn-archive/archive.git] / package / lua / patches / 300-opcode_performance.patch
1 --- a/src/lvm.c
2 +++ b/src/lvm.c
3 @@ -31,6 +31,9 @@
4 /* limit for table tag-method chains (to avoid loops) */
5 #define MAXTAGLOOP 100
6
7 +#ifdef __GNUC__
8 +#define COMPUTED_GOTO 1
9 +#endif
10
11 /*
12 * If 'obj' is a string, it is tried to be interpreted as a number.
13 @@ -564,12 +567,63 @@
14 ARITH_OP1_END
15 #endif
16
17 +#ifdef COMPUTED_GOTO
18 +#define OPCODE_TARGET(op) DO_OP_##op:
19 +#define CALL_OPCODE(op) goto *opcodes[op];
20 +#define OPCODE_PTR(op) [OP_##op] = &&DO_OP_##op
21 +#else
22 +#define OPCODE_TARGET(op) case OP_##op:
23 +#define CALL_OPCODE(op) switch (op)
24 +#endif
25 +
26
27 void luaV_execute (lua_State *L, int nexeccalls) {
28 LClosure *cl;
29 StkId base;
30 TValue *k;
31 const Instruction *pc;
32 +#ifdef COMPUTED_GOTO
33 + static const void *opcodes[] = {
34 + OPCODE_PTR(MOVE),
35 + OPCODE_PTR(LOADK),
36 + OPCODE_PTR(LOADBOOL),
37 + OPCODE_PTR(LOADNIL),
38 + OPCODE_PTR(GETUPVAL),
39 + OPCODE_PTR(GETGLOBAL),
40 + OPCODE_PTR(GETTABLE),
41 + OPCODE_PTR(SETGLOBAL),
42 + OPCODE_PTR(SETUPVAL),
43 + OPCODE_PTR(SETTABLE),
44 + OPCODE_PTR(NEWTABLE),
45 + OPCODE_PTR(SELF),
46 + OPCODE_PTR(ADD),
47 + OPCODE_PTR(SUB),
48 + OPCODE_PTR(MUL),
49 + OPCODE_PTR(DIV),
50 + OPCODE_PTR(MOD),
51 + OPCODE_PTR(POW),
52 + OPCODE_PTR(UNM),
53 + OPCODE_PTR(NOT),
54 + OPCODE_PTR(LEN),
55 + OPCODE_PTR(CONCAT),
56 + OPCODE_PTR(JMP),
57 + OPCODE_PTR(EQ),
58 + OPCODE_PTR(LT),
59 + OPCODE_PTR(LE),
60 + OPCODE_PTR(TEST),
61 + OPCODE_PTR(TESTSET),
62 + OPCODE_PTR(CALL),
63 + OPCODE_PTR(TAILCALL),
64 + OPCODE_PTR(RETURN),
65 + OPCODE_PTR(FORLOOP),
66 + OPCODE_PTR(FORPREP),
67 + OPCODE_PTR(TFORLOOP),
68 + OPCODE_PTR(SETLIST),
69 + OPCODE_PTR(CLOSE),
70 + OPCODE_PTR(CLOSURE),
71 + OPCODE_PTR(VARARG)
72 + };
73 +#endif
74 reentry: /* entry point */
75 lua_assert(isLua(L->ci));
76 pc = L->savedpc;
77 @@ -594,33 +648,33 @@
78 lua_assert(base == L->base && L->base == L->ci->base);
79 lua_assert(base <= L->top && L->top <= L->stack + L->stacksize);
80 lua_assert(L->top == L->ci->top || luaG_checkopenop(i));
81 - switch (GET_OPCODE(i)) {
82 - case OP_MOVE: {
83 + CALL_OPCODE(GET_OPCODE(i)) {
84 + OPCODE_TARGET(MOVE) {
85 setobjs2s(L, ra, RB(i));
86 continue;
87 }
88 - case OP_LOADK: {
89 + OPCODE_TARGET(LOADK) {
90 setobj2s(L, ra, KBx(i));
91 continue;
92 }
93 - case OP_LOADBOOL: {
94 + OPCODE_TARGET(LOADBOOL) {
95 setbvalue(ra, GETARG_B(i));
96 if (GETARG_C(i)) pc++; /* skip next instruction (if C) */
97 continue;
98 }
99 - case OP_LOADNIL: {
100 + OPCODE_TARGET(LOADNIL) {
101 TValue *rb = RB(i);
102 do {
103 setnilvalue(rb--);
104 } while (rb >= ra);
105 continue;
106 }
107 - case OP_GETUPVAL: {
108 + OPCODE_TARGET(GETUPVAL) {
109 int b = GETARG_B(i);
110 setobj2s(L, ra, cl->upvals[b]->v);
111 continue;
112 }
113 - case OP_GETGLOBAL: {
114 + OPCODE_TARGET(GETGLOBAL) {
115 TValue g;
116 TValue *rb = KBx(i);
117 sethvalue(L, &g, cl->env);
118 @@ -628,88 +682,88 @@
119 Protect(luaV_gettable(L, &g, rb, ra));
120 continue;
121 }
122 - case OP_GETTABLE: {
123 + OPCODE_TARGET(GETTABLE) {
124 Protect(luaV_gettable(L, RB(i), RKC(i), ra));
125 continue;
126 }
127 - case OP_SETGLOBAL: {
128 + OPCODE_TARGET(SETGLOBAL) {
129 TValue g;
130 sethvalue(L, &g, cl->env);
131 lua_assert(ttisstring(KBx(i)));
132 Protect(luaV_settable(L, &g, KBx(i), ra));
133 continue;
134 }
135 - case OP_SETUPVAL: {
136 + OPCODE_TARGET(SETUPVAL) {
137 UpVal *uv = cl->upvals[GETARG_B(i)];
138 setobj(L, uv->v, ra);
139 luaC_barrier(L, uv, ra);
140 continue;
141 }
142 - case OP_SETTABLE: {
143 + OPCODE_TARGET(SETTABLE) {
144 Protect(luaV_settable(L, ra, RKB(i), RKC(i)));
145 continue;
146 }
147 - case OP_NEWTABLE: {
148 + OPCODE_TARGET(NEWTABLE) {
149 int b = GETARG_B(i);
150 int c = GETARG_C(i);
151 sethvalue(L, ra, luaH_new(L, luaO_fb2int(b), luaO_fb2int(c)));
152 Protect(luaC_checkGC(L));
153 continue;
154 }
155 - case OP_SELF: {
156 + OPCODE_TARGET(SELF) {
157 StkId rb = RB(i);
158 setobjs2s(L, ra+1, rb);
159 Protect(luaV_gettable(L, rb, RKC(i), ra));
160 continue;
161 }
162 - case OP_ADD: {
163 + OPCODE_TARGET(ADD) {
164 TValue *rb = RKB(i), *rc= RKC(i);
165 arith_op_continue( luai_numadd, try_addint, luai_vectadd );
166 Protect(Arith(L, ra, rb, rc, TM_ADD)); \
167 continue;
168 }
169 - case OP_SUB: {
170 + OPCODE_TARGET(SUB) {
171 TValue *rb = RKB(i), *rc= RKC(i);
172 arith_op_continue( luai_numsub, try_subint, luai_vectsub );
173 Protect(Arith(L, ra, rb, rc, TM_SUB));
174 continue;
175 }
176 - case OP_MUL: {
177 + OPCODE_TARGET(MUL) {
178 TValue *rb = RKB(i), *rc= RKC(i);
179 arith_op_continue(luai_nummul, try_mulint, luai_vectmul);
180 Protect(Arith(L, ra, rb, rc, TM_MUL));
181 continue;
182 }
183 - case OP_DIV: {
184 + OPCODE_TARGET(DIV) {
185 TValue *rb = RKB(i), *rc= RKC(i);
186 arith_op_continue(luai_numdiv, try_divint, luai_vectdiv);
187 Protect(Arith(L, ra, rb, rc, TM_DIV));
188 continue;
189 }
190 - case OP_MOD: {
191 + OPCODE_TARGET(MOD) {
192 TValue *rb = RKB(i), *rc= RKC(i);
193 arith_op_continue_scalar(luai_nummod, try_modint); /* scalars only */
194 Protect(Arith(L, ra, rb, rc, TM_MOD));
195 continue;
196 }
197 - case OP_POW: {
198 + OPCODE_TARGET(POW) {
199 TValue *rb = RKB(i), *rc= RKC(i);
200 arith_op_continue(luai_numpow, try_powint, luai_vectpow);
201 Protect(Arith(L, ra, rb, rc, TM_POW));
202 continue;
203 }
204 - case OP_UNM: {
205 + OPCODE_TARGET(UNM) {
206 TValue *rb = RB(i);
207 arith_op1_continue(luai_numunm, try_unmint, luai_vectunm);
208 Protect(Arith(L, ra, rb, rb, TM_UNM));
209 continue;
210 }
211 - case OP_NOT: {
212 + OPCODE_TARGET(NOT) {
213 int res = l_isfalse(RB(i)); /* next assignment may change this value */
214 setbvalue(ra, res);
215 continue;
216 }
217 - case OP_LEN: {
218 + OPCODE_TARGET(LEN) {
219 const TValue *rb = RB(i);
220 switch (ttype(rb)) {
221 case LUA_TTABLE: {
222 @@ -729,18 +783,18 @@
223 }
224 continue;
225 }
226 - case OP_CONCAT: {
227 + OPCODE_TARGET(CONCAT) {
228 int b = GETARG_B(i);
229 int c = GETARG_C(i);
230 Protect(luaV_concat(L, c-b+1, c); luaC_checkGC(L));
231 setobjs2s(L, RA(i), base+b);
232 continue;
233 }
234 - case OP_JMP: {
235 + OPCODE_TARGET(JMP) {
236 dojump(L, pc, GETARG_sBx(i));
237 continue;
238 }
239 - case OP_EQ: {
240 + OPCODE_TARGET(EQ) {
241 TValue *rb = RKB(i);
242 TValue *rc = RKC(i);
243 Protect(
244 @@ -750,7 +804,7 @@
245 pc++;
246 continue;
247 }
248 - case OP_LT: {
249 + OPCODE_TARGET(LT) {
250 Protect(
251 if (luaV_lessthan(L, RKB(i), RKC(i)) == GETARG_A(i))
252 dojump(L, pc, GETARG_sBx(*pc));
253 @@ -758,7 +812,7 @@
254 pc++;
255 continue;
256 }
257 - case OP_LE: {
258 + OPCODE_TARGET(LE) {
259 Protect(
260 if (lessequal(L, RKB(i), RKC(i)) == GETARG_A(i))
261 dojump(L, pc, GETARG_sBx(*pc));
262 @@ -766,13 +820,13 @@
263 pc++;
264 continue;
265 }
266 - case OP_TEST: {
267 + OPCODE_TARGET(TEST) {
268 if (l_isfalse(ra) != GETARG_C(i))
269 dojump(L, pc, GETARG_sBx(*pc));
270 pc++;
271 continue;
272 }
273 - case OP_TESTSET: {
274 + OPCODE_TARGET(TESTSET) {
275 TValue *rb = RB(i);
276 if (l_isfalse(rb) != GETARG_C(i)) {
277 setobjs2s(L, ra, rb);
278 @@ -781,7 +835,7 @@
279 pc++;
280 continue;
281 }
282 - case OP_CALL: {
283 + OPCODE_TARGET(CALL) {
284 int b = GETARG_B(i);
285 int nresults = GETARG_C(i) - 1;
286 if (b != 0) L->top = ra+b; /* else previous instruction set top */
287 @@ -802,7 +856,7 @@
288 }
289 }
290 }
291 - case OP_TAILCALL: {
292 + OPCODE_TARGET(TAILCALL) {
293 int b = GETARG_B(i);
294 if (b != 0) L->top = ra+b; /* else previous instruction set top */
295 L->savedpc = pc;
296 @@ -834,7 +888,7 @@
297 }
298 }
299 }
300 - case OP_RETURN: {
301 + OPCODE_TARGET(RETURN) {
302 int b = GETARG_B(i);
303 if (b != 0) L->top = ra+b-1;
304 if (L->openupval) luaF_close(L, base);
305 @@ -849,7 +903,7 @@
306 goto reentry;
307 }
308 }
309 - case OP_FORLOOP: {
310 + OPCODE_TARGET(FORLOOP) {
311 /* If start,step and limit are all integers, we don't need to check
312 * against overflow in the looping.
313 */
314 @@ -877,7 +931,7 @@
315 }
316 continue;
317 }
318 - case OP_FORPREP: {
319 + OPCODE_TARGET(FORPREP) {
320 const TValue *init = ra;
321 const TValue *plimit = ra+1;
322 const TValue *pstep = ra+2;
323 @@ -900,7 +954,7 @@
324 dojump(L, pc, GETARG_sBx(i));
325 continue;
326 }
327 - case OP_TFORLOOP: {
328 + OPCODE_TARGET(TFORLOOP) {
329 StkId cb = ra + 3; /* call base */
330 setobjs2s(L, cb+2, ra+2);
331 setobjs2s(L, cb+1, ra+1);
332 @@ -916,7 +970,7 @@
333 pc++;
334 continue;
335 }
336 - case OP_SETLIST: {
337 + OPCODE_TARGET(SETLIST) {
338 int n = GETARG_B(i);
339 int c = GETARG_C(i);
340 int last;
341 @@ -938,11 +992,11 @@
342 }
343 continue;
344 }
345 - case OP_CLOSE: {
346 + OPCODE_TARGET(CLOSE) {
347 luaF_close(L, ra);
348 continue;
349 }
350 - case OP_CLOSURE: {
351 + OPCODE_TARGET(CLOSURE) {
352 Proto *p;
353 Closure *ncl;
354 int nup, j;
355 @@ -962,7 +1016,7 @@
356 Protect(luaC_checkGC(L));
357 continue;
358 }
359 - case OP_VARARG: {
360 + OPCODE_TARGET(VARARG) {
361 int b = GETARG_B(i) - 1;
362 int j;
363 CallInfo *ci = L->ci;