diff options
-rw-r--r-- | doc/status.html | 11 | ||||
-rw-r--r-- | src/jit/dump.lua | 4 | ||||
-rw-r--r-- | src/lib_debug.c | 12 | ||||
-rw-r--r-- | src/lib_jit.c | 14 | ||||
-rw-r--r-- | src/lib_package.c | 8 | ||||
-rw-r--r-- | src/lib_string.c | 2 | ||||
-rw-r--r-- | src/lj_api.c | 40 | ||||
-rw-r--r-- | src/lj_ccall.c | 2 | ||||
-rw-r--r-- | src/lj_cconv.c | 2 | ||||
-rw-r--r-- | src/lj_crecord.c | 6 | ||||
-rw-r--r-- | src/lj_dispatch.c | 2 | ||||
-rw-r--r-- | src/lj_ir.c | 6 | ||||
-rw-r--r-- | src/lj_obj.c | 5 | ||||
-rw-r--r-- | src/lj_obj.h | 57 | ||||
-rw-r--r-- | src/lj_snap.c | 9 | ||||
-rw-r--r-- | src/lj_state.c | 6 | ||||
-rw-r--r-- | src/lj_strfmt.c | 2 |
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 |
92 | garbage collector. | 92 | garbage collector. |
93 | </li> | 93 | </li> |
94 | <li> | ||
95 | LuaJIT on 64 bit systems provides a <b>limited range</b> of 47 bits for the | ||
96 | <b>legacy <tt>lightuserdata</tt></b> data type. | ||
97 | This is only relevant on x64 systems which use the negative part of the | ||
98 | virtual address space in user mode, e.g. Solaris/x64, and on ARM64 systems | ||
99 | configured with a 48 bit or 52 bit VA. | ||
100 | Avoid using <tt>lightuserdata</tt> to hold pointers that may point outside | ||
101 | of that range, e.g. variables on the stack. In general, avoid this data | ||
102 | type for new code and replace it with (much more performant) FFI bindings. | ||
103 | FFI 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 | ||
288 | static void hookf(lua_State *L, lua_Debug *ar) | 288 | static 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 | ||
550 | static const char KEY_PROFILE_THREAD = 't'; | 550 | #define KEY_PROFILE_THREAD (U64x(80000000,00000000)|'t') |
551 | static const char KEY_PROFILE_FUNC = 'f'; | 551 | #define KEY_PROFILE_FUNC (U64x(80000000,00000000)|'f') |
552 | 552 | ||
553 | static void jit_profile_callback(lua_State *L2, lua_State *L, int samples, | 553 | static 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 | ||
430 | static int lj_cf_package_require(lua_State *L) | 430 | static 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 | ||
622 | LUA_API const void *lua_topointer(lua_State *L, int idx) | 622 | LUA_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 | ||
711 | static 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 | |||
710 | LUA_API void lua_pushlightuserdata(lua_State *L, void *p) | 736 | LUA_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. */ |
37 | const void * LJ_FASTCALL lj_obj_ptr(cTValue *o) | 37 | const 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 | ||
290 | typedef uint32_t StrHash; /* String hash value. */ | 297 | typedef 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))) | ||
836 | static 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 | ||
845 | static LJ_AINLINE void setlightudV(TValue *o, void *p) | 872 | static 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 | ||
876 | static LJ_AINLINE void checklivetv(lua_State *L, TValue *o, const char *msg) | 893 | static 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. */ |
1018 | LJ_FUNC int LJ_FASTCALL lj_obj_equal(cTValue *o1, cTValue *o2); | 1035 | LJ_FUNC int LJ_FASTCALL lj_obj_equal(cTValue *o1, cTValue *o2); |
1019 | LJ_FUNC const void * LJ_FASTCALL lj_obj_ptr(cTValue *o); | 1036 | LJ_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 | } |