summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilliam Wilgus <me.theuser@yahoo.com>2018-11-17 02:44:30 -0500
committerWilliam Wilgus <me.theuser@yahoo.com>2019-07-11 00:09:54 -0500
commita332924f68e1237ec69af84ef10362fd9b4623c3 (patch)
tree5ae8ad47430b1befb87d259c636b3789f558350b
parentc6fcb1cf45b249b059c2d53a062f9a6c7f449047 (diff)
downloadrockbox-a332924f68e1237ec69af84ef10362fd9b4623c3.tar.gz
rockbox-a332924f68e1237ec69af84ef10362fd9b4623c3.zip
lua late bound cfunction tables
We have quite a bit of ram tied up in lua with our c libraries I was searching for a way to free up some of this when I came across read only tables in e-lua but that involved a lot of patching through the source Instead I came up with this.. it frees about 15k ram without much slowdown in code execution since after a function gets called it is automatically added to the table If you have a performance issue you can call the bind method to bind a specific function or the whole table in one shot for instance rb table rb("lcd_clear") -- binds/returns function rb.lcd_clear() rb(nil) -- binds every function in rb table + removes latebind metatable .. -- added pairs and ipairs code from lua 5.2 -- cleaned up code + made more seamless existing fields are now saved rather than overwritten when table is bound Change-Id: I1c20e76b736c032dedc727d2e58928641e40191d
-rw-r--r--apps/plugins/lua/lauxlib.c132
1 files changed, 132 insertions, 0 deletions
diff --git a/apps/plugins/lua/lauxlib.c b/apps/plugins/lua/lauxlib.c
index 5e7c15931d..2e4b3b1e3c 100644
--- a/apps/plugins/lua/lauxlib.c
+++ b/apps/plugins/lua/lauxlib.c
@@ -254,10 +254,142 @@ static int libsize_storenames (lua_State *L, const char* libname, const luaL_Reg
254} 254}
255 255
256 256
257#if 0
257LUALIB_API void (luaL_register) (lua_State *L, const char *libname, 258LUALIB_API void (luaL_register) (lua_State *L, const char *libname,
258 const luaL_Reg *l) { 259 const luaL_Reg *l) {
259 luaI_openlib(L, libname, l, 0); 260 luaI_openlib(L, libname, l, 0);
260} 261}
262#else /* late bind cfunction tables to save ram */
263static int latebind_func_index(lua_State *L)
264{
265 const luaL_Reg *llib;
266 /* name @ top of stack 1(basetable;name)-1*/
267 const char *name = lua_tostring(L, -1);
268
269 lua_pushstring (L, "__latebind");/* basetable;name;__latebind;*/
270 lua_rawget (L, -3);/* basetable;name;__latebind(t);*/
271
272 luaL_argcheck(L, lua_istable(L, -3) && lua_istable(L, -1), 1,
273 "__latebind table expected");
274 /* (btable;name;__latebind(t)) */
275
276 /* lookup late bound func(s), lua_objlen allows check of multiple luaL_Reg */
277 for(int i = lua_objlen(L, -1); i > 0; i--) {
278 lua_rawgeti (L, -1, i);/* btable;name;__lb(t);llib*/
279 llib = (const luaL_Reg *) lua_touserdata (L, -1);
280 lua_pop(L, 1); /* (btable;name;__lb(t);llib) -> (btable;name;__lb(t)) */
281
282 if(!llib)
283 continue;
284
285 for (; llib->name; llib++) {
286 if(!name || strcmp(name, llib->name) == 0) {
287 /* don't overwrite existing keys within basetable */
288 lua_pushstring(L, llib->name); /* (btable;name;__lb(t);llib->name) */
289 lua_rawget(L, -4); /* (btable;name;__lb(t);btable[func]?) */
290
291 if(lua_isnil(L, -1)) {
292 /* if function is used it is added to the base table */
293 lua_pop(L, 1);
294 lua_pushcclosure(L, llib->func, 0); /* (btable;name;__lb(t);llib->func) */
295 }
296
297 if(!name) /* nil name binds all functions in table immediately */
298 lua_setfield(L, -4, llib->name); /* (btable;name;mtable) */
299 else {
300 lua_pushvalue(L, -1); /* dupe closure or existing func */
301 /* (btable;name;__lb(t);llib->func;llib->func) */
302 lua_setfield(L, -5, llib->name); /* (btable;name;__lb(t);llib->func) */
303 /* returns the closure */
304 return 1;
305 }
306 }
307 }
308 }
309
310 lua_pop(L, 2); /* (btable;name;__lb(t)) -> (btable) */
311 if(!name) {
312 lua_pushnil(L); /* remove metatable (btable;name;__lb(t);nil)*/
313 lua_setmetatable(L, -2);
314 lua_pushnil(L); /* remove __latebind table*/
315 lua_setfield (L, -2, "__latebind");
316 }
317
318 return 0;
319}
320
321
322static int latebind_func_pairs(lua_State *L)
323{
324 /* basetable @ top of stack 1(basetable)-1 */
325 luaL_argcheck(L, lua_istable(L, 1), 1, "table expected");
326 lua_getglobal(L, "pairs"); /* function to be called / returned (btable;pairs) */
327
328 lua_createtable(L, 0, 15); /* btable;pairs;newtable; */
329 /* clone base table */
330 lua_pushnil(L); /* first key */
331 while(lua_next(L, 1) != 0) {
332 /* (btable;pairs;ntable;k;v) */
333 lua_pushvalue(L, -2); /* dupe key Stk = (..;k;v -> ..k;v;k)*/
334 lua_insert(L, -2); /* Stk = (..k;k;v) */
335 lua_rawset(L, 3); /* btable;pairs;ntable;k */
336 }
337
338 lua_pushnil(L); /*nil name retrieves all unbound late bound functions */
339 latebind_func_index(L);/* (btable;pairs;ntable;nil) -> (btable;pairs;ntable) */
340
341 /* (btable;pairs;ntable) */
342 lua_call(L, 1, 3); /* pairs(ntable) -> (btable;iter;state;value) */
343
344 return 3;
345}
346
347
348LUALIB_API void (luaL_register) (lua_State *L, const char *libname,
349 const luaL_Reg *l) {
350 if(!libname)
351 {
352 /* if there is no libname register normally */
353 luaI_openlib(L, libname, l, 0);
354 return;
355 }
356
357 /* store empty table instead of passed luaL_Reg table */
358 static const struct luaL_reg late_lib [] =
359 {
360 {NULL, NULL}
361 };
362
363 static const struct luaL_reg late_meta [] =
364 {
365 {"__index", latebind_func_index},
366 {"__pairs", latebind_func_pairs},
367 {"__call", latebind_func_index}, /* allows t("func") -- nil binds all */
368 {NULL, NULL}
369 };
370
371 libsize_storenames(L, libname, l); /* store func names */
372 luaI_openlib(L, libname, late_lib, 0); /* basetable; */
373
374 luaL_findtable(L, -1,"__latebind", 0); /* create table if doesn't exist */
375 /* basetable;__latebind(t); */
376 /* save pointer to real luaL_reg */
377 lua_pushlightuserdata (L, (void *) l); /*basetable;__lb(t);userdata;*/
378 lua_rawseti(L, -2, lua_objlen(L, -2) + 1); /*lb(t)[n] = userdata */
379
380 lua_pop(L, 1);/* (basetable;__latebind(t)) -> (basetable) */
381
382 if(luaL_newmetatable(L, "META_LATEBIND"))
383 {
384 luaI_openlib(L, NULL, late_meta, 0); /*basetable;metatable*/
385 lua_pushvalue(L, -1); /* dupe the metatable (basetable;mt;mt) */
386 lua_setfield (L, -2, "__metatable"); /* metatable[__metatable] = metatable */
387 }
388
389 lua_setmetatable(L, -2); /* (basetable;mt) -> (basetable+mtable) */
390 /* base table is top of stack (basetable) */
391}
392#endif
261 393
262#if 0 394#if 0
263static int libsize (const luaL_Reg *l) { 395static int libsize (const luaL_Reg *l) {