Proposals for fixing light userdata issue on virtual address > 47 bits platform

  • From: Zhongwei Yao <zhongwei.yao@xxxxxxxxxx>
  • To: luajit@xxxxxxxxxxxxx
  • Date: Fri, 5 May 2017 10:11:14 +0800

Hi, all,

Current LuaJIT's light userdata will cause errors when its payload value is
larger than 47 bits (e.g. ARM64 platform). Here are 2 cases:
  -. lua_cpcall Lua API
      -. an example is attached in the file: foo.c
      -. this issue is also mentioned at
https://github.com/LuaJIT/LuaJIT/issues/255
  -. luaJIT_setmode Luajit API's LUAJIT_MODE_WRAPCFUNC

Here are my 2 proposals to work around this issue. Which one do you prefer?
Or do you have other suggestions?

1. wrap light userdata in userdata for everywhere light userdata is used.
    pros: Lua application code needs not any update.
    cons: many parts of Luajit needs to be patched. For example Lua API,
bytecode implementation, IR implementation etc. Please refer my draft patch
for details.

    I've worked out a draft patch for this proposal with a lot "FIXME"s:
https://github.com/zhongweiy/LuaJIT/commit/a18262b71c0bd6164258d60e3cf5d0e8846da088
. And the modification (includes FIXME) may be incomplete. Please tell me
if you find any missing.

2. provide alternative Lua API work around this issue. (refer foo.c and
lua_cpcall2 for details)
    pros: compared with proposal 1, this fix in Luajit is relatively easy.
    cons: user application code also needs an update.

    Here is one possible new API (lua_cpcall2) for lua_cpcall:
*https://github.com/zhongweiy/LuaJIT/commit/657b641d929608c04ec4efba0f176f91170733ac
<https://github.com/zhongweiy/LuaJIT/commit/657b641d929608c04ec4efba0f176f91170733ac>*

    Workaround for luaJIT_setmode() is similar:
        - Application use userdata to wrap light userdata and push to Lua.
        - Application call luaJIT_setmode(L, idx, LUAJIT_MODE_WRAPCFUNC2).
        - In Luajit, VM will get userdata specified by idx and then unwrap
it to get the user passed function pointer.


-- 
Best regards,
Zhongwei
#include <stdio.h>
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>

int callback(lua_State *L) {
  int *p = (int *)lua_touserdata(L, -1);
  *p = 119;
  return 0; //Number of values on stack to 'return' to lua.
}

int callback2(lua_State *L) {
    int **ud = (int **)lua_touserdata(L, -1);
    **ud = 2;
    return 0;
}

int main(int argc, char *argv[])
{
    lua_State *L = luaL_newstate();
    if (!L)
        return 1;

    luaL_openlibs(L);

    int x = 3;
    printf("before lua_cpcall: x (addr:%p) = %d\n", &x, x);
    int status = lua_cpcall(L, callback, &x);
    if (status != 0) {
      fprintf(stderr, "luajit internal error (error no:%d): %s\n", status, 
lua_tostring(L, -1));
      lua_pop(L, 1);
    } else {
      printf("after lua_cpcall: x = %d\n", x);
    }

    lua_close(L);
    return 0;
}

Other related posts:

  • » Proposals for fixing light userdata issue on virtual address > 47 bits platform - Zhongwei Yao