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
Diffstat (limited to '')
| -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); |
