mirror of https://github.com/rusefi/lua.git
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.
This commit is contained in:
parent
d282652561
commit
ab1aca94e8
50
lparser.c
50
lparser.c
|
@ -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) {
|
static void test_then_block (LexState *ls, int *escapelist) {
|
||||||
/* test_then_block -> [IF | ELSEIF] cond THEN block */
|
/* test_then_block -> [IF | ELSEIF] cond THEN block */
|
||||||
BlockCnt bl;
|
BlockCnt bl;
|
||||||
int line;
|
|
||||||
FuncState *fs = ls->fs;
|
FuncState *fs = ls->fs;
|
||||||
TString *jlb = NULL;
|
|
||||||
int target = NO_JUMP;
|
|
||||||
expdesc v;
|
expdesc v;
|
||||||
int jf; /* instruction to skip 'then' code (if condition is false) */
|
int jf; /* instruction to skip 'then' code (if condition is false) */
|
||||||
luaX_next(ls); /* skip IF or ELSEIF */
|
luaX_next(ls); /* skip IF or ELSEIF */
|
||||||
expr(ls, &v); /* read condition */
|
expr(ls, &v); /* read condition */
|
||||||
checknext(ls, TK_THEN);
|
checknext(ls, TK_THEN);
|
||||||
line = ls->linenumber;
|
if (ls->t.token == TK_BREAK) { /* 'if x then break' ? */
|
||||||
if (issinglejump(ls, &jlb, &target)) { /* 'if x then goto' ? */
|
int line = ls->linenumber;
|
||||||
luaK_goiffalse(ls->fs, &v); /* will jump to label if condition is true */
|
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' */
|
enterblock(fs, &bl, 0); /* must enter block before 'goto' */
|
||||||
if (jlb != NULL) /* forward jump? */
|
newgotoentry(ls, luaS_newliteral(ls->L, "break"), line, v.t);
|
||||||
newgotoentry(ls, jlb, line, v.t); /* will be resolved later */
|
|
||||||
else /* backward jump */
|
|
||||||
luaK_patchlist(fs, v.t, target); /* jump directly to 'target' */
|
|
||||||
while (testnext(ls, ';')) {} /* skip semicolons */
|
while (testnext(ls, ';')) {} /* skip semicolons */
|
||||||
if (block_follow(ls, 0)) { /* jump is the entire block? */
|
if (block_follow(ls, 0)) { /* jump is the entire block? */
|
||||||
leaveblock(fs);
|
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 */
|
else /* must skip over 'then' part if condition is false */
|
||||||
jf = luaK_jump(fs);
|
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 */
|
luaK_goiftrue(ls->fs, &v); /* skip over block if condition is false */
|
||||||
enterblock(fs, &bl, 0);
|
enterblock(fs, &bl, 0);
|
||||||
jf = v.f;
|
jf = v.f;
|
||||||
|
|
|
@ -392,28 +392,6 @@ check(function (a, b)
|
||||||
end,
|
end,
|
||||||
'TEST', 'JMP', 'TEST', 'JMP', 'ADDI', 'MMBINI', 'JMP', 'RETURN0')
|
'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,
|
checkequal(function () return 6 or true or nil end,
|
||||||
function () return k6 or kTrue or kNil end)
|
function () return k6 or kTrue or kNil end)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue