aboutsummaryrefslogtreecommitdiff
path: root/lparser.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2020-11-11 14:41:41 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2020-11-11 14:41:41 -0300
commitab1aca94e83d2eff1605ea1854df023c814cef21 (patch)
tree16b87253f000cb0052133bf2e1ede3d4b2b730ef /lparser.c
parentd28265256110a0c5437247d443ddedc2a7aab116 (diff)
downloadlua-ab1aca94e83d2eff1605ea1854df023c814cef21.tar.gz
lua-ab1aca94e83d2eff1605ea1854df023c814cef21.tar.bz2
lua-ab1aca94e83d2eff1605ea1854df023c814cef21.zip
Removed optimization for «if ... then goto»
That optimization was too complex and caused some weird traces when debugging. The more common case «if ... then break» was kept.
Diffstat (limited to 'lparser.c')
-rw-r--r--lparser.c50
1 files changed, 6 insertions, 44 deletions
diff --git a/lparser.c b/lparser.c
index fb7a1264..77813a74 100644
--- a/lparser.c
+++ b/lparser.c
@@ -1623,59 +1623,21 @@ static void forstat (LexState *ls, int line) {
1623} 1623}
1624 1624
1625 1625
1626/*
1627** Check whether next instruction is a single jump (a 'break', a 'goto'
1628** to a forward label, or a 'goto' to a backward label with no variable
1629** to close). If so, set the name of the 'label' it is jumping to
1630** ("break" for a 'break') or to where it is jumping to ('target') and
1631** return true. If not a single jump, leave input unchanged, to be
1632** handled as a regular statement.
1633*/
1634static int issinglejump (LexState *ls, TString **label, int *target) {
1635 if (testnext(ls, TK_BREAK)) { /* a break? */
1636 *label = luaS_newliteral(ls->L, "break");
1637 return 1;
1638 }
1639 else if (ls->t.token != TK_GOTO || luaX_lookahead(ls) != TK_NAME)
1640 return 0; /* not a valid goto */
1641 else {
1642 TString *lname = ls->lookahead.seminfo.ts; /* label's id */
1643 Labeldesc *lb = findlabel(ls, lname);
1644 if (lb) { /* a backward jump? */
1645 /* does it need to close variables? */
1646 if (luaY_nvarstack(ls->fs) > stacklevel(ls->fs, lb->nactvar))
1647 return 0; /* not a single jump; cannot optimize */
1648 *target = lb->pc;
1649 }
1650 else /* jump forward */
1651 *label = lname;
1652 luaX_next(ls); /* skip goto */
1653 luaX_next(ls); /* skip name */
1654 return 1;
1655 }
1656}
1657
1658
1659static void test_then_block (LexState *ls, int *escapelist) { 1626static void test_then_block (LexState *ls, int *escapelist) {
1660 /* test_then_block -> [IF | ELSEIF] cond THEN block */ 1627 /* test_then_block -> [IF | ELSEIF] cond THEN block */
1661 BlockCnt bl; 1628 BlockCnt bl;
1662 int line;
1663 FuncState *fs = ls->fs; 1629 FuncState *fs = ls->fs;
1664 TString *jlb = NULL;
1665 int target = NO_JUMP;
1666 expdesc v; 1630 expdesc v;
1667 int jf; /* instruction to skip 'then' code (if condition is false) */ 1631 int jf; /* instruction to skip 'then' code (if condition is false) */
1668 luaX_next(ls); /* skip IF or ELSEIF */ 1632 luaX_next(ls); /* skip IF or ELSEIF */
1669 expr(ls, &v); /* read condition */ 1633 expr(ls, &v); /* read condition */
1670 checknext(ls, TK_THEN); 1634 checknext(ls, TK_THEN);
1671 line = ls->linenumber; 1635 if (ls->t.token == TK_BREAK) { /* 'if x then break' ? */
1672 if (issinglejump(ls, &jlb, &target)) { /* 'if x then goto' ? */ 1636 int line = ls->linenumber;
1673 luaK_goiffalse(ls->fs, &v); /* will jump to label if condition is true */ 1637 luaK_goiffalse(ls->fs, &v); /* will jump if condition is true */
1638 luaX_next(ls); /* skip 'break' */
1674 enterblock(fs, &bl, 0); /* must enter block before 'goto' */ 1639 enterblock(fs, &bl, 0); /* must enter block before 'goto' */
1675 if (jlb != NULL) /* forward jump? */ 1640 newgotoentry(ls, luaS_newliteral(ls->L, "break"), line, v.t);
1676 newgotoentry(ls, jlb, line, v.t); /* will be resolved later */
1677 else /* backward jump */
1678 luaK_patchlist(fs, v.t, target); /* jump directly to 'target' */
1679 while (testnext(ls, ';')) {} /* skip semicolons */ 1641 while (testnext(ls, ';')) {} /* skip semicolons */
1680 if (block_follow(ls, 0)) { /* jump is the entire block? */ 1642 if (block_follow(ls, 0)) { /* jump is the entire block? */
1681 leaveblock(fs); 1643 leaveblock(fs);
@@ -1684,7 +1646,7 @@ static void test_then_block (LexState *ls, int *escapelist) {
1684 else /* must skip over 'then' part if condition is false */ 1646 else /* must skip over 'then' part if condition is false */
1685 jf = luaK_jump(fs); 1647 jf = luaK_jump(fs);
1686 } 1648 }
1687 else { /* regular case (not a jump) */ 1649 else { /* regular case (not a break) */
1688 luaK_goiftrue(ls->fs, &v); /* skip over block if condition is false */ 1650 luaK_goiftrue(ls->fs, &v); /* skip over block if condition is false */
1689 enterblock(fs, &bl, 0); 1651 enterblock(fs, &bl, 0);
1690 jf = v.f; 1652 jf = v.f;