aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMike Pall <mike>2020-09-30 01:31:27 +0200
committerMike Pall <mike>2020-09-30 01:34:49 +0200
commite9af1abec542e6f9851ff2368e7f196b6382a44c (patch)
tree4b6d76732347a402abb43c6efa5ec3e01a4d61f0 /src
parente67e2040be693122b54fc83797cdc9eb07221aea (diff)
downloadluajit-e9af1abec542e6f9851ff2368e7f196b6382a44c.tar.gz
luajit-e9af1abec542e6f9851ff2368e7f196b6382a44c.tar.bz2
luajit-e9af1abec542e6f9851ff2368e7f196b6382a44c.zip
Add support for full-range 64 bit lightuserdata.
Diffstat (limited to 'src')
-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
16 files changed, 121 insertions, 56 deletions
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 }