sginsberg

Lua Proxy Patch

Jan 25th, 2020
451
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1.  src/lapi.c     | 35 +++++++++++++++++++++++++++++++++++
  2.  src/lbaselib.c | 30 ++++++++++++++++++++++++++++++
  3.  src/ldo.c      |  4 ++++
  4.  src/lgc.c      | 18 ++++++++++++++++++
  5.  src/lobject.h  | 25 +++++++++++++++++++++++++
  6.  src/lstate.h   |  6 ++++++
  7.  src/ltm.c      | 40 ++++++++++++++++++++++++++++++++++++++++
  8.  src/lua.h      | 11 +++++++++++
  9.  src/luaconf.h  |  1 +
  10.  src/lvm.c      | 24 ++++++++++++++++++++++++
  11.  10 files changed, 194 insertions(+)
  12.  
  13. diff --git src/lapi.c src/lapi.c
  14. index 02b7fab..3f7b3b0 100644
  15. --- src/lapi.c
  16. +++ src/lapi.c
  17. @@ -436,6 +436,9 @@ LUA_API const void *lua_topointer (lua_State *L, int idx) {
  18.      case LUA_TTHREAD: return thvalue(o);
  19.      case LUA_TUSERDATA: return getudatamem(uvalue(o));
  20.      case LUA_TLIGHTUSERDATA: return pvalue(o);
  21. +#if defined(LUA_PROXY_ENABLED)
  22. +    case LUA_TPROXY: return pxvalue(o);
  23. +#endif
  24.      default: return NULL;
  25.    }
  26.  }
  27. @@ -707,6 +710,11 @@ LUA_API int lua_getmetatable (lua_State *L, int objindex) {
  28.      case LUA_TUSERDATA:
  29.        mt = uvalue(obj)->metatable;
  30.        break;
  31. +#if defined(LUA_PROXY_ENABLED)
  32. +    case LUA_TPROXY:
  33. +      mt = pxvalue(obj)->metatable;
  34. +      break;
  35. +#endif
  36.      default:
  37.        mt = G(L)->mt[ttnov(obj)];
  38.        break;
  39. @@ -872,6 +880,16 @@ LUA_API int lua_setmetatable (lua_State *L, int objindex) {
  40.        }
  41.        break;
  42.      }
  43. +#if defined(LUA_PROXY_ENABLED)
  44. +    case LUA_TPROXY: {
  45. +      pxvalue(obj)->metatable = mt;
  46. +      if (mt) {
  47. +        luaC_objbarrier(L, gcvalue(obj), mt);
  48. +        luaC_checkfinalizer(L, gcvalue(obj), mt);
  49. +      }
  50. +      break;
  51. +    }
  52. +#endif
  53.      default: {
  54.        G(L)->mt[ttnov(obj)] = mt;
  55.        break;
  56. @@ -1297,3 +1315,20 @@ LUA_API void lua_upvaluejoin (lua_State *L, int fidx1, int n1,
  57.  }
  58.  
  59.  
  60. +#if defined(LUA_PROXY_ENABLED)
  61. +/* Envelops a value at the given index and pushes the proxy unto the stack */
  62. +LUA_API void lua_envelop (lua_State *L, int idx) {
  63. +  GCObject *o;
  64. +  Proxy *px;
  65. +  lua_lock(L);
  66. +  o = luaC_newobj(L, LUA_TPROXY, sizeof(Proxy));
  67. +  px = gco2px(o);
  68. +  px->value = *index2addr(L, idx);  /* set enveloped value */
  69. +  px->metatable = NULL;  /* no initial metatable */
  70. +  setpxvalue(L, L->top, px);
  71. +  api_incr_top(L);
  72. +  lua_unlock(L);
  73. +}
  74. +#endif
  75. +
  76. +
  77. diff --git src/lbaselib.c src/lbaselib.c
  78. index 6460e4f..7c50ed4 100644
  79. --- src/lbaselib.c
  80. +++ src/lbaselib.c
  81. @@ -123,10 +123,20 @@ static int luaB_getmetatable (lua_State *L) {
  82.  
  83.  
  84.  static int luaB_setmetatable (lua_State *L) {
  85. +#if !defined(LUA_PROXY_ENABLED)
  86.    int t = lua_type(L, 2);
  87.    luaL_checktype(L, 1, LUA_TTABLE);
  88.    luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2,
  89.                      "nil or table expected");
  90. +#else
  91. +  int t1, t2;
  92. +  t1  = lua_type(L, 1);
  93. +  luaL_argcheck(L, t1 == LUA_TTABLE || t1 == LUA_TPROXY, 1,
  94. +                    "table or proxy expected");
  95. +  t2 = lua_type(L, 2);
  96. +  luaL_argcheck(L, t2 == LUA_TNIL || t2 == LUA_TTABLE, 2,
  97. +                    "nil or table expected");  
  98. +#endif
  99.    if (luaL_getmetafield(L, 1, "__metatable") != LUA_TNIL)
  100.      return luaL_error(L, "cannot change a protected metatable");
  101.    lua_settop(L, 2);
  102. @@ -450,10 +460,30 @@ static int luaB_tostring (lua_State *L) {
  103.  }
  104.  
  105.  
  106. +#if defined(LUA_PROXY_ENABLED)
  107. +/* proxy = envelop(value, metatable) */
  108. +static int luaB_envelop (lua_State *L) {
  109. +  luaL_checkany(L, 1);
  110. +  if (!lua_isnoneornil(L, 2)) {  /* have metatable? */
  111. +    luaL_checktype(L, 2, LUA_TTABLE);
  112. +    lua_envelop(L, 1);
  113. +    lua_pushvalue(L, 2);
  114. +    lua_setmetatable(L, -2);
  115. +  }
  116. +  else  /* no metatable */
  117. +    lua_envelop(L, 1);
  118. +  return 1;
  119. +}
  120. +#endif
  121. +
  122. +
  123.  static const luaL_Reg base_funcs[] = {
  124.    {"assert", luaB_assert},
  125.    {"collectgarbage", luaB_collectgarbage},
  126.    {"dofile", luaB_dofile},
  127. +#if defined(LUA_PROXY_ENABLED)
  128. +  {"envelop", luaB_envelop},
  129. +#endif
  130.    {"error", luaB_error},
  131.    {"getmetatable", luaB_getmetatable},
  132.    {"ipairs", luaB_ipairs},
  133. diff --git src/ldo.c src/ldo.c
  134. index 316e45c..c8b0db4 100644
  135. --- src/ldo.c
  136. +++ src/ldo.c
  137. @@ -317,6 +317,10 @@ static void tryfuncTM (lua_State *L, StkId func) {
  138.    StkId p;
  139.    if (!ttisfunction(tm))
  140.      luaG_typeerror(L, func, "call");
  141. +#if defined(LUA_PROXY_ENABLED)
  142. +  if (ttisproxy(func))
  143. +    setobj2s(L, func, &pxvalue(func)->value);
  144. +#endif
  145.    /* Open a hole inside the stack at 'func' */
  146.    for (p = L->top; p > func; p--)
  147.      setobjs2s(L, p, p-1);
  148. diff --git src/lgc.c src/lgc.c
  149. index db4df82..2a68eba 100644
  150. --- src/lgc.c
  151. +++ src/lgc.c
  152. @@ -278,6 +278,18 @@ static void reallymarkobject (global_State *g, GCObject *o) {
  153.        linkgclist(gco2p(o), g->gray);
  154.        break;
  155.      }
  156. +#if defined(LUA_PROXY_ENABLED)
  157. +    case LUA_TPROXY: {
  158. +      Proxy *px = gco2px(o);
  159. +      if (iscollectable(&px->value)) {  /* mark value if required */
  160. +        markobject(g, gcvalue(&px->value));
  161. +      }
  162. +      markobjectN(g, px->metatable);  /* mark any metatable */
  163. +      gray2black(o);
  164. +      g->GCmemtrav += sizeof(Proxy);
  165. +      break;
  166. +    }
  167. +#endif
  168.      default: lua_assert(0); break;
  169.    }
  170.  }
  171. @@ -716,6 +728,12 @@ static void freeobj (lua_State *L, GCObject *o) {
  172.        luaM_freemem(L, o, sizelstring(gco2ts(o)->u.lnglen));
  173.        break;
  174.      }
  175. +#if defined(LUA_PROXY_ENABLED)
  176. +    case LUA_TPROXY: {
  177. +      luaM_freemem(L, o, sizeof(Proxy));
  178. +      break;
  179. +    }
  180. +#endif
  181.      default: lua_assert(0);
  182.    }
  183.  }
  184. diff --git src/lobject.h src/lobject.h
  185. index 2408861..52e4ae7 100644
  186. --- src/lobject.h
  187. +++ src/lobject.h
  188. @@ -156,6 +156,9 @@ typedef struct lua_TValue {
  189.  #define ttislcf(o)     checktag((o), LUA_TLCF)
  190.  #define ttisfulluserdata(o)    checktag((o), ctb(LUA_TUSERDATA))
  191.  #define ttisthread(o)      checktag((o), ctb(LUA_TTHREAD))
  192. +#if defined(LUA_PROXY_ENABLED)
  193. +#define ttisproxy(o)       checktag((o), ctb(LUA_TPROXY))
  194. +#endif
  195.  #define ttisdeadkey(o)     checktag((o), LUA_TDEADKEY)
  196.  
  197.  
  198. @@ -175,6 +178,9 @@ typedef struct lua_TValue {
  199.  #define hvalue(o)  check_exp(ttistable(o), gco2t(val_(o).gc))
  200.  #define bvalue(o)  check_exp(ttisboolean(o), val_(o).b)
  201.  #define thvalue(o) check_exp(ttisthread(o), gco2th(val_(o).gc))
  202. +#if defined(LUA_PROXY_ENABLED)
  203. +#define pxvalue(o) check_exp(ttisproxy(o), gco2px(val_(o).gc))
  204. +#endif
  205.  /* a dead value may get the 'gc' field, but cannot access its contents */
  206.  #define deadvalue(o)   check_exp(ttisdeadkey(o), cast(void *, val_(o).gc))
  207.  
  208. @@ -237,6 +243,13 @@ typedef struct lua_TValue {
  209.      val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TTHREAD)); \
  210.      checkliveness(L,io); }
  211.  
  212. +#if defined(LUA_PROXY_ENABLED)
  213. +#define setpxvalue(L,obj,x) \
  214. +  { TValue *io = (obj); Proxy *x_ = (x); \
  215. +    val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TPROXY)); \
  216. +    checkliveness(L,io); }
  217. +#endif
  218. +
  219.  #define setclLvalue(L,obj,x) \
  220.    { TValue *io = (obj); LClosure *x_ = (x); \
  221.      val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TLCL)); \
  222. @@ -519,6 +532,18 @@ typedef struct Table {
  223.  #define sizenode(t)    (twoto((t)->lsizenode))
  224.  
  225.  
  226. +#if defined(LUA_PROXY_ENABLED)
  227. +/*
  228. +** Proxies
  229. +*/
  230. +typedef struct Proxy {
  231. +  CommonHeader;
  232. +  TValue value;
  233. +  Table *metatable;
  234. +} Proxy;
  235. +#endif
  236. +
  237. +
  238.  /*
  239.  ** (address of) a fixed nil value
  240.  */
  241. diff --git src/lstate.h src/lstate.h
  242. index 56b3741..2f59bc6 100644
  243. --- src/lstate.h
  244. +++ src/lstate.h
  245. @@ -216,6 +216,9 @@ union GCUnion {
  246.    struct Table h;
  247.    struct Proto p;
  248.    struct lua_State th;  /* thread */
  249. +#if defined(LUA_PROXY_ENABLED)
  250. +  struct Proxy px;
  251. +#endif
  252.  };
  253.  
  254.  
  255. @@ -232,6 +235,9 @@ union GCUnion {
  256.  #define gco2t(o)  check_exp((o)->tt == LUA_TTABLE, &((cast_u(o))->h))
  257.  #define gco2p(o)  check_exp((o)->tt == LUA_TPROTO, &((cast_u(o))->p))
  258.  #define gco2th(o)  check_exp((o)->tt == LUA_TTHREAD, &((cast_u(o))->th))
  259. +#if defined(LUA_PROXY_ENABLED)
  260. +#define gco2px(o)  check_exp((o)->tt == LUA_TPROXY, &((cast_u(o))->px))
  261. +#endif
  262.  
  263.  
  264.  /* macro to convert a Lua object into a GCObject */
  265. diff --git src/ltm.c src/ltm.c
  266. index 0e7c713..92d8779 100644
  267. --- src/ltm.c
  268. +++ src/ltm.c
  269. @@ -29,7 +29,11 @@ static const char udatatypename[] = "userdata";
  270.  LUAI_DDEF const char *const luaT_typenames_[LUA_TOTALTAGS] = {
  271.    "no value",
  272.    "nil", "boolean", udatatypename, "number",
  273. +#if !defined(LUA_PROXY_ENABLED)
  274.    "string", "table", "function", udatatypename, "thread",
  275. +#else
  276. +  "string", "table", "function", udatatypename, "thread", "proxy",
  277. +#endif
  278.    "proto" /* this last case is used for tests only */
  279.  };
  280.  
  281. @@ -76,6 +80,11 @@ const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, TMS event) {
  282.      case LUA_TUSERDATA:
  283.        mt = uvalue(o)->metatable;
  284.        break;
  285. +#if defined(LUA_PROXY_ENABLED)
  286. +    case LUA_TPROXY:
  287. +      mt = pxvalue(o)->metatable;
  288. +      break;
  289. +#endif
  290.      default:
  291.        mt = G(L)->mt[ttnov(o)];
  292.    }
  293. @@ -89,12 +98,22 @@ const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, TMS event) {
  294.  */
  295.  const char *luaT_objtypename (lua_State *L, const TValue *o) {
  296.    Table *mt;
  297. +#if !defined(LUA_PROXY_ENABLED)
  298.    if ((ttistable(o) && (mt = hvalue(o)->metatable) != NULL) ||
  299.        (ttisfulluserdata(o) && (mt = uvalue(o)->metatable) != NULL)) {
  300.      const TValue *name = luaH_getshortstr(mt, luaS_new(L, "__name"));
  301.      if (ttisstring(name))  /* is '__name' a string? */
  302.        return getstr(tsvalue(name));  /* use it as type name */
  303.    }
  304. +#else
  305. +  if ((ttistable(o) && (mt = hvalue(o)->metatable) != NULL) ||
  306. +      (ttisfulluserdata(o) && (mt = uvalue(o)->metatable) != NULL) ||
  307. +      (ttisproxy(o) && (mt = pxvalue(o)->metatable) != NULL)) {
  308. +    const TValue *name = luaH_getshortstr(mt, luaS_new(L, "__name"));
  309. +    if (ttisstring(name))  /* is '__name' a string? */
  310. +      return getstr(tsvalue(name));  /* use it as type name */
  311. +  }
  312. +#endif
  313.    return ttypename(ttnov(o));  /* else use standard type name */
  314.  }
  315.  
  316. @@ -123,12 +142,33 @@ void luaT_callTM (lua_State *L, const TValue *f, const TValue *p1,
  317.  
  318.  int luaT_callbinTM (lua_State *L, const TValue *p1, const TValue *p2,
  319.                      StkId res, TMS event) {
  320. +#if !defined(LUA_PROXY_ENABLED)
  321.    const TValue *tm = luaT_gettmbyobj(L, p1, event);  /* try first operand */
  322.    if (ttisnil(tm))
  323.      tm = luaT_gettmbyobj(L, p2, event);  /* try second operand */
  324.    if (ttisnil(tm)) return 0;
  325.    luaT_callTM(L, tm, p1, p2, res, 1);
  326.    return 1;
  327. +#else
  328. +  const TValue *lhs = p1;
  329. +  const TValue *rhs = p2;
  330. +  const TValue *tm = luaT_gettmbyobj(L, p1, event);  /* try first operand */
  331. +  if (!ttisnil(tm)) {
  332. +    if (ttisproxy(p1)) {
  333. +      lhs = &pxvalue(p1)->value;
  334. +      if (luaV_equalobj(L, p1, p2))  /* special case */
  335. +        rhs = lhs;
  336. +    }
  337. +  }
  338. +  else {
  339. +    tm = luaT_gettmbyobj(L, p2, event);  /* try second operand */
  340. +    if (ttisnil(tm)) return 0;
  341. +    if (ttisproxy(p2))
  342. +      rhs = &pxvalue(p2)->value;
  343. +  }
  344. +  luaT_callTM(L, tm, lhs, rhs, res, 1);
  345. +  return 1;
  346. +#endif
  347.  }
  348.  
  349.  
  350. diff --git src/lua.h src/lua.h
  351. index c236e36..4f1feff 100644
  352. --- src/lua.h
  353. +++ src/lua.h
  354. @@ -70,8 +70,15 @@ typedef struct lua_State lua_State;
  355.  #define LUA_TFUNCTION      6
  356.  #define LUA_TUSERDATA      7
  357.  #define LUA_TTHREAD        8
  358. +#if defined(LUA_PROXY_ENABLED)
  359. +#define LUA_TPROXY     9
  360. +#endif
  361.  
  362. +#if! defined(LUA_PROXY_ENABLED)
  363.  #define LUA_NUMTAGS        9
  364. +#else
  365. +#define LUA_NUMTAGS        10
  366. +#endif
  367.  
  368.  
  369.  
  370. @@ -328,6 +335,10 @@ LUA_API size_t   (lua_stringtonumber) (lua_State *L, const char *s);
  371.  LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud);
  372.  LUA_API void      (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud);
  373.  
  374. +#if defined(LUA_PROXY_ENABLED)
  375. +LUA_API void (lua_envelop) (lua_State *L, int idx);
  376. +#endif
  377. +
  378.  
  379.  
  380.  /*
  381. diff --git src/luaconf.h src/luaconf.h
  382. index 9eeeea6..8c1bb65 100644
  383. --- src/luaconf.h
  384. +++ src/luaconf.h
  385. @@ -781,6 +781,7 @@
  386.  ** Local configuration. You can use this space to add your redefinitions
  387.  ** without modifying the main part of the file.
  388.  */
  389. +#define LUA_PROXY_ENABLED
  390.  
  391.  
  392.  
  393. diff --git src/lvm.c src/lvm.c
  394. index cc43d87..a618983 100644
  395. --- src/lvm.c
  396. +++ src/lvm.c
  397. @@ -179,7 +179,12 @@ void luaV_finishget (lua_State *L, const TValue *t, TValue *key, StkId val,
  398.        /* else will try the metamethod */
  399.      }
  400.      if (ttisfunction(tm)) {  /* is metamethod a function? */
  401. +#if !defined(LUA_PROXY_ENABLED)
  402.        luaT_callTM(L, tm, t, key, val, 1);  /* call it */
  403. +#else
  404. +      luaT_callTM(L, tm, ttisproxy(t) ? &pxvalue(t)->value : t,
  405. +                  key, val, 1);  /* call it */
  406. +#endif
  407.        return;
  408.      }
  409.      t = tm;  /* else try to access 'tm[key]' */
  410. @@ -226,7 +231,12 @@ void luaV_finishset (lua_State *L, const TValue *t, TValue *key,
  411.      }
  412.      /* try the metamethod */
  413.      if (ttisfunction(tm)) {
  414. +#if !defined(LUA_PROXY_ENABLED)
  415.        luaT_callTM(L, tm, t, key, val, 0);
  416. +#else
  417. +      luaT_callTM(L, tm, ttisproxy(t) ? &pxvalue(t)->value : t,
  418. +                  key, val, 0);
  419. +#endif
  420.        return;
  421.      }
  422.      t = tm;  /* else repeat assignment over 'tm' */
  423. @@ -440,6 +450,16 @@ int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) {
  424.          tm = fasttm(L, hvalue(t2)->metatable, TM_EQ);
  425.        break;  /* will try TM */
  426.      }
  427. +#if defined(LUA_PROXY_ENABLED)
  428. +    case LUA_TPROXY: {
  429. +      if (pxvalue(t1) == pxvalue(t2)) return 1;
  430. +      else if (L == NULL) return 0;
  431. +      tm = fasttm(L, pxvalue(t1)->metatable, TM_EQ);
  432. +      if (tm == NULL)
  433. +        tm = fasttm(L, pxvalue(t2)->metatable, TM_EQ);
  434. +      break;  /* will try TM */
  435. +    }
  436. +#endif
  437.      default:
  438.        return gcvalue(t1) == gcvalue(t2);
  439.    }
  440. @@ -536,6 +556,10 @@ void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) {
  441.        tm = luaT_gettmbyobj(L, rb, TM_LEN);
  442.        if (ttisnil(tm))  /* no metamethod? */
  443.          luaG_typeerror(L, rb, "get length of");
  444. +#if defined(LUA_PROXY_ENABLED)
  445. +      if (ttisproxy(rb))
  446. +        rb = &pxvalue(rb)->value;
  447. +#endif
  448.        break;
  449.      }
  450.    }
RAW Paste Data