diff --git a/CMakeLists.txt b/CMakeLists.txt index 339d7a87..22a76da7 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -216,7 +216,7 @@ endif() set(MEGA_ZLIB_VER "1.2.12") set(MEGA_LUA51_VER "5.1.5") -set(MEGA_LUAJIT_VER "2.1.0-e826d0c") +set(MEGA_LUAJIT_VER "2.1.1710088188") set(MEGA_LIBOGG_VER "1.3.2") set(MEGA_LIBVORBIS_VER "1.3.5") set(MEGA_LIBTHEORA_VER "1.1.1") @@ -351,7 +351,7 @@ if(MSVC) BUILD_BYPRODUCTS "${CMAKE_BINARY_DIR}/bin/lua51.lib" "${CMAKE_BINARY_DIR}/bin/lua51.dll" ) set_target_properties(luajit PROPERTIES - INTERFACE_INCLUDE_DIRECTORIES "MEGA_LUAJIT_INCLUDE ${MEGA_LUAJIT_SOURCE_DIR}/src" + INTERFACE_INCLUDE_DIRECTORIES "${MEGA_LUAJIT_SOURCE_DIR}/src" IMPORTED_IMPLIB "${CMAKE_BINARY_DIR}/bin/lua51.lib" IMPORTED_LOCATION "${CMAKE_BINARY_DIR}/bin/lua51.dll" ) diff --git a/libs/LuaJIT/.relver b/libs/LuaJIT/.relver index a09d4bf1..b1fbd688 100644 --- a/libs/LuaJIT/.relver +++ b/libs/LuaJIT/.relver @@ -1 +1 @@ -1700008891 +1710088188 diff --git a/libs/LuaJIT/android/arm64-v8a/jit/bcsave.lua b/libs/LuaJIT/android/arm64-v8a/jit/bcsave.lua index 390d297c..131bf39b 100644 --- a/libs/LuaJIT/android/arm64-v8a/jit/bcsave.lua +++ b/libs/LuaJIT/android/arm64-v8a/jit/bcsave.lua @@ -29,6 +29,9 @@ Save LuaJIT bytecode: luajit -b[options] input output -l Only list bytecode. -s Strip debug info (default). -g Keep debug info. + -W Generate 32 bit (non-GC64) bytecode. + -X Generate 64 bit (GC64) bytecode. + -d Generate bytecode in deterministic manner. -n name Set module name (default: auto-detect from input name). -t type Set output file type (default: auto-detect from output name). -a arch Override architecture for object files (default: native). @@ -51,8 +54,9 @@ local function check(ok, ...) end local function readfile(ctx, input) - if type(input) == "function" then return input end - if ctx.filename then + if ctx.string then + return check(loadstring(input, nil, ctx.mode)) + elseif ctx.filename then local data if input == "-" then data = io.stdin:read("*a") @@ -61,10 +65,10 @@ local function readfile(ctx, input) data = assert(fp:read("*a")) assert(fp:close()) end - return check(load(data, ctx.filename)) + return check(load(data, ctx.filename, ctx.mode)) else if input == "-" then input = nil end - return check(loadfile(input)) + return check(loadfile(input, ctx.mode)) end end @@ -624,7 +628,7 @@ end local function bcsave(ctx, input, output) local f = readfile(ctx, input) - local s = string.dump(f, ctx.strip) + local s = string.dump(f, ctx.mode) local t = ctx.type if not t then t = detecttype(output) @@ -647,9 +651,11 @@ local function docmd(...) local n = 1 local list = false local ctx = { - strip = true, arch = jit.arch, os = jit.os:lower(), - type = false, modname = false, + mode = "bt", arch = jit.arch, os = jit.os:lower(), + type = false, modname = false, string = false, } + local strip = "s" + local gc64 = "" while n <= #arg do local a = arg[n] if type(a) == "string" and a:sub(1, 1) == "-" and a ~= "-" then @@ -660,14 +666,18 @@ local function docmd(...) if opt == "l" then list = true elseif opt == "s" then - ctx.strip = true + strip = "s" elseif opt == "g" then - ctx.strip = false + strip = "" + elseif opt == "W" or opt == "X" then + gc64 = opt + elseif opt == "d" then + ctx.mode = ctx.mode .. opt else if arg[n] == nil or m ~= #a then usage() end if opt == "e" then if n ~= 1 then usage() end - arg[1] = check(loadstring(arg[1])) + ctx.string = true elseif opt == "n" then ctx.modname = checkmodname(tremove(arg, n)) elseif opt == "t" then @@ -687,6 +697,7 @@ local function docmd(...) n = n + 1 end end + ctx.mode = ctx.mode .. strip .. gc64 if list then if #arg == 0 or #arg > 2 then usage() end bclist(ctx, arg[1], arg[2] or "-") diff --git a/libs/LuaJIT/android/arm64-v8a/jit/vmdef.lua b/libs/LuaJIT/android/arm64-v8a/jit/vmdef.lua index ef31b783..75bc8b87 100644 --- a/libs/LuaJIT/android/arm64-v8a/jit/vmdef.lua +++ b/libs/LuaJIT/android/arm64-v8a/jit/vmdef.lua @@ -1,6 +1,6 @@ -- This is a generated file. DO NOT EDIT! -assert(require("jit").version == "LuaJIT 2.1.1700008891", "LuaJIT core/library version mismatch") +assert(require("jit").version == "LuaJIT 2.1.1710088188", "LuaJIT core/library version mismatch") return { diff --git a/libs/LuaJIT/android/arm64-v8a/libluajit.a b/libs/LuaJIT/android/arm64-v8a/libluajit.a index 3897ef2e..d7354680 100644 Binary files a/libs/LuaJIT/android/arm64-v8a/libluajit.a and b/libs/LuaJIT/android/arm64-v8a/libluajit.a differ diff --git a/libs/LuaJIT/android/arm64-v8a/libluajit.so b/libs/LuaJIT/android/arm64-v8a/libluajit.so index 7f080415..cf113c39 100644 Binary files a/libs/LuaJIT/android/arm64-v8a/libluajit.so and b/libs/LuaJIT/android/arm64-v8a/libluajit.so differ diff --git a/libs/LuaJIT/android/arm64-v8a/luajit.h b/libs/LuaJIT/android/arm64-v8a/luajit.h index 94814d91..39794a55 100644 --- a/libs/LuaJIT/android/arm64-v8a/luajit.h +++ b/libs/LuaJIT/android/arm64-v8a/luajit.h @@ -30,9 +30,9 @@ #include "lua.h" -#define LUAJIT_VERSION "LuaJIT 2.1.1700008891" +#define LUAJIT_VERSION "LuaJIT 2.1.1710088188" #define LUAJIT_VERSION_NUM 20199 /* Deprecated. */ -#define LUAJIT_VERSION_SYM luaJIT_version_2_1_1700008891 +#define LUAJIT_VERSION_SYM luaJIT_version_2_1_1710088188 #define LUAJIT_COPYRIGHT "Copyright (C) 2005-2023 Mike Pall" #define LUAJIT_URL "https://luajit.org/" diff --git a/libs/LuaJIT/android/armeabi-v7a/jit/bcsave.lua b/libs/LuaJIT/android/armeabi-v7a/jit/bcsave.lua index 390d297c..131bf39b 100644 --- a/libs/LuaJIT/android/armeabi-v7a/jit/bcsave.lua +++ b/libs/LuaJIT/android/armeabi-v7a/jit/bcsave.lua @@ -29,6 +29,9 @@ Save LuaJIT bytecode: luajit -b[options] input output -l Only list bytecode. -s Strip debug info (default). -g Keep debug info. + -W Generate 32 bit (non-GC64) bytecode. + -X Generate 64 bit (GC64) bytecode. + -d Generate bytecode in deterministic manner. -n name Set module name (default: auto-detect from input name). -t type Set output file type (default: auto-detect from output name). -a arch Override architecture for object files (default: native). @@ -51,8 +54,9 @@ local function check(ok, ...) end local function readfile(ctx, input) - if type(input) == "function" then return input end - if ctx.filename then + if ctx.string then + return check(loadstring(input, nil, ctx.mode)) + elseif ctx.filename then local data if input == "-" then data = io.stdin:read("*a") @@ -61,10 +65,10 @@ local function readfile(ctx, input) data = assert(fp:read("*a")) assert(fp:close()) end - return check(load(data, ctx.filename)) + return check(load(data, ctx.filename, ctx.mode)) else if input == "-" then input = nil end - return check(loadfile(input)) + return check(loadfile(input, ctx.mode)) end end @@ -624,7 +628,7 @@ end local function bcsave(ctx, input, output) local f = readfile(ctx, input) - local s = string.dump(f, ctx.strip) + local s = string.dump(f, ctx.mode) local t = ctx.type if not t then t = detecttype(output) @@ -647,9 +651,11 @@ local function docmd(...) local n = 1 local list = false local ctx = { - strip = true, arch = jit.arch, os = jit.os:lower(), - type = false, modname = false, + mode = "bt", arch = jit.arch, os = jit.os:lower(), + type = false, modname = false, string = false, } + local strip = "s" + local gc64 = "" while n <= #arg do local a = arg[n] if type(a) == "string" and a:sub(1, 1) == "-" and a ~= "-" then @@ -660,14 +666,18 @@ local function docmd(...) if opt == "l" then list = true elseif opt == "s" then - ctx.strip = true + strip = "s" elseif opt == "g" then - ctx.strip = false + strip = "" + elseif opt == "W" or opt == "X" then + gc64 = opt + elseif opt == "d" then + ctx.mode = ctx.mode .. opt else if arg[n] == nil or m ~= #a then usage() end if opt == "e" then if n ~= 1 then usage() end - arg[1] = check(loadstring(arg[1])) + ctx.string = true elseif opt == "n" then ctx.modname = checkmodname(tremove(arg, n)) elseif opt == "t" then @@ -687,6 +697,7 @@ local function docmd(...) n = n + 1 end end + ctx.mode = ctx.mode .. strip .. gc64 if list then if #arg == 0 or #arg > 2 then usage() end bclist(ctx, arg[1], arg[2] or "-") diff --git a/libs/LuaJIT/android/armeabi-v7a/jit/vmdef.lua b/libs/LuaJIT/android/armeabi-v7a/jit/vmdef.lua index ef31b783..75bc8b87 100644 --- a/libs/LuaJIT/android/armeabi-v7a/jit/vmdef.lua +++ b/libs/LuaJIT/android/armeabi-v7a/jit/vmdef.lua @@ -1,6 +1,6 @@ -- This is a generated file. DO NOT EDIT! -assert(require("jit").version == "LuaJIT 2.1.1700008891", "LuaJIT core/library version mismatch") +assert(require("jit").version == "LuaJIT 2.1.1710088188", "LuaJIT core/library version mismatch") return { diff --git a/libs/LuaJIT/android/armeabi-v7a/libluajit.a b/libs/LuaJIT/android/armeabi-v7a/libluajit.a index bcdbf892..f59778d4 100644 Binary files a/libs/LuaJIT/android/armeabi-v7a/libluajit.a and b/libs/LuaJIT/android/armeabi-v7a/libluajit.a differ diff --git a/libs/LuaJIT/android/armeabi-v7a/libluajit.so b/libs/LuaJIT/android/armeabi-v7a/libluajit.so index de87a204..a1a1b40f 100644 Binary files a/libs/LuaJIT/android/armeabi-v7a/libluajit.so and b/libs/LuaJIT/android/armeabi-v7a/libluajit.so differ diff --git a/libs/LuaJIT/android/armeabi-v7a/luajit.h b/libs/LuaJIT/android/armeabi-v7a/luajit.h index 94814d91..39794a55 100644 --- a/libs/LuaJIT/android/armeabi-v7a/luajit.h +++ b/libs/LuaJIT/android/armeabi-v7a/luajit.h @@ -30,9 +30,9 @@ #include "lua.h" -#define LUAJIT_VERSION "LuaJIT 2.1.1700008891" +#define LUAJIT_VERSION "LuaJIT 2.1.1710088188" #define LUAJIT_VERSION_NUM 20199 /* Deprecated. */ -#define LUAJIT_VERSION_SYM luaJIT_version_2_1_1700008891 +#define LUAJIT_VERSION_SYM luaJIT_version_2_1_1710088188 #define LUAJIT_COPYRIGHT "Copyright (C) 2005-2023 Mike Pall" #define LUAJIT_URL "https://luajit.org/" diff --git a/libs/LuaJIT/android/x86/jit/bcsave.lua b/libs/LuaJIT/android/x86/jit/bcsave.lua index 390d297c..131bf39b 100644 --- a/libs/LuaJIT/android/x86/jit/bcsave.lua +++ b/libs/LuaJIT/android/x86/jit/bcsave.lua @@ -29,6 +29,9 @@ Save LuaJIT bytecode: luajit -b[options] input output -l Only list bytecode. -s Strip debug info (default). -g Keep debug info. + -W Generate 32 bit (non-GC64) bytecode. + -X Generate 64 bit (GC64) bytecode. + -d Generate bytecode in deterministic manner. -n name Set module name (default: auto-detect from input name). -t type Set output file type (default: auto-detect from output name). -a arch Override architecture for object files (default: native). @@ -51,8 +54,9 @@ local function check(ok, ...) end local function readfile(ctx, input) - if type(input) == "function" then return input end - if ctx.filename then + if ctx.string then + return check(loadstring(input, nil, ctx.mode)) + elseif ctx.filename then local data if input == "-" then data = io.stdin:read("*a") @@ -61,10 +65,10 @@ local function readfile(ctx, input) data = assert(fp:read("*a")) assert(fp:close()) end - return check(load(data, ctx.filename)) + return check(load(data, ctx.filename, ctx.mode)) else if input == "-" then input = nil end - return check(loadfile(input)) + return check(loadfile(input, ctx.mode)) end end @@ -624,7 +628,7 @@ end local function bcsave(ctx, input, output) local f = readfile(ctx, input) - local s = string.dump(f, ctx.strip) + local s = string.dump(f, ctx.mode) local t = ctx.type if not t then t = detecttype(output) @@ -647,9 +651,11 @@ local function docmd(...) local n = 1 local list = false local ctx = { - strip = true, arch = jit.arch, os = jit.os:lower(), - type = false, modname = false, + mode = "bt", arch = jit.arch, os = jit.os:lower(), + type = false, modname = false, string = false, } + local strip = "s" + local gc64 = "" while n <= #arg do local a = arg[n] if type(a) == "string" and a:sub(1, 1) == "-" and a ~= "-" then @@ -660,14 +666,18 @@ local function docmd(...) if opt == "l" then list = true elseif opt == "s" then - ctx.strip = true + strip = "s" elseif opt == "g" then - ctx.strip = false + strip = "" + elseif opt == "W" or opt == "X" then + gc64 = opt + elseif opt == "d" then + ctx.mode = ctx.mode .. opt else if arg[n] == nil or m ~= #a then usage() end if opt == "e" then if n ~= 1 then usage() end - arg[1] = check(loadstring(arg[1])) + ctx.string = true elseif opt == "n" then ctx.modname = checkmodname(tremove(arg, n)) elseif opt == "t" then @@ -687,6 +697,7 @@ local function docmd(...) n = n + 1 end end + ctx.mode = ctx.mode .. strip .. gc64 if list then if #arg == 0 or #arg > 2 then usage() end bclist(ctx, arg[1], arg[2] or "-") diff --git a/libs/LuaJIT/android/x86/jit/vmdef.lua b/libs/LuaJIT/android/x86/jit/vmdef.lua index ef31b783..75bc8b87 100644 --- a/libs/LuaJIT/android/x86/jit/vmdef.lua +++ b/libs/LuaJIT/android/x86/jit/vmdef.lua @@ -1,6 +1,6 @@ -- This is a generated file. DO NOT EDIT! -assert(require("jit").version == "LuaJIT 2.1.1700008891", "LuaJIT core/library version mismatch") +assert(require("jit").version == "LuaJIT 2.1.1710088188", "LuaJIT core/library version mismatch") return { diff --git a/libs/LuaJIT/android/x86/libluajit.a b/libs/LuaJIT/android/x86/libluajit.a index 9c3acd27..1da53f4c 100644 Binary files a/libs/LuaJIT/android/x86/libluajit.a and b/libs/LuaJIT/android/x86/libluajit.a differ diff --git a/libs/LuaJIT/android/x86/libluajit.so b/libs/LuaJIT/android/x86/libluajit.so index 6ef78dda..999a1492 100644 Binary files a/libs/LuaJIT/android/x86/libluajit.so and b/libs/LuaJIT/android/x86/libluajit.so differ diff --git a/libs/LuaJIT/android/x86/luajit.h b/libs/LuaJIT/android/x86/luajit.h index 94814d91..39794a55 100644 --- a/libs/LuaJIT/android/x86/luajit.h +++ b/libs/LuaJIT/android/x86/luajit.h @@ -30,9 +30,9 @@ #include "lua.h" -#define LUAJIT_VERSION "LuaJIT 2.1.1700008891" +#define LUAJIT_VERSION "LuaJIT 2.1.1710088188" #define LUAJIT_VERSION_NUM 20199 /* Deprecated. */ -#define LUAJIT_VERSION_SYM luaJIT_version_2_1_1700008891 +#define LUAJIT_VERSION_SYM luaJIT_version_2_1_1710088188 #define LUAJIT_COPYRIGHT "Copyright (C) 2005-2023 Mike Pall" #define LUAJIT_URL "https://luajit.org/" diff --git a/libs/LuaJIT/android/x86_64/jit/bcsave.lua b/libs/LuaJIT/android/x86_64/jit/bcsave.lua index 390d297c..131bf39b 100644 --- a/libs/LuaJIT/android/x86_64/jit/bcsave.lua +++ b/libs/LuaJIT/android/x86_64/jit/bcsave.lua @@ -29,6 +29,9 @@ Save LuaJIT bytecode: luajit -b[options] input output -l Only list bytecode. -s Strip debug info (default). -g Keep debug info. + -W Generate 32 bit (non-GC64) bytecode. + -X Generate 64 bit (GC64) bytecode. + -d Generate bytecode in deterministic manner. -n name Set module name (default: auto-detect from input name). -t type Set output file type (default: auto-detect from output name). -a arch Override architecture for object files (default: native). @@ -51,8 +54,9 @@ local function check(ok, ...) end local function readfile(ctx, input) - if type(input) == "function" then return input end - if ctx.filename then + if ctx.string then + return check(loadstring(input, nil, ctx.mode)) + elseif ctx.filename then local data if input == "-" then data = io.stdin:read("*a") @@ -61,10 +65,10 @@ local function readfile(ctx, input) data = assert(fp:read("*a")) assert(fp:close()) end - return check(load(data, ctx.filename)) + return check(load(data, ctx.filename, ctx.mode)) else if input == "-" then input = nil end - return check(loadfile(input)) + return check(loadfile(input, ctx.mode)) end end @@ -624,7 +628,7 @@ end local function bcsave(ctx, input, output) local f = readfile(ctx, input) - local s = string.dump(f, ctx.strip) + local s = string.dump(f, ctx.mode) local t = ctx.type if not t then t = detecttype(output) @@ -647,9 +651,11 @@ local function docmd(...) local n = 1 local list = false local ctx = { - strip = true, arch = jit.arch, os = jit.os:lower(), - type = false, modname = false, + mode = "bt", arch = jit.arch, os = jit.os:lower(), + type = false, modname = false, string = false, } + local strip = "s" + local gc64 = "" while n <= #arg do local a = arg[n] if type(a) == "string" and a:sub(1, 1) == "-" and a ~= "-" then @@ -660,14 +666,18 @@ local function docmd(...) if opt == "l" then list = true elseif opt == "s" then - ctx.strip = true + strip = "s" elseif opt == "g" then - ctx.strip = false + strip = "" + elseif opt == "W" or opt == "X" then + gc64 = opt + elseif opt == "d" then + ctx.mode = ctx.mode .. opt else if arg[n] == nil or m ~= #a then usage() end if opt == "e" then if n ~= 1 then usage() end - arg[1] = check(loadstring(arg[1])) + ctx.string = true elseif opt == "n" then ctx.modname = checkmodname(tremove(arg, n)) elseif opt == "t" then @@ -687,6 +697,7 @@ local function docmd(...) n = n + 1 end end + ctx.mode = ctx.mode .. strip .. gc64 if list then if #arg == 0 or #arg > 2 then usage() end bclist(ctx, arg[1], arg[2] or "-") diff --git a/libs/LuaJIT/android/x86_64/jit/vmdef.lua b/libs/LuaJIT/android/x86_64/jit/vmdef.lua index ef31b783..75bc8b87 100644 --- a/libs/LuaJIT/android/x86_64/jit/vmdef.lua +++ b/libs/LuaJIT/android/x86_64/jit/vmdef.lua @@ -1,6 +1,6 @@ -- This is a generated file. DO NOT EDIT! -assert(require("jit").version == "LuaJIT 2.1.1700008891", "LuaJIT core/library version mismatch") +assert(require("jit").version == "LuaJIT 2.1.1710088188", "LuaJIT core/library version mismatch") return { diff --git a/libs/LuaJIT/android/x86_64/libluajit.a b/libs/LuaJIT/android/x86_64/libluajit.a index 307b969f..12918830 100644 Binary files a/libs/LuaJIT/android/x86_64/libluajit.a and b/libs/LuaJIT/android/x86_64/libluajit.a differ diff --git a/libs/LuaJIT/android/x86_64/libluajit.so b/libs/LuaJIT/android/x86_64/libluajit.so index 807c2efb..5b82b749 100644 Binary files a/libs/LuaJIT/android/x86_64/libluajit.so and b/libs/LuaJIT/android/x86_64/libluajit.so differ diff --git a/libs/LuaJIT/android/x86_64/luajit.h b/libs/LuaJIT/android/x86_64/luajit.h index 94814d91..39794a55 100644 --- a/libs/LuaJIT/android/x86_64/luajit.h +++ b/libs/LuaJIT/android/x86_64/luajit.h @@ -30,9 +30,9 @@ #include "lua.h" -#define LUAJIT_VERSION "LuaJIT 2.1.1700008891" +#define LUAJIT_VERSION "LuaJIT 2.1.1710088188" #define LUAJIT_VERSION_NUM 20199 /* Deprecated. */ -#define LUAJIT_VERSION_SYM luaJIT_version_2_1_1700008891 +#define LUAJIT_VERSION_SYM luaJIT_version_2_1_1710088188 #define LUAJIT_COPYRIGHT "Copyright (C) 2005-2023 Mike Pall" #define LUAJIT_URL "https://luajit.org/" diff --git a/libs/LuaJIT/doc/extensions.html b/libs/LuaJIT/doc/extensions.html index a4f20841..c1c9a808 100644 --- a/libs/LuaJIT/doc/extensions.html +++ b/libs/LuaJIT/doc/extensions.html @@ -160,13 +160,33 @@ passes any arguments after the error function to the function which is called in a protected context.

