From c6fcb1cf45b249b059c2d53a062f9a6c7f449047 Mon Sep 17 00:00:00 2001 From: William Wilgus Date: Sun, 11 Nov 2018 18:27:19 -0500 Subject: lua inbinary strings Allows saving of ram by reusing strings already stored in the binary and storing a pointer instead of malloc and copy to get them inside the lua state Saves about 1.5K overall Derivative of work by bogdanm RAM optimizations: pseudo RO strings, functions in Flash https://github.com/elua/elua/commit/d54659b5723bcd2b1e3900362398c72c18a9aa0b Change-Id: I21d6dcfa32523877efd9f70fb0f88f2a02872649 --- apps/plugins/lua/lauxlib.c | 21 ++++++++++++++++++--- apps/plugins/lua/lgc.c | 2 +- apps/plugins/lua/llex.c | 4 ++-- apps/plugins/lua/lobject.c | 15 +++++++++++++++ apps/plugins/lua/lobject.h | 4 +++- apps/plugins/lua/lstring.c | 33 ++++++++++++++++++++++++++------- apps/plugins/lua/lstring.h | 23 ++++++++++++++++------- apps/plugins/lua/ltm.c | 6 ++---- apps/plugins/lua/rockconf.h | 1 + apps/plugins/lua/rocklib.c | 4 ++++ 10 files changed, 88 insertions(+), 25 deletions(-) (limited to 'apps/plugins/lua') diff --git a/apps/plugins/lua/lauxlib.c b/apps/plugins/lua/lauxlib.c index 9597f63c60..5e7c15931d 100644 --- a/apps/plugins/lua/lauxlib.c +++ b/apps/plugins/lua/lauxlib.c @@ -11,10 +11,12 @@ #include #include #include +#include "lstring.h" /* ROCKLUA ADDED */ /* This file uses only the official API of Lua. ** Any function declared here could be written as an application function. +** Note ** luaS_newlloc breaks this guarantee ROCKLUA ADDED */ #define lauxlib_c @@ -239,23 +241,36 @@ LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) { } + /* ROCKLUA ADDED */ +static int libsize_storenames (lua_State *L, const char* libname, const luaL_Reg *l) { + int size = 0; + if (libname) + luaS_newlloc(L, libname, TSTR_INBIN); + for (; l->name; l++) { + size++; + luaS_newlloc(L, l->name, TSTR_INBIN); + } + return size; +} + + LUALIB_API void (luaL_register) (lua_State *L, const char *libname, const luaL_Reg *l) { luaI_openlib(L, libname, l, 0); } - +#if 0 static int libsize (const luaL_Reg *l) { int size = 0; for (; l->name; l++) size++; return size; } - +#endif LUALIB_API void luaI_openlib (lua_State *L, const char *libname, const luaL_Reg *l, int nup) { + int size = libsize_storenames(L, libname, l); if (libname) { - int size = libsize(l); /* check whether lib already exists */ luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 1); lua_getfield(L, -1, libname); /* get _LOADED[libname] */ diff --git a/apps/plugins/lua/lgc.c b/apps/plugins/lua/lgc.c index e909c79a96..98194c1771 100644 --- a/apps/plugins/lua/lgc.c +++ b/apps/plugins/lua/lgc.c @@ -388,7 +388,7 @@ static void freeobj (lua_State *L, GCObject *o) { } case LUA_TSTRING: { G(L)->strt.nuse--; - luaM_freemem(L, o, sizestring(gco2ts(o))); + luaM_freemem(L, o, sizetstring((gco2ts(o))->type, (gco2ts(o))->len)); break; } case LUA_TUSERDATA: { diff --git a/apps/plugins/lua/llex.c b/apps/plugins/lua/llex.c index 6f78d48983..723d46c1ce 100644 --- a/apps/plugins/lua/llex.c +++ b/apps/plugins/lua/llex.c @@ -64,8 +64,8 @@ static void save (LexState *ls, int c) { void luaX_init (lua_State *L) { int i; for (i=0; itsv.reserved = cast_byte(i+1); /* reserved word */ } diff --git a/apps/plugins/lua/lobject.c b/apps/plugins/lua/lobject.c index a351ff41da..65a23cf938 100644 --- a/apps/plugins/lua/lobject.c +++ b/apps/plugins/lua/lobject.c @@ -107,6 +107,21 @@ static void pushstr (lua_State *L, const char *str) { } +/* ROCKLUA ADDED -- Retrieves C string from TString */ +const char *luaO_getstring(const TString * ts){ + const char *string; +#ifdef INBINARYSTRINGS + if (testbits((ts)->tsv.type, TSTR_INBIN)) + string = *(cast(const char **, (ts) + 1)); + else +#else + if (true) +#endif + string = cast(const char *, (ts) + 1); + return string; +} + + /* this function handles only `%d', `%c', %f, %p, and `%s' formats */ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) { int n = 1; diff --git a/apps/plugins/lua/lobject.h b/apps/plugins/lua/lobject.h index 93288fe0fb..26d2a81b49 100644 --- a/apps/plugins/lua/lobject.h +++ b/apps/plugins/lua/lobject.h @@ -201,13 +201,14 @@ typedef union TString { struct { CommonHeader; lu_byte reserved; + lu_byte type; unsigned int hash; size_t len; } tsv; } TString; -#define getstr(ts) cast(const char *, (ts) + 1) +#define getstr(ts) (luaO_getstring(ts)) /* ROCKLUA ADDED */ #define svalue(o) getstr(rawtsvalue(o)) @@ -371,6 +372,7 @@ LUAI_FUNC int luaO_int2fb (unsigned int x); LUAI_FUNC int luaO_fb2int (int x); LUAI_FUNC int luaO_rawequalObj (const TValue *t1, const TValue *t2); LUAI_FUNC int luaO_str2d (const char *s, lua_Number *result); +LUAI_FUNC const char *luaO_getstring(const TString * ts); /* ROCKLUA ADDED */ LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp); LUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...); diff --git a/apps/plugins/lua/lstring.c b/apps/plugins/lua/lstring.c index 49113151cc..bf0536e311 100644 --- a/apps/plugins/lua/lstring.c +++ b/apps/plugins/lua/lstring.c @@ -2,6 +2,8 @@ ** $Id: lstring.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $ ** String table (keeps all strings handled by Lua) ** See Copyright Notice in lua.h +** luaS_newllocstr is adapted from "elua -- pseudo RO strings" +** by bogdanm, distributed under a MIT license. */ @@ -48,19 +50,26 @@ void luaS_resize (lua_State *L, int newsize) { static TString *newlstr (lua_State *L, const char *str, size_t l, - unsigned int h) { + unsigned int h, char type) { TString *ts; stringtable *tb; - if (l+1 > (MAX_SIZET - sizeof(TString))/sizeof(char)) + if (l > ((MAX_SIZET - sizeof(TString))/sizeof(char)) - sizeof("")) luaM_toobig(L); - ts = cast(TString *, luaM_malloc(L, (l+1)*sizeof(char)+sizeof(TString))); + ts = cast(TString *, luaM_malloc(L, sizetstring(type, l))); ts->tsv.len = l; ts->tsv.hash = h; ts->tsv.marked = luaC_white(G(L)); + if (testbits(type, TSTR_FIXED)) + luaS_fix(ts); ts->tsv.tt = LUA_TSTRING; ts->tsv.reserved = 0; - memcpy(ts+1, str, l*sizeof(char)); - ((char *)(ts+1))[l] = '\0'; /* ending 0 */ + ts->tsv.type = cast_byte(type); + if (testbits(type, TSTR_INBIN)) /* ROCKLUA ADDED */ + *(const char **)(ts+1) = str; /* store a pointer to the string instead */ + else { + memcpy(ts+1, str, l*sizeof(char)); + ((char *)(ts+1))[l] = '\0'; /* ending 0 */ + } tb = &G(L)->strt; h = lmod(h, tb->size); ts->tsv.next = tb->hash[h]; /* chain new entry */ @@ -72,8 +81,16 @@ static TString *newlstr (lua_State *L, const char *str, size_t l, } -TString *luaS_newlstr (lua_State *L, const char *str, size_t l) { +TString *luaS_newllocstr (lua_State *L, const char *str, size_t l, char type) { GCObject *o; + if (testbits(type, TSTR_CHKSZ)) + l = strlen(str); +#ifdef INBINARYSTRINGS + else if (!testbits(type, TSTR_ISLIT)) +#else + if (true) +#endif + resetbits(type, TSTR_INBIN); /* only whole strings can be used inbin */ unsigned int h = cast(unsigned int, l); /* seed */ size_t step = (l>>5)+1; /* if string is too long, don't hash all its chars */ size_t l1; @@ -86,10 +103,12 @@ TString *luaS_newlstr (lua_State *L, const char *str, size_t l) { if (ts->tsv.len == l && (memcmp(str, getstr(ts), l) == 0)) { /* string may be dead */ if (isdead(G(L), o)) changewhite(o); + if (testbits(type, TSTR_FIXED)) + luaS_fix(ts); return ts; } } - return newlstr(L, str, l, h); /* not found */ + return newlstr(L, str, l, h, type); /* not found */ } diff --git a/apps/plugins/lua/lstring.h b/apps/plugins/lua/lstring.h index c88e4c12a9..8ca69b8de3 100644 --- a/apps/plugins/lua/lstring.h +++ b/apps/plugins/lua/lstring.h @@ -12,20 +12,29 @@ #include "lobject.h" #include "lstate.h" - -#define sizestring(s) (sizeof(union TString)+((s)->len+1)*sizeof(char)) +/* ROCKLUA ADDED */ +#define TSTR_INBLOB 0 /* string will be allocated at end of tstring struct */ +#define TSTR_INBIN 1 /* string is static within binary, pointer stored */ +#define TSTR_FIXED 2 /* string won't be collected for duration of L state */ +#define TSTR_CHKSZ 4 /* luaS_newllocstr shall determine size of string */ +#define TSTR_ISLIT 8 | TSTR_INBIN /* literal string static within binary */ +#define sizetstring(t, l) (sizeof(union TString) + (testbits((t), TSTR_INBIN) ? \ + sizeof(const char **) : ((l)+1)*sizeof(char))) #define sizeudata(u) (sizeof(union Udata)+(u)->len) -#define luaS_new(L, s) (luaS_newlstr(L, s, strlen(s))) -#define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \ - (sizeof(s)/sizeof(char))-1)) +#define luaS_new(L, s) (luaS_newllocstr(L, s, 0, TSTR_INBLOB | TSTR_CHKSZ)) +#define luaS_newlstr(L, s, len) (luaS_newllocstr(L, s, len, TSTR_INBLOB)) +#define luaS_newlloc(L, s, t) (luaS_newllocstr(L, s, 0, ((t) | TSTR_CHKSZ))) +#define luaS_newliteral(L, s) (luaS_newllocstr(L, "" s, \ + (sizeof(s)/sizeof(char))-1, TSTR_ISLIT)) #define luaS_fix(s) l_setbit((s)->tsv.marked, FIXEDBIT) LUAI_FUNC void luaS_resize (lua_State *L, int newsize); LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, Table *e); -LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l); - +/* ROCKLUA ADDED */ +LUAI_FUNC TString *luaS_newllocstr (lua_State *L, + const char *str, size_t l, char type); #endif diff --git a/apps/plugins/lua/ltm.c b/apps/plugins/lua/ltm.c index c27f0f6fab..946028006f 100644 --- a/apps/plugins/lua/ltm.c +++ b/apps/plugins/lua/ltm.c @@ -36,10 +36,8 @@ void luaT_init (lua_State *L) { "__concat", "__call" }; int i; - for (i=0; itmname[i] = luaS_new(L, luaT_eventname[i]); - luaS_fix(G(L)->tmname[i]); /* never collect these names */ - } + for (i=0; itmname[i] = luaS_newlloc(L, luaT_eventname[i], TSTR_INBIN | TSTR_FIXED); } diff --git a/apps/plugins/lua/rockconf.h b/apps/plugins/lua/rockconf.h index a13146d7e9..89ab82e377 100644 --- a/apps/plugins/lua/rockconf.h +++ b/apps/plugins/lua/rockconf.h @@ -31,6 +31,7 @@ #undef LUA_PATH_DEFAULT #define LUA_PATH_DEFAULT "$/?.lua;" "$/?/init.lua;" VIEWERS_DIR"/lua/?.lua;" VIEWERS_DIR"/lua/?/init.lua;" +#define INBINARYSTRINGS /* Static strings stored as pointer rather than copied into lua state */ #include diff --git a/apps/plugins/lua/rocklib.c b/apps/plugins/lua/rocklib.c index 9ad6411b2f..426dd079af 100644 --- a/apps/plugins/lua/rocklib.c +++ b/apps/plugins/lua/rocklib.c @@ -25,6 +25,7 @@ #define LUA_LIB #include "lua.h" +#include "lstring.h" #include "lauxlib.h" #include "rocklib.h" @@ -835,6 +836,7 @@ LUALIB_API int luaopen_rock(lua_State *L) static const struct lua_int_reg* rlci = rlib_const_int; for (; rlci->name; rlci++) { lua_pushinteger(L, rlci->value); + luaS_newlloc(L, rlci->name, TSTR_INBIN); lua_setfield(L, -2, rlci->name); } @@ -853,7 +855,9 @@ LUALIB_API int luaopen_rock(lua_State *L) static const struct lua_str_reg* rlcs = rlib_const_str; for (; rlcs->name; rlcs++) { + luaS_newlloc(L, rlcs->value, TSTR_INBIN); lua_pushstring(L, rlcs->value); + luaS_newlloc(L, rlcs->name, TSTR_INBIN); lua_setfield(L, -2, rlcs->name); } -- cgit v1.2.3