diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2000-06-16 14:51:40 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2000-06-16 14:51:40 -0300 |
commit | 2e1b32d87339c22b0518481fa260edf3bfbc01d3 (patch) | |
tree | 5dbca324c1b96790350bc3a86b5c80a97c4a4761 | |
parent | 89a3ec08f37d127fc3c7756cb7cf71586959f8c4 (diff) | |
download | lua-2e1b32d87339c22b0518481fa260edf3bfbc01d3.tar.gz lua-2e1b32d87339c22b0518481fa260edf3bfbc01d3.tar.bz2 lua-2e1b32d87339c22b0518481fa260edf3bfbc01d3.zip |
optimizations for "while 1", "until nil", and the like
-rw-r--r-- | lcode.c | 153 | ||||
-rw-r--r-- | lcode.h | 3 |
2 files changed, 102 insertions, 54 deletions
@@ -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 | ||
270 | static void luaK_testgo (FuncState *fs, expdesc *v, int invert, OpCode jump) { | 270 | static 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 | ||
295 | void luaK_goiffalse (FuncState *fs, expdesc *v, int keepvalue) { | 304 | static 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; |
@@ -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); | |||
36 | void luaK_patchlist (FuncState *fs, int list, int target); | 36 | void luaK_patchlist (FuncState *fs, int list, int target); |
37 | void luaK_concat (FuncState *fs, int *l1, int l2); | 37 | void luaK_concat (FuncState *fs, int *l1, int l2); |
38 | void luaK_goiftrue (FuncState *fs, expdesc *v, int keepvalue); | 38 | void luaK_goiftrue (FuncState *fs, expdesc *v, int keepvalue); |
39 | void luaK_goiffalse (FuncState *fs, expdesc *v, int keepvalue); | ||
40 | int luaK_getlabel (FuncState *fs); | 39 | int luaK_getlabel (FuncState *fs); |
41 | void luaK_deltastack (FuncState *fs, int delta); | 40 | void luaK_deltastack (FuncState *fs, int delta); |
42 | void luaK_kstr (LexState *ls, int c); | 41 | void luaK_kstr (LexState *ls, int c); |