From 4cc5853c29495a17b0a94093358617feda209261 Mon Sep 17 00:00:00 2001 From: John Date: Sat, 25 Sep 2021 12:12:27 +0200 Subject: [PATCH] LuaJIT: import upstream patches to fix crashes on aarch64 without this luajit just crashes on e.g. native neovim builds and under certain conditions also during running neovim e.g. with nvim-cmp + nvim-cmp-lsp --- .../aarch64-Fix-exit-stub-patching.patch | 231 +++++++ ...1abec542e6f9851ff2368e7f196b6382a44c.patch | 562 ++++++++++++++++++ srcpkgs/LuaJIT/template | 2 +- 3 files changed, 794 insertions(+), 1 deletion(-) create mode 100644 srcpkgs/LuaJIT/patches/aarch64-Fix-exit-stub-patching.patch create mode 100644 srcpkgs/LuaJIT/patches/e9af1abec542e6f9851ff2368e7f196b6382a44c.patch diff --git a/srcpkgs/LuaJIT/patches/aarch64-Fix-exit-stub-patching.patch b/srcpkgs/LuaJIT/patches/aarch64-Fix-exit-stub-patching.patch new file mode 100644 index 000000000000..487a1cd1ca78 --- /dev/null +++ b/srcpkgs/LuaJIT/patches/aarch64-Fix-exit-stub-patching.patch @@ -0,0 +1,231 @@ +commit 9da06535092d6d9dec442641a26c64bce5574322 +Author: Mike Pall +Date: Sun Jun 24 14:08:59 2018 +0200 + + ARM64: Fix exit stub patching. + + Contributed by Javier Guerra Giraldez. + +diff --git a/src/lj_asm_arm64.h b/src/lj_asm_arm64.h +index cbb186d3..baafa21a 100644 +--- a/src/lj_asm_arm64.h ++++ b/src/lj_asm_arm64.h +@@ -56,11 +56,11 @@ static void asm_exitstub_setup(ASMState *as, ExitNo nexits) + asm_mclimit(as); + /* 1: str lr,[sp]; bl ->vm_exit_handler; movz w0,traceno; bl <1; bl <1; ... */ + for (i = nexits-1; (int32_t)i >= 0; i--) +- *--mxp = A64I_LE(A64I_BL|((-3-i)&0x03ffffffu)); +- *--mxp = A64I_LE(A64I_MOVZw|A64F_U16(as->T->traceno)); ++ *--mxp = A64I_LE(A64I_BL | A64F_S26(-3-i)); ++ *--mxp = A64I_LE(A64I_MOVZw | A64F_U16(as->T->traceno)); + mxp--; +- *mxp = A64I_LE(A64I_BL|(((MCode *)(void *)lj_vm_exit_handler-mxp)&0x03ffffffu)); +- *--mxp = A64I_LE(A64I_STRx|A64F_D(RID_LR)|A64F_N(RID_SP)); ++ *mxp = A64I_LE(A64I_BL | A64F_S26(((MCode *)(void *)lj_vm_exit_handler-mxp))); ++ *--mxp = A64I_LE(A64I_STRx | A64F_D(RID_LR) | A64F_N(RID_SP)); + as->mctop = mxp; + } + +@@ -77,7 +77,7 @@ static void asm_guardcc(ASMState *as, A64CC cc) + MCode *p = as->mcp; + if (LJ_UNLIKELY(p == as->invmcp)) { + as->loopinv = 1; +- *p = A64I_B | ((target-p) & 0x03ffffffu); ++ *p = A64I_B | A64F_S26(target-p); + emit_cond_branch(as, cc^1, p-1); + return; + } +@@ -91,7 +91,7 @@ static void asm_guardtnb(ASMState *as, A64Ins ai, Reg r, uint32_t bit) + MCode *p = as->mcp; + if (LJ_UNLIKELY(p == as->invmcp)) { + as->loopinv = 1; +- *p = A64I_B | ((target-p) & 0x03ffffffu); ++ *p = A64I_B | A64F_S26(target-p); + emit_tnb(as, ai^0x01000000u, r, bit, p-1); + return; + } +@@ -105,7 +105,7 @@ static void asm_guardcnb(ASMState *as, A64Ins ai, Reg r) + MCode *p = as->mcp; + if (LJ_UNLIKELY(p == as->invmcp)) { + as->loopinv = 1; +- *p = A64I_B | ((target-p) & 0x03ffffffu); ++ *p = A64I_B | A64F_S26(target-p); + emit_cnb(as, ai^0x01000000u, r, p-1); + return; + } +@@ -1850,7 +1850,7 @@ static void asm_loop_fixup(ASMState *as) + p[-2] |= ((uint32_t)delta & mask) << 5; + } else { + ptrdiff_t delta = target - (p - 1); +- p[-1] = A64I_B | ((uint32_t)(delta) & 0x03ffffffu); ++ p[-1] = A64I_B | A64F_S26(delta); + } + } + +@@ -1919,7 +1919,7 @@ static void asm_tail_fixup(ASMState *as, TraceNo lnk) + } + /* Patch exit branch. */ + target = lnk ? traceref(as->J, lnk)->mcode : (MCode *)lj_vm_exit_interp; +- p[-1] = A64I_B | (((target-p)+1)&0x03ffffffu); ++ p[-1] = A64I_B | A64F_S26((target-p)+1); + } + + /* Prepare tail of code. */ +@@ -1982,40 +1982,50 @@ void lj_asm_patchexit(jit_State *J, GCtrace *T, ExitNo exitno, MCode *target) + { + MCode *p = T->mcode; + MCode *pe = (MCode *)((char *)p + T->szmcode); +- MCode *cstart = NULL, *cend = p; ++ MCode *cstart = NULL; + MCode *mcarea = lj_mcode_patch(J, p, 0); + MCode *px = exitstub_trace_addr(T, exitno); ++ /* Note: this assumes a trace exit is only ever patched once. */ + for (; p < pe; p++) { + /* Look for exitstub branch, replace with branch to target. */ ++ ptrdiff_t delta = target - p; + MCode ins = A64I_LE(*p); + if ((ins & 0xff000000u) == 0x54000000u && + ((ins ^ ((px-p)<<5)) & 0x00ffffe0u) == 0) { +- /* Patch bcc exitstub. */ +- *p = A64I_LE((ins & 0xff00001fu) | (((target-p)<<5) & 0x00ffffe0u)); +- cend = p+1; +- if (!cstart) cstart = p; ++ /* Patch bcc, if within range. */ ++ if (A64F_S_OK(delta, 19)) { ++ *p = A64I_LE((ins & 0xff00001fu) | A64F_S19(delta)); ++ if (!cstart) cstart = p; ++ } + } else if ((ins & 0xfc000000u) == 0x14000000u && + ((ins ^ (px-p)) & 0x03ffffffu) == 0) { +- /* Patch b exitstub. */ +- *p = A64I_LE((ins & 0xfc000000u) | ((target-p) & 0x03ffffffu)); +- cend = p+1; ++ /* Patch b. */ ++ lua_assert(A64F_S_OK(delta, 26)); ++ *p = A64I_LE((ins & 0xfc000000u) | A64F_S26(delta)); + if (!cstart) cstart = p; + } else if ((ins & 0x7e000000u) == 0x34000000u && + ((ins ^ ((px-p)<<5)) & 0x00ffffe0u) == 0) { +- /* Patch cbz/cbnz exitstub. */ +- *p = A64I_LE((ins & 0xff00001f) | (((target-p)<<5) & 0x00ffffe0u)); +- cend = p+1; +- if (!cstart) cstart = p; ++ /* Patch cbz/cbnz, if within range. */ ++ if (A64F_S_OK(delta, 19)) { ++ *p = A64I_LE((ins & 0xff00001fu) | A64F_S19(delta)); ++ if (!cstart) cstart = p; ++ } + } else if ((ins & 0x7e000000u) == 0x36000000u && + ((ins ^ ((px-p)<<5)) & 0x0007ffe0u) == 0) { +- /* Patch tbz/tbnz exitstub. */ +- *p = A64I_LE((ins & 0xfff8001fu) | (((target-p)<<5) & 0x0007ffe0u)); +- cend = p+1; +- if (!cstart) cstart = p; ++ /* Patch tbz/tbnz, if within range. */ ++ if (A64F_S_OK(delta, 14)) { ++ *p = A64I_LE((ins & 0xfff8001fu) | A64F_S14(delta)); ++ if (!cstart) cstart = p; ++ } + } + } +- lua_assert(cstart != NULL); +- lj_mcode_sync(cstart, cend); ++ { /* Always patch long-range branch in exit stub itself. */ ++ ptrdiff_t delta = target - px; ++ lua_assert(A64F_S_OK(delta, 26)); ++ *px = A64I_B | A64F_S26(delta); ++ if (!cstart) cstart = px; ++ } ++ lj_mcode_sync(cstart, px+1); + lj_mcode_patch(J, mcarea, 1); + } + +diff --git a/src/lj_emit_arm64.h b/src/lj_emit_arm64.h +index 6da4c7d4..1001b1d8 100644 +--- a/src/lj_emit_arm64.h ++++ b/src/lj_emit_arm64.h +@@ -241,7 +241,7 @@ static void emit_loadk(ASMState *as, Reg rd, uint64_t u64, int is64) + #define mcpofs(as, k) \ + ((intptr_t)((uintptr_t)(k) - (uintptr_t)(as->mcp - 1))) + #define checkmcpofs(as, k) \ +- ((((mcpofs(as, k)>>2) + 0x00040000) >> 19) == 0) ++ (A64F_S_OK(mcpofs(as, k)>>2, 19)) + + static Reg ra_allock(ASMState *as, intptr_t k, RegSet allow); + +@@ -312,7 +312,7 @@ static void emit_cond_branch(ASMState *as, A64CC cond, MCode *target) + { + MCode *p = --as->mcp; + ptrdiff_t delta = target - p; +- lua_assert(((delta + 0x40000) >> 19) == 0); ++ lua_assert(A64F_S_OK(delta, 19)); + *p = A64I_BCC | A64F_S19(delta) | cond; + } + +@@ -320,24 +320,24 @@ static void emit_branch(ASMState *as, A64Ins ai, MCode *target) + { + MCode *p = --as->mcp; + ptrdiff_t delta = target - p; +- lua_assert(((delta + 0x02000000) >> 26) == 0); +- *p = ai | ((uint32_t)delta & 0x03ffffffu); ++ lua_assert(A64F_S_OK(delta, 26)); ++ *p = ai | A64F_S26(delta); + } + + static void emit_tnb(ASMState *as, A64Ins ai, Reg r, uint32_t bit, MCode *target) + { + MCode *p = --as->mcp; + ptrdiff_t delta = target - p; +- lua_assert(bit < 63 && ((delta + 0x2000) >> 14) == 0); ++ lua_assert(bit < 63 && A64F_S_OK(delta, 14)); + if (bit > 31) ai |= A64I_X; +- *p = ai | A64F_BIT(bit & 31) | A64F_S14((uint32_t)delta & 0x3fffu) | r; ++ *p = ai | A64F_BIT(bit & 31) | A64F_S14(delta) | r; + } + + static void emit_cnb(ASMState *as, A64Ins ai, Reg r, MCode *target) + { + MCode *p = --as->mcp; + ptrdiff_t delta = target - p; +- lua_assert(((delta + 0x40000) >> 19) == 0); ++ lua_assert(A64F_S_OK(delta, 19)); + *p = ai | A64F_S19(delta) | r; + } + +@@ -347,8 +347,8 @@ static void emit_call(ASMState *as, void *target) + { + MCode *p = --as->mcp; + ptrdiff_t delta = (char *)target - (char *)p; +- if ((((delta>>2) + 0x02000000) >> 26) == 0) { +- *p = A64I_BL | ((uint32_t)(delta>>2) & 0x03ffffffu); ++ if (A64F_S_OK(delta>>2, 26)) { ++ *p = A64I_BL | A64F_S26(delta>>2); + } else { /* Target out of range: need indirect call. But don't use R0-R7. */ + Reg r = ra_allock(as, i64ptr(target), + RSET_RANGE(RID_X8, RID_MAX_GPR)-RSET_FIXED); +diff --git a/src/lj_target_arm64.h b/src/lj_target_arm64.h +index 520023ae..a207a2ba 100644 +--- a/src/lj_target_arm64.h ++++ b/src/lj_target_arm64.h +@@ -132,9 +132,9 @@ static LJ_AINLINE uint32_t *exitstub_trace_addr_(uint32_t *p, uint32_t exitno) + #define A64F_IMMR(x) ((x) << 16) + #define A64F_U16(x) ((x) << 5) + #define A64F_U12(x) ((x) << 10) +-#define A64F_S26(x) (x) ++#define A64F_S26(x) (((uint32_t)(x) & 0x03ffffffu)) + #define A64F_S19(x) (((uint32_t)(x) & 0x7ffffu) << 5) +-#define A64F_S14(x) ((x) << 5) ++#define A64F_S14(x) (((uint32_t)(x) & 0x3fffu) << 5) + #define A64F_S9(x) ((x) << 12) + #define A64F_BIT(x) ((x) << 19) + #define A64F_SH(sh, x) (((sh) << 22) | ((x) << 10)) +@@ -145,6 +145,9 @@ static LJ_AINLINE uint32_t *exitstub_trace_addr_(uint32_t *p, uint32_t exitno) + #define A64F_LSL16(x) (((x) / 16) << 21) + #define A64F_BSH(sh) ((sh) << 10) + ++/* Check for valid field range. */ ++#define A64F_S_OK(x, b) ((((x) + (1 << (b-1))) >> (b)) == 0) ++ + typedef enum A64Ins { + A64I_S = 0x20000000, + A64I_X = 0x80000000, diff --git a/srcpkgs/LuaJIT/patches/e9af1abec542e6f9851ff2368e7f196b6382a44c.patch b/srcpkgs/LuaJIT/patches/e9af1abec542e6f9851ff2368e7f196b6382a44c.patch new file mode 100644 index 000000000000..a217866c392c --- /dev/null +++ b/srcpkgs/LuaJIT/patches/e9af1abec542e6f9851ff2368e7f196b6382a44c.patch @@ -0,0 +1,562 @@ +From e9af1abec542e6f9851ff2368e7f196b6382a44c Mon Sep 17 00:00:00 2001 +From: Mike Pall +Date: Wed, 30 Sep 2020 01:31:27 +0200 +Subject: [PATCH] Add support for full-range 64 bit lightuserdata. + +--- + doc/status.html | 11 --------- + src/jit/dump.lua | 4 +++- + src/lib_debug.c | 12 +++++----- + src/lib_jit.c | 14 ++++++------ + src/lib_package.c | 8 +++---- + src/lib_string.c | 2 +- + src/lj_api.c | 40 +++++++++++++++++++++++++++++---- + src/lj_ccall.c | 2 +- + src/lj_cconv.c | 2 +- + src/lj_crecord.c | 6 ++--- + src/lj_dispatch.c | 2 +- + src/lj_ir.c | 6 +++-- + src/lj_obj.c | 5 +++-- + src/lj_obj.h | 57 ++++++++++++++++++++++++++++++----------------- + src/lj_snap.c | 9 +++++++- + src/lj_state.c | 6 +++++ + src/lj_strfmt.c | 2 +- + 17 files changed, 121 insertions(+), 67 deletions(-) + +#diff --git a/doc/status.html b/doc/status.html +#index 0aafe13a2..fd0ae8bae 100644 +#--- a/doc/status.html +#+++ b/doc/status.html +#@@ -91,17 +91,6 @@

