diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2020-11-11 14:41:41 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2020-11-11 14:41:41 -0300 |
commit | ab1aca94e83d2eff1605ea1854df023c814cef21 (patch) | |
tree | 16b87253f000cb0052133bf2e1ede3d4b2b730ef | |
parent | d28265256110a0c5437247d443ddedc2a7aab116 (diff) | |
download | lua-github-ab1aca94e83d2eff1605ea1854df023c814cef21.tar.gz |
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.
-rw-r--r-- | lparser.c | 50 | ||||
-rw-r--r-- | testes/code.lua | 22 |
2 files changed, 6 insertions, 66 deletions
@@ -1623,59 +1623,21 @@ static void forstat (LexState *ls, int line) { } -/* -** Check whether next instruction is a single jump (a 'break', a 'goto' -** to a forward label, or a 'goto' to a backward label with no variable -** to close). If so, set the name of the 'label' it is jumping to -** ("break" for a 'break') or to where it is jumping to ('target') and -** return true. If not a single jump, leave input unchanged, to be -** handled as a regular statement. -*/ -static int issinglejump (LexState *ls, TString **label, int *target) { - if (testnext(ls, TK_BREAK)) { /* a break? */ - *label = luaS_newliteral(ls->L, "break"); - return 1; - } - else if (ls->t.token != TK_GOTO || luaX_lookahead(ls) != TK_NAME) - return 0; /* not a valid goto */ - else { - TString *lname = ls->lookahead.seminfo.ts; /* label's id */ - Labeldesc *lb = findlabel(ls, lname); - if (lb) { /* a backward jump? */ - /* does it need to close variables? */ - if (luaY_nvarstack(ls->fs) > stacklevel(ls->fs, lb->nactvar)) - return 0; /* not a single jump; cannot optimize */ - *target = lb->pc; - } - else /* jump forward */ - *label = lname; - luaX_next(ls); /* skip goto */ - luaX_next(ls); /* skip name */ - return 1; - } -} - - static void test_then_block (LexState *ls, int *escapelist) { /* test_then_block -> [IF | ELSEIF] cond THEN block */ BlockCnt bl; - int line; FuncState *fs = ls->fs; - TString *jlb = NULL; - int target = NO_JUMP; expdesc v; int jf; /* instruction to skip 'then' code (if condition is false) */ luaX_next(ls); /* skip IF or ELSEIF */ expr(ls, &v); /* read condition */ checknext(ls, TK_THEN); - line = ls->linenumber; - if (issinglejump(ls, &jlb, &target)) { /* 'if x then goto' ? */ - luaK_goiffalse(ls->fs, &v); /* will jump to label if condition is true */ + if (ls->t.token == TK_BREAK) { /* 'if x then break' ? */ + int line = ls->linenumber; + luaK_goiffalse(ls->fs, &v); /* will jump if condition is true */ + luaX_next(ls); /* skip 'break' */ enterblock(fs, &bl, 0); /* must enter block before 'goto' */ - if (jlb != NULL) /* forward jump? */ - newgotoentry(ls, jlb, line, v.t); /* will be resolved later */ - else /* backward jump */ - luaK_patchlist(fs, v.t, target); /* jump directly to 'target' */ + newgotoentry(ls, luaS_newliteral(ls->L, "break"), line, v.t); while (testnext(ls, ';')) {} /* skip semicolons */ if (block_follow(ls, 0)) { /* jump is the entire block? */ leaveblock(fs); @@ -1684,7 +1646,7 @@ static void test_then_block (LexState *ls, int *escapelist) { else /* must skip over 'then' part if condition is false */ jf = luaK_jump(fs); } - else { /* regular case (not a jump) */ + else { /* regular case (not a break) */ luaK_goiftrue(ls->fs, &v); /* skip over block if condition is false */ enterblock(fs, &bl, 0); jf = v.f; diff --git a/testes/code.lua b/testes/code.lua index 34b04668..1f971cd7 100644 --- a/testes/code.lua +++ b/testes/code.lua @@ -392,28 +392,6 @@ check(function (a, b) end, 'TEST', 'JMP', 'TEST', 'JMP', 'ADDI', 'MMBINI', 'JMP', 'RETURN0') -checkequal( -function (a) while a < 10 do a = a + 1 end end, -function (a) - ::loop:: - if not (a < 10) then goto exit end - a = a + 1 - goto loop -::exit:: -end -) - -checkequal( -function (a) repeat local x = a + 1; a = x until a > 0 end, -function (a) - ::loop:: do - local x = a + 1 - a = x - end - if not (a > 0) then goto loop end -end -) - checkequal(function () return 6 or true or nil end, function () return k6 or kTrue or kNil end) |