-

loadfile() etc. handle UTF-8 source code

+

load*() 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.

+

load*() add a mode parameter

+

+As an extension from Lua 5.2, the functions loadstring(), +loadfile() and (new) load() add an optional +mode parameter. +

+

+The default mode string is "bt", which allows loading of both +source code and bytecode. Use "t" to allow only source code +or "b" to allow only bytecode to be loaded. +

+

+By default, the load* functions generate the native bytecode format. +For cross-compilation purposes, add W to the mode string to +force the 32 bit format and X to force the 64 bit format. +Add both to force the opposite format. Note that non-native bytecode +generated by load* cannot be run, but can still be passed +to string.dump. +

+

tostring() etc. canonicalize NaN and ±Inf

All number-to-string conversions consistently convert non-finite numbers @@ -186,26 +206,33 @@ works independently of the current locale and it supports hex floating-point numbers (e.g. 0x1.5p-3).

-

string.dump(f [,strip]) generates portable bytecode

+

string.dump(f [,mode]) 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 +true or to a string which contains the character s, +'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. +that LuaJIT supports. However, the bytecode compatibility versions must +match. Bytecode only stays compatible within a major+minor version +(x.y.aaa → x.y.bbb), except for development branches. Foreign bytecode +(e.g. from Lua 5.1) is incompatible and cannot be loaded.

