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
This commit is contained in:
John 2021-09-25 12:12:27 +02:00 committed by John Zimmermann
parent 9d45acdc53
commit 30253fbfc2
3 changed files with 794 additions and 1 deletions

View file

@ -0,0 +1,231 @@
commit 9da06535092d6d9dec442641a26c64bce5574322
Author: Mike Pall <mike>
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,

View file

@ -0,0 +1,562 @@
From e9af1abec542e6f9851ff2368e7f196b6382a44c Mon Sep 17 00:00:00 2001
From: Mike Pall <mike>
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 @@ <h2>Current Status</h2>
# <tt>lua_atpanic</tt> on x64. This issue will be fixed with the new
# garbage collector.
# </li>
#-<li>
#-LuaJIT on 64 bit systems provides a <b>limited range</b> of 47 bits for the
#-<b>legacy <tt>lightuserdata</tt></b> 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 <tt>lightuserdata</tt> 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.
#-</li>
# </ul>
# <br class="flush">
# </div>
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));
}

View file

@ -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}"