diff options
-rw-r--r-- | lcode.c | 118 | ||||
-rw-r--r-- | lstring.c | 14 | ||||
-rw-r--r-- | lstring.h | 4 | ||||
-rw-r--r-- | lvm.c | 3 |
4 files changed, 89 insertions, 50 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lcode.c,v 1.5 2000/03/03 20:30:47 roberto Exp roberto $ | 2 | ** $Id: lcode.c,v 1.8 2000/03/09 13:57:37 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 | */ |
@@ -100,6 +100,28 @@ static void luaK_conc (LexState *ls) { | |||
100 | } | 100 | } |
101 | 101 | ||
102 | 102 | ||
103 | static void luaK_eq (LexState *ls) { | ||
104 | Instruction *previous = previous_instruction(ls); | ||
105 | if (*previous == CREATE_U(PUSHNIL, 1)) { | ||
106 | *previous = CREATE_0(NOTOP); | ||
107 | luaK_deltastack(ls, -1); /* undo effect of PUSHNIL */ | ||
108 | } | ||
109 | else | ||
110 | luaK_S(ls, IFEQJMP, 0, -2); | ||
111 | } | ||
112 | |||
113 | |||
114 | static void luaK_neq (LexState *ls) { | ||
115 | Instruction *previous = previous_instruction(ls); | ||
116 | if (*previous == CREATE_U(PUSHNIL, 1)) { | ||
117 | ls->fs->pc--; /* remove PUSHNIL */ | ||
118 | luaK_deltastack(ls, -1); /* undo effect of PUSHNIL */ | ||
119 | } | ||
120 | else | ||
121 | luaK_S(ls, IFNEQJMP, 0, -2); | ||
122 | } | ||
123 | |||
124 | |||
103 | void luaK_retcode (LexState *ls, int nlocals, int nexps) { | 125 | void luaK_retcode (LexState *ls, int nlocals, int nexps) { |
104 | Instruction *previous = previous_instruction(ls); | 126 | Instruction *previous = previous_instruction(ls); |
105 | if (nexps > 0 && GET_OPCODE(*previous) == CALL) { | 127 | if (nexps > 0 && GET_OPCODE(*previous) == CALL) { |
@@ -116,9 +138,7 @@ static void luaK_pushnil (LexState *ls, int n) { | |||
116 | Instruction *previous = previous_instruction(ls); | 138 | Instruction *previous = previous_instruction(ls); |
117 | luaK_deltastack(ls, n); | 139 | luaK_deltastack(ls, n); |
118 | switch(GET_OPCODE(*previous)) { | 140 | switch(GET_OPCODE(*previous)) { |
119 | case PUSHNIL: | 141 | case PUSHNIL: SETARG_U(*previous, GETARG_U(*previous)+n); break; |
120 | SETARG_U(*previous, GETARG_U(*previous)+n); | ||
121 | break; | ||
122 | default: luaK_primitivecode(ls, CREATE_U(PUSHNIL, n)); | 142 | default: luaK_primitivecode(ls, CREATE_U(PUSHNIL, n)); |
123 | } | 143 | } |
124 | } | 144 | } |
@@ -281,6 +301,8 @@ static OpCode invertjump (OpCode op) { | |||
281 | case IFLEJMP: return IFGTJMP; | 301 | case IFLEJMP: return IFGTJMP; |
282 | case IFGTJMP: return IFLEJMP; | 302 | case IFGTJMP: return IFLEJMP; |
283 | case IFGEJMP: return IFLTJMP; | 303 | case IFGEJMP: return IFLTJMP; |
304 | case IFTJMP: case ONTJMP: return IFFJMP; | ||
305 | case IFFJMP: case ONFJMP: return IFTJMP; | ||
284 | default: | 306 | default: |
285 | LUA_INTERNALERROR(NULL, "invalid jump instruction"); | 307 | LUA_INTERNALERROR(NULL, "invalid jump instruction"); |
286 | return ENDCODE; /* to avoid warnings */ | 308 | return ENDCODE; /* to avoid warnings */ |
@@ -288,13 +310,23 @@ static OpCode invertjump (OpCode op) { | |||
288 | } | 310 | } |
289 | 311 | ||
290 | 312 | ||
313 | static void luaK_jump (LexState *ls, OpCode jump) { | ||
314 | Instruction *previous = previous_instruction(ls); | ||
315 | luaK_deltastack(ls, -1); | ||
316 | if (*previous == CREATE_0(NOTOP)) | ||
317 | *previous = CREATE_S(invertjump(jump), 0); | ||
318 | else | ||
319 | luaK_primitivecode(ls, CREATE_S(jump, 0)); | ||
320 | } | ||
321 | |||
322 | |||
291 | static void insert_last (FuncState *fs, int *list) { | 323 | static void insert_last (FuncState *fs, int *list) { |
292 | int temp = *list; | 324 | int first = *list; |
293 | *list = fs->pc-1; | 325 | *list = fs->pc-1; /* insert last instruction in the list */ |
294 | if (temp == 0) /* chain list */ | 326 | if (first == 0) |
295 | SETARG_S(fs->f->code[*list], 0); | 327 | SETARG_S(fs->f->code[*list], 0); |
296 | else | 328 | else |
297 | SETARG_S(fs->f->code[*list], temp-fs->pc); | 329 | SETARG_S(fs->f->code[*list], first-fs->pc); |
298 | } | 330 | } |
299 | 331 | ||
300 | 332 | ||
@@ -305,18 +337,18 @@ static void luaK_patchlistaux (LexState *ls, int list, int target, | |||
305 | for (;;) { | 337 | for (;;) { |
306 | Instruction *i = &code[list]; | 338 | Instruction *i = &code[list]; |
307 | OpCode op = GET_OPCODE(*i); | 339 | OpCode op = GET_OPCODE(*i); |
308 | int temp = GETARG_S(*i); | 340 | int next = GETARG_S(*i); |
309 | if (op == special) | 341 | if (op == special) /* this `op' already has a value */ |
310 | SETARG_S(*i, special_target-(list+1)); | 342 | SETARG_S(*i, special_target-(list+1)); |
311 | else { | 343 | else { |
312 | SETARG_S(*i, target-(list+1)); | 344 | SETARG_S(*i, target-(list+1)); /* do the patch */ |
313 | if (op == ONTJMP) | 345 | if (op == ONTJMP) /* remove eventual values */ |
314 | SET_OPCODE(*i, IFTJMP); | 346 | SET_OPCODE(*i, IFTJMP); |
315 | else if (op == ONFJMP) | 347 | else if (op == ONFJMP) |
316 | SET_OPCODE(*i, IFFJMP); | 348 | SET_OPCODE(*i, IFFJMP); |
317 | } | 349 | } |
318 | if (temp == 0) return; | 350 | if (next == 0) return; |
319 | list += temp+1; | 351 | list += next+1; |
320 | } | 352 | } |
321 | } | 353 | } |
322 | } | 354 | } |
@@ -327,15 +359,15 @@ void luaK_patchlist (LexState *ls, int list, int target) { | |||
327 | } | 359 | } |
328 | 360 | ||
329 | 361 | ||
330 | static int has_jumps (FuncState *fs, int list, OpCode ignore) { | 362 | static int need_value (FuncState *fs, int list, OpCode hasvalue) { |
331 | if (list == 0) return 0; | 363 | if (list == 0) return 0; |
332 | else { | 364 | else { /* check whether list has a jump without a value */ |
333 | Instruction *code = fs->f->code; | 365 | Instruction *code = fs->f->code; |
334 | for (;;) { | 366 | for (;;) { |
335 | int temp = GETARG_S(code[list]); | 367 | int next = GETARG_S(code[list]); |
336 | if (GET_OPCODE(code[list]) != ignore) return 1; | 368 | if (GET_OPCODE(code[list]) != hasvalue) return 1; |
337 | else if (temp == 0) return 0; | 369 | else if (next == 0) return 0; |
338 | list += temp+1; | 370 | list += next+1; |
339 | } | 371 | } |
340 | } | 372 | } |
341 | } | 373 | } |
@@ -348,12 +380,12 @@ static void concatlists (LexState *ls, int *l1, int l2) { | |||
348 | FuncState *fs = ls->fs; | 380 | FuncState *fs = ls->fs; |
349 | int list = *l1; | 381 | int list = *l1; |
350 | for (;;) { /* traverse `l1' */ | 382 | for (;;) { /* traverse `l1' */ |
351 | int temp = GETARG_S(fs->f->code[list]); | 383 | int next = GETARG_S(fs->f->code[list]); |
352 | if (temp == 0) { /* end of list? */ | 384 | if (next == 0) { /* end of list? */ |
353 | SETARG_S(fs->f->code[list], l2-(list+1)); /* end points to `l2' */ | 385 | SETARG_S(fs->f->code[list], l2-(list+1)); /* end points to `l2' */ |
354 | return; | 386 | return; |
355 | } | 387 | } |
356 | list += temp+1; | 388 | list += next+1; |
357 | } | 389 | } |
358 | } | 390 | } |
359 | } | 391 | } |
@@ -368,7 +400,7 @@ void luaK_goiftrue (LexState *ls, expdesc *v, int keepvalue) { | |||
368 | SET_OPCODE(*previous, invertjump(GET_OPCODE(*previous))); | 400 | SET_OPCODE(*previous, invertjump(GET_OPCODE(*previous))); |
369 | else { | 401 | else { |
370 | OpCode jump = keepvalue ? ONFJMP : IFFJMP; | 402 | OpCode jump = keepvalue ? ONFJMP : IFFJMP; |
371 | luaK_S(ls, jump, 0, -1); | 403 | luaK_jump(ls, jump); |
372 | } | 404 | } |
373 | insert_last(fs, &v->u.l.f); | 405 | insert_last(fs, &v->u.l.f); |
374 | luaK_patchlist(ls, v->u.l.t, luaK_getlabel(ls)); | 406 | luaK_patchlist(ls, v->u.l.t, luaK_getlabel(ls)); |
@@ -378,12 +410,12 @@ void luaK_goiftrue (LexState *ls, expdesc *v, int keepvalue) { | |||
378 | 410 | ||
379 | void luaK_goiffalse (LexState *ls, expdesc *v, int keepvalue) { | 411 | void luaK_goiffalse (LexState *ls, expdesc *v, int keepvalue) { |
380 | FuncState *fs = ls->fs; | 412 | FuncState *fs = ls->fs; |
381 | Instruction *previous; | 413 | Instruction previous; |
382 | discharge1(ls, v); | 414 | discharge1(ls, v); |
383 | previous = &fs->f->code[fs->pc-1]; | 415 | previous = fs->f->code[fs->pc-1]; |
384 | if (!ISJUMP(GET_OPCODE(*previous))) { | 416 | if (!ISJUMP(GET_OPCODE(previous))) { |
385 | OpCode jump = keepvalue ? ONTJMP : IFTJMP; | 417 | OpCode jump = keepvalue ? ONTJMP : IFTJMP; |
386 | luaK_S(ls, jump, 0, -1); | 418 | luaK_jump(ls, jump); |
387 | } | 419 | } |
388 | insert_last(fs, &v->u.l.t); | 420 | insert_last(fs, &v->u.l.t); |
389 | luaK_patchlist(ls, v->u.l.f, luaK_getlabel(ls)); | 421 | luaK_patchlist(ls, v->u.l.f, luaK_getlabel(ls)); |
@@ -395,8 +427,8 @@ void luaK_tostack (LexState *ls, expdesc *v, int onlyone) { | |||
395 | if (discharge(ls, v)) return; | 427 | if (discharge(ls, v)) return; |
396 | else { /* is an expression */ | 428 | else { /* is an expression */ |
397 | FuncState *fs = ls->fs; | 429 | FuncState *fs = ls->fs; |
398 | Instruction *previous = &fs->f->code[fs->pc-1]; | 430 | OpCode previous = GET_OPCODE(fs->f->code[fs->pc-1]); |
399 | if (!ISJUMP(GET_OPCODE(*previous)) && v->u.l.f == 0 && v->u.l.t == 0) { | 431 | if (!ISJUMP(previous) && v->u.l.f == 0 && v->u.l.t == 0) { |
400 | /* it is an expression without jumps */ | 432 | /* it is an expression without jumps */ |
401 | if (onlyone && v->k == VEXP) | 433 | if (onlyone && v->k == VEXP) |
402 | luaK_setcallreturns(ls, 1); /* call must return 1 value */ | 434 | luaK_setcallreturns(ls, 1); /* call must return 1 value */ |
@@ -406,25 +438,25 @@ void luaK_tostack (LexState *ls, expdesc *v, int onlyone) { | |||
406 | int p_nil = 0; /* position of an eventual PUSHNIL */ | 438 | int p_nil = 0; /* position of an eventual PUSHNIL */ |
407 | int p_1 = 0; /* position of an eventual PUSHINT */ | 439 | int p_1 = 0; /* position of an eventual PUSHINT */ |
408 | int final; /* position after whole expression */ | 440 | int final; /* position after whole expression */ |
409 | if (ISJUMP(GET_OPCODE(*previous))) { | 441 | if (ISJUMP(previous)) { |
410 | insert_last(fs, &v->u.l.t); | 442 | insert_last(fs, &v->u.l.t); /* put `previous' in true list */ |
411 | p_nil = luaK_0(ls, PUSHNILJMP, 0); | 443 | p_nil = luaK_0(ls, PUSHNILJMP, 0); |
412 | p_1 = luaK_S(ls, PUSHINT, 1, 1); | 444 | p_1 = luaK_S(ls, PUSHINT, 1, 1); |
413 | } | 445 | } |
414 | else { /* still may need a PUSHNIL or a PUSHINT */ | 446 | else { /* still may need a PUSHNIL or a PUSHINT */ |
415 | int need_nil = has_jumps(fs, v->u.l.f, ONFJMP); /* needs a PUSHNIL? */ | 447 | int need_nil = need_value(fs, v->u.l.f, ONFJMP); |
416 | int need_1 = has_jumps(fs, v->u.l.t, ONTJMP); /* needs a PUSHINT? */ | 448 | int need_1 = need_value(fs, v->u.l.t, ONTJMP); |
417 | if (need_nil && need_1) { | 449 | if (need_nil && need_1) { |
418 | luaK_S(ls, JMP, 2, 0); | 450 | luaK_S(ls, JMP, 2, 0); /* skip both pushes */ |
419 | p_nil = luaK_0(ls, PUSHNILJMP, 0); | 451 | p_nil = luaK_0(ls, PUSHNILJMP, 0); |
420 | p_1 = luaK_S(ls, PUSHINT, 1, 1); | 452 | p_1 = luaK_S(ls, PUSHINT, 1, 0); |
421 | } | 453 | } |
422 | else if (need_nil || need_1) { | 454 | else if (need_nil || need_1) { |
423 | luaK_S(ls, JMP, 1, 0); | 455 | luaK_S(ls, JMP, 1, 0); /* skip one push */ |
424 | if (need_nil) | 456 | if (need_nil) |
425 | p_nil = luaK_0(ls, PUSHNIL, 1); | 457 | p_nil = luaK_U(ls, PUSHNIL, 1, 0); |
426 | else /* need_1 */ | 458 | else /* need_1 */ |
427 | p_1 = luaK_S(ls, PUSHINT, 1, 1); | 459 | p_1 = luaK_S(ls, PUSHINT, 1, 0); |
428 | } | 460 | } |
429 | } | 461 | } |
430 | final = luaK_getlabel(ls); | 462 | final = luaK_getlabel(ls); |
@@ -462,7 +494,7 @@ void luaK_infix (LexState *ls, int op, expdesc *v) { | |||
462 | else if (op == OR) | 494 | else if (op == OR) |
463 | luaK_goiffalse(ls, v, 1); | 495 | luaK_goiffalse(ls, v, 1); |
464 | else | 496 | else |
465 | luaK_tostack(ls, v, 1); | 497 | luaK_tostack(ls, v, 1); /* all other binary operators need a value */ |
466 | } | 498 | } |
467 | 499 | ||
468 | 500 | ||
@@ -480,7 +512,7 @@ void luaK_posfix (LexState *ls, int op, expdesc *v1, expdesc *v2) { | |||
480 | concatlists(ls, &v1->u.l.t, v2->u.l.t); | 512 | concatlists(ls, &v1->u.l.t, v2->u.l.t); |
481 | } | 513 | } |
482 | else { | 514 | else { |
483 | luaK_tostack(ls, v2, 1); /* `v2' must have a value */ | 515 | luaK_tostack(ls, v2, 1); /* `v2' must be a value */ |
484 | switch (op) { | 516 | switch (op) { |
485 | case '+': luaK_add(ls); break; | 517 | case '+': luaK_add(ls); break; |
486 | case '-': luaK_sub(ls); break; | 518 | case '-': luaK_sub(ls); break; |
@@ -488,8 +520,8 @@ void luaK_posfix (LexState *ls, int op, expdesc *v1, expdesc *v2) { | |||
488 | case '/': luaK_0(ls, DIVOP, -1); break; | 520 | case '/': luaK_0(ls, DIVOP, -1); break; |
489 | case '^': luaK_0(ls, POWOP, -1); break; | 521 | case '^': luaK_0(ls, POWOP, -1); break; |
490 | case CONC: luaK_conc(ls); break; | 522 | case CONC: luaK_conc(ls); break; |
491 | case EQ: luaK_S(ls, IFEQJMP, 0, -2); break; | 523 | case EQ: luaK_eq(ls); break; |
492 | case NE: luaK_S(ls, IFNEQJMP, 0, -2); break; | 524 | case NE: luaK_neq(ls); break; |
493 | case '>': luaK_S(ls, IFGTJMP, 0, -2); break; | 525 | case '>': luaK_S(ls, IFGTJMP, 0, -2); break; |
494 | case '<': luaK_S(ls, IFLTJMP, 0, -2); break; | 526 | case '<': luaK_S(ls, IFLTJMP, 0, -2); break; |
495 | case GE: luaK_S(ls, IFGEJMP, 0, -2); break; | 527 | case GE: luaK_S(ls, IFGEJMP, 0, -2); break; |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstring.c,v 1.31 1999/12/14 18:42:57 roberto Exp roberto $ | 2 | ** $Id: lstring.c,v 1.32 2000/03/03 14:58:26 roberto Exp roberto $ |
3 | ** String table (keeps all strings handled by Lua) | 3 | ** String table (keeps all strings handled by Lua) |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -46,8 +46,9 @@ void luaS_freeall (lua_State *L) { | |||
46 | 46 | ||
47 | static unsigned long hash_s (const char *s, long l) { | 47 | static unsigned long hash_s (const char *s, long l) { |
48 | unsigned long h = l; /* seed */ | 48 | unsigned long h = l; /* seed */ |
49 | while (l--) | 49 | long step = (l>>6)+1; /* if string is too long, don't hash all its chars */ |
50 | h = h ^ ((h<<5)+(h>>2)+(unsigned char)*(s++)); | 50 | for (; l>0; l-=step) |
51 | h = h ^ ((h<<5)+(h>>2)+(unsigned char)*(s++)); | ||
51 | return h; | 52 | return h; |
52 | } | 53 | } |
53 | 54 | ||
@@ -120,7 +121,8 @@ static void newentry (lua_State *L, stringtable *tb, TaggedString *ts, int h) { | |||
120 | 121 | ||
121 | TaggedString *luaS_newlstr (lua_State *L, const char *str, long l) { | 122 | TaggedString *luaS_newlstr (lua_State *L, const char *str, long l) { |
122 | unsigned long h = hash_s(str, l); | 123 | unsigned long h = hash_s(str, l); |
123 | stringtable *tb = &L->string_root[h%NUM_HASHSTR]; | 124 | stringtable *tb = &L->string_root[(l==0) ? 0 : |
125 | ((unsigned int)(str[0]+str[l-1]))&(NUM_HASHSTR-1)]; | ||
124 | int h1 = h&(tb->size-1); | 126 | int h1 = h&(tb->size-1); |
125 | TaggedString *ts; | 127 | TaggedString *ts; |
126 | for (ts = tb->hash[h1]; ts; ts = ts->nexthash) { | 128 | for (ts = tb->hash[h1]; ts; ts = ts->nexthash) { |
@@ -134,6 +136,10 @@ TaggedString *luaS_newlstr (lua_State *L, const char *str, long l) { | |||
134 | } | 136 | } |
135 | 137 | ||
136 | 138 | ||
139 | /* | ||
140 | ** uses '%' for one hashing with userdata because addresses are too regular, | ||
141 | ** so two '&' operations would be highly correlated | ||
142 | */ | ||
137 | TaggedString *luaS_createudata (lua_State *L, void *udata, int tag) { | 143 | TaggedString *luaS_createudata (lua_State *L, void *udata, int tag) { |
138 | unsigned long h = IntPoint(L, udata); | 144 | unsigned long h = IntPoint(L, udata); |
139 | stringtable *tb = &L->string_root[(h%NUM_HASHUDATA)+NUM_HASHSTR]; | 145 | stringtable *tb = &L->string_root[(h%NUM_HASHUDATA)+NUM_HASHSTR]; |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstring.h,v 1.15 1999/12/14 18:42:57 roberto Exp roberto $ | 2 | ** $Id: lstring.h,v 1.16 2000/03/03 14:58:26 roberto Exp roberto $ |
3 | ** String table (keep all strings handled by Lua) | 3 | ** String table (keep all strings handled by Lua) |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -12,7 +12,7 @@ | |||
12 | #include "lstate.h" | 12 | #include "lstate.h" |
13 | 13 | ||
14 | 14 | ||
15 | #define NUM_HASHSTR 31 | 15 | #define NUM_HASHSTR 32 |
16 | #define NUM_HASHUDATA 31 | 16 | #define NUM_HASHUDATA 31 |
17 | #define NUM_HASHS (NUM_HASHSTR+NUM_HASHUDATA) | 17 | #define NUM_HASHS (NUM_HASHSTR+NUM_HASHUDATA) |
18 | 18 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lvm.c,v 1.90 2000/03/03 14:58:26 roberto Exp roberto $ | 2 | ** $Id: lvm.c,v 1.93 2000/03/09 13:57:37 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 | */ |
@@ -360,6 +360,7 @@ StkId luaV_execute (lua_State *L, const Closure *cl, const TProtoFunc *tf, | |||
360 | 360 | ||
361 | case PUSHNIL: { | 361 | case PUSHNIL: { |
362 | int n = GETARG_U(i); | 362 | int n = GETARG_U(i); |
363 | LUA_ASSERT(L, n>0, "invalid argument"); | ||
363 | do { | 364 | do { |
364 | ttype(top++) = LUA_T_NIL; | 365 | ttype(top++) = LUA_T_NIL; |
365 | } while (--n > 0); | 366 | } while (--n > 0); |