aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2000-06-16 14:51:40 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2000-06-16 14:51:40 -0300
commit2e1b32d87339c22b0518481fa260edf3bfbc01d3 (patch)
tree5dbca324c1b96790350bc3a86b5c80a97c4a4761
parent89a3ec08f37d127fc3c7756cb7cf71586959f8c4 (diff)
downloadlua-2e1b32d87339c22b0518481fa260edf3bfbc01d3.tar.gz
lua-2e1b32d87339c22b0518481fa260edf3bfbc01d3.tar.bz2
lua-2e1b32d87339c22b0518481fa260edf3bfbc01d3.zip
optimizations for "while 1", "until nil", and the like
-rw-r--r--lcode.c153
-rw-r--r--lcode.h3
2 files changed, 102 insertions, 54 deletions
diff --git a/lcode.c b/lcode.c
index dad9fc8d..e2a8dc94 100644
--- a/lcode.c
+++ b/lcode.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lcode.c,v 1.34 2000/06/05 14:56:18 roberto Exp roberto $ 2** $Id: lcode.c,v 1.35 2000/06/12 13:52:05 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*/
@@ -268,20 +268,29 @@ void luaK_concat (FuncState *fs, int *l1, int l2) {
268 268
269 269
270static void luaK_testgo (FuncState *fs, expdesc *v, int invert, OpCode jump) { 270static void luaK_testgo (FuncState *fs, expdesc *v, int invert, OpCode jump) {
271 int prevpos; /* position of last instruction */
271 Instruction *previous; 272 Instruction *previous;
272 int *golist = &v->u.l.f; 273 int *golist, *exitlist;
273 int *exitlist = &v->u.l.t; 274 if (!invert) {
274 if (invert) { /* interchange `golist' and `exitlist' */ 275 golist = &v->u.l.f; /* go if false */
275 int *temp = golist; golist = exitlist; exitlist = temp; 276 exitlist = &v->u.l.t; /* exit if true */
277 }
278 else {
279 golist = &v->u.l.t; /* go if true */
280 exitlist = &v->u.l.f; /* exit if false */
276 } 281 }
277 discharge1(fs, v); 282 discharge1(fs, v);
278 previous = &fs->f->code[fs->pc-1]; 283 prevpos = fs->pc-1;
279 LUA_ASSERT(L, GET_OPCODE(*previous) != OP_SETLINE, "bad place to set line"); 284 previous = &fs->f->code[prevpos];
285 LUA_ASSERT(L, *previous==previous_instruction(fs), "no jump allowed here");
286 LUA_ASSERT(L, GET_OPCODE(*previous) != OP_SETLINE, "no setline allowed here");
280 if (!ISJUMP(GET_OPCODE(*previous))) 287 if (!ISJUMP(GET_OPCODE(*previous)))
281 luaK_code1(fs, jump, NO_JUMP); 288 prevpos = luaK_code1(fs, jump, NO_JUMP);
282 else if (invert) 289 else { /* last instruction is already a jump */
283 SET_OPCODE(*previous, invertjump(GET_OPCODE(*previous))); 290 if (invert)
284 luaK_concat(fs, exitlist, fs->pc-1); /* insert last jump in `exitlist' */ 291 SET_OPCODE(*previous, invertjump(GET_OPCODE(*previous)));
292 }
293 luaK_concat(fs, exitlist, prevpos); /* insert last jump in `exitlist' */
285 luaK_patchlist(fs, *golist, luaK_getlabel(fs)); 294 luaK_patchlist(fs, *golist, luaK_getlabel(fs));
286 *golist = NO_JUMP; 295 *golist = NO_JUMP;
287} 296}
@@ -292,7 +301,7 @@ void luaK_goiftrue (FuncState *fs, expdesc *v, int keepvalue) {
292} 301}
293 302
294 303
295void luaK_goiffalse (FuncState *fs, expdesc *v, int keepvalue) { 304static void luaK_goiffalse (FuncState *fs, expdesc *v, int keepvalue) {
296 luaK_testgo(fs, v, 0, keepvalue ? OP_JMPONT : OP_JMPT); 305 luaK_testgo(fs, v, 0, keepvalue ? OP_JMPONT : OP_JMPT);
297} 306}
298 307
@@ -319,8 +328,8 @@ void luaK_tostack (LexState *ls, expdesc *v, int onlyone) {
319 int j = NO_JUMP; /* eventual jump over values */ 328 int j = NO_JUMP; /* eventual jump over values */
320 int p_nil = NO_JUMP; /* position of an eventual PUSHNIL */ 329 int p_nil = NO_JUMP; /* position of an eventual PUSHNIL */
321 int p_1 = NO_JUMP; /* position of an eventual PUSHINT */ 330 int p_1 = NO_JUMP; /* position of an eventual PUSHINT */
322 if (ISJUMP(previous) || need_value(fs, v->u.l.f, OP_JMPONF) || 331 if (ISJUMP(previous) || need_value(fs, v->u.l.f, OP_JMPONF)
323 need_value(fs, v->u.l.t, OP_JMPONT)) { 332 || need_value(fs, v->u.l.t, OP_JMPONT)) {
324 /* expression needs values */ 333 /* expression needs values */
325 if (ISJUMP(previous)) 334 if (ISJUMP(previous))
326 luaK_concat(fs, &v->u.l.t, fs->pc-1); /* put `previous' in t. list */ 335 luaK_concat(fs, &v->u.l.t, fs->pc-1); /* put `previous' in t. list */
@@ -425,34 +434,33 @@ int luaK_code2 (FuncState *fs, OpCode o, int arg1, int arg2) {
425 int delta = luaK_opproperties[o].delta; 434 int delta = luaK_opproperties[o].delta;
426 int optm = 0; /* 1 when there is an optimization */ 435 int optm = 0; /* 1 when there is an optimization */
427 switch (o) { 436 switch (o) {
428 437 case OP_CLOSURE: {
429 case OP_CLOSURE:
430 delta = -arg2+1; 438 delta = -arg2+1;
431 break; 439 break;
432 440 }
433 case OP_SETTABLE: 441 case OP_SETTABLE: {
434 delta = -arg2; 442 delta = -arg2;
435 break; 443 break;
436 444 }
437 case OP_SETLIST: 445 case OP_SETLIST: {
438 if (arg2 == 0) return NO_JUMP; /* nothing to do */ 446 if (arg2 == 0) return NO_JUMP; /* nothing to do */
439 delta = -arg2; 447 delta = -arg2;
440 break; 448 break;
441 449 }
442 case OP_SETMAP: 450 case OP_SETMAP: {
443 if (arg1 == 0) return NO_JUMP; /* nothing to do */ 451 if (arg1 == 0) return NO_JUMP; /* nothing to do */
444 delta = -2*arg1; 452 delta = -2*arg1;
445 break; 453 break;
446 454 }
447 case OP_RETURN: 455 case OP_RETURN: {
448 if (GET_OPCODE(i) == OP_CALL && GETARG_B(i) == MULT_RET) { 456 if (GET_OPCODE(i) == OP_CALL && GETARG_B(i) == MULT_RET) {
449 SET_OPCODE(i, OP_TAILCALL); 457 SET_OPCODE(i, OP_TAILCALL);
450 SETARG_B(i, arg1); 458 SETARG_B(i, arg1);
451 optm = 1; 459 optm = 1;
452 } 460 }
453 break; 461 break;
454 462 }
455 case OP_PUSHNIL: 463 case OP_PUSHNIL: {
456 if (arg1 == 0) return NO_JUMP; /* nothing to do */ 464 if (arg1 == 0) return NO_JUMP; /* nothing to do */
457 delta = arg1; 465 delta = arg1;
458 switch(GET_OPCODE(i)) { 466 switch(GET_OPCODE(i)) {
@@ -460,8 +468,8 @@ int luaK_code2 (FuncState *fs, OpCode o, int arg1, int arg2) {
460 default: break; 468 default: break;
461 } 469 }
462 break; 470 break;
463 471 }
464 case OP_POP: 472 case OP_POP: {
465 if (arg1 == 0) return NO_JUMP; /* nothing to do */ 473 if (arg1 == 0) return NO_JUMP; /* nothing to do */
466 delta = -arg1; 474 delta = -arg1;
467 switch(GET_OPCODE(i)) { 475 switch(GET_OPCODE(i)) {
@@ -469,8 +477,8 @@ int luaK_code2 (FuncState *fs, OpCode o, int arg1, int arg2) {
469 default: break; 477 default: break;
470 } 478 }
471 break; 479 break;
472 480 }
473 case OP_GETTABLE: 481 case OP_GETTABLE: {
474 switch(GET_OPCODE(i)) { 482 switch(GET_OPCODE(i)) {
475 case OP_PUSHSTRING: /* `t.x' */ 483 case OP_PUSHSTRING: /* `t.x' */
476 SET_OPCODE(i, OP_GETDOTTED); 484 SET_OPCODE(i, OP_GETDOTTED);
@@ -483,15 +491,15 @@ int luaK_code2 (FuncState *fs, OpCode o, int arg1, int arg2) {
483 default: break; 491 default: break;
484 } 492 }
485 break; 493 break;
486 494 }
487 case OP_ADD: 495 case OP_ADD: {
488 switch(GET_OPCODE(i)) { 496 switch(GET_OPCODE(i)) {
489 case OP_PUSHINT: SET_OPCODE(i, OP_ADDI); optm = 1; break; /* `a+k' */ 497 case OP_PUSHINT: SET_OPCODE(i, OP_ADDI); optm = 1; break; /* `a+k' */
490 default: break; 498 default: break;
491 } 499 }
492 break; 500 break;
493 501 }
494 case OP_SUB: 502 case OP_SUB: {
495 switch(GET_OPCODE(i)) { 503 switch(GET_OPCODE(i)) {
496 case OP_PUSHINT: /* `a-k' */ 504 case OP_PUSHINT: /* `a-k' */
497 i = CREATE_S(OP_ADDI, -GETARG_S(i)); 505 i = CREATE_S(OP_ADDI, -GETARG_S(i));
@@ -500,8 +508,8 @@ int luaK_code2 (FuncState *fs, OpCode o, int arg1, int arg2) {
500 default: break; 508 default: break;
501 } 509 }
502 break; 510 break;
503 511 }
504 case OP_CONCAT: 512 case OP_CONCAT: {
505 delta = -arg1+1; 513 delta = -arg1+1;
506 switch(GET_OPCODE(i)) { 514 switch(GET_OPCODE(i)) {
507 case OP_CONCAT: /* `a..b..c' */ 515 case OP_CONCAT: /* `a..b..c' */
@@ -511,8 +519,8 @@ int luaK_code2 (FuncState *fs, OpCode o, int arg1, int arg2) {
511 default: break; 519 default: break;
512 } 520 }
513 break; 521 break;
514 522 }
515 case OP_MINUS: 523 case OP_MINUS: {
516 switch(GET_OPCODE(i)) { 524 switch(GET_OPCODE(i)) {
517 case OP_PUSHINT: /* `-k' */ 525 case OP_PUSHINT: /* `-k' */
518 SETARG_S(i, -GETARG_S(i)); 526 SETARG_S(i, -GETARG_S(i));
@@ -525,50 +533,91 @@ int luaK_code2 (FuncState *fs, OpCode o, int arg1, int arg2) {
525 default: break; 533 default: break;
526 } 534 }
527 break; 535 break;
528 536 }
529 case OP_JMPNE: 537 case OP_JMPNE: {
530 if (i == CREATE_U(OP_PUSHNIL, 1)) { /* `a~=nil' */ 538 if (i == CREATE_U(OP_PUSHNIL, 1)) { /* `a~=nil' */
531 i = CREATE_S(OP_JMPT, NO_JUMP); 539 i = CREATE_S(OP_JMPT, NO_JUMP);
532 optm = 1; 540 optm = 1;
533 } 541 }
534 break; 542 break;
535 543 }
536 case OP_JMPEQ: 544 case OP_JMPEQ: {
537 if (i == CREATE_U(OP_PUSHNIL, 1)) { /* `a==nil' */ 545 if (i == CREATE_U(OP_PUSHNIL, 1)) { /* `a==nil' */
538 i = CREATE_0(OP_NOT); 546 i = CREATE_0(OP_NOT);
539 delta = -1; /* just undo effect of previous PUSHNIL */ 547 delta = -1; /* just undo effect of previous PUSHNIL */
540 optm = 1; 548 optm = 1;
541 } 549 }
542 break; 550 break;
543 551 }
544 case OP_JMPT: 552 case OP_JMPT:
553 case OP_JMPONT: {
554 switch (GET_OPCODE(i)) {
555 case OP_NOT: {
556 i = CREATE_S(OP_JMPF, NO_JUMP);
557 optm = 1;
558 break;
559 }
560 case OP_PUSHINT: {
561 if (o == OP_JMPT) { /* JMPONT must keep original integer value */
562 i = CREATE_S(OP_JMP, NO_JUMP);
563 optm = 1;
564 }
565 break;
566 }
567 case OP_PUSHNIL: {
568 if (GETARG_U(i) == 1) {
569 fs->pc--; /* erase previous instruction */
570 luaK_deltastack(fs, -1); /* correct stack */
571 return NO_JUMP;
572 }
573 break;
574 }
575 default: break;
576 }
577 break;
578 }
545 case OP_JMPF: 579 case OP_JMPF:
546 case OP_JMPONT: 580 case OP_JMPONF: {
547 case OP_JMPONF:
548 switch (GET_OPCODE(i)) { 581 switch (GET_OPCODE(i)) {
549 case OP_NOT: i = CREATE_S(invertjump(o), NO_JUMP); optm = 1; break; 582 case OP_NOT: {
583 i = CREATE_S(OP_JMPT, NO_JUMP);
584 optm = 1;
585 break;
586 }
587 case OP_PUSHINT: { /* `while 1 do ...' */
588 fs->pc--; /* erase previous instruction */
589 luaK_deltastack(fs, -1); /* correct stack */
590 return NO_JUMP;
591 }
592 case OP_PUSHNIL: { /* `repeat ... until nil' */
593 if (GETARG_U(i) == 1) {
594 i = CREATE_S(OP_JMP, NO_JUMP);
595 optm = 1;
596 }
597 break;
598 }
550 default: break; 599 default: break;
551 } 600 }
552 break; 601 break;
553 602 }
554 case OP_GETDOTTED: 603 case OP_GETDOTTED:
555 case OP_GETINDEXED: 604 case OP_GETINDEXED:
556 case OP_TAILCALL: 605 case OP_TAILCALL:
557 case OP_ADDI: 606 case OP_ADDI: {
558 LUA_INTERNALERROR(L, "instruction used only for optimizations"); 607 LUA_INTERNALERROR(L, "instruction used only for optimizations");
559 break; 608 break;
560 609 }
561 default: 610 default: {
562 LUA_ASSERT(L, delta != VD, "invalid delta"); 611 LUA_ASSERT(L, delta != VD, "invalid delta");
563 break; 612 break;
564 613 }
565 } 614 }
566 luaK_deltastack(fs, delta); 615 luaK_deltastack(fs, delta);
567 if (optm) { /* optimize: put instruction in place of last one */ 616 if (optm) { /* optimize: put instruction in place of last one */
568 fs->f->code[fs->pc-1] = i; /* change previous instruction */ 617 fs->f->code[fs->pc-1] = i; /* change previous instruction */
569 return fs->pc-1; /* do not generate new instruction */ 618 return fs->pc-1; /* do not generate new instruction */
570 } 619 }
571 /* build new instruction */ 620 /* else build new instruction */
572 switch ((enum Mode)luaK_opproperties[o].mode) { 621 switch ((enum Mode)luaK_opproperties[o].mode) {
573 case iO: i = CREATE_0(o); break; 622 case iO: i = CREATE_0(o); break;
574 case iU: i = CREATE_U(o, arg1); break; 623 case iU: i = CREATE_U(o, arg1); break;
diff --git a/lcode.h b/lcode.h
index 285383c0..283c0f84 100644
--- a/lcode.h
+++ b/lcode.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lcode.h,v 1.12 2000/04/12 18:47:03 roberto Exp roberto $ 2** $Id: lcode.h,v 1.13 2000/05/22 18:44:46 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*/
@@ -36,7 +36,6 @@ int luaK_jump (FuncState *fs);
36void luaK_patchlist (FuncState *fs, int list, int target); 36void luaK_patchlist (FuncState *fs, int list, int target);
37void luaK_concat (FuncState *fs, int *l1, int l2); 37void luaK_concat (FuncState *fs, int *l1, int l2);
38void luaK_goiftrue (FuncState *fs, expdesc *v, int keepvalue); 38void luaK_goiftrue (FuncState *fs, expdesc *v, int keepvalue);
39void luaK_goiffalse (FuncState *fs, expdesc *v, int keepvalue);
40int luaK_getlabel (FuncState *fs); 39int luaK_getlabel (FuncState *fs);
41void luaK_deltastack (FuncState *fs, int delta); 40void luaK_deltastack (FuncState *fs, int delta);
42void luaK_kstr (LexState *ls, int c); 41void luaK_kstr (LexState *ls, int c);