Note: LJ_GC64 mode requires a different frame layout, which implies -a different, incompatible bytecode format for all 64 bit ports. This may be -rectified in the future. +a different, incompatible bytecode format between 32 bit and 64 bit ports. +This may be rectified in the future. In the meantime, use the W +and X modes of the load* functions +for cross-compilation purposes. +

+

+Due to VM hardening, bytecode is not deterministic. Add d to the +mode string to dump it in a deterministic manner: identical source code +always gives a byte-for-byte identical bytecode dump. This feature is +mainly useful for reproducible builds.

table.new(narray, nhash) allocates a pre-sized table

@@ -286,7 +313,7 @@ enabled:

diff --git a/libs/LuaJIT/doc/running.html b/libs/LuaJIT/doc/running.html index 9dd2b411..142b810f 100644 --- a/libs/LuaJIT/doc/running.html +++ b/libs/LuaJIT/doc/running.html @@ -106,6 +106,9 @@ are accepted:

  • -l — Only list bytecode.
  • -s — Strip debug info (this is the default).
  • -g — Keep debug info.
  • +
  • -W — Generate 32 bit (non-GC64) bytecode.
  • +
  • -X — Generate 64 bit (GC64) bytecode.
  • +
  • -d — Generate bytecode in deterministic manner.
  • -n name — Set module name (default: auto-detect from input name)
  • -t type — Set output file type (default: auto-detect from output name).
  • -a arch — Override architecture for object files (default: native).
  • diff --git a/libs/LuaJIT/dynasm/dasm_x86.lua b/libs/LuaJIT/dynasm/dasm_x86.lua index 787163c0..7c789f82 100644 --- a/libs/LuaJIT/dynasm/dasm_x86.lua +++ b/libs/LuaJIT/dynasm/dasm_x86.lua @@ -627,7 +627,11 @@ local function wputmrmsib(t, imark, s, vsreg, psz, sk) werror("NYI: rip-relative displacement followed by immediate") end -- The previous byte in the action buffer cannot be 0xe9 or 0x80-0x8f. - wputlabel("REL_", disp[1], 2) + if disp[2] == "iPJ" then + waction("REL_A", disp[1]) + else + wputlabel("REL_", disp[1], 2) + end else wputdarg(disp) end @@ -744,9 +748,9 @@ local function dispexpr(expr) return imm*map_opsizenum[ops] end local mode, iexpr = immexpr(dispt) - if mode == "iJ" then + if mode == "iJ" or mode == "iPJ" then if c == "-" then werror("cannot invert label reference") end - return { iexpr } + return { iexpr, mode } end return expr -- Need to return original signed expression. end @@ -1147,6 +1151,8 @@ local map_op = { rep_0 = "F3", repe_0 = "F3", repz_0 = "F3", + endbr32_0 = "F30F1EFB", + endbr64_0 = "F30F1EFA", -- F4: *hlt cmc_0 = "F5", -- F6: test... mb,i; div... mb diff --git a/libs/LuaJIT/dynasm/dynasm.lua b/libs/LuaJIT/dynasm/dynasm.lua index 5be75f7f..0d15a872 100644 --- a/libs/LuaJIT/dynasm/dynasm.lua +++ b/libs/LuaJIT/dynasm/dynasm.lua @@ -75,7 +75,7 @@ local function wline(line, needindent) g_synclineno = g_synclineno + 1 end --- Write assembler line as a comment, if requestd. +-- Write assembler line as a comment, if requested. local function wcomment(aline) if g_opt.comment then wline(g_opt.comment..aline..g_opt.endcomment, true) diff --git a/libs/LuaJIT/src/host/genlibbc.lua b/libs/LuaJIT/src/host/genlibbc.lua index 3621c3f5..e697fceb 100644 --- a/libs/LuaJIT/src/host/genlibbc.lua +++ b/libs/LuaJIT/src/host/genlibbc.lua @@ -138,65 +138,73 @@ local function fixup_dump(dump, fixup) return { dump = ndump, startbc = startbc, sizebc = sizebc } end -local function find_defs(src) +local function find_defs(src, mode) local defs = {} for name, code in string.gmatch(src, "LJLIB_LUA%(([^)]*)%)%s*/%*(.-)%*/") do - local env = {} local tcode, fixup = transform_lua(code) - local func = assert(load(tcode, "", nil, env))() - defs[name] = fixup_dump(string.dump(func, true), fixup) + local func = assert(load(tcode, "", mode)) + defs[name] = fixup_dump(string.dump(func, mode), fixup) defs[#defs+1] = name end return defs end -local function gen_header(defs) +local function gen_header(defs32, defs64) local t = {} local function w(x) t[#t+1] = x end w("/* This is a generated file. DO NOT EDIT! */\n\n") w("static const int libbc_endian = ") w(isbe and 1 or 0) w(";\n\n") - local s, sb = "", "" - for i,name in ipairs(defs) do - local d = defs[name] - s = s .. d.dump - sb = sb .. string.char(i) .. ("\0"):rep(d.startbc - 1) - .. (isbe and "\0\0\0\255" or "\255\0\0\0"):rep(d.sizebc) - .. ("\0"):rep(#d.dump - d.startbc - d.sizebc*4) - end - w("static const uint8_t libbc_code[] = {\n") - local n = 0 - for i=1,#s do - local x = string.byte(s, i) - local xb = string.byte(sb, i) - if xb == 255 then - local name = BCN[x] - local m = #name + 4 - if n + m > 78 then n = 0; w("\n") end - n = n + m - w("BC_"); w(name) - else - local m = x < 10 and 2 or (x < 100 and 3 or 4) - if xb == 0 then - if n + m > 78 then n = 0; w("\n") end - else - local name = defs[xb]:gsub("_", ".") - if n ~= 0 then w("\n") end - w("/* "); w(name); w(" */ ") - n = #name + 7 - end - n = n + m - w(x) + for j,defs in ipairs{defs64, defs32} do + local s, sb = "", "" + for i,name in ipairs(defs) do + local d = defs[name] + s = s .. d.dump + sb = sb .. string.char(i) .. ("\0"):rep(d.startbc - 1) + .. (isbe and "\0\0\0\255" or "\255\0\0\0"):rep(d.sizebc) + .. ("\0"):rep(#d.dump - d.startbc - d.sizebc*4) + end + if j == 1 then + w("static const uint8_t libbc_code[] = {\n#if LJ_FR2\n") + else + w("\n#else\n") + end + local n = 0 + for i=1,#s do + local x = string.byte(s, i) + local xb = string.byte(sb, i) + if xb == 255 then + local name = BCN[x] + local m = #name + 4 + if n + m > 78 then n = 0; w("\n") end + n = n + m + w("BC_"); w(name) + else + local m = x < 10 and 2 or (x < 100 and 3 or 4) + if xb == 0 then + if n + m > 78 then n = 0; w("\n") end + else + local name = defs[xb]:gsub("_", ".") + if n ~= 0 then w("\n") end + w("/* "); w(name); w(" */ ") + n = #name + 7 + end + n = n + m + w(x) + end + w(",") end - w(",") end - w("\n0\n};\n\n") + w("\n#endif\n0\n};\n\n") w("static const struct { const char *name; int ofs; } libbc_map[] = {\n") - local m = 0 - for _,name in ipairs(defs) do - w('{"'); w(name); w('",'); w(m) w('},\n') - m = m + #defs[name].dump + local m32, m64 = 0, 0 + for i,name in ipairs(defs32) do + assert(name == defs64[i]) + w('{"'); w(name); w('",'); w(m32) w('},\n') + m32 = m32 + #defs32[name].dump + m64 = m64 + #defs64[name].dump + assert(m32 == m64) end - w("{NULL,"); w(m); w("}\n};\n\n") + w("{NULL,"); w(m32); w("}\n};\n\n") return table.concat(t) end @@ -219,7 +227,8 @@ end local outfile = parse_arg(arg) local src = read_files(arg) -local defs = find_defs(src) -local hdr = gen_header(defs) +local defs32 = find_defs(src, "Wdts") +local defs64 = find_defs(src, "Xdts") +local hdr = gen_header(defs32, defs64) write_file(outfile, hdr) diff --git a/libs/LuaJIT/src/host/genversion.lua b/libs/LuaJIT/src/host/genversion.lua index 28f7206c..f0925160 100644 --- a/libs/LuaJIT/src/host/genversion.lua +++ b/libs/LuaJIT/src/host/genversion.lua @@ -29,7 +29,7 @@ local function file_write_mod(file, data) assert(fp:close()) end -local text = file_read(FILE_ROLLING_H) +local text = file_read(FILE_ROLLING_H):gsub("#error.-\n", "") local relver = file_read(FILE_RELVER_TXT):match("(%d+)") if relver then diff --git a/libs/LuaJIT/src/jit/bcsave.lua b/libs/LuaJIT/src/jit/bcsave.lua index 390d297c..131bf39b 100644 --- a/libs/LuaJIT/src/jit/bcsave.lua +++ b/libs/LuaJIT/src/jit/bcsave.lua @@ -29,6 +29,9 @@ Save LuaJIT bytecode: luajit -b[options] input output -l Only list bytecode. -s Strip debug info (default). -g Keep debug info. + -W Generate 32 bit (non-GC64) bytecode. + -X Generate 64 bit (GC64) bytecode. + -d Generate bytecode in deterministic manner. -n name Set module name (default: auto-detect from input name). -t type Set output file type (default: auto-detect from output name). -a arch Override architecture for object files (default: native). @@ -51,8 +54,9 @@ local function check(ok, ...) end local function readfile(ctx, input) - if type(input) == "function" then return input end - if ctx.filename then + if ctx.string then + return check(loadstring(input, nil, ctx.mode)) + elseif ctx.filename then local data if input == "-" then data = io.stdin:read("*a") @@ -61,10 +65,10 @@ local function readfile(ctx, input) data = assert(fp:read("*a")) assert(fp:close()) end - return check(load(data, ctx.filename)) + return check(load(data, ctx.filename, ctx.mode)) else if input == "-" then input = nil end - return check(loadfile(input)) + return check(loadfile(input, ctx.mode)) end end @@ -624,7 +628,7 @@ end local function bcsave(ctx, input, output) local f = readfile(ctx, input) - local s = string.dump(f, ctx.strip) + local s = string.dump(f, ctx.mode) local t = ctx.type if not t then t = detecttype(output) @@ -647,9 +651,11 @@ local function docmd(...) local n = 1 local list = false local ctx = { - strip = true, arch = jit.arch, os = jit.os:lower(), - type = false, modname = false, + mode = "bt", arch = jit.arch, os = jit.os:lower(), + type = false, modname = false, string = false, } + local strip = "s" + local gc64 = "" while n <= #arg do local a = arg[n] if type(a) == "string" and a:sub(1, 1) == "-" and a ~= "-" then @@ -660,14 +666,18 @@ local function docmd(...) if opt == "l" then list = true elseif opt == "s" then - ctx.strip = true + strip = "s" elseif opt == "g" then - ctx.strip = false + strip = "" + elseif opt == "W" or opt == "X" then + gc64 = opt + elseif opt == "d" then + ctx.mode = ctx.mode .. opt else if arg[n] == nil or m ~= #a then usage() end if opt == "e" then if n ~= 1 then usage() end - arg[1] = check(loadstring(arg[1])) + ctx.string = true elseif opt == "n" then ctx.modname = checkmodname(tremove(arg, n)) elseif opt == "t" then @@ -687,6 +697,7 @@ local function docmd(...) n = n + 1 end end + ctx.mode = ctx.mode .. strip .. gc64 if list then if #arg == 0 or #arg > 2 then usage() end bclist(ctx, arg[1], arg[2] or "-") diff --git a/libs/LuaJIT/src/lib_base.c b/libs/LuaJIT/src/lib_base.c index 4e6f8a30..d644b4f2 100644 --- a/libs/LuaJIT/src/lib_base.c +++ b/libs/LuaJIT/src/lib_base.c @@ -360,7 +360,11 @@ LJLIB_ASM_(xpcall) LJLIB_REC(.) static int load_aux(lua_State *L, int status, int envarg) { if (status == LUA_OK) { - if (tvistab(L->base+envarg-1)) { + /* + ** Set environment table for top-level function. + ** Don't do this for non-native bytecode, which returns a prototype. + */ + if (tvistab(L->base+envarg-1) && tvisfunc(L->top-1)) { GCfunc *fn = funcV(L->top-1); GCtab *t = tabV(L->base+envarg-1); setgcref(fn->c.env, obj2gco(t)); diff --git a/libs/LuaJIT/src/lib_jit.c b/libs/LuaJIT/src/lib_jit.c index c0294927..b83c865a 100644 --- a/libs/LuaJIT/src/lib_jit.c +++ b/libs/LuaJIT/src/lib_jit.c @@ -161,24 +161,6 @@ LJLIB_PUSH(top-2) LJLIB_SET(version) /* -- Reflection API for Lua functions ------------------------------------ */ -/* Return prototype of first argument (Lua function or prototype object) */ -static GCproto *check_Lproto(lua_State *L, int nolua) -{ - TValue *o = L->base; - if (L->top > o) { - if (tvisproto(o)) { - return protoV(o); - } else if (tvisfunc(o)) { - if (isluafunc(funcV(o))) - return funcproto(funcV(o)); - else if (nolua) - return NULL; - } - } - lj_err_argt(L, 1, LUA_TFUNCTION); - return NULL; /* unreachable */ -} - static void setintfield(lua_State *L, GCtab *t, const char *name, int32_t val) { setintV(lj_tab_setstr(L, t, lj_str_newz(L, name)), val); @@ -187,7 +169,7 @@ static void setintfield(lua_State *L, GCtab *t, const char *name, int32_t val) /* local info = jit.util.funcinfo(func [,pc]) */ LJLIB_CF(jit_util_funcinfo) { - GCproto *pt = check_Lproto(L, 1); + GCproto *pt = lj_lib_checkLproto(L, 1, 1); if (pt) { BCPos pc = (BCPos)lj_lib_optint(L, 2, 0); GCtab *t; @@ -229,7 +211,7 @@ LJLIB_CF(jit_util_funcinfo) /* local ins, m = jit.util.funcbc(func, pc) */ LJLIB_CF(jit_util_funcbc) { - GCproto *pt = check_Lproto(L, 0); + GCproto *pt = lj_lib_checkLproto(L, 1, 0); BCPos pc = (BCPos)lj_lib_checkint(L, 2); if (pc < pt->sizebc) { BCIns ins = proto_bc(pt)[pc]; @@ -246,7 +228,7 @@ LJLIB_CF(jit_util_funcbc) /* local k = jit.util.funck(func, idx) */ LJLIB_CF(jit_util_funck) { - GCproto *pt = check_Lproto(L, 0); + GCproto *pt = lj_lib_checkLproto(L, 1, 0); ptrdiff_t idx = (ptrdiff_t)lj_lib_checkint(L, 2); if (idx >= 0) { if (idx < (ptrdiff_t)pt->sizekn) { @@ -266,7 +248,7 @@ LJLIB_CF(jit_util_funck) /* local name = jit.util.funcuvname(func, idx) */ LJLIB_CF(jit_util_funcuvname) { - GCproto *pt = check_Lproto(L, 0); + GCproto *pt = lj_lib_checkLproto(L, 1, 0); uint32_t idx = (uint32_t)lj_lib_checkint(L, 2); if (idx < pt->sizeuv) { setstrV(L, L->top-1, lj_str_newz(L, lj_debug_uvname(pt, idx))); diff --git a/libs/LuaJIT/src/lib_string.c b/libs/LuaJIT/src/lib_string.c index 29bcb8fe..255689ce 100644 --- a/libs/LuaJIT/src/lib_string.c +++ b/libs/LuaJIT/src/lib_string.c @@ -122,11 +122,25 @@ static int writer_buf(lua_State *L, const void *p, size_t size, void *sb) LJLIB_CF(string_dump) { - GCfunc *fn = lj_lib_checkfunc(L, 1); - int strip = L->base+1 < L->top && tvistruecond(L->base+1); - SBuf *sb = lj_buf_tmp_(L); /* Assumes lj_bcwrite() doesn't use tmpbuf. */ + GCproto *pt = lj_lib_checkLproto(L, 1, 1); + uint32_t flags = 0; + SBuf *sb; + TValue *o = L->base+1; + if (o < L->top) { + if (tvisstr(o)) { + const char *mode = strVdata(o); + char c; + while ((c = *mode++)) { + if (c == 's') flags |= BCDUMP_F_STRIP; + if (c == 'd') flags |= BCDUMP_F_DETERMINISTIC; + } + } else if (tvistruecond(o)) { + flags |= BCDUMP_F_STRIP; + } + } + sb = lj_buf_tmp_(L); /* Assumes lj_bcwrite() doesn't use tmpbuf. */ L->top = L->base+1; - if (!isluafunc(fn) || lj_bcwrite(L, funcproto(fn), writer_buf, sb, strip)) + if (!pt || lj_bcwrite(L, pt, writer_buf, sb, flags)) lj_err_caller(L, LJ_ERR_STRDUMP); setstrV(L, L->top-1, lj_buf_str(L, sb)); lj_gc_check(L); diff --git a/libs/LuaJIT/src/lj_api.c b/libs/LuaJIT/src/lj_api.c index d4048d79..1ad71678 100644 --- a/libs/LuaJIT/src/lj_api.c +++ b/libs/LuaJIT/src/lj_api.c @@ -1052,6 +1052,7 @@ LUA_API int lua_setmetatable(lua_State *L, int idx) /* Flush cache, since traces specialize to basemt. But not during __gc. */ if (lj_trace_flushall(L)) lj_err_caller(L, LJ_ERR_NOGCMM); + o = index2adr(L, idx); /* Stack may have been reallocated. */ if (tvisbool(o)) { /* NOBARRIER: basemt is a GC root. */ setgcref(basemt_it(g, LJ_TTRUE), obj2gco(mt)); diff --git a/libs/LuaJIT/src/lj_asm_arm.h b/libs/LuaJIT/src/lj_asm_arm.h index 348cd79f..bd5fbeb1 100644 --- a/libs/LuaJIT/src/lj_asm_arm.h +++ b/libs/LuaJIT/src/lj_asm_arm.h @@ -2042,11 +2042,12 @@ static void asm_stack_restore(ASMState *as, SnapShot *snap) SnapEntry *map = &as->T->snapmap[snap->mapofs]; SnapEntry *flinks = &as->T->snapmap[snap_nextofs(as->T, snap)-1]; MSize n, nent = snap->nent; + int32_t bias = 0; /* Store the value of all modified slots to the Lua stack. */ for (n = 0; n < nent; n++) { SnapEntry sn = map[n]; BCReg s = snap_slot(sn); - int32_t ofs = 8*((int32_t)s-1); + int32_t ofs = 8*((int32_t)s-1) - bias; IRRef ref = snap_ref(sn); IRIns *ir = IR(ref); if ((sn & SNAP_NORESTORE)) @@ -2065,6 +2066,12 @@ static void asm_stack_restore(ASMState *as, SnapShot *snap) emit_lso(as, ARMI_STR, tmp, RID_BASE, ofs+4); #else Reg src = ra_alloc1(as, ref, RSET_FPR); + if (LJ_UNLIKELY(ofs < -1020 || ofs > 1020)) { + int32_t adj = ofs & 0xffffff00; /* K12-friendly. */ + bias += adj; + ofs -= adj; + emit_addptr(as, RID_BASE, -adj); + } emit_vlso(as, ARMI_VSTR_D, src, RID_BASE, ofs); #endif } else { @@ -2093,6 +2100,7 @@ static void asm_stack_restore(ASMState *as, SnapShot *snap) } checkmclim(as); } + emit_addptr(as, RID_BASE, bias); lj_assertA(map + nent == flinks, "inconsistent frames in snapshot"); } diff --git a/libs/LuaJIT/src/lj_asm_mips.h b/libs/LuaJIT/src/lj_asm_mips.h index d4e40c91..5b83e34d 100644 --- a/libs/LuaJIT/src/lj_asm_mips.h +++ b/libs/LuaJIT/src/lj_asm_mips.h @@ -653,11 +653,11 @@ static void asm_conv(ASMState *as, IRIns *ir) rset_exclude(RSET_GPR, dest)); emit_fg(as, MIPSI_TRUNC_L_D, tmp, left); /* Delay slot. */ #if !LJ_TARGET_MIPSR6 - emit_branch(as, MIPSI_BC1T, 0, 0, l_end); - emit_fgh(as, MIPSI_C_OLT_D, 0, left, tmp); + emit_branch(as, MIPSI_BC1T, 0, 0, l_end); + emit_fgh(as, MIPSI_C_OLT_D, 0, left, tmp); #else - emit_branch(as, MIPSI_BC1NEZ, 0, (left&31), l_end); - emit_fgh(as, MIPSI_CMP_LT_D, left, left, tmp); + emit_branch(as, MIPSI_BC1NEZ, 0, (tmp&31), l_end); + emit_fgh(as, MIPSI_CMP_LT_D, tmp, left, tmp); #endif emit_lsptr(as, MIPSI_LDC1, (tmp & 31), (void *)&as->J->k64[LJ_K64_2P63], @@ -670,11 +670,11 @@ static void asm_conv(ASMState *as, IRIns *ir) rset_exclude(RSET_GPR, dest)); emit_fg(as, MIPSI_TRUNC_L_S, tmp, left); /* Delay slot. */ #if !LJ_TARGET_MIPSR6 - emit_branch(as, MIPSI_BC1T, 0, 0, l_end); - emit_fgh(as, MIPSI_C_OLT_S, 0, left, tmp); + emit_branch(as, MIPSI_BC1T, 0, 0, l_end); + emit_fgh(as, MIPSI_C_OLT_S, 0, left, tmp); #else - emit_branch(as, MIPSI_BC1NEZ, 0, (left&31), l_end); - emit_fgh(as, MIPSI_CMP_LT_S, left, left, tmp); + emit_branch(as, MIPSI_BC1NEZ, 0, (tmp&31), l_end); + emit_fgh(as, MIPSI_CMP_LT_S, tmp, left, tmp); #endif emit_lsptr(as, MIPSI_LWC1, (tmp & 31), (void *)&as->J->k32[LJ_K32_2P63], @@ -690,8 +690,8 @@ static void asm_conv(ASMState *as, IRIns *ir) MIPSIns mi = irt_is64(ir->t) ? (st == IRT_NUM ? MIPSI_TRUNC_L_D : MIPSI_TRUNC_L_S) : (st == IRT_NUM ? MIPSI_TRUNC_W_D : MIPSI_TRUNC_W_S); - emit_tg(as, irt_is64(ir->t) ? MIPSI_DMFC1 : MIPSI_MFC1, dest, left); - emit_fg(as, mi, left, left); + emit_tg(as, irt_is64(ir->t) ? MIPSI_DMFC1 : MIPSI_MFC1, dest, tmp); + emit_fg(as, mi, tmp, left); #endif } } diff --git a/libs/LuaJIT/src/lj_bcdump.h b/libs/LuaJIT/src/lj_bcdump.h index 6ba71e25..3e56e39c 100644 --- a/libs/LuaJIT/src/lj_bcdump.h +++ b/libs/LuaJIT/src/lj_bcdump.h @@ -46,6 +46,8 @@ #define BCDUMP_F_KNOWN (BCDUMP_F_FR2*2-1) +#define BCDUMP_F_DETERMINISTIC 0x80000000 + /* Type codes for the GC constants of a prototype. Plus length for strings. */ enum { BCDUMP_KGC_CHILD, BCDUMP_KGC_TAB, BCDUMP_KGC_I64, BCDUMP_KGC_U64, @@ -61,7 +63,7 @@ enum { /* -- Bytecode reader/writer ---------------------------------------------- */ LJ_FUNC int lj_bcwrite(lua_State *L, GCproto *pt, lua_Writer writer, - void *data, int strip); + void *data, uint32_t flags); LJ_FUNC GCproto *lj_bcread_proto(LexState *ls); LJ_FUNC GCproto *lj_bcread(LexState *ls); diff --git a/libs/LuaJIT/src/lj_bcread.c b/libs/LuaJIT/src/lj_bcread.c index c98c0d42..637ef067 100644 --- a/libs/LuaJIT/src/lj_bcread.c +++ b/libs/LuaJIT/src/lj_bcread.c @@ -281,8 +281,11 @@ static void bcread_knum(LexState *ls, GCproto *pt, MSize sizekn) static void bcread_bytecode(LexState *ls, GCproto *pt, MSize sizebc) { BCIns *bc = proto_bc(pt); - bc[0] = BCINS_AD((pt->flags & PROTO_VARARG) ? BC_FUNCV : BC_FUNCF, - pt->framesize, 0); + BCIns op; + if (ls->fr2 != LJ_FR2) op = BC_NOT; /* Mark non-native prototype. */ + else if ((pt->flags & PROTO_VARARG)) op = BC_FUNCV; + else op = BC_FUNCF; + bc[0] = BCINS_AD(op, pt->framesize, 0); bcread_block(ls, bc+1, (sizebc-1)*(MSize)sizeof(BCIns)); /* Swap bytecode instructions if the endianess differs. */ if (bcread_swap(ls)) { @@ -395,7 +398,7 @@ static int bcread_header(LexState *ls) bcread_byte(ls) != BCDUMP_VERSION) return 0; bcread_flags(ls) = flags = bcread_uleb128(ls); if ((flags & ~(BCDUMP_F_KNOWN)) != 0) return 0; - if ((flags & BCDUMP_F_FR2) != LJ_FR2*BCDUMP_F_FR2) return 0; + if ((flags & BCDUMP_F_FR2) != (uint32_t)ls->fr2*BCDUMP_F_FR2) return 0; if ((flags & BCDUMP_F_FFI)) { #if LJ_HASFFI lua_State *L = ls->L; diff --git a/libs/LuaJIT/src/lj_bcwrite.c b/libs/LuaJIT/src/lj_bcwrite.c index dd969413..ddfa46c5 100644 --- a/libs/LuaJIT/src/lj_bcwrite.c +++ b/libs/LuaJIT/src/lj_bcwrite.c @@ -27,7 +27,9 @@ typedef struct BCWriteCtx { GCproto *pt; /* Root prototype. */ lua_Writer wfunc; /* Writer callback. */ void *wdata; /* Writer callback data. */ - int strip; /* Strip debug info. */ + TValue **heap; /* Heap used for deterministic sorting. */ + uint32_t heapsz; /* Size of heap. */ + uint32_t flags; /* BCDUMP_F_* flags. */ int status; /* Status from writer callback. */ #ifdef LUA_USE_ASSERT global_State *g; @@ -76,6 +78,75 @@ static void bcwrite_ktabk(BCWriteCtx *ctx, cTValue *o, int narrow) ctx->sb.w = p; } +/* Compare two template table keys. */ +static LJ_AINLINE int bcwrite_ktabk_lt(TValue *a, TValue *b) +{ + uint32_t at = itype(a), bt = itype(b); + if (at != bt) { /* This also handles false and true keys. */ + return at < bt; + } else if (at == LJ_TSTR) { + return lj_str_cmp(strV(a), strV(b)) < 0; + } else { + return a->u64 < b->u64; /* This works for numbers and integers. */ + } +} + +/* Insert key into a sorted heap. */ +static void bcwrite_ktabk_heap_insert(TValue **heap, MSize idx, MSize end, + TValue *key) +{ + MSize child; + while ((child = idx * 2 + 1) < end) { + /* Find lower of the two children. */ + TValue *c0 = heap[child]; + if (child + 1 < end) { + TValue *c1 = heap[child + 1]; + if (bcwrite_ktabk_lt(c1, c0)) { + c0 = c1; + child++; + } + } + if (bcwrite_ktabk_lt(key, c0)) break; /* Key lower? Found our position. */ + heap[idx] = c0; /* Move lower child up. */ + idx = child; /* Descend. */ + } + heap[idx] = key; /* Insert key here. */ +} + +/* Resize heap, dropping content. */ +static void bcwrite_heap_resize(BCWriteCtx *ctx, uint32_t nsz) +{ + lua_State *L = sbufL(&ctx->sb); + if (ctx->heapsz) { + lj_mem_freevec(G(L), ctx->heap, ctx->heapsz, TValue *); + ctx->heapsz = 0; + } + if (nsz) { + ctx->heap = lj_mem_newvec(L, nsz, TValue *); + ctx->heapsz = nsz; + } +} + +/* Write hash part of template table in sorted order. */ +static void bcwrite_ktab_sorted_hash(BCWriteCtx *ctx, Node *node, MSize nhash) +{ + TValue **heap = ctx->heap; + MSize i = nhash; + for (;; node--) { /* Build heap. */ + if (!tvisnil(&node->key)) { + bcwrite_ktabk_heap_insert(heap, --i, nhash, &node->key); + if (i == 0) break; + } + } + do { /* Drain heap. */ + TValue *key = heap[0]; /* Output lowest key from top. */ + bcwrite_ktabk(ctx, key, 0); + bcwrite_ktabk(ctx, (TValue *)((char *)key - offsetof(Node, key)), 1); + key = heap[--nhash]; /* Remove last key. */ + bcwrite_ktabk_heap_insert(heap, 0, nhash, key); /* Re-insert. */ + } while (nhash); +} + /* Write a template table. */ static void bcwrite_ktab(BCWriteCtx *ctx, char *p, const GCtab *t) { @@ -92,7 +163,7 @@ static void bcwrite_ktab(BCWriteCtx *ctx, char *p, const GCtab *t) MSize i, hmask = t->hmask; Node *node = noderef(t->node); for (i = 0; i <= hmask; i++) - nhash += !tvisnil(&node[i].val); + nhash += !tvisnil(&node[i].key); } /* Write number of array slots and hash slots. */ p = lj_strfmt_wuleb128(p, narray); @@ -105,14 +176,20 @@ static void bcwrite_ktab(BCWriteCtx *ctx, char *p, const GCtab *t) bcwrite_ktabk(ctx, o, 1); } if (nhash) { /* Write hash entries. */ - MSize i = nhash; Node *node = noderef(t->node) + t->hmask; - for (;; node--) - if (!tvisnil(&node->val)) { - bcwrite_ktabk(ctx, &node->key, 0); - bcwrite_ktabk(ctx, &node->val, 1); - if (--i == 0) break; - } + if ((ctx->flags & BCDUMP_F_DETERMINISTIC) && nhash > 1) { + if (ctx->heapsz < nhash) + bcwrite_heap_resize(ctx, t->hmask + 1); + bcwrite_ktab_sorted_hash(ctx, node, nhash); + } else { + MSize i = nhash; + for (;; node--) + if (!tvisnil(&node->key)) { + bcwrite_ktabk(ctx, &node->key, 0); + bcwrite_ktabk(ctx, &node->val, 1); + if (--i == 0) break; + } + } } } @@ -269,7 +346,7 @@ static void bcwrite_proto(BCWriteCtx *ctx, GCproto *pt) p = lj_strfmt_wuleb128(p, pt->sizekgc); p = lj_strfmt_wuleb128(p, pt->sizekn); p = lj_strfmt_wuleb128(p, pt->sizebc-1); - if (!ctx->strip) { + if (!(ctx->flags & BCDUMP_F_STRIP)) { if (proto_lineinfo(pt)) sizedbg = pt->sizept - (MSize)((char *)proto_lineinfo(pt) - (char *)pt); p = lj_strfmt_wuleb128(p, sizedbg); @@ -317,11 +394,10 @@ static void bcwrite_header(BCWriteCtx *ctx) *p++ = BCDUMP_HEAD2; *p++ = BCDUMP_HEAD3; *p++ = BCDUMP_VERSION; - *p++ = (ctx->strip ? BCDUMP_F_STRIP : 0) + + *p++ = (ctx->flags & (BCDUMP_F_STRIP | BCDUMP_F_FR2)) + LJ_BE*BCDUMP_F_BE + - ((ctx->pt->flags & PROTO_FFI) ? BCDUMP_F_FFI : 0) + - LJ_FR2*BCDUMP_F_FR2; - if (!ctx->strip) { + ((ctx->pt->flags & PROTO_FFI) ? BCDUMP_F_FFI : 0); + if (!(ctx->flags & BCDUMP_F_STRIP)) { p = lj_strfmt_wuleb128(p, len); p = lj_buf_wmem(p, name, len); } @@ -352,14 +428,16 @@ static TValue *cpwriter(lua_State *L, lua_CFunction dummy, void *ud) /* Write bytecode for a prototype. */ int lj_bcwrite(lua_State *L, GCproto *pt, lua_Writer writer, void *data, - int strip) + uint32_t flags) { BCWriteCtx ctx; int status; ctx.pt = pt; ctx.wfunc = writer; ctx.wdata = data; - ctx.strip = strip; + ctx.heapsz = 0; + if ((bc_op(proto_bc(pt)[0]) != BC_NOT) == LJ_FR2) flags |= BCDUMP_F_FR2; + ctx.flags = flags; ctx.status = 0; #ifdef LUA_USE_ASSERT ctx.g = G(L); @@ -368,6 +446,7 @@ int lj_bcwrite(lua_State *L, GCproto *pt, lua_Writer writer, void *data, status = lj_vm_cpcall(L, NULL, &ctx, cpwriter); if (status == 0) status = ctx.status; lj_buf_free(G(sbufL(&ctx.sb)), &ctx.sb); + bcwrite_heap_resize(&ctx, 0); return status; } diff --git a/libs/LuaJIT/src/lj_debug.c b/libs/LuaJIT/src/lj_debug.c index fa189b6e..8d8b9eb5 100644 --- a/libs/LuaJIT/src/lj_debug.c +++ b/libs/LuaJIT/src/lj_debug.c @@ -64,6 +64,7 @@ static BCPos debug_framepc(lua_State *L, GCfunc *fn, cTValue *nextframe) if (cf == NULL || (char *)cframe_pc(cf) == (char *)cframe_L(cf)) return NO_BCPOS; ins = cframe_pc(cf); /* Only happens during error/hook handling. */ + if (!ins) return NO_BCPOS; } else { if (frame_islua(nextframe)) { ins = frame_pc(nextframe); diff --git a/libs/LuaJIT/src/lj_err.c b/libs/LuaJIT/src/lj_err.c index 7b11e4d0..414ef477 100644 --- a/libs/LuaJIT/src/lj_err.c +++ b/libs/LuaJIT/src/lj_err.c @@ -818,7 +818,14 @@ LJ_NOINLINE void lj_err_mem(lua_State *L) TValue *base = tvref(G(L)->jit_base); if (base) L->base = base; } - if (curr_funcisL(L)) L->top = curr_topL(L); + if (curr_funcisL(L)) { + L->top = curr_topL(L); + if (LJ_UNLIKELY(L->top > tvref(L->maxstack))) { + /* The current Lua frame violates the stack. Replace it with a dummy. */ + L->top = L->base; + setframe_gc(L->base - 1 - LJ_FR2, obj2gco(L), LJ_TTHREAD); + } + } setstrV(L, L->top++, lj_err_str(L, LJ_ERR_ERRMEM)); lj_err_throw(L, LUA_ERRMEM); } @@ -879,9 +886,11 @@ LJ_NOINLINE void LJ_FASTCALL lj_err_run(lua_State *L) { ptrdiff_t ef = (LJ_HASJIT && tvref(G(L)->jit_base)) ? 0 : finderrfunc(L); if (ef) { - TValue *errfunc = restorestack(L, ef); - TValue *top = L->top; + TValue *errfunc, *top; + lj_state_checkstack(L, LUA_MINSTACK * 2); /* Might raise new error. */ lj_trace_abort(G(L)); + errfunc = restorestack(L, ef); + top = L->top; if (!tvisfunc(errfunc) || L->status == LUA_ERRERR) { setstrV(L, top-1, lj_err_str(L, LJ_ERR_ERRERR)); lj_err_throw(L, LUA_ERRERR); @@ -896,7 +905,15 @@ LJ_NOINLINE void LJ_FASTCALL lj_err_run(lua_State *L) lj_err_throw(L, LUA_ERRRUN); } +/* Stack overflow error. */ +void LJ_FASTCALL lj_err_stkov(lua_State *L) +{ + lj_debug_addloc(L, err2msg(LJ_ERR_STKOV), L->base-1, NULL); + lj_err_run(L); +} + #if LJ_HASJIT +/* Rethrow error after doing a trace exit. */ LJ_NOINLINE void LJ_FASTCALL lj_err_trace(lua_State *L, int errcode) { if (errcode == LUA_ERRRUN) diff --git a/libs/LuaJIT/src/lj_err.h b/libs/LuaJIT/src/lj_err.h index 8768fefd..67686cb7 100644 --- a/libs/LuaJIT/src/lj_err.h +++ b/libs/LuaJIT/src/lj_err.h @@ -23,6 +23,7 @@ LJ_DATA const char *lj_err_allmsg; LJ_FUNC GCstr *lj_err_str(lua_State *L, ErrMsg em); LJ_FUNCA_NORET void LJ_FASTCALL lj_err_throw(lua_State *L, int errcode); LJ_FUNC_NORET void lj_err_mem(lua_State *L); +LJ_FUNC_NORET void LJ_FASTCALL lj_err_stkov(lua_State *L); LJ_FUNC_NORET void LJ_FASTCALL lj_err_run(lua_State *L); #if LJ_HASJIT LJ_FUNCA_NORET void LJ_FASTCALL lj_err_trace(lua_State *L, int errcode); diff --git a/libs/LuaJIT/src/lj_ffrecord.c b/libs/LuaJIT/src/lj_ffrecord.c index 1233e5f7..03d0e6ec 100644 --- a/libs/LuaJIT/src/lj_ffrecord.c +++ b/libs/LuaJIT/src/lj_ffrecord.c @@ -98,6 +98,14 @@ static ptrdiff_t results_wanted(jit_State *J) return -1; } +static TValue *rec_stop_stitch_cp(lua_State *L, lua_CFunction dummy, void *ud) +{ + jit_State *J = (jit_State *)ud; + lj_record_stop(J, LJ_TRLINK_STITCH, 0); + UNUSED(L); UNUSED(dummy); + return NULL; +} + /* Trace stitching: add continuation below frame to start a new trace. */ static void recff_stitch(jit_State *J) { @@ -108,10 +116,7 @@ static void recff_stitch(jit_State *J) TValue *nframe = base + 1 + LJ_FR2; const BCIns *pc = frame_pc(base-1); TValue *pframe = frame_prevl(base-1); - - /* Check for this now. Throwing in lj_record_stop messes up the stack. */ - if (J->cur.nsnap >= (MSize)J->param[JIT_P_maxsnap]) - lj_trace_err(J, LJ_TRERR_SNAPOV); + int errcode; /* Move func + args up in Lua stack and insert continuation. */ memmove(&base[1], &base[-1-LJ_FR2], sizeof(TValue)*nslot); @@ -136,13 +141,19 @@ static void recff_stitch(jit_State *J) J->baseslot += 2 + LJ_FR2; J->framedepth++; - lj_record_stop(J, LJ_TRLINK_STITCH, 0); + errcode = lj_vm_cpcall(L, NULL, J, rec_stop_stitch_cp); /* Undo Lua stack changes. */ memmove(&base[-1-LJ_FR2], &base[1], sizeof(TValue)*nslot); setframe_pc(base-1, pc); L->base -= 2 + LJ_FR2; L->top -= 2 + LJ_FR2; + + if (errcode) { + if (errcode == LUA_ERRRUN) + copyTV(L, L->top-1, L->top + (1 + LJ_FR2)); + lj_err_throw(L, errcode); /* Propagate errors. */ + } } /* Fallback handler for fast functions that are not recorded (yet). */ @@ -1204,6 +1215,12 @@ static void LJ_FASTCALL recff_buffer_method_set(jit_State *J, RecordFFData *rd) if (tref_isstr(tr)) { TRef trp = emitir(IRT(IR_STRREF, IRT_PGC), tr, lj_ir_kint(J, 0)); TRef len = emitir(IRTI(IR_FLOAD), tr, IRFL_STR_LEN); + IRIns *irp = IR(tref_ref(trp)); + /* trp must point into the anchored obj, even after folding. */ + if (irp->o == IR_STRREF) + tr = irp->op1; + else if (!tref_isk(tr)) + trp = emitir(IRT(IR_ADD, IRT_PGC), tr, lj_ir_kintpgc(J, sizeof(GCstr))); lj_ir_call(J, IRCALL_lj_bufx_set, trbuf, trp, len, tr); #if LJ_HASFFI } else if (tref_iscdata(tr)) { @@ -1444,6 +1461,15 @@ static void LJ_FASTCALL recff_table_new(jit_State *J, RecordFFData *rd) { TRef tra = lj_opt_narrow_toint(J, J->base[0]); TRef trh = lj_opt_narrow_toint(J, J->base[1]); + if (tref_isk(tra) && tref_isk(trh)) { + int32_t a = IR(tref_ref(tra))->i; + if (a < 0x7fff) { + uint32_t hbits = hsize2hbits(IR(tref_ref(trh))->i); + a = a > 0 ? a+1 : 0; + J->base[0] = emitir(IRTG(IR_TNEW, IRT_TAB), (uint32_t)a, hbits); + return; + } + } J->base[0] = lj_ir_call(J, IRCALL_lj_tab_new_ah, tra, trh); UNUSED(rd); } diff --git a/libs/LuaJIT/src/lj_gc.c b/libs/LuaJIT/src/lj_gc.c index c3a0c258..eebc751b 100644 --- a/libs/LuaJIT/src/lj_gc.c +++ b/libs/LuaJIT/src/lj_gc.c @@ -108,6 +108,9 @@ static void gc_mark_start(global_State *g) gc_markobj(g, tabref(mainthread(g)->env)); gc_marktv(g, &g->registrytv); gc_mark_gcroot(g); +#if LJ_HASFFI + if (ctype_ctsG(g)) gc_markobj(g, ctype_ctsG(g)->finalizer); +#endif g->gc.state = GCSpropagate; } diff --git a/libs/LuaJIT/src/lj_gdbjit.c b/libs/LuaJIT/src/lj_gdbjit.c index e8a66635..56094cf1 100644 --- a/libs/LuaJIT/src/lj_gdbjit.c +++ b/libs/LuaJIT/src/lj_gdbjit.c @@ -637,7 +637,7 @@ static void LJ_FASTCALL gdbjit_debugabbrev(GDBJITctx *ctx) DUV(DW_AT_low_pc); DUV(DW_FORM_addr); DUV(DW_AT_high_pc); DUV(DW_FORM_addr); DUV(DW_AT_stmt_list); DUV(DW_FORM_data4); - DB(0); DB(0); + DB(0); DB(0); DB(0); ctx->p = p; } diff --git a/libs/LuaJIT/src/lj_ir.h b/libs/LuaJIT/src/lj_ir.h index dbfba258..cc73a849 100644 --- a/libs/LuaJIT/src/lj_ir.h +++ b/libs/LuaJIT/src/lj_ir.h @@ -383,6 +383,7 @@ typedef struct IRType1 { uint8_t irt; } IRType1; #define irt_isu32(t) (irt_type(t) == IRT_U32) #define irt_isi64(t) (irt_type(t) == IRT_I64) #define irt_isu64(t) (irt_type(t) == IRT_U64) +#define irt_isp32(t) (irt_type(t) == IRT_P32) #define irt_isfp(t) (irt_isnum(t) || irt_isfloat(t)) #define irt_isinteger(t) (irt_typerange((t), IRT_I8, IRT_INT)) diff --git a/libs/LuaJIT/src/lj_lex.c b/libs/LuaJIT/src/lj_lex.c index 61b04c4b..bd81dc40 100644 --- a/libs/LuaJIT/src/lj_lex.c +++ b/libs/LuaJIT/src/lj_lex.c @@ -411,6 +411,7 @@ int lj_lex_setup(lua_State *L, LexState *ls) ls->linenumber = 1; ls->lastline = 1; ls->endmark = 0; + ls->fr2 = LJ_FR2; /* Generate native bytecode by default. */ lex_next(ls); /* Read-ahead first char. */ if (ls->c == 0xef && ls->p + 2 <= ls->pe && (uint8_t)ls->p[0] == 0xbb && (uint8_t)ls->p[1] == 0xbf) { /* Skip UTF-8 BOM (if buffered). */ diff --git a/libs/LuaJIT/src/lj_lex.h b/libs/LuaJIT/src/lj_lex.h index e46fbd89..2ef7fc77 100644 --- a/libs/LuaJIT/src/lj_lex.h +++ b/libs/LuaJIT/src/lj_lex.h @@ -74,6 +74,7 @@ typedef struct LexState { MSize sizebcstack; /* Size of bytecode stack. */ uint32_t level; /* Syntactical nesting level. */ int endmark; /* Trust bytecode end marker, even if not at EOF. */ + int fr2; /* Generate bytecode for LJ_FR2 mode. */ } LexState; LJ_FUNC int lj_lex_setup(lua_State *L, LexState *ls); diff --git a/libs/LuaJIT/src/lj_lib.c b/libs/LuaJIT/src/lj_lib.c index ebe0dc78..06ae4fcf 100644 --- a/libs/LuaJIT/src/lj_lib.c +++ b/libs/LuaJIT/src/lj_lib.c @@ -62,6 +62,7 @@ static const uint8_t *lib_read_lfunc(lua_State *L, const uint8_t *p, GCtab *tab) ls.pe = (const char *)~(uintptr_t)0; ls.c = -1; ls.level = (BCDUMP_F_STRIP|(LJ_BE*BCDUMP_F_BE)); + ls.fr2 = LJ_FR2; ls.chunkname = name; pt = lj_bcread_proto(&ls); pt->firstline = ~(BCLine)0; @@ -266,6 +267,23 @@ GCfunc *lj_lib_checkfunc(lua_State *L, int narg) return funcV(o); } +GCproto *lj_lib_checkLproto(lua_State *L, int narg, int nolua) +{ + TValue *o = L->base + narg-1; + if (L->top > o) { + if (tvisproto(o)) { + return protoV(o); + } else if (tvisfunc(o)) { + if (isluafunc(funcV(o))) + return funcproto(funcV(o)); + else if (nolua) + return NULL; + } + } + lj_err_argt(L, narg, LUA_TFUNCTION); + return NULL; /* unreachable */ +} + GCtab *lj_lib_checktab(lua_State *L, int narg) { TValue *o = L->base + narg-1; diff --git a/libs/LuaJIT/src/lj_lib.h b/libs/LuaJIT/src/lj_lib.h index 6c3a1c83..a48e3c98 100644 --- a/libs/LuaJIT/src/lj_lib.h +++ b/libs/LuaJIT/src/lj_lib.h @@ -42,6 +42,7 @@ LJ_FUNC lua_Number lj_lib_checknum(lua_State *L, int narg); LJ_FUNC int32_t lj_lib_checkint(lua_State *L, int narg); LJ_FUNC int32_t lj_lib_optint(lua_State *L, int narg, int32_t def); LJ_FUNC GCfunc *lj_lib_checkfunc(lua_State *L, int narg); +LJ_FUNC GCproto *lj_lib_checkLproto(lua_State *L, int narg, int nolua); LJ_FUNC GCtab *lj_lib_checktab(lua_State *L, int narg); LJ_FUNC GCtab *lj_lib_checktabornil(lua_State *L, int narg); LJ_FUNC int lj_lib_checkopt(lua_State *L, int narg, int def, const char *lst); diff --git a/libs/LuaJIT/src/lj_load.c b/libs/LuaJIT/src/lj_load.c index 07304487..152ef6da 100644 --- a/libs/LuaJIT/src/lj_load.c +++ b/libs/LuaJIT/src/lj_load.c @@ -34,14 +34,28 @@ static TValue *cpparser(lua_State *L, lua_CFunction dummy, void *ud) UNUSED(dummy); cframe_errfunc(L->cframe) = -1; /* Inherit error function. */ bc = lj_lex_setup(L, ls); - if (ls->mode && !strchr(ls->mode, bc ? 'b' : 't')) { - setstrV(L, L->top++, lj_err_str(L, LJ_ERR_XMODE)); - lj_err_throw(L, LUA_ERRSYNTAX); + if (ls->mode) { + int xmode = 1; + const char *mode = ls->mode; + char c; + while ((c = *mode++)) { + if (c == (bc ? 'b' : 't')) xmode = 0; + if (c == (LJ_FR2 ? 'W' : 'X')) ls->fr2 = !LJ_FR2; + } + if (xmode) { + setstrV(L, L->top++, lj_err_str(L, LJ_ERR_XMODE)); + lj_err_throw(L, LUA_ERRSYNTAX); + } } pt = bc ? lj_bcread(ls) : lj_parse(ls); - fn = lj_func_newL_empty(L, pt, tabref(L->env)); - /* Don't combine above/below into one statement. */ - setfuncV(L, L->top++, fn); + if (ls->fr2 == LJ_FR2) { + fn = lj_func_newL_empty(L, pt, tabref(L->env)); + /* Don't combine above/below into one statement. */ + setfuncV(L, L->top++, fn); + } else { + /* Non-native generation returns a dumpable, but non-runnable prototype. */ + setprotoV(L, L->top++, pt); + } return NULL; } @@ -159,9 +173,10 @@ LUALIB_API int luaL_loadstring(lua_State *L, const char *s) LUA_API int lua_dump(lua_State *L, lua_Writer writer, void *data) { cTValue *o = L->top-1; + uint32_t flags = LJ_FR2*BCDUMP_F_FR2; /* Default mode for legacy C API. */ lj_checkapi(L->top > L->base, "top slot empty"); if (tvisfunc(o) && isluafunc(funcV(o))) - return lj_bcwrite(L, funcproto(funcV(o)), writer, data, 0); + return lj_bcwrite(L, funcproto(funcV(o)), writer, data, flags); else return 1; } diff --git a/libs/LuaJIT/src/lj_opt_mem.c b/libs/LuaJIT/src/lj_opt_mem.c index 631ac9e4..29b33f29 100644 --- a/libs/LuaJIT/src/lj_opt_mem.c +++ b/libs/LuaJIT/src/lj_opt_mem.c @@ -217,25 +217,23 @@ static TRef fwd_ahload(jit_State *J, IRRef xref) } ref = store->prev; } - if (ir->o == IR_TNEW && !irt_isnil(fins->t)) - return 0; /* Type instability in loop-carried dependency. */ - if (irt_ispri(fins->t)) { - return TREF_PRI(irt_type(fins->t)); - } else if (irt_isnum(fins->t) || (LJ_DUALNUM && irt_isint(fins->t)) || - irt_isstr(fins->t)) { + /* Simplified here: let loop_unroll() figure out any type instability. */ + if (ir->o == IR_TNEW) { + return TREF_NIL; + } else { TValue keyv; cTValue *tv; IRIns *key = IR(xr->op2); if (key->o == IR_KSLOT) key = IR(key->op1); lj_ir_kvalue(J->L, &keyv, key); tv = lj_tab_get(J->L, ir_ktab(IR(ir->op1)), &keyv); - if (itype2irt(tv) != irt_type(fins->t)) - return 0; /* Type instability in loop-carried dependency. */ - if (irt_isnum(fins->t)) + if (tvispri(tv)) + return TREF_PRI(itype2irt(tv)); + else if (tvisnum(tv)) return lj_ir_knum_u64(J, tv->u64); - else if (LJ_DUALNUM && irt_isint(fins->t)) + else if (tvisint(tv)) return lj_ir_kint(J, intV(tv)); - else + else if (tvisgcv(tv)) return lj_ir_kstr(J, strV(tv)); } /* Othwerwise: don't intern as a constant. */ @@ -962,6 +960,8 @@ int lj_opt_fwd_wasnonnil(jit_State *J, IROpT loadop, IRRef xref) if (skref == xkref || !irref_isk(skref) || !irref_isk(xkref)) return 0; /* A nil store with same const key or var key MAY alias. */ /* Different const keys CANNOT alias. */ + } else if (irt_isp32(IR(skref)->t) != irt_isp32(IR(xkref)->t)) { + return 0; /* HREF and HREFK MAY alias. */ } /* Different key types CANNOT alias. */ } /* Other non-nil stores MAY alias. */ ref = store->prev; diff --git a/libs/LuaJIT/src/lj_parse.c b/libs/LuaJIT/src/lj_parse.c index a30921af..5a44f8db 100644 --- a/libs/LuaJIT/src/lj_parse.c +++ b/libs/LuaJIT/src/lj_parse.c @@ -667,19 +667,20 @@ static void bcemit_store(FuncState *fs, ExpDesc *var, ExpDesc *e) /* Emit method lookup expression. */ static void bcemit_method(FuncState *fs, ExpDesc *e, ExpDesc *key) { - BCReg idx, func, obj = expr_toanyreg(fs, e); + BCReg idx, func, fr2, obj = expr_toanyreg(fs, e); expr_free(fs, e); func = fs->freereg; - bcemit_AD(fs, BC_MOV, func+1+LJ_FR2, obj); /* Copy object to 1st argument. */ + fr2 = fs->ls->fr2; + bcemit_AD(fs, BC_MOV, func+1+fr2, obj); /* Copy object to 1st argument. */ lj_assertFS(expr_isstrk(key), "bad usage"); idx = const_str(fs, key); if (idx <= BCMAX_C) { - bcreg_reserve(fs, 2+LJ_FR2); + bcreg_reserve(fs, 2+fr2); bcemit_ABC(fs, BC_TGETS, func, obj, idx); } else { - bcreg_reserve(fs, 3+LJ_FR2); - bcemit_AD(fs, BC_KSTR, func+2+LJ_FR2, idx); - bcemit_ABC(fs, BC_TGETV, func, obj, func+2+LJ_FR2); + bcreg_reserve(fs, 3+fr2); + bcemit_AD(fs, BC_KSTR, func+2+fr2, idx); + bcemit_ABC(fs, BC_TGETV, func, obj, func+2+fr2); fs->freereg--; } e->u.s.info = func; @@ -1326,9 +1327,12 @@ static void fs_fixup_bc(FuncState *fs, GCproto *pt, BCIns *bc, MSize n) { BCInsLine *base = fs->bcbase; MSize i; + BCIns op; pt->sizebc = n; - bc[0] = BCINS_AD((fs->flags & PROTO_VARARG) ? BC_FUNCV : BC_FUNCF, - fs->framesize, 0); + if (fs->ls->fr2 != LJ_FR2) op = BC_NOT; /* Mark non-native prototype. */ + else if ((fs->flags & PROTO_VARARG)) op = BC_FUNCV; + else op = BC_FUNCF; + bc[0] = BCINS_AD(op, fs->framesize, 0); for (i = 1; i < n; i++) bc[i] = base[i].ins; } @@ -1936,11 +1940,11 @@ static void parse_args(LexState *ls, ExpDesc *e) lj_assertFS(e->k == VNONRELOC, "bad expr type %d", e->k); base = e->u.s.info; /* Base register for call. */ if (args.k == VCALL) { - ins = BCINS_ABC(BC_CALLM, base, 2, args.u.s.aux - base - 1 - LJ_FR2); + ins = BCINS_ABC(BC_CALLM, base, 2, args.u.s.aux - base - 1 - ls->fr2); } else { if (args.k != VVOID) expr_tonextreg(fs, &args); - ins = BCINS_ABC(BC_CALL, base, 2, fs->freereg - base - LJ_FR2); + ins = BCINS_ABC(BC_CALL, base, 2, fs->freereg - base - ls->fr2); } expr_init(e, VCALL, bcemit_INS(fs, ins)); e->u.s.aux = base; @@ -1980,7 +1984,7 @@ static void expr_primary(LexState *ls, ExpDesc *v) parse_args(ls, v); } else if (ls->tok == '(' || ls->tok == TK_string || ls->tok == '{') { expr_tonextreg(fs, v); - if (LJ_FR2) bcreg_reserve(fs, 1); + if (ls->fr2) bcreg_reserve(fs, 1); parse_args(ls, v); } else { break; @@ -2565,7 +2569,7 @@ static void parse_for_iter(LexState *ls, GCstr *indexname) line = ls->linenumber; assign_adjust(ls, 3, expr_list(ls, &e), &e); /* The iterator needs another 3 [4] slots (func [pc] | state ctl). */ - bcreg_bump(fs, 3+LJ_FR2); + bcreg_bump(fs, 3+ls->fr2); isnext = (nvars <= 5 && predict_next(ls, fs, exprpc)); var_add(ls, 3); /* Hidden control variables. */ lex_check(ls, TK_do); diff --git a/libs/LuaJIT/src/lj_record.c b/libs/LuaJIT/src/lj_record.c index b7af5896..48bbbb20 100644 --- a/libs/LuaJIT/src/lj_record.c +++ b/libs/LuaJIT/src/lj_record.c @@ -903,6 +903,7 @@ void lj_record_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults) { TValue *frame = J->L->base - 1; ptrdiff_t i; + BCReg baseadj = 0; for (i = 0; i < gotresults; i++) (void)getslot(J, rbase+i); /* Ensure all results have a reference. */ while (frame_ispcall(frame)) { /* Immediately resolve pcall() returns. */ @@ -911,6 +912,7 @@ void lj_record_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults) lj_trace_err(J, LJ_TRERR_NYIRETL); lj_assertJ(J->baseslot > 1+LJ_FR2, "bad baseslot for return"); gotresults++; + baseadj += cbase; rbase += cbase; J->baseslot -= (BCReg)cbase; J->base -= cbase; @@ -935,6 +937,7 @@ void lj_record_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults) if (--J->framedepth < 0) /* NYI: return of vararg func to lower frame. */ lj_trace_err(J, LJ_TRERR_NYIRETL); lj_assertJ(J->baseslot > 1+LJ_FR2, "bad baseslot for return"); + baseadj += cbase; rbase += cbase; J->baseslot -= (BCReg)cbase; J->base -= cbase; @@ -948,7 +951,7 @@ void lj_record_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults) if ((pt->flags & PROTO_NOJIT)) lj_trace_err(J, LJ_TRERR_CJITOFF); if (J->framedepth == 0 && J->pt && frame == J->L->base - 1) { - if (check_downrec_unroll(J, pt)) { + if (!J->cur.root && check_downrec_unroll(J, pt)) { J->maxslot = (BCReg)(rbase + gotresults); lj_snap_purge(J); lj_record_stop(J, LJ_TRLINK_DOWNREC, J->cur.traceno); /* Down-rec. */ @@ -970,6 +973,8 @@ void lj_record_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults) lj_trace_err(J, LJ_TRERR_LLEAVE); } else if (J->needsnap) { /* Tailcalled to ff with side-effects. */ lj_trace_err(J, LJ_TRERR_NYIRETL); /* No way to insert snapshot here. */ + } else if (1 + pt->framesize >= LJ_MAX_JSLOTS) { + lj_trace_err(J, LJ_TRERR_STACKOV); } else { /* Return to lower frame. Guard for the target we return to. */ TRef trpt = lj_ir_kgc(J, obj2gco(pt), IRT_PROTO); TRef trpc = lj_ir_kptr(J, (void *)frame_pc(frame)); @@ -1003,7 +1008,8 @@ void lj_record_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults) BCReg bslot = bc_b(*(frame_contpc(frame)-1)); TRef tr = gotresults ? J->base[cbase+rbase] : TREF_NIL; if (bslot != J->maxslot) { /* Concatenate the remainder. */ - TValue *b = J->L->base, save; /* Simulate lower frame and result. */ + /* Simulate lower frame and result. */ + TValue *b = J->L->base - baseadj, save; /* Can't handle MM_concat + CALLT + fast func side-effects. */ if (J->postproc != LJ_POST_NONE) lj_trace_err(J, LJ_TRERR_NYIRETL); @@ -1016,7 +1022,7 @@ void lj_record_ret(jit_State *J, BCReg rbase, ptrdiff_t gotresults) J->L->base = b - cbase; tr = rec_cat(J, bslot, cbase-(2<L->base + cbase; /* Undo. */ - J->L->base = b; + J->L->base = b + baseadj; copyTV(J->L, b-(2<o, ir_k64(ir)->u64); case IR_KPTR: return lj_ir_kptr(J, ir_kptr(ir)); /* Continuation. */ + case IR_KNULL: return lj_ir_knull(J, irt_type(ir->t)); default: lj_assertJ(0, "bad IR constant op %d", ir->o); return TREF_NIL; } } @@ -557,13 +558,15 @@ void lj_snap_replay(jit_State *J, GCtrace *T) IRRef refp = snap_ref(sn); IRIns *ir = &T->ir[refp]; if (regsp_reg(ir->r) == RID_SUNK) { + uint8_t m; if (J->slot[snap_slot(sn)] != snap_slot(sn)) continue; pass23 = 1; lj_assertJ(ir->o == IR_TNEW || ir->o == IR_TDUP || ir->o == IR_CNEW || ir->o == IR_CNEWI, "sunk parent IR %04d has bad op %d", refp - REF_BIAS, ir->o); - if (ir->op1 >= T->nk) snap_pref(J, T, map, nent, seen, ir->op1); - if (ir->op2 >= T->nk) snap_pref(J, T, map, nent, seen, ir->op2); + m = lj_ir_mode[ir->o]; + if (irm_op1(m) == IRMref) snap_pref(J, T, map, nent, seen, ir->op1); + if (irm_op2(m) == IRMref) snap_pref(J, T, map, nent, seen, ir->op2); if (LJ_HASFFI && ir->o == IR_CNEWI) { if (LJ_32 && refp+1 < T->nins && (ir+1)->o == IR_HIOP) snap_pref(J, T, map, nent, seen, (ir+1)->op2); @@ -591,14 +594,16 @@ void lj_snap_replay(jit_State *J, GCtrace *T) IRIns *ir = &T->ir[refp]; if (regsp_reg(ir->r) == RID_SUNK) { TRef op1, op2; + uint8_t m; if (J->slot[snap_slot(sn)] != snap_slot(sn)) { /* De-dup allocs. */ J->slot[snap_slot(sn)] = J->slot[J->slot[snap_slot(sn)]]; continue; } op1 = ir->op1; - if (op1 >= T->nk) op1 = snap_pref(J, T, map, nent, seen, op1); + m = lj_ir_mode[ir->o]; + if (irm_op1(m) == IRMref) op1 = snap_pref(J, T, map, nent, seen, op1); op2 = ir->op2; - if (op2 >= T->nk) op2 = snap_pref(J, T, map, nent, seen, op2); + if (irm_op2(m) == IRMref) op2 = snap_pref(J, T, map, nent, seen, op2); if (LJ_HASFFI && ir->o == IR_CNEWI) { if (LJ_32 && refp+1 < T->nins && (ir+1)->o == IR_HIOP) { lj_needsplit(J); /* Emit joining HIOP. */ @@ -624,9 +629,25 @@ void lj_snap_replay(jit_State *J, GCtrace *T) if (irr->o == IR_HREFK || irr->o == IR_AREF) { IRIns *irf = &T->ir[irr->op1]; tmp = emitir(irf->ot, tmp, irf->op2); + } else if (irr->o == IR_NEWREF) { + IRRef allocref = tref_ref(tr); + IRRef keyref = tref_ref(key); + IRRef newref_ref = J->chain[IR_NEWREF]; + IRIns *newref = &J->cur.ir[newref_ref]; + lj_assertJ(irref_isk(keyref), + "sunk store for parent IR %04d with bad key %04d", + refp - REF_BIAS, keyref - REF_BIAS); + if (newref_ref > allocref && newref->op2 == keyref) { + lj_assertJ(newref->op1 == allocref, + "sunk store for parent IR %04d with bad tab %04d", + refp - REF_BIAS, allocref - REF_BIAS); + tmp = newref_ref; + goto skip_newref; + } } } tmp = emitir(irr->ot, tmp, key); + skip_newref: val = snap_pref(J, T, map, nent, seen, irs->op2); if (val == 0) { IRIns *irc = &T->ir[irs->op2]; @@ -882,9 +903,13 @@ static void snap_unsink(jit_State *J, GCtrace *T, ExitState *ex, if (irk->o == IR_FREF) { switch (irk->op2) { case IRFL_TAB_META: - snap_restoreval(J, T, ex, snapno, rfilt, irs->op2, &tmp); - /* NOBARRIER: The table is new (marked white). */ - setgcref(t->metatable, obj2gco(tabV(&tmp))); + if (T->ir[irs->op2].o == IR_KNULL) { + setgcrefnull(t->metatable); + } else { + snap_restoreval(J, T, ex, snapno, rfilt, irs->op2, &tmp); + /* NOBARRIER: The table is new (marked white). */ + setgcref(t->metatable, obj2gco(tabV(&tmp))); + } break; case IRFL_TAB_NOMM: /* Negative metamethod cache invalidated by lj_tab_set() below. */ diff --git a/libs/LuaJIT/src/lj_state.c b/libs/LuaJIT/src/lj_state.c index 7e4961bd..af17e4b5 100644 --- a/libs/LuaJIT/src/lj_state.c +++ b/libs/LuaJIT/src/lj_state.c @@ -102,27 +102,49 @@ void lj_state_shrinkstack(lua_State *L, MSize used) /* Try to grow stack. */ void LJ_FASTCALL lj_state_growstack(lua_State *L, MSize need) { - MSize n; - if (L->stacksize >= LJ_STACK_MAXEX) { - /* 4. Throw 'error in error handling' when we are _over_ the limit. */ - if (L->stacksize > LJ_STACK_MAXEX) - lj_err_throw(L, LUA_ERRERR); /* Does not invoke an error handler. */ - /* 1. We are _at_ the limit after the last growth. */ - if (L->status < LUA_ERRRUN) { /* 2. Throw 'stack overflow'. */ - L->status = LUA_ERRRUN; /* Prevent ending here again for pushed msg. */ - lj_err_msg(L, LJ_ERR_STKOV); /* May invoke an error handler. */ + MSize n = L->stacksize + need; + if (LJ_LIKELY(n < LJ_STACK_MAX)) { /* The stack can grow as requested. */ + if (n < 2 * L->stacksize) { /* Try to double the size. */ + n = 2 * L->stacksize; + if (n > LJ_STACK_MAX) + n = LJ_STACK_MAX; + } + resizestack(L, n); + } else { /* Request would overflow. Raise a stack overflow error. */ + if (LJ_HASJIT) { + TValue *base = tvref(G(L)->jit_base); + if (base) L->base = base; + } + if (curr_funcisL(L)) { + L->top = curr_topL(L); + if (L->top > tvref(L->maxstack)) { + /* The current Lua frame violates the stack, so replace it with a + ** dummy. This can happen when BC_IFUNCF is trying to grow the stack. + */ + L->top = L->base; + setframe_gc(L->base - 1 - LJ_FR2, obj2gco(L), LJ_TTHREAD); + } + } + if (L->stacksize <= LJ_STACK_MAXEX) { + /* An error handler might want to inspect the stack overflow error, but + ** will need some stack space to run in. We give it a stack size beyond + ** the normal limit in order to do so, then rely on lj_state_relimitstack + ** calls during unwinding to bring us back to a convential stack size. + ** The + 1 is space for the error message, and 2 * LUA_MINSTACK is for + ** the lj_state_checkstack() call in lj_err_run(). + */ + resizestack(L, LJ_STACK_MAX + 1 + 2 * LUA_MINSTACK); + lj_err_stkov(L); /* May invoke an error handler. */ + } else { + /* If we're here, then the stack overflow error handler is requesting + ** to grow the stack even further. We have no choice but to abort the + ** error handler. + */ + GCstr *em = lj_err_str(L, LJ_ERR_STKOV); /* Might OOM. */ + setstrV(L, L->top++, em); /* There is always space to push an error. */ + lj_err_throw(L, LUA_ERRERR); /* Does not invoke an error handler. */ } - /* 3. Add space (over the limit) for pushed message and error handler. */ } - n = L->stacksize + need; - if (n > LJ_STACK_MAX) { - n += 2*LUA_MINSTACK; - } else if (n < 2*L->stacksize) { - n = 2*L->stacksize; - if (n >= LJ_STACK_MAX) - n = LJ_STACK_MAX; - } - resizestack(L, n); } void LJ_FASTCALL lj_state_growstack1(lua_State *L) diff --git a/libs/LuaJIT/src/lj_strfmt_num.c b/libs/LuaJIT/src/lj_strfmt_num.c index 79ec0263..c6e776aa 100644 --- a/libs/LuaJIT/src/lj_strfmt_num.c +++ b/libs/LuaJIT/src/lj_strfmt_num.c @@ -454,7 +454,8 @@ static char *lj_strfmt_wfnum(SBuf *sb, SFormat sf, lua_Number n, char *p) prec--; if (!i) { if (ndlo == ndhi) { prec = 0; break; } - lj_strfmt_wuint9(tail, nd[++ndlo]); + ndlo = (ndlo + 1) & 0x3f; + lj_strfmt_wuint9(tail, nd[ndlo]); i = 9; } } diff --git a/libs/LuaJIT/src/lj_trace.c b/libs/LuaJIT/src/lj_trace.c index fee78e2e..a5e316e1 100644 --- a/libs/LuaJIT/src/lj_trace.c +++ b/libs/LuaJIT/src/lj_trace.c @@ -928,7 +928,7 @@ int LJ_FASTCALL lj_trace_exit(jit_State *J, void *exptr) } else if (G(L)->gc.state == GCSatomic || G(L)->gc.state == GCSfinalize) { if (!(G(L)->hookmask & HOOK_GC)) lj_gc_step(L); /* Exited because of GC: drive GC forward. */ - } else { + } else if ((J->flags & JIT_F_ON)) { trace_hotside(J, pc); } /* Return MULTRES or 0 or -17. */ diff --git a/libs/LuaJIT/src/luajit_rolling.h b/libs/LuaJIT/src/luajit_rolling.h index e564477a..2d04402c 100644 --- a/libs/LuaJIT/src/luajit_rolling.h +++ b/libs/LuaJIT/src/luajit_rolling.h @@ -76,4 +76,5 @@ LUA_API const char *luaJIT_profile_dumpstack(lua_State *L, const char *fmt, /* Enforce (dynamic) linker error for version mismatches. Call from main. */ LUA_API void LUAJIT_VERSION_SYM(void); +#error "DO NOT USE luajit_rolling.h -- only include build-generated luajit.h" #endif diff --git a/libs/LuaJIT/src/msvcbuild.bat b/libs/LuaJIT/src/msvcbuild.bat index cd25beee..91cfd065 100644 --- a/libs/LuaJIT/src/msvcbuild.bat +++ b/libs/LuaJIT/src/msvcbuild.bat @@ -16,6 +16,7 @@ @rem Add more debug flags here, e.g. DEBUGCFLAGS=/DLUA_USE_APICHECK @set DEBUGCFLAGS= @set LJCOMPILE=cl /nologo /c /O2 /W3 /D_CRT_SECURE_NO_DEPRECATE /D_CRT_STDIO_INLINE=__declspec(dllexport)__inline +@set LJDYNBUILD=/MD /DLUA_BUILD_AS_DLL @set LJLINK=link /nologo @set LJMT=mt /nologo @set LJLIB=lib /nologo /nodefaultlib @@ -93,12 +94,13 @@ buildvm -m folddef -o lj_folddef.h lj_opt_fold.c @shift @set BUILDTYPE=debug @set LJCOMPILE=%LJCOMPILE% /Zi %DEBUGCFLAGS% +@set LJDYNBUILD=/MDd /DLUA_BUILD_AS_DLL @set LJLINK=%LJLINK% /opt:ref /opt:icf /incremental:no :NODEBUG @set LJLINK=%LJLINK% /%BUILDTYPE% @if "%1"=="amalg" goto :AMALGDLL @if "%1"=="static" goto :STATIC -%LJCOMPILE% /MD /DLUA_BUILD_AS_DLL lj_*.c lib_*.c +%LJCOMPILE% %LJDYNBUILD% lj_*.c lib_*.c @if errorlevel 1 goto :BAD %LJLINK% /DLL /out:%LJDLLNAME% lj_*.obj lib_*.obj @if errorlevel 1 goto :BAD @@ -110,7 +112,7 @@ buildvm -m folddef -o lj_folddef.h lj_opt_fold.c @if errorlevel 1 goto :BAD @goto :MTDLL :AMALGDLL -%LJCOMPILE% /MD /DLUA_BUILD_AS_DLL ljamalg.c +%LJCOMPILE% %LJDYNBUILD% ljamalg.c @if errorlevel 1 goto :BAD %LJLINK% /DLL /out:%LJDLLNAME% ljamalg.obj lj_vm.obj @if errorlevel 1 goto :BAD