Skip to content

Commit

Permalink
Ensure backwards jumps get a yk_location.
Browse files Browse the repository at this point in the history
I noticed that the mandelbrot benchmark was not triggering the JIT.
This was because we only assigned locations to `for` loops, but this
benchmark contains mostly `while` looping.

Lua has no deidcated bytecode for `while` loops. Instead it uses
unstructured control flow using conditionals and jumps.

Here's an example:
```
i = 10
while i > 0 do
    i = i - 1
end
```

Becomes:
```
main <a.lua:0,0> (11 instructions at 0xbfc160)
0+ params, 2 slots, 1 upvalue, 0 locals, 2 constants, 0 functions
        1       [1]     VARARGPREP      0
        2       [1]     SETTABUP        0 0 1k  ; _ENV "i" 10
        3       [2]     GETTABUP        0 0 0   ; _ENV "i"
        4       [2]     GTI             0 0 0
        5       [2]     JMP             5       ; to 11
        6       [3]     GETTABUP        0 0 0   ; _ENV "i"
        7       [3]     ADDI            0 0 -1
        8       [3]     MMBINI          0 1 7 0 ; __sub
        9       [3]     SETTABUP        0 0 0   ; _ENV "i"
        10      [3]     JMP             -8      ; to 3
        11      [4]     RETURN          0 1 1   ; 0 out
```

In this example `JMP -8` is a CFG back edge that makes the loop.

This commit makes yklua recognise back edges as potential loops so that
they get JITted if/when they get hot. This is of course a proxy: not all
back edges are necessarily loops, but it should (tm) be a decent enough
approximation for our purposes.

I measured about a 12% slowdown with this change. We can't not trace
while loops and expect to be faster, so we will have to take this on for
now.
  • Loading branch information
vext01 committed Nov 18, 2024
1 parent 3bad330 commit eb13d42
Showing 1 changed file with 4 additions and 1 deletion.
5 changes: 4 additions & 1 deletion src/lvm.c
Original file line number Diff line number Diff line change
Expand Up @@ -1222,8 +1222,11 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
vmfetch();
#ifdef USE_YK
YkLocation *ykloc = NULL;
if (GET_OPCODE(i) == OP_FORLOOP || GET_OPCODE(i) == OP_TFORLOOP)
if ((GET_OPCODE(i) == OP_FORLOOP) ||
(GET_OPCODE(i) == OP_TFORLOOP) ||
((GET_OPCODE(i) == OP_JMP) && (GETARG_sJ(i) < 0))) {
ykloc = &cl->p->yklocs[pcRel(pc, cl->p)];
}
yk_mt_control_point(G(L)->yk_mt, ykloc);
#endif
#if 0
Expand Down

0 comments on commit eb13d42

Please sign in to comment.