LuaJIT is a
tracing JIT compiler which compiles loops. When it encounters an instruction that it can't compile, like a
coroutine function, the trace is aborted. That goes for LuaJIT 2.0; version 2.1 can do "trace stitching", which consists of resuming traces after a NYI instruction is executed. I don't know if the trace can propagate through coroutine switches, but I wouldn't count on it.
Coroutines are not treated specially, but coroutine switches may be a different beast. Anyway, if the code inside the coroutine contains a compilable loop, that loop will run in compiled mode. When it encounters a NYI instruction, like a call to coroutine.yield(), that part won't be compiled. If the yield is in a loop, that loop won't be compiled unless the yield is very rarely executed.
For example, the loops in this coroutine run in compiled mode (try the difference with jit.on() and jit.off() to see):
Code: Select all
jit.on()
--jit.off()
local function sumPrimes(n)
local P = 3
local isFactor = {}
for i = 2, n do
if not isFactor[i] then
for j = i*i, n, i do
isFactor[j] = true
end
end
end
local sum = 0
for i = 2, n do
if not isFactor[i] then
sum = sum + i
end
end
coroutine.yield(sum)
end
local co = coroutine.create(sumPrimes)
local a = os.clock()
local success, result = assert(coroutine.resume(co, 2713131))
print(result)
print(os.clock()-a)
That's because the loops don't have anything that breaks the traces.
(I know it's a stupid use of a coroutine, when a normal function call would be much simpler, but it's just for illustrative purposes)