aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/status.html11
-rw-r--r--src/jit/dump.lua4
-rw-r--r--src/lib_debug.c12
-rw-r--r--src/lib_jit.c14
-rw-r--r--src/lib_package.c8
-rw-r--r--src/lib_string.c2
-rw-r--r--src/lj_api.c40
-rw-r--r--src/lj_ccall.c2
-rw-r--r--src/lj_cconv.c2
-rw-r--r--src/lj_crecord.c6
-rw-r--r--src/lj_dispatch.c2
-rw-r--r--src/lj_ir.c6
-rw-r--r--src/lj_obj.c5
-rw-r--r--src/lj_obj.h57
-rw-r--r--src/lj_snap.c9
-rw-r--r--src/lj_state.c6
-rw-r--r--src/lj_strfmt.c2
17 files changed, 121 insertions, 67 deletions
diff --git a/doc/status.html b/doc/status.html
index 0aafe13a..fd0ae8ba 100644
--- a/doc/status.html
+++ b/doc/status.html
@@ -91,17 +91,6 @@ handled correctly. The error may fall through an on-trace
91<tt>lua_atpanic</tt> on x64. This issue will be fixed with the new 91<tt>lua_atpanic</tt> on x64. This issue will be fixed with the new
92garbage collector. 92garbage collector.
93</li> 93</li>
94<li>
95LuaJIT on 64 bit systems provides a <b>limited range</b> of 47 bits for the
96<b>legacy <tt>lightuserdata</tt></b> data type.
97This is only relevant on x64 systems which use the negative part of the
98virtual address space in user mode, e.g. Solaris/x64, and on ARM64 systems
99configured with a 48 bit or 52 bit VA.
100Avoid using <tt>lightuserdata</tt> to hold pointers that may point outside
101of that range, e.g. variables on the stack. In general, avoid this data
102type for new code and replace it with (much more performant) FFI bindings.
103FFI cdata pointers can address the full 64 bit range.
104</li>
105</ul> 94</ul>
106<br class="flush"> 95<br class="flush">
107</div> 96</div>
diff --git a/src/jit/dump.lua b/src/jit/dump.lua
index 0cb38b58..06d1e258 100644
--- a/src/jit/dump.lua
+++ b/src/jit/dump.lua
@@ -315,7 +315,9 @@ local function formatk(tr, idx, sn)
315 local tn = type(k) 315 local tn = type(k)
316 local s 316 local s
317 if tn == "number" then 317 if tn == "number" then
318 if band(sn or 0, 0x30000) ~= 0 then 318 if t < 12 then
319 s = k == 0 and "NULL" or format("[0x%08x]", k)
320 elseif band(sn or 0, 0x30000) ~= 0 then
319 s = band(sn, 0x20000) ~= 0 and "contpc" or "ftsz" 321 s = band(sn, 0x20000) ~= 0 and "contpc" or "ftsz"
320 elseif k == 2^52+2^51 then 322 elseif k == 2^52+2^51 then
321 s = "bias" 323 s = "bias"
diff --git a/src/lib_debug.c b/src/lib_debug.c
index 6737c462..41b30e17 100644
--- a/src/lib_debug.c
+++ b/src/lib_debug.c
@@ -231,8 +231,8 @@ LJLIB_CF(debug_upvalueid)
231 int32_t n = lj_lib_checkint(L, 2) - 1; 231 int32_t n = lj_lib_checkint(L, 2) - 1;
232 if ((uint32_t)n >= fn->l.nupvalues) 232 if ((uint32_t)n >= fn->l.nupvalues)
233 lj_err_arg(L, 2, LJ_ERR_IDXRNG); 233 lj_err_arg(L, 2, LJ_ERR_IDXRNG);
234 setlightudV(L->top-1, isluafunc(fn) ? (void *)gcref(fn->l.uvptr[n]) : 234 lua_pushlightuserdata(L, isluafunc(fn) ? (void *)gcref(fn->l.uvptr[n]) :
235 (void *)&fn->c.upvalue[n]); 235 (void *)&fn->c.upvalue[n]);
236 return 1; 236 return 1;
237} 237}
238 238
@@ -283,13 +283,13 @@ LJLIB_CF(debug_setuservalue)
283 283
284/* ------------------------------------------------------------------------ */ 284/* ------------------------------------------------------------------------ */
285 285
286#define KEY_HOOK ((void *)0x3004) 286#define KEY_HOOK (U64x(80000000,00000000)|'h')
287 287
288static void hookf(lua_State *L, lua_Debug *ar) 288static void hookf(lua_State *L, lua_Debug *ar)
289{ 289{
290 static const char *const hooknames[] = 290 static const char *const hooknames[] =
291 {"call", "return", "line", "count", "tail return"}; 291 {"call", "return", "line", "count", "tail return"};
292 lua_pushlightuserdata(L, KEY_HOOK); 292 (L->top++)->u64 = KEY_HOOK;
293 lua_rawget(L, LUA_REGISTRYINDEX); 293 lua_rawget(L, LUA_REGISTRYINDEX);
294 if (lua_isfunction(L, -1)) { 294 if (lua_isfunction(L, -1)) {
295 lua_pushstring(L, hooknames[(int)ar->event]); 295 lua_pushstring(L, hooknames[(int)ar->event]);
@@ -334,7 +334,7 @@ LJLIB_CF(debug_sethook)
334 count = luaL_optint(L, arg+3, 0); 334 count = luaL_optint(L, arg+3, 0);
335 func = hookf; mask = makemask(smask, count); 335 func = hookf; mask = makemask(smask, count);
336 } 336 }
337 lua_pushlightuserdata(L, KEY_HOOK); 337 (L->top++)->u64 = KEY_HOOK;
338 lua_pushvalue(L, arg+1); 338 lua_pushvalue(L, arg+1);
339 lua_rawset(L, LUA_REGISTRYINDEX); 339 lua_rawset(L, LUA_REGISTRYINDEX);
340 lua_sethook(L, func, mask, count); 340 lua_sethook(L, func, mask, count);
@@ -349,7 +349,7 @@ LJLIB_CF(debug_gethook)
349 if (hook != NULL && hook != hookf) { /* external hook? */ 349 if (hook != NULL && hook != hookf) { /* external hook? */
350 lua_pushliteral(L, "external hook"); 350 lua_pushliteral(L, "external hook");
351 } else { 351 } else {
352 lua_pushlightuserdata(L, KEY_HOOK); 352 (L->top++)->u64 = KEY_HOOK;
353 lua_rawget(L, LUA_REGISTRYINDEX); /* get hook */ 353 lua_rawget(L, LUA_REGISTRYINDEX); /* get hook */
354 } 354 }
355 lua_pushstring(L, unmakemask(mask, buff)); 355 lua_pushstring(L, unmakemask(mask, buff));
diff --git a/src/lib_jit.c b/src/lib_jit.c
index 21e01d3e..dd2628f6 100644
--- a/src/lib_jit.c
+++ b/src/lib_jit.c
@@ -547,15 +547,15 @@ LJLIB_CF(jit_opt_start)
547 547
548/* Not loaded by default, use: local profile = require("jit.profile") */ 548/* Not loaded by default, use: local profile = require("jit.profile") */
549 549
550static const char KEY_PROFILE_THREAD = 't'; 550#define KEY_PROFILE_THREAD (U64x(80000000,00000000)|'t')
551static const char KEY_PROFILE_FUNC = 'f'; 551#define KEY_PROFILE_FUNC (U64x(80000000,00000000)|'f')
552 552
553static void jit_profile_callback(lua_State *L2, lua_State *L, int samples, 553static void jit_profile_callback(lua_State *L2, lua_State *L, int samples,
554 int vmstate) 554 int vmstate)
555{ 555{
556 TValue key; 556 TValue key;
557 cTValue *tv; 557 cTValue *tv;
558 setlightudV(&key, (void *)&KEY_PROFILE_FUNC); 558 key.u64 = KEY_PROFILE_FUNC;
559 tv = lj_tab_get(L, tabV(registry(L)), &key); 559 tv = lj_tab_get(L, tabV(registry(L)), &key);
560 if (tvisfunc(tv)) { 560 if (tvisfunc(tv)) {
561 char vmst = (char)vmstate; 561 char vmst = (char)vmstate;
@@ -582,9 +582,9 @@ LJLIB_CF(jit_profile_start)
582 lua_State *L2 = lua_newthread(L); /* Thread that runs profiler callback. */ 582 lua_State *L2 = lua_newthread(L); /* Thread that runs profiler callback. */
583 TValue key; 583 TValue key;
584 /* Anchor thread and function in registry. */ 584 /* Anchor thread and function in registry. */
585 setlightudV(&key, (void *)&KEY_PROFILE_THREAD); 585 key.u64 = KEY_PROFILE_THREAD;
586 setthreadV(L, lj_tab_set(L, registry, &key), L2); 586 setthreadV(L, lj_tab_set(L, registry, &key), L2);
587 setlightudV(&key, (void *)&KEY_PROFILE_FUNC); 587 key.u64 = KEY_PROFILE_FUNC;
588 setfuncV(L, lj_tab_set(L, registry, &key), func); 588 setfuncV(L, lj_tab_set(L, registry, &key), func);
589 lj_gc_anybarriert(L, registry); 589 lj_gc_anybarriert(L, registry);
590 luaJIT_profile_start(L, mode ? strdata(mode) : "", 590 luaJIT_profile_start(L, mode ? strdata(mode) : "",
@@ -599,9 +599,9 @@ LJLIB_CF(jit_profile_stop)
599 TValue key; 599 TValue key;
600 luaJIT_profile_stop(L); 600 luaJIT_profile_stop(L);
601 registry = tabV(registry(L)); 601 registry = tabV(registry(L));
602 setlightudV(&key, (void *)&KEY_PROFILE_THREAD); 602 key.u64 = KEY_PROFILE_THREAD;
603 setnilV(lj_tab_set(L, registry, &key)); 603 setnilV(lj_tab_set(L, registry, &key));
604 setlightudV(&key, (void *)&KEY_PROFILE_FUNC); 604 key.u64 = KEY_PROFILE_FUNC;
605 setnilV(lj_tab_set(L, registry, &key)); 605 setnilV(lj_tab_set(L, registry, &key));
606 lj_gc_anybarriert(L, registry); 606 lj_gc_anybarriert(L, registry);
607 return 0; 607 return 0;
diff --git a/src/lib_package.c b/src/lib_package.c
index b6917121..752b23b4 100644
--- a/src/lib_package.c
+++ b/src/lib_package.c
@@ -425,7 +425,7 @@ static int lj_cf_package_loader_preload(lua_State *L)
425 425
426/* ------------------------------------------------------------------------ */ 426/* ------------------------------------------------------------------------ */
427 427
428#define sentinel ((void *)0x4004) 428#define KEY_SENTINEL (U64x(80000000,00000000)|'s')
429 429
430static int lj_cf_package_require(lua_State *L) 430static int lj_cf_package_require(lua_State *L)
431{ 431{
@@ -435,7 +435,7 @@ static int lj_cf_package_require(lua_State *L)
435 lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); 435 lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED");
436 lua_getfield(L, 2, name); 436 lua_getfield(L, 2, name);
437 if (lua_toboolean(L, -1)) { /* is it there? */ 437 if (lua_toboolean(L, -1)) { /* is it there? */
438 if (lua_touserdata(L, -1) == sentinel) /* check loops */ 438 if ((L->top-1)->u64 == KEY_SENTINEL) /* check loops */
439 luaL_error(L, "loop or previous error loading module " LUA_QS, name); 439 luaL_error(L, "loop or previous error loading module " LUA_QS, name);
440 return 1; /* package is already loaded */ 440 return 1; /* package is already loaded */
441 } 441 }
@@ -458,14 +458,14 @@ static int lj_cf_package_require(lua_State *L)
458 else 458 else
459 lua_pop(L, 1); 459 lua_pop(L, 1);
460 } 460 }
461 lua_pushlightuserdata(L, sentinel); 461 (L->top++)->u64 = KEY_SENTINEL;
462 lua_setfield(L, 2, name); /* _LOADED[name] = sentinel */ 462 lua_setfield(L, 2, name); /* _LOADED[name] = sentinel */
463 lua_pushstring(L, name); /* pass name as argument to module */ 463 lua_pushstring(L, name); /* pass name as argument to module */
464 lua_call(L, 1, 1); /* run loaded module */ 464 lua_call(L, 1, 1); /* run loaded module */
465 if (!lua_isnil(L, -1)) /* non-nil return? */ 465 if (!lua_isnil(L, -1)) /* non-nil return? */
466 lua_setfield(L, 2, name); /* _LOADED[name] = returned value */ 466 lua_setfield(L, 2, name); /* _LOADED[name] = returned value */
467 lua_getfield(L, 2, name); 467 lua_getfield(L, 2, name);
468 if (lua_touserdata(L, -1) == sentinel) { /* module did not set a value? */ 468 if ((L->top-1)->u64 == KEY_SENTINEL) { /* module did not set a value? */
469 lua_pushboolean(L, 1); /* use true as result */ 469 lua_pushboolean(L, 1); /* use true as result */
470 lua_pushvalue(L, -1); /* extra copy to be returned */ 470 lua_pushvalue(L, -1); /* extra copy to be returned */
471 lua_setfield(L, 2, name); /* _LOADED[name] = true */ 471 lua_setfield(L, 2, name); /* _LOADED[name] = true */
diff --git a/src/lib_string.c b/src/lib_string.c
index 0d9290bc..969e0423 100644
--- a/src/lib_string.c
+++ b/src/lib_string.c
@@ -714,7 +714,7 @@ again:
714 lj_strfmt_putfchar(sb, sf, lj_lib_checkint(L, arg)); 714 lj_strfmt_putfchar(sb, sf, lj_lib_checkint(L, arg));
715 break; 715 break;
716 case STRFMT_PTR: /* No formatting. */ 716 case STRFMT_PTR: /* No formatting. */
717 lj_strfmt_putptr(sb, lj_obj_ptr(L->base+arg-1)); 717 lj_strfmt_putptr(sb, lj_obj_ptr(G(L), L->base+arg-1));
718 break; 718 break;
719 default: 719 default:
720 lj_assertL(0, "bad string format type"); 720 lj_assertL(0, "bad string format type");
diff --git a/src/lj_api.c b/src/lj_api.c
index f53ecc35..ecaf8a2b 100644
--- a/src/lj_api.c
+++ b/src/lj_api.c
@@ -608,7 +608,7 @@ LUA_API void *lua_touserdata(lua_State *L, int idx)
608 if (tvisudata(o)) 608 if (tvisudata(o))
609 return uddata(udataV(o)); 609 return uddata(udataV(o));
610 else if (tvislightud(o)) 610 else if (tvislightud(o))
611 return lightudV(o); 611 return lightudV(G(L), o);
612 else 612 else
613 return NULL; 613 return NULL;
614} 614}
@@ -621,7 +621,7 @@ LUA_API lua_State *lua_tothread(lua_State *L, int idx)
621 621
622LUA_API const void *lua_topointer(lua_State *L, int idx) 622LUA_API const void *lua_topointer(lua_State *L, int idx)
623{ 623{
624 return lj_obj_ptr(index2adr(L, idx)); 624 return lj_obj_ptr(G(L), index2adr(L, idx));
625} 625}
626 626
627/* -- Stack setters (object creation) ------------------------------------- */ 627/* -- Stack setters (object creation) ------------------------------------- */
@@ -707,9 +707,38 @@ LUA_API void lua_pushboolean(lua_State *L, int b)
707 incr_top(L); 707 incr_top(L);
708} 708}
709 709
710#if LJ_64
711static void *lightud_intern(lua_State *L, void *p)
712{
713 global_State *g = G(L);
714 uint64_t u = (uint64_t)p;
715 uint32_t up = lightudup(u);
716 uint32_t *segmap = mref(g->gc.lightudseg, uint32_t);
717 MSize segnum = g->gc.lightudnum;
718 if (segmap) {
719 MSize seg;
720 for (seg = 0; seg <= segnum; seg++)
721 if (segmap[seg] == up) /* Fast path. */
722 return (void *)(((uint64_t)seg << LJ_LIGHTUD_BITS_LO) | lightudlo(u));
723 segnum++;
724 }
725 if (!((segnum-1) & segnum) && segnum != 1) {
726 if (segnum >= (1 << LJ_LIGHTUD_BITS_SEG)) lj_err_msg(L, LJ_ERR_BADLU);
727 lj_mem_reallocvec(L, segmap, segnum, segnum ? 2*segnum : 2u, uint32_t);
728 setmref(g->gc.lightudseg, segmap);
729 }
730 g->gc.lightudnum = segnum;
731 segmap[segnum] = up;
732 return (void *)(((uint64_t)segnum << LJ_LIGHTUD_BITS_LO) | lightudlo(u));
733}
734#endif
735
710LUA_API void lua_pushlightuserdata(lua_State *L, void *p) 736LUA_API void lua_pushlightuserdata(lua_State *L, void *p)
711{ 737{
712 setlightudV(L->top, checklightudptr(L, p)); 738#if LJ_64
739 p = lightud_intern(L, p);
740#endif
741 setrawlightudV(L->top, p);
713 incr_top(L); 742 incr_top(L);
714} 743}
715 744
@@ -1149,7 +1178,10 @@ static TValue *cpcall(lua_State *L, lua_CFunction func, void *ud)
1149 fn->c.f = func; 1178 fn->c.f = func;
1150 setfuncV(L, top++, fn); 1179 setfuncV(L, top++, fn);
1151 if (LJ_FR2) setnilV(top++); 1180 if (LJ_FR2) setnilV(top++);
1152 setlightudV(top++, checklightudptr(L, ud)); 1181#if LJ_64
1182 ud = lightud_intern(L, ud);
1183#endif
1184 setrawlightudV(top++, ud);
1153 cframe_nres(L->cframe) = 1+0; /* Zero results. */ 1185 cframe_nres(L->cframe) = 1+0; /* Zero results. */
1154 L->top = top; 1186 L->top = top;
1155 return top-1; /* Now call the newly allocated C function. */ 1187 return top-1; /* Now call the newly allocated C function. */
diff --git a/src/lj_ccall.c b/src/lj_ccall.c
index 5ac1b4da..c126ddcc 100644
--- a/src/lj_ccall.c
+++ b/src/lj_ccall.c
@@ -1167,7 +1167,7 @@ int lj_ccall_func(lua_State *L, GCcdata *cd)
1167 lj_vm_ffi_call(&cc); 1167 lj_vm_ffi_call(&cc);
1168 if (cts->cb.slot != ~0u) { /* Blacklist function that called a callback. */ 1168 if (cts->cb.slot != ~0u) { /* Blacklist function that called a callback. */
1169 TValue tv; 1169 TValue tv;
1170 setlightudV(&tv, (void *)cc.func); 1170 tv.u64 = ((uintptr_t)(void *)cc.func >> 2) | U64x(800000000, 00000000);
1171 setboolV(lj_tab_set(L, cts->miscmap, &tv), 1); 1171 setboolV(lj_tab_set(L, cts->miscmap, &tv), 1);
1172 } 1172 }
1173 ct = (CType *)((intptr_t)ct+(intptr_t)cts->tab); /* May be reallocated. */ 1173 ct = (CType *)((intptr_t)ct+(intptr_t)cts->tab); /* May be reallocated. */
diff --git a/src/lj_cconv.c b/src/lj_cconv.c
index 400c2ae6..37c8aa1a 100644
--- a/src/lj_cconv.c
+++ b/src/lj_cconv.c
@@ -620,7 +620,7 @@ void lj_cconv_ct_tv(CTState *cts, CType *d,
620 if (ud->udtype == UDTYPE_IO_FILE) 620 if (ud->udtype == UDTYPE_IO_FILE)
621 tmpptr = *(void **)tmpptr; 621 tmpptr = *(void **)tmpptr;
622 } else if (tvislightud(o)) { 622 } else if (tvislightud(o)) {
623 tmpptr = lightudV(o); 623 tmpptr = lightudV(cts->g, o);
624 } else if (tvisfunc(o)) { 624 } else if (tvisfunc(o)) {
625 void *p = lj_ccallback_new(cts, d, funcV(o)); 625 void *p = lj_ccallback_new(cts, d, funcV(o));
626 if (p) { 626 if (p) {
diff --git a/src/lj_crecord.c b/src/lj_crecord.c
index 7ae1479e..f6824bff 100644
--- a/src/lj_crecord.c
+++ b/src/lj_crecord.c
@@ -646,8 +646,7 @@ static TRef crec_ct_tv(jit_State *J, CType *d, TRef dp, TRef sp, cTValue *sval)
646 } 646 }
647 } else if (tref_islightud(sp)) { 647 } else if (tref_islightud(sp)) {
648#if LJ_64 648#if LJ_64
649 sp = emitir(IRT(IR_BAND, IRT_P64), sp, 649 lj_trace_err(J, LJ_TRERR_NYICONV);
650 lj_ir_kint64(J, U64x(00007fff,ffffffff)));
651#endif 650#endif
652 } else { /* NYI: tref_istab(sp). */ 651 } else { /* NYI: tref_istab(sp). */
653 IRType t; 652 IRType t;
@@ -1212,8 +1211,7 @@ static int crec_call(jit_State *J, RecordFFData *rd, GCcdata *cd)
1212 TRef tr; 1211 TRef tr;
1213 TValue tv; 1212 TValue tv;
1214 /* Check for blacklisted C functions that might call a callback. */ 1213 /* Check for blacklisted C functions that might call a callback. */
1215 setlightudV(&tv, 1214 tv.u64 = ((uintptr_t)cdata_getptr(cdataptr(cd), (LJ_64 && tp == IRT_P64) ? 8 : 4) >> 2) | U64x(800000000, 00000000);
1216 cdata_getptr(cdataptr(cd), (LJ_64 && tp == IRT_P64) ? 8 : 4));
1217 if (tvistrue(lj_tab_get(J->L, cts->miscmap, &tv))) 1215 if (tvistrue(lj_tab_get(J->L, cts->miscmap, &tv)))
1218 lj_trace_err(J, LJ_TRERR_BLACKL); 1216 lj_trace_err(J, LJ_TRERR_BLACKL);
1219 if (ctype_isvoid(ctr->info)) { 1217 if (ctype_isvoid(ctr->info)) {
diff --git a/src/lj_dispatch.c b/src/lj_dispatch.c
index c608e223..1d0ff549 100644
--- a/src/lj_dispatch.c
+++ b/src/lj_dispatch.c
@@ -295,7 +295,7 @@ int luaJIT_setmode(lua_State *L, int idx, int mode)
295 if (idx != 0) { 295 if (idx != 0) {
296 cTValue *tv = idx > 0 ? L->base + (idx-1) : L->top + idx; 296 cTValue *tv = idx > 0 ? L->base + (idx-1) : L->top + idx;
297 if (tvislightud(tv)) 297 if (tvislightud(tv))
298 g->wrapf = (lua_CFunction)lightudV(tv); 298 g->wrapf = (lua_CFunction)lightudV(g, tv);
299 else 299 else
300 return 0; /* Failed. */ 300 return 0; /* Failed. */
301 } else { 301 } else {
diff --git a/src/lj_ir.c b/src/lj_ir.c
index b5e94eb8..3ce29954 100644
--- a/src/lj_ir.c
+++ b/src/lj_ir.c
@@ -389,8 +389,10 @@ void lj_ir_kvalue(lua_State *L, TValue *tv, const IRIns *ir)
389 case IR_KPRI: setpriV(tv, irt_toitype(ir->t)); break; 389 case IR_KPRI: setpriV(tv, irt_toitype(ir->t)); break;
390 case IR_KINT: setintV(tv, ir->i); break; 390 case IR_KINT: setintV(tv, ir->i); break;
391 case IR_KGC: setgcV(L, tv, ir_kgc(ir), irt_toitype(ir->t)); break; 391 case IR_KGC: setgcV(L, tv, ir_kgc(ir), irt_toitype(ir->t)); break;
392 case IR_KPTR: case IR_KKPTR: setlightudV(tv, ir_kptr(ir)); break; 392 case IR_KPTR: case IR_KKPTR:
393 case IR_KNULL: setlightudV(tv, NULL); break; 393 setnumV(tv, (lua_Number)(uintptr_t)ir_kptr(ir));
394 break;
395 case IR_KNULL: setintV(tv, 0); break;
394 case IR_KNUM: setnumV(tv, ir_knum(ir)->n); break; 396 case IR_KNUM: setnumV(tv, ir_knum(ir)->n); break;
395#if LJ_HASFFI 397#if LJ_HASFFI
396 case IR_KINT64: { 398 case IR_KINT64: {
diff --git a/src/lj_obj.c b/src/lj_obj.c
index 5d16e0e5..6458c6ad 100644
--- a/src/lj_obj.c
+++ b/src/lj_obj.c
@@ -34,12 +34,13 @@ int LJ_FASTCALL lj_obj_equal(cTValue *o1, cTValue *o2)
34} 34}
35 35
36/* Return pointer to object or its object data. */ 36/* Return pointer to object or its object data. */
37const void * LJ_FASTCALL lj_obj_ptr(cTValue *o) 37const void * LJ_FASTCALL lj_obj_ptr(global_State *g, cTValue *o)
38{ 38{
39 UNUSED(g);
39 if (tvisudata(o)) 40 if (tvisudata(o))
40 return uddata(udataV(o)); 41 return uddata(udataV(o));
41 else if (tvislightud(o)) 42 else if (tvislightud(o))
42 return lightudV(o); 43 return lightudV(g, o);
43 else if (LJ_HASFFI && tviscdata(o)) 44 else if (LJ_HASFFI && tviscdata(o))
44 return cdataptr(cdataV(o)); 45 return cdataptr(cdataV(o));
45 else if (tvisgcv(o)) 46 else if (tvisgcv(o))
diff --git a/src/lj_obj.h b/src/lj_obj.h
index 9d4bec08..9a783a5c 100644
--- a/src/lj_obj.h
+++ b/src/lj_obj.h
@@ -232,7 +232,7 @@ typedef const TValue cTValue;
232** ---MSW---.---LSW--- 232** ---MSW---.---LSW---
233** primitive types | itype | | 233** primitive types | itype | |
234** lightuserdata | itype | void * | (32 bit platforms) 234** lightuserdata | itype | void * | (32 bit platforms)
235** lightuserdata |ffff| void * | (64 bit platforms, 47 bit pointers) 235** lightuserdata |ffff|seg| ofs | (64 bit platforms)
236** GC objects | itype | GCRef | 236** GC objects | itype | GCRef |
237** int (LJ_DUALNUM)| itype | int | 237** int (LJ_DUALNUM)| itype | int |
238** number -------double------ 238** number -------double------
@@ -245,7 +245,8 @@ typedef const TValue cTValue;
245** 245**
246** ------MSW------.------LSW------ 246** ------MSW------.------LSW------
247** primitive types |1..1|itype|1..................1| 247** primitive types |1..1|itype|1..................1|
248** GC objects/lightud |1..1|itype|-------GCRef--------| 248** GC objects |1..1|itype|-------GCRef--------|
249** lightuserdata |1..1|itype|seg|------ofs-------|
249** int (LJ_DUALNUM) |1..1|itype|0..0|-----int-------| 250** int (LJ_DUALNUM) |1..1|itype|0..0|-----int-------|
250** number ------------double------------- 251** number ------------double-------------
251** 252**
@@ -285,6 +286,12 @@ typedef const TValue cTValue;
285#define LJ_GCVMASK (((uint64_t)1 << 47) - 1) 286#define LJ_GCVMASK (((uint64_t)1 << 47) - 1)
286#endif 287#endif
287 288
289#if LJ_64
290/* To stay within 47 bits, lightuserdata is segmented. */
291#define LJ_LIGHTUD_BITS_SEG 8
292#define LJ_LIGHTUD_BITS_LO (47 - LJ_LIGHTUD_BITS_SEG)
293#endif
294
288/* -- String object ------------------------------------------------------- */ 295/* -- String object ------------------------------------------------------- */
289 296
290typedef uint32_t StrHash; /* String hash value. */ 297typedef uint32_t StrHash; /* String hash value. */
@@ -580,7 +587,11 @@ typedef struct GCState {
580 uint8_t currentwhite; /* Current white color. */ 587 uint8_t currentwhite; /* Current white color. */
581 uint8_t state; /* GC state. */ 588 uint8_t state; /* GC state. */
582 uint8_t nocdatafin; /* No cdata finalizer called. */ 589 uint8_t nocdatafin; /* No cdata finalizer called. */
583 uint8_t unused2; 590#if LJ_64
591 uint8_t lightudnum; /* Number of lightuserdata segments - 1. */
592#else
593 uint8_t unused1;
594#endif
584 MSize sweepstr; /* Sweep position in string table. */ 595 MSize sweepstr; /* Sweep position in string table. */
585 GCRef root; /* List of all collectable objects. */ 596 GCRef root; /* List of all collectable objects. */
586 MRef sweep; /* Sweep position in root list. */ 597 MRef sweep; /* Sweep position in root list. */
@@ -592,6 +603,9 @@ typedef struct GCState {
592 GCSize estimate; /* Estimate of memory actually in use. */ 603 GCSize estimate; /* Estimate of memory actually in use. */
593 MSize stepmul; /* Incremental GC step granularity. */ 604 MSize stepmul; /* Incremental GC step granularity. */
594 MSize pause; /* Pause between successive GC cycles. */ 605 MSize pause; /* Pause between successive GC cycles. */
606#if LJ_64
607 MRef lightudseg; /* Upper bits of lightuserdata segments. */
608#endif
595} GCState; 609} GCState;
596 610
597/* String interning state. */ 611/* String interning state. */
@@ -813,10 +827,23 @@ typedef union GCobj {
813#endif 827#endif
814#define boolV(o) check_exp(tvisbool(o), (LJ_TFALSE - itype(o))) 828#define boolV(o) check_exp(tvisbool(o), (LJ_TFALSE - itype(o)))
815#if LJ_64 829#if LJ_64
816#define lightudV(o) \ 830#define lightudseg(u) \
817 check_exp(tvislightud(o), (void *)((o)->u64 & U64x(00007fff,ffffffff))) 831 (((u) >> LJ_LIGHTUD_BITS_LO) & ((1 << LJ_LIGHTUD_BITS_SEG)-1))
832#define lightudlo(u) \
833 ((u) & (((uint64_t)1 << LJ_LIGHTUD_BITS_LO) - 1))
834#define lightudup(p) \
835 ((uint32_t)(((p) >> LJ_LIGHTUD_BITS_LO) << (LJ_LIGHTUD_BITS_LO-32)))
836static LJ_AINLINE void *lightudV(global_State *g, cTValue *o)
837{
838 uint64_t u = o->u64;
839 uint64_t seg = lightudseg(u);
840 uint32_t *segmap = mref(g->gc.lightudseg, uint32_t);
841 lj_assertG(tvislightud(o), "lightuserdata expected");
842 lj_assertG(seg <= g->gc.lightudnum, "bad lightuserdata segment %d", seg);
843 return (void *)(((uint64_t)segmap[seg] << 32) | lightudlo(u));
844}
818#else 845#else
819#define lightudV(o) check_exp(tvislightud(o), gcrefp((o)->gcr, void)) 846#define lightudV(g, o) check_exp(tvislightud(o), gcrefp((o)->gcr, void))
820#endif 847#endif
821#define gcV(o) check_exp(tvisgcv(o), gcval(o)) 848#define gcV(o) check_exp(tvisgcv(o), gcval(o))
822#define strV(o) check_exp(tvisstr(o), &gcval(o)->str) 849#define strV(o) check_exp(tvisstr(o), &gcval(o)->str)
@@ -842,7 +869,7 @@ typedef union GCobj {
842#define setpriV(o, i) (setitype((o), (i))) 869#define setpriV(o, i) (setitype((o), (i)))
843#endif 870#endif
844 871
845static LJ_AINLINE void setlightudV(TValue *o, void *p) 872static LJ_AINLINE void setrawlightudV(TValue *o, void *p)
846{ 873{
847#if LJ_GC64 874#if LJ_GC64
848 o->u64 = (uint64_t)p | (((uint64_t)LJ_TLIGHTUD) << 47); 875 o->u64 = (uint64_t)p | (((uint64_t)LJ_TLIGHTUD) << 47);
@@ -853,24 +880,14 @@ static LJ_AINLINE void setlightudV(TValue *o, void *p)
853#endif 880#endif
854} 881}
855 882
856#if LJ_64 883#if LJ_FR2 || LJ_32
857#define checklightudptr(L, p) \
858 (((uint64_t)(p) >> 47) ? (lj_err_msg(L, LJ_ERR_BADLU), NULL) : (p))
859#else
860#define checklightudptr(L, p) (p)
861#endif
862
863#if LJ_FR2
864#define contptr(f) ((void *)(f)) 884#define contptr(f) ((void *)(f))
865#define setcont(o, f) ((o)->u64 = (uint64_t)(uintptr_t)contptr(f)) 885#define setcont(o, f) ((o)->u64 = (uint64_t)(uintptr_t)contptr(f))
866#elif LJ_64 886#else
867#define contptr(f) \ 887#define contptr(f) \
868 ((void *)(uintptr_t)(uint32_t)((intptr_t)(f) - (intptr_t)lj_vm_asm_begin)) 888 ((void *)(uintptr_t)(uint32_t)((intptr_t)(f) - (intptr_t)lj_vm_asm_begin))
869#define setcont(o, f) \ 889#define setcont(o, f) \
870 ((o)->u64 = (uint64_t)(void *)(f) - (uint64_t)lj_vm_asm_begin) 890 ((o)->u64 = (uint64_t)(void *)(f) - (uint64_t)lj_vm_asm_begin)
871#else
872#define contptr(f) ((void *)(f))
873#define setcont(o, f) setlightudV((o), contptr(f))
874#endif 891#endif
875 892
876static LJ_AINLINE void checklivetv(lua_State *L, TValue *o, const char *msg) 893static LJ_AINLINE void checklivetv(lua_State *L, TValue *o, const char *msg)
@@ -1016,6 +1033,6 @@ LJ_DATA const char *const lj_obj_itypename[~LJ_TNUMX+1];
1016 1033
1017/* Compare two objects without calling metamethods. */ 1034/* Compare two objects without calling metamethods. */
1018LJ_FUNC int LJ_FASTCALL lj_obj_equal(cTValue *o1, cTValue *o2); 1035LJ_FUNC int LJ_FASTCALL lj_obj_equal(cTValue *o1, cTValue *o2);
1019LJ_FUNC const void * LJ_FASTCALL lj_obj_ptr(cTValue *o); 1036LJ_FUNC const void * LJ_FASTCALL lj_obj_ptr(global_State *g, cTValue *o);
1020 1037
1021#endif 1038#endif
diff --git a/src/lj_snap.c b/src/lj_snap.c
index 36f81528..f1358cf2 100644
--- a/src/lj_snap.c
+++ b/src/lj_snap.c
@@ -638,7 +638,14 @@ static void snap_restoreval(jit_State *J, GCtrace *T, ExitState *ex,
638 IRType1 t = ir->t; 638 IRType1 t = ir->t;
639 RegSP rs = ir->prev; 639 RegSP rs = ir->prev;
640 if (irref_isk(ref)) { /* Restore constant slot. */ 640 if (irref_isk(ref)) { /* Restore constant slot. */
641 lj_ir_kvalue(J->L, o, ir); 641 if (ir->o == IR_KPTR) {
642 o->u64 = (uint64_t)(uintptr_t)ir_kptr(ir);
643 } else {
644 lj_assertJ(!(ir->o == IR_KKPTR || ir->o == IR_KNULL),
645 "restore of const from IR %04d with bad op %d",
646 ref - REF_BIAS, ir->o);
647 lj_ir_kvalue(J->L, o, ir);
648 }
642 return; 649 return;
643 } 650 }
644 if (LJ_UNLIKELY(bloomtest(rfilt, ref))) 651 if (LJ_UNLIKELY(bloomtest(rfilt, ref)))
diff --git a/src/lj_state.c b/src/lj_state.c
index 4f77e71f..2b031d97 100644
--- a/src/lj_state.c
+++ b/src/lj_state.c
@@ -174,6 +174,12 @@ static void close_state(lua_State *L)
174 lj_str_freetab(g); 174 lj_str_freetab(g);
175 lj_buf_free(g, &g->tmpbuf); 175 lj_buf_free(g, &g->tmpbuf);
176 lj_mem_freevec(g, tvref(L->stack), L->stacksize, TValue); 176 lj_mem_freevec(g, tvref(L->stack), L->stacksize, TValue);
177#if LJ_64
178 if (mref(g->gc.lightudseg, uint32_t)) {
179 MSize segnum = g->gc.lightudnum ? (2 << lj_fls(g->gc.lightudnum)) : 2;
180 lj_mem_freevec(g, mref(g->gc.lightudseg, uint32_t), segnum, uint32_t);
181 }
182#endif
177 lj_assertG(g->gc.total == sizeof(GG_State), 183 lj_assertG(g->gc.total == sizeof(GG_State),
178 "memory leak of %lld bytes", 184 "memory leak of %lld bytes",
179 (long long)(g->gc.total - sizeof(GG_State))); 185 (long long)(g->gc.total - sizeof(GG_State)));
diff --git a/src/lj_strfmt.c b/src/lj_strfmt.c
index 331d9474..207c544e 100644
--- a/src/lj_strfmt.c
+++ b/src/lj_strfmt.c
@@ -393,7 +393,7 @@ GCstr * LJ_FASTCALL lj_strfmt_obj(lua_State *L, cTValue *o)
393 p = lj_buf_wmem(p, "builtin#", 8); 393 p = lj_buf_wmem(p, "builtin#", 8);
394 p = lj_strfmt_wint(p, funcV(o)->c.ffid); 394 p = lj_strfmt_wint(p, funcV(o)->c.ffid);
395 } else { 395 } else {
396 p = lj_strfmt_wptr(p, lj_obj_ptr(o)); 396 p = lj_strfmt_wptr(p, lj_obj_ptr(G(L), o));
397 } 397 }
398 return lj_str_new(L, buf, (size_t)(p - buf)); 398 return lj_str_new(L, buf, (size_t)(p - buf));
399 } 399 }