LuaJIT is fully upwards-compatible with Lua 5.1. It supports all » standard Lua library functions and the full set of » Lua/C API functions.
LuaJIT is also fully ABI-compatible to Lua 5.1 at the linker/dynamic loader level. This means you can compile a C module against the standard Lua headers and load the same shared library from either Lua or LuaJIT.
LuaJIT extends the standard Lua VM with new functionality and adds several extension modules. Please note that this page is only about functional enhancements and not about performance enhancements, such as the optimized VM, the faster interpreter or the JIT compiler.
Extensions Modules
LuaJIT comes with several built-in extension modules:
bit.* — Bitwise operations
LuaJIT supports all bitwise operations as defined by » Lua BitOp:
bit.tobit bit.tohex bit.bnot bit.band bit.bor bit.bxor bit.lshift bit.rshift bit.arshift bit.rol bit.ror bit.bswap
This module is a LuaJIT built-in — you don't need to download or install Lua BitOp. The Lua BitOp site has full documentation for all » Lua BitOp API functions.
Please make sure to require the module before using any of its functions:
local bit = require("bit")
An already installed Lua BitOp module is ignored by LuaJIT. This way you can use bit operations from both Lua and LuaJIT on a shared installation.
ffi.* — FFI library
The FFI library allows calling external C functions and the use of C data structures from pure Lua code.
jit.* — JIT compiler control
The functions in this module control the behavior of the JIT compiler engine.
C API extensions
LuaJIT adds some extra functions to the Lua/C API.
Enhanced Standard Library Functions
xpcall(f, err [,args...]) passes arguments
Unlike the standard implementation in Lua 5.1, xpcall() passes any arguments after the error function to the function which is called in a protected context.
loadfile() etc. handle UTF-8 source code
Non-ASCII characters are handled transparently by the Lua source code parser. This allows the use of UTF-8 characters in identifiers and strings. A UTF-8 BOM is skipped at the start of the source code.
tostring() etc. canonicalize NaN and ±Inf
All number-to-string conversions consistently convert non-finite numbers to the same strings on all platforms. NaN results in "nan", positive infinity results in "inf" and negative infinity results in "-inf".
string.dump(f [,strip]) generates portable bytecode
An extra argument has been added to string.dump(). If set to true, 'stripped' bytecode without debug information is generated. This speeds up later bytecode loading and reduces memory usage. See also the -b command line option.
The generated bytecode is portable and can be loaded on any architecture that LuaJIT supports, independent of word size or endianess. However the bytecode compatibility versions must match. Bytecode stays compatible for dot releases (x.y.0 → x.y.1), but may change with major or minor releases (2.0 → 2.1) or between any beta release. Foreign bytecode (e.g. from Lua 5.1) is incompatible and cannot be loaded.
Enhanced PRNG for math.random()
LuaJIT uses a Tausworthe PRNG with period 2^223 to implement math.random() and math.randomseed(). The quality of the PRNG results is much superior compared to the standard Lua implementation which uses the platform-specific ANSI rand().
The PRNG generates the same sequences from the same seeds on all platforms and makes use of all bits in the seed argument. math.random() without arguments generates 52 pseudo-random bits for every call. The result is uniformly distributed between 0 and 1. It's correctly scaled up and rounded for math.random(n [,m]) to preserve uniformity.
io.* functions handle 64 bit file offsets
The file I/O functions in the standard io.* library handle 64 bit file offsets. In particular this means it's possible to open files larger than 2 Gigabytes and to reposition or obtain the current file position for offsets beyond 2 GB (fp:seek() method).
debug.* functions identify metamethods
debug.getinfo() and lua_getinfo() also return information about invoked metamethods. The namewhat field is set to "metamethod" and the name field has the name of the corresponding metamethod (e.g. "__index").
Fully Resumable VM
The LuaJIT 2.x VM is fully resumable. This means you can yield from a coroutine even across contexts, where this would not possible with the standard Lua 5.1 VM: e.g. you can yield across pcall() and xpcall(), across iterators and across metamethods.
Note however that LuaJIT 2.x doesn't use » Coco anymore. This means the overhead for creating coroutines is much smaller and no extra C stacks need to be allocated. OTOH you can no longer yield across arbitrary C functions. Keep this in mind when upgrading from LuaJIT 1.x.
C++ Exception Interoperability
LuaJIT has built-in support for interoperating with C++ exceptions. The available range of features depends on the target platform and the toolchain used to compile LuaJIT:
Platform | Compiler | Interoperability |
POSIX/x64, DWARF2 unwinding | GCC 4.3+ | Full |
Other platforms, DWARF2 unwinding | GCC | Limited |
Windows/x64 | MSVC or WinSDK | Full |
Windows/x86 | Any | No |
Other platforms | Other compilers | No |
Full interoperability means:
- C++ exceptions can be caught on the Lua side with pcall(), lua_pcall() etc.
- C++ exceptions will be converted to the generic Lua error "C++ exception", unless you use the C call wrapper feature.
- It's safe to throw C++ exceptions across non-protected Lua frames on the C stack. The contents of the C++ exception object pass through unmodified.
- Lua errors can be caught on the C++ side with catch(...). The corresponding Lua error message can be retrieved from the Lua stack.
- Throwing Lua errors across C++ frames is safe. C++ destructors will be called.
Limited interoperability means:
- C++ exceptions can be caught on the Lua side with pcall(), lua_pcall() etc.
- C++ exceptions will be converted to the generic Lua error "C++ exception", unless you use the C call wrapper feature.
- C++ exceptions will be caught by non-protected Lua frames and are rethrown as a generic Lua error. The C++ exception object will be destroyed.
- Lua errors cannot be caught on the C++ side.
- Throwing Lua errors across C++ frames will not call C++ destructors.
No interoperability means:
- It's not safe to throw C++ exceptions across Lua frames.
- C++ exceptions cannot be caught on the Lua side.
- Lua errors cannot be caught on the C++ side.
- Throwing Lua errors across C++ frames will not call C++ destructors.
- Additionally, on Windows/x86 with SEH-based C++ exceptions: it's not safe to throw a Lua error across any frames containing a C++ function with any try/catch construct or using variables with (implicit) destructors. This also applies to any functions which may be inlined in such a function. It doesn't matter whether lua_error() is called inside or outside of a try/catch or whether any object actually needs to be destroyed: the SEH chain is corrupted and this will eventually lead to the termination of the process.