Current Status

+# lua_atpanic on x64. This issue will be fixed with the new +# garbage collector. +# +#-
  • +#-LuaJIT on 64 bit systems provides a limited range of 47 bits for the +#-legacy lightuserdata data type. +#-This is only relevant on x64 systems which use the negative part of the +#-virtual address space in user mode, e.g. Solaris/x64, and on ARM64 systems +#-configured with a 48 bit or 52 bit VA. +#-Avoid using lightuserdata to hold pointers that may point outside +#-of that range, e.g. variables on the stack. In general, avoid this data +#-type for new code and replace it with (much more performant) FFI bindings. +#-FFI cdata pointers can address the full 64 bit range. +#-
  • +# +#
    +# +Index: luajit/src/jit/dump.lua +=================================================================== +--- luajit.orig/src/jit/dump.lua ++++ luajit/src/jit/dump.lua +@@ -315,7 +315,9 @@ + local tn = type(k) + local s + if tn == "number" then +- if band(sn or 0, 0x30000) ~= 0 then ++ if t < 12 then ++ s = k == 0 and "NULL" or format("[0x%08x]", k) ++ elseif band(sn or 0, 0x30000) ~= 0 then + s = band(sn, 0x20000) ~= 0 and "contpc" or "ftsz" + elseif k == 2^52+2^51 then + s = "bias" +Index: luajit/src/lib_debug.c +=================================================================== +--- luajit.orig/src/lib_debug.c ++++ luajit/src/lib_debug.c +@@ -231,8 +231,8 @@ + int32_t n = lj_lib_checkint(L, 2) - 1; + if ((uint32_t)n >= fn->l.nupvalues) + lj_err_arg(L, 2, LJ_ERR_IDXRNG); +- setlightudV(L->top-1, isluafunc(fn) ? (void *)gcref(fn->l.uvptr[n]) : +- (void *)&fn->c.upvalue[n]); ++ lua_pushlightuserdata(L, isluafunc(fn) ? (void *)gcref(fn->l.uvptr[n]) : ++ (void *)&fn->c.upvalue[n]); + return 1; + } + +@@ -283,13 +283,13 @@ + + /* ------------------------------------------------------------------------ */ + +-#define KEY_HOOK ((void *)0x3004) ++#define KEY_HOOK (U64x(80000000,00000000)|'h') + + static void hookf(lua_State *L, lua_Debug *ar) + { + static const char *const hooknames[] = + {"call", "return", "line", "count", "tail return"}; +- lua_pushlightuserdata(L, KEY_HOOK); ++ (L->top++)->u64 = KEY_HOOK; + lua_rawget(L, LUA_REGISTRYINDEX); + if (lua_isfunction(L, -1)) { + lua_pushstring(L, hooknames[(int)ar->event]); +@@ -334,7 +334,7 @@ + count = luaL_optint(L, arg+3, 0); + func = hookf; mask = makemask(smask, count); + } +- lua_pushlightuserdata(L, KEY_HOOK); ++ (L->top++)->u64 = KEY_HOOK; + lua_pushvalue(L, arg+1); + lua_rawset(L, LUA_REGISTRYINDEX); + lua_sethook(L, func, mask, count); +@@ -349,7 +349,7 @@ + if (hook != NULL && hook != hookf) { /* external hook? */ + lua_pushliteral(L, "external hook"); + } else { +- lua_pushlightuserdata(L, KEY_HOOK); ++ (L->top++)->u64 = KEY_HOOK; + lua_rawget(L, LUA_REGISTRYINDEX); /* get hook */ + } + lua_pushstring(L, unmakemask(mask, buff)); +Index: luajit/src/lib_jit.c +=================================================================== +--- luajit.orig/src/lib_jit.c ++++ luajit/src/lib_jit.c +@@ -540,15 +540,15 @@ + + /* Not loaded by default, use: local profile = require("jit.profile") */ + +-static const char KEY_PROFILE_THREAD = 't'; +-static const char KEY_PROFILE_FUNC = 'f'; ++#define KEY_PROFILE_THREAD (U64x(80000000,00000000)|'t') ++#define KEY_PROFILE_FUNC (U64x(80000000,00000000)|'f') + + static void jit_profile_callback(lua_State *L2, lua_State *L, int samples, + int vmstate) + { + TValue key; + cTValue *tv; +- setlightudV(&key, (void *)&KEY_PROFILE_FUNC); ++ key.u64 = KEY_PROFILE_FUNC; + tv = lj_tab_get(L, tabV(registry(L)), &key); + if (tvisfunc(tv)) { + char vmst = (char)vmstate; +@@ -575,9 +575,9 @@ + lua_State *L2 = lua_newthread(L); /* Thread that runs profiler callback. */ + TValue key; + /* Anchor thread and function in registry. */ +- setlightudV(&key, (void *)&KEY_PROFILE_THREAD); ++ key.u64 = KEY_PROFILE_THREAD; + setthreadV(L, lj_tab_set(L, registry, &key), L2); +- setlightudV(&key, (void *)&KEY_PROFILE_FUNC); ++ key.u64 = KEY_PROFILE_FUNC; + setfuncV(L, lj_tab_set(L, registry, &key), func); + lj_gc_anybarriert(L, registry); + luaJIT_profile_start(L, mode ? strdata(mode) : "", +@@ -592,9 +592,9 @@ + TValue key; + luaJIT_profile_stop(L); + registry = tabV(registry(L)); +- setlightudV(&key, (void *)&KEY_PROFILE_THREAD); ++ key.u64 = KEY_PROFILE_THREAD; + setnilV(lj_tab_set(L, registry, &key)); +- setlightudV(&key, (void *)&KEY_PROFILE_FUNC); ++ key.u64 = KEY_PROFILE_FUNC; + setnilV(lj_tab_set(L, registry, &key)); + lj_gc_anybarriert(L, registry); + return 0; +Index: luajit/src/lib_package.c +=================================================================== +--- luajit.orig/src/lib_package.c ++++ luajit/src/lib_package.c +@@ -398,7 +398,7 @@ + + /* ------------------------------------------------------------------------ */ + +-#define sentinel ((void *)0x4004) ++#define KEY_SENTINEL (U64x(80000000,00000000)|'s') + + static int lj_cf_package_require(lua_State *L) + { +@@ -408,7 +408,7 @@ + lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); + lua_getfield(L, 2, name); + if (lua_toboolean(L, -1)) { /* is it there? */ +- if (lua_touserdata(L, -1) == sentinel) /* check loops */ ++ if ((L->top-1)->u64 == KEY_SENTINEL) /* check loops */ + luaL_error(L, "loop or previous error loading module " LUA_QS, name); + return 1; /* package is already loaded */ + } +@@ -431,14 +431,14 @@ + else + lua_pop(L, 1); + } +- lua_pushlightuserdata(L, sentinel); ++ (L->top++)->u64 = KEY_SENTINEL; + lua_setfield(L, 2, name); /* _LOADED[name] = sentinel */ + lua_pushstring(L, name); /* pass name as argument to module */ + lua_call(L, 1, 1); /* run loaded module */ + if (!lua_isnil(L, -1)) /* non-nil return? */ + lua_setfield(L, 2, name); /* _LOADED[name] = returned value */ + lua_getfield(L, 2, name); +- if (lua_touserdata(L, -1) == sentinel) { /* module did not set a value? */ ++ if ((L->top-1)->u64 == KEY_SENTINEL) { /* module did not set a value? */ + lua_pushboolean(L, 1); /* use true as result */ + lua_pushvalue(L, -1); /* extra copy to be returned */ + lua_setfield(L, 2, name); /* _LOADED[name] = true */ +Index: luajit/src/lib_string.c +=================================================================== +--- luajit.orig/src/lib_string.c ++++ luajit/src/lib_string.c +@@ -714,7 +714,7 @@ + lj_strfmt_putfchar(sb, sf, lj_lib_checkint(L, arg)); + break; + case STRFMT_PTR: /* No formatting. */ +- lj_strfmt_putptr(sb, lj_obj_ptr(L->base+arg-1)); ++ lj_strfmt_putptr(sb, lj_obj_ptr(G(L), L->base+arg-1)); + break; + default: + lua_assert(0); +Index: luajit/src/lj_api.c +=================================================================== +--- luajit.orig/src/lj_api.c ++++ luajit/src/lj_api.c +@@ -595,7 +595,7 @@ + if (tvisudata(o)) + return uddata(udataV(o)); + else if (tvislightud(o)) +- return lightudV(o); ++ return lightudV(G(L), o); + else + return NULL; + } +@@ -608,7 +608,7 @@ + + LUA_API const void *lua_topointer(lua_State *L, int idx) + { +- return lj_obj_ptr(index2adr(L, idx)); ++ return lj_obj_ptr(G(L), index2adr(L, idx)); + } + + /* -- Stack setters (object creation) ------------------------------------- */ +@@ -694,9 +694,38 @@ + incr_top(L); + } + ++#if LJ_64 ++static void *lightud_intern(lua_State *L, void *p) ++{ ++ global_State *g = G(L); ++ uint64_t u = (uint64_t)p; ++ uint32_t up = lightudup(u); ++ uint32_t *segmap = mref(g->gc.lightudseg, uint32_t); ++ MSize segnum = g->gc.lightudnum; ++ if (segmap) { ++ MSize seg; ++ for (seg = 0; seg <= segnum; seg++) ++ if (segmap[seg] == up) /* Fast path. */ ++ return (void *)(((uint64_t)seg << LJ_LIGHTUD_BITS_LO) | lightudlo(u)); ++ segnum++; ++ } ++ if (!((segnum-1) & segnum) && segnum != 1) { ++ if (segnum >= (1 << LJ_LIGHTUD_BITS_SEG)) lj_err_msg(L, LJ_ERR_BADLU); ++ lj_mem_reallocvec(L, segmap, segnum, segnum ? 2*segnum : 2u, uint32_t); ++ setmref(g->gc.lightudseg, segmap); ++ } ++ g->gc.lightudnum = segnum; ++ segmap[segnum] = up; ++ return (void *)(((uint64_t)segnum << LJ_LIGHTUD_BITS_LO) | lightudlo(u)); ++} ++#endif ++ + LUA_API void lua_pushlightuserdata(lua_State *L, void *p) + { +- setlightudV(L->top, checklightudptr(L, p)); ++#if LJ_64 ++ p = lightud_intern(L, p); ++#endif ++ setrawlightudV(L->top, p); + incr_top(L); + } + +@@ -1138,7 +1167,10 @@ + fn->c.f = func; + setfuncV(L, top++, fn); + if (LJ_FR2) setnilV(top++); +- setlightudV(top++, checklightudptr(L, ud)); ++#if LJ_64 ++ ud = lightud_intern(L, ud); ++#endif ++ setrawlightudV(top++, ud); + cframe_nres(L->cframe) = 1+0; /* Zero results. */ + L->top = top; + return top-1; /* Now call the newly allocated C function. */ +Index: luajit/src/lj_ccall.c +=================================================================== +--- luajit.orig/src/lj_ccall.c ++++ luajit/src/lj_ccall.c +@@ -1314,7 +1314,7 @@ + lj_vm_ffi_call(&cc); + if (cts->cb.slot != ~0u) { /* Blacklist function that called a callback. */ + TValue tv; +- setlightudV(&tv, (void *)cc.func); ++ tv.u64 = ((uintptr_t)(void *)cc.func >> 2) | U64x(800000000, 00000000); + setboolV(lj_tab_set(L, cts->miscmap, &tv), 1); + } + ct = (CType *)((intptr_t)ct+(intptr_t)cts->tab); /* May be reallocated. */ +Index: luajit/src/lj_cconv.c +=================================================================== +--- luajit.orig/src/lj_cconv.c ++++ luajit/src/lj_cconv.c +@@ -611,7 +611,7 @@ + if (ud->udtype == UDTYPE_IO_FILE) + tmpptr = *(void **)tmpptr; + } else if (tvislightud(o)) { +- tmpptr = lightudV(o); ++ tmpptr = lightudV(cts->g, o); + } else if (tvisfunc(o)) { + void *p = lj_ccallback_new(cts, d, funcV(o)); + if (p) { +Index: luajit/src/lj_crecord.c +=================================================================== +--- luajit.orig/src/lj_crecord.c ++++ luajit/src/lj_crecord.c +@@ -643,8 +643,7 @@ + } + } else if (tref_islightud(sp)) { + #if LJ_64 +- sp = emitir(IRT(IR_BAND, IRT_P64), sp, +- lj_ir_kint64(J, U64x(00007fff,ffffffff))); ++ lj_trace_err(J, LJ_TRERR_NYICONV); + #endif + } else { /* NYI: tref_istab(sp). */ + IRType t; +@@ -1209,8 +1208,7 @@ + TRef tr; + TValue tv; + /* Check for blacklisted C functions that might call a callback. */ +- setlightudV(&tv, +- cdata_getptr(cdataptr(cd), (LJ_64 && tp == IRT_P64) ? 8 : 4)); ++ tv.u64 = ((uintptr_t)cdata_getptr(cdataptr(cd), (LJ_64 && tp == IRT_P64) ? 8 : 4) >> 2) | U64x(800000000, 00000000); + if (tvistrue(lj_tab_get(J->L, cts->miscmap, &tv))) + lj_trace_err(J, LJ_TRERR_BLACKL); + if (ctype_isvoid(ctr->info)) { +Index: luajit/src/lj_dispatch.c +=================================================================== +--- luajit.orig/src/lj_dispatch.c ++++ luajit/src/lj_dispatch.c +@@ -302,7 +302,7 @@ + if (idx != 0) { + cTValue *tv = idx > 0 ? L->base + (idx-1) : L->top + idx; + if (tvislightud(tv)) +- g->wrapf = (lua_CFunction)lightudV(tv); ++ g->wrapf = (lua_CFunction)lightudV(g, tv); + else + return 0; /* Failed. */ + } else { +Index: luajit/src/lj_ir.c +=================================================================== +--- luajit.orig/src/lj_ir.c ++++ luajit/src/lj_ir.c +@@ -386,8 +386,10 @@ + case IR_KPRI: setpriV(tv, irt_toitype(ir->t)); break; + case IR_KINT: setintV(tv, ir->i); break; + case IR_KGC: setgcV(L, tv, ir_kgc(ir), irt_toitype(ir->t)); break; +- case IR_KPTR: case IR_KKPTR: setlightudV(tv, ir_kptr(ir)); break; +- case IR_KNULL: setlightudV(tv, NULL); break; ++ case IR_KPTR: case IR_KKPTR: ++ setnumV(tv, (lua_Number)(uintptr_t)ir_kptr(ir)); ++ break; ++ case IR_KNULL: setintV(tv, 0); break; + case IR_KNUM: setnumV(tv, ir_knum(ir)->n); break; + #if LJ_HASFFI + case IR_KINT64: { +Index: luajit/src/lj_obj.c +=================================================================== +--- luajit.orig/src/lj_obj.c ++++ luajit/src/lj_obj.c +@@ -34,12 +34,13 @@ + } + + /* Return pointer to object or its object data. */ +-const void * LJ_FASTCALL lj_obj_ptr(cTValue *o) ++const void * LJ_FASTCALL lj_obj_ptr(global_State *g, cTValue *o) + { ++ UNUSED(g); + if (tvisudata(o)) + return uddata(udataV(o)); + else if (tvislightud(o)) +- return lightudV(o); ++ return lightudV(g, o); + else if (LJ_HASFFI && tviscdata(o)) + return cdataptr(cdataV(o)); + else if (tvisgcv(o)) +Index: luajit/src/lj_obj.h +=================================================================== +--- luajit.orig/src/lj_obj.h ++++ luajit/src/lj_obj.h +@@ -232,7 +232,7 @@ + ** ---MSW---.---LSW--- + ** primitive types | itype | | + ** lightuserdata | itype | void * | (32 bit platforms) +-** lightuserdata |ffff| void * | (64 bit platforms, 47 bit pointers) ++** lightuserdata |ffff|seg| ofs | (64 bit platforms) + ** GC objects | itype | GCRef | + ** int (LJ_DUALNUM)| itype | int | + ** number -------double------ +@@ -245,7 +245,8 @@ + ** + ** ------MSW------.------LSW------ + ** primitive types |1..1|itype|1..................1| +-** GC objects/lightud |1..1|itype|-------GCRef--------| ++** GC objects |1..1|itype|-------GCRef--------| ++** lightuserdata |1..1|itype|seg|------ofs-------| + ** int (LJ_DUALNUM) |1..1|itype|0..0|-----int-------| + ** number ------------double------------- + ** +@@ -285,6 +286,12 @@ + #define LJ_GCVMASK (((uint64_t)1 << 47) - 1) + #endif + ++#if LJ_64 ++/* To stay within 47 bits, lightuserdata is segmented. */ ++#define LJ_LIGHTUD_BITS_SEG 8 ++#define LJ_LIGHTUD_BITS_LO (47 - LJ_LIGHTUD_BITS_SEG) ++#endif ++ + /* -- String object ------------------------------------------------------- */ + + /* String object header. String payload follows. */ +@@ -576,7 +583,11 @@ + uint8_t currentwhite; /* Current white color. */ + uint8_t state; /* GC state. */ + uint8_t nocdatafin; /* No cdata finalizer called. */ +- uint8_t unused2; ++#if LJ_64 ++ uint8_t lightudnum; /* Number of lightuserdata segments - 1. */ ++#else ++ uint8_t unused1; ++#endif + MSize sweepstr; /* Sweep position in string table. */ + GCRef root; /* List of all collectable objects. */ + MRef sweep; /* Sweep position in root list. */ +@@ -588,6 +599,9 @@ + GCSize estimate; /* Estimate of memory actually in use. */ + MSize stepmul; /* Incremental GC step granularity. */ + MSize pause; /* Pause between successive GC cycles. */ ++#if LJ_64 ++ MRef lightudseg; /* Upper bits of lightuserdata segments. */ ++#endif + } GCState; + + /* Global state, shared by all threads of a Lua universe. */ +@@ -795,10 +809,23 @@ + #endif + #define boolV(o) check_exp(tvisbool(o), (LJ_TFALSE - itype(o))) + #if LJ_64 +-#define lightudV(o) \ +- check_exp(tvislightud(o), (void *)((o)->u64 & U64x(00007fff,ffffffff))) ++#define lightudseg(u) \ ++ (((u) >> LJ_LIGHTUD_BITS_LO) & ((1 << LJ_LIGHTUD_BITS_SEG)-1)) ++#define lightudlo(u) \ ++ ((u) & (((uint64_t)1 << LJ_LIGHTUD_BITS_LO) - 1)) ++#define lightudup(p) \ ++ ((uint32_t)(((p) >> LJ_LIGHTUD_BITS_LO) << (LJ_LIGHTUD_BITS_LO-32))) ++static LJ_AINLINE void *lightudV(global_State *g, cTValue *o) ++{ ++ uint64_t u = o->u64; ++ uint64_t seg = lightudseg(u); ++ uint32_t *segmap = mref(g->gc.lightudseg, uint32_t); ++ lua_assert(tvislightud(o)); ++ lua_assert(seg <= g->gc.lightudnum); ++ return (void *)(((uint64_t)segmap[seg] << 32) | lightudlo(u)); ++} + #else +-#define lightudV(o) check_exp(tvislightud(o), gcrefp((o)->gcr, void)) ++#define lightudV(g, o) check_exp(tvislightud(o), gcrefp((o)->gcr, void)) + #endif + #define gcV(o) check_exp(tvisgcv(o), gcval(o)) + #define strV(o) check_exp(tvisstr(o), &gcval(o)->str) +@@ -824,7 +851,7 @@ + #define setpriV(o, i) (setitype((o), (i))) + #endif + +-static LJ_AINLINE void setlightudV(TValue *o, void *p) ++static LJ_AINLINE void setrawlightudV(TValue *o, void *p) + { + #if LJ_GC64 + o->u64 = (uint64_t)p | (((uint64_t)LJ_TLIGHTUD) << 47); +@@ -835,24 +862,14 @@ + #endif + } + +-#if LJ_64 +-#define checklightudptr(L, p) \ +- (((uint64_t)(p) >> 47) ? (lj_err_msg(L, LJ_ERR_BADLU), NULL) : (p)) +-#else +-#define checklightudptr(L, p) (p) +-#endif +- +-#if LJ_FR2 ++#if LJ_FR2 || LJ_32 + #define contptr(f) ((void *)(f)) + #define setcont(o, f) ((o)->u64 = (uint64_t)(uintptr_t)contptr(f)) +-#elif LJ_64 ++#else + #define contptr(f) \ + ((void *)(uintptr_t)(uint32_t)((intptr_t)(f) - (intptr_t)lj_vm_asm_begin)) + #define setcont(o, f) \ + ((o)->u64 = (uint64_t)(void *)(f) - (uint64_t)lj_vm_asm_begin) +-#else +-#define contptr(f) ((void *)(f)) +-#define setcont(o, f) setlightudV((o), contptr(f)) + #endif + + #define tvchecklive(L, o) \ +@@ -978,6 +995,6 @@ + + /* Compare two objects without calling metamethods. */ + LJ_FUNC int LJ_FASTCALL lj_obj_equal(cTValue *o1, cTValue *o2); +-LJ_FUNC const void * LJ_FASTCALL lj_obj_ptr(cTValue *o); ++LJ_FUNC const void * LJ_FASTCALL lj_obj_ptr(global_State *g, cTValue *o); + + #endif +Index: luajit/src/lj_snap.c +=================================================================== +--- luajit.orig/src/lj_snap.c ++++ luajit/src/lj_snap.c +@@ -626,7 +626,12 @@ + IRType1 t = ir->t; + RegSP rs = ir->prev; + if (irref_isk(ref)) { /* Restore constant slot. */ +- lj_ir_kvalue(J->L, o, ir); ++ if (ir->o == IR_KPTR) { ++ o->u64 = (uint64_t)(uintptr_t)ir_kptr(ir); ++ } else { ++ lua_assert(!(ir->o == IR_KKPTR || ir->o == IR_KNULL)); ++ lj_ir_kvalue(J->L, o, ir); ++ } + return; + } + if (LJ_UNLIKELY(bloomtest(rfilt, ref))) +Index: luajit/src/lj_state.c +=================================================================== +--- luajit.orig/src/lj_state.c ++++ luajit/src/lj_state.c +@@ -171,6 +171,12 @@ + lj_mem_freevec(g, g->strhash, g->strmask+1, GCRef); + lj_buf_free(g, &g->tmpbuf); + lj_mem_freevec(g, tvref(L->stack), L->stacksize, TValue); ++#if LJ_64 ++ if (mref(g->gc.lightudseg, uint32_t)) { ++ MSize segnum = g->gc.lightudnum ? (2 << lj_fls(g->gc.lightudnum)) : 2; ++ lj_mem_freevec(g, mref(g->gc.lightudseg, uint32_t), segnum, uint32_t); ++ } ++#endif + lua_assert(g->gc.total == sizeof(GG_State)); + #ifndef LUAJIT_USE_SYSMALLOC + if (g->allocf == lj_alloc_f) +Index: luajit/src/lj_strfmt.c +=================================================================== +--- luajit.orig/src/lj_strfmt.c ++++ luajit/src/lj_strfmt.c +@@ -393,7 +393,7 @@ + p = lj_buf_wmem(p, "builtin#", 8); + p = lj_strfmt_wint(p, funcV(o)->c.ffid); + } else { +- p = lj_strfmt_wptr(p, lj_obj_ptr(o)); ++ p = lj_strfmt_wptr(p, lj_obj_ptr(G(L), o)); + } + return lj_str_new(L, buf, (size_t)(p - buf)); + } diff --git a/srcpkgs/LuaJIT/template b/srcpkgs/LuaJIT/template index 5b8ab1beda11..778a8df0e593 100644 --- a/srcpkgs/LuaJIT/template +++ b/srcpkgs/LuaJIT/template @@ -1,7 +1,7 @@ # Template file for 'LuaJIT' pkgname=LuaJIT version=2.1.0beta3 -revision=1 +revision=2 _so_version=2.1.0 _dist_version=${_so_version}-beta3 wrksrc="${pkgname}-${_dist_version}"