diff options
| -rw-r--r-- | src/lj_parse.c | 81 |
1 files changed, 42 insertions, 39 deletions
diff --git a/src/lj_parse.c b/src/lj_parse.c index 2811e6eb..f5f59d03 100644 --- a/src/lj_parse.c +++ b/src/lj_parse.c | |||
| @@ -419,14 +419,48 @@ static void expr_discharge(FuncState *fs, ExpDesc *e) | |||
| 419 | e->k = VRELOCABLE; | 419 | e->k = VRELOCABLE; |
| 420 | } | 420 | } |
| 421 | 421 | ||
| 422 | /* Emit bytecode to set a range of registers to nil. */ | ||
| 423 | static void bcemit_nil(FuncState *fs, BCReg from, BCReg n) | ||
| 424 | { | ||
| 425 | if (fs->pc > fs->lasttarget) { /* No jumps to current position? */ | ||
| 426 | BCIns *ip = &fs->bcbase[fs->pc-1].ins; | ||
| 427 | BCReg pto, pfrom = bc_a(*ip); | ||
| 428 | switch (bc_op(*ip)) { /* Try to merge with the previous instruction. */ | ||
| 429 | case BC_KPRI: | ||
| 430 | if (bc_d(*ip) != ~LJ_TNIL) break; | ||
| 431 | if (from == pfrom) { | ||
| 432 | if (n == 1) return; | ||
| 433 | } else if (from == pfrom+1) { | ||
| 434 | from = pfrom; | ||
| 435 | n++; | ||
| 436 | } else { | ||
| 437 | break; | ||
| 438 | } | ||
| 439 | fs->pc--; /* Drop KPRI. */ | ||
| 440 | break; | ||
| 441 | case BC_KNIL: | ||
| 442 | pto = bc_d(*ip); | ||
| 443 | if (pfrom <= from && from <= pto+1) { /* Can we connect both ranges? */ | ||
| 444 | if (from+n-1 > pto) | ||
| 445 | setbc_d(ip, from+n-1); /* Patch previous instruction range. */ | ||
| 446 | return; | ||
| 447 | } | ||
| 448 | break; | ||
| 449 | default: | ||
| 450 | break; | ||
| 451 | } | ||
| 452 | } | ||
| 453 | /* Emit new instruction or replace old instruction. */ | ||
| 454 | bcemit_INS(fs, n == 1 ? BCINS_AD(BC_KPRI, from, VKNIL) : | ||
| 455 | BCINS_AD(BC_KNIL, from, from+n-1)); | ||
| 456 | } | ||
| 457 | |||
| 422 | /* Discharge an expression to a specific register. Ignore branches. */ | 458 | /* Discharge an expression to a specific register. Ignore branches. */ |
| 423 | static void expr_toreg_nobranch(FuncState *fs, ExpDesc *e, BCReg reg) | 459 | static void expr_toreg_nobranch(FuncState *fs, ExpDesc *e, BCReg reg) |
| 424 | { | 460 | { |
| 425 | BCIns ins; | 461 | BCIns ins; |
| 426 | expr_discharge(fs, e); | 462 | expr_discharge(fs, e); |
| 427 | if (e->k <= VKTRUE) { | 463 | if (e->k == VKSTR) { |
| 428 | ins = BCINS_AD(BC_KPRI, reg, const_pri(e)); | ||
| 429 | } else if (e->k == VKSTR) { | ||
| 430 | ins = BCINS_AD(BC_KSTR, reg, const_str(fs, e)); | 464 | ins = BCINS_AD(BC_KSTR, reg, const_str(fs, e)); |
| 431 | } else if (e->k == VKNUM) { | 465 | } else if (e->k == VKNUM) { |
| 432 | lua_Number n = expr_numV(e); | 466 | lua_Number n = expr_numV(e); |
| @@ -442,6 +476,11 @@ static void expr_toreg_nobranch(FuncState *fs, ExpDesc *e, BCReg reg) | |||
| 442 | if (reg == e->u.s.info) | 476 | if (reg == e->u.s.info) |
| 443 | goto noins; | 477 | goto noins; |
| 444 | ins = BCINS_AD(BC_MOV, reg, e->u.s.info); | 478 | ins = BCINS_AD(BC_MOV, reg, e->u.s.info); |
| 479 | } else if (e->k == VKNIL) { | ||
| 480 | bcemit_nil(fs, reg, 1); | ||
| 481 | goto noins; | ||
| 482 | } else if (e->k <= VKTRUE) { | ||
| 483 | ins = BCINS_AD(BC_KPRI, reg, const_pri(e)); | ||
| 445 | } else { | 484 | } else { |
| 446 | lua_assert(e->k == VVOID || e->k == VJMP); | 485 | lua_assert(e->k == VVOID || e->k == VJMP); |
| 447 | return; | 486 | return; |
| @@ -577,42 +616,6 @@ static void bcemit_method(FuncState *fs, ExpDesc *e, ExpDesc *key) | |||
| 577 | e->k = VNONRELOC; | 616 | e->k = VNONRELOC; |
| 578 | } | 617 | } |
| 579 | 618 | ||
| 580 | /* Emit bytecode to set a range of registers to nil. */ | ||
| 581 | static void bcemit_nil(FuncState *fs, BCReg from, BCReg n) | ||
| 582 | { | ||
| 583 | if (fs->pc > fs->lasttarget) { /* No jumps to current position? */ | ||
| 584 | BCIns *ip = &fs->bcbase[fs->pc-1].ins; | ||
| 585 | BCReg pto, pfrom = bc_a(*ip); | ||
| 586 | switch (bc_op(*ip)) { /* Try to merge with the previous instruction. */ | ||
| 587 | case BC_KPRI: | ||
| 588 | if (bc_d(*ip) != ~LJ_TNIL) break; | ||
| 589 | if (from == pfrom) { | ||
| 590 | if (n == 1) return; | ||
| 591 | } else if (from == pfrom+1) { | ||
| 592 | from = pfrom; | ||
| 593 | n++; | ||
| 594 | } else { | ||
| 595 | break; | ||
| 596 | } | ||
| 597 | fs->pc--; /* Drop KPRI. */ | ||
| 598 | break; | ||
| 599 | case BC_KNIL: | ||
| 600 | pto = bc_d(*ip); | ||
| 601 | if (pfrom <= from && from <= pto+1) { /* Can we connect both ranges? */ | ||
| 602 | if (from+n-1 > pto) | ||
| 603 | setbc_d(ip, from+n-1); /* Patch previous instruction range. */ | ||
| 604 | return; | ||
| 605 | } | ||
| 606 | break; | ||
| 607 | default: | ||
| 608 | break; | ||
| 609 | } | ||
| 610 | } | ||
| 611 | /* Emit new instruction or replace old instruction. */ | ||
| 612 | bcemit_INS(fs, n == 1 ? BCINS_AD(BC_KPRI, from, VKNIL) : | ||
| 613 | BCINS_AD(BC_KNIL, from, from+n-1)); | ||
| 614 | } | ||
| 615 | |||
| 616 | /* -- Bytecode emitter for branches --------------------------------------- */ | 619 | /* -- Bytecode emitter for branches --------------------------------------- */ |
| 617 | 620 | ||
| 618 | /* Emit unconditional branch. */ | 621 | /* Emit unconditional branch. */ |
