mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-10-13 18:17:39 -04:00
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
d54659b572
Change-Id: I21d6dcfa32523877efd9f70fb0f88f2a02872649
This commit is contained in:
parent
42240f6990
commit
c6fcb1cf45
10 changed files with 88 additions and 25 deletions
|
@ -11,10 +11,12 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include "lstring.h" /* ROCKLUA ADDED */
|
||||||
|
|
||||||
|
|
||||||
/* This file uses only the official API of Lua.
|
/* This file uses only the official API of Lua.
|
||||||
** Any function declared here could be written as an application function.
|
** Any function declared here could be written as an application function.
|
||||||
|
** Note ** luaS_newlloc breaks this guarantee ROCKLUA ADDED
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define lauxlib_c
|
#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,
|
LUALIB_API void (luaL_register) (lua_State *L, const char *libname,
|
||||||
const luaL_Reg *l) {
|
const luaL_Reg *l) {
|
||||||
luaI_openlib(L, libname, l, 0);
|
luaI_openlib(L, libname, l, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
static int libsize (const luaL_Reg *l) {
|
static int libsize (const luaL_Reg *l) {
|
||||||
int size = 0;
|
int size = 0;
|
||||||
for (; l->name; l++) size++;
|
for (; l->name; l++) size++;
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
LUALIB_API void luaI_openlib (lua_State *L, const char *libname,
|
LUALIB_API void luaI_openlib (lua_State *L, const char *libname,
|
||||||
const luaL_Reg *l, int nup) {
|
const luaL_Reg *l, int nup) {
|
||||||
|
int size = libsize_storenames(L, libname, l);
|
||||||
if (libname) {
|
if (libname) {
|
||||||
int size = libsize(l);
|
|
||||||
/* check whether lib already exists */
|
/* check whether lib already exists */
|
||||||
luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 1);
|
luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 1);
|
||||||
lua_getfield(L, -1, libname); /* get _LOADED[libname] */
|
lua_getfield(L, -1, libname); /* get _LOADED[libname] */
|
||||||
|
|
|
@ -388,7 +388,7 @@ static void freeobj (lua_State *L, GCObject *o) {
|
||||||
}
|
}
|
||||||
case LUA_TSTRING: {
|
case LUA_TSTRING: {
|
||||||
G(L)->strt.nuse--;
|
G(L)->strt.nuse--;
|
||||||
luaM_freemem(L, o, sizestring(gco2ts(o)));
|
luaM_freemem(L, o, sizetstring((gco2ts(o))->type, (gco2ts(o))->len));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LUA_TUSERDATA: {
|
case LUA_TUSERDATA: {
|
||||||
|
|
|
@ -64,8 +64,8 @@ static void save (LexState *ls, int c) {
|
||||||
void luaX_init (lua_State *L) {
|
void luaX_init (lua_State *L) {
|
||||||
int i;
|
int i;
|
||||||
for (i=0; i<NUM_RESERVED; i++) {
|
for (i=0; i<NUM_RESERVED; i++) {
|
||||||
TString *ts = luaS_new(L, luaX_tokens[i]);
|
/* reserved words are never collected */
|
||||||
luaS_fix(ts); /* reserved words are never collected */
|
TString *ts = luaS_newlloc(L, luaX_tokens[i], TSTR_INBIN | TSTR_FIXED);
|
||||||
lua_assert(strlen(luaX_tokens[i])+1 <= TOKEN_LEN);
|
lua_assert(strlen(luaX_tokens[i])+1 <= TOKEN_LEN);
|
||||||
ts->tsv.reserved = cast_byte(i+1); /* reserved word */
|
ts->tsv.reserved = cast_byte(i+1); /* reserved word */
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 */
|
/* this function handles only `%d', `%c', %f, %p, and `%s' formats */
|
||||||
const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {
|
const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {
|
||||||
int n = 1;
|
int n = 1;
|
||||||
|
|
|
@ -201,13 +201,14 @@ typedef union TString {
|
||||||
struct {
|
struct {
|
||||||
CommonHeader;
|
CommonHeader;
|
||||||
lu_byte reserved;
|
lu_byte reserved;
|
||||||
|
lu_byte type;
|
||||||
unsigned int hash;
|
unsigned int hash;
|
||||||
size_t len;
|
size_t len;
|
||||||
} tsv;
|
} tsv;
|
||||||
} TString;
|
} TString;
|
||||||
|
|
||||||
|
|
||||||
#define getstr(ts) cast(const char *, (ts) + 1)
|
#define getstr(ts) (luaO_getstring(ts)) /* ROCKLUA ADDED */
|
||||||
#define svalue(o) getstr(rawtsvalue(o))
|
#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_fb2int (int x);
|
||||||
LUAI_FUNC int luaO_rawequalObj (const TValue *t1, const TValue *t2);
|
LUAI_FUNC int luaO_rawequalObj (const TValue *t1, const TValue *t2);
|
||||||
LUAI_FUNC int luaO_str2d (const char *s, lua_Number *result);
|
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,
|
LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt,
|
||||||
va_list argp);
|
va_list argp);
|
||||||
LUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...);
|
LUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...);
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
** $Id: lstring.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $
|
** $Id: lstring.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $
|
||||||
** String table (keeps all strings handled by Lua)
|
** String table (keeps all strings handled by Lua)
|
||||||
** See Copyright Notice in lua.h
|
** 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,
|
static TString *newlstr (lua_State *L, const char *str, size_t l,
|
||||||
unsigned int h) {
|
unsigned int h, char type) {
|
||||||
TString *ts;
|
TString *ts;
|
||||||
stringtable *tb;
|
stringtable *tb;
|
||||||
if (l+1 > (MAX_SIZET - sizeof(TString))/sizeof(char))
|
if (l > ((MAX_SIZET - sizeof(TString))/sizeof(char)) - sizeof(""))
|
||||||
luaM_toobig(L);
|
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.len = l;
|
||||||
ts->tsv.hash = h;
|
ts->tsv.hash = h;
|
||||||
ts->tsv.marked = luaC_white(G(L));
|
ts->tsv.marked = luaC_white(G(L));
|
||||||
|
if (testbits(type, TSTR_FIXED))
|
||||||
|
luaS_fix(ts);
|
||||||
ts->tsv.tt = LUA_TSTRING;
|
ts->tsv.tt = LUA_TSTRING;
|
||||||
ts->tsv.reserved = 0;
|
ts->tsv.reserved = 0;
|
||||||
memcpy(ts+1, str, l*sizeof(char));
|
ts->tsv.type = cast_byte(type);
|
||||||
((char *)(ts+1))[l] = '\0'; /* ending 0 */
|
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;
|
tb = &G(L)->strt;
|
||||||
h = lmod(h, tb->size);
|
h = lmod(h, tb->size);
|
||||||
ts->tsv.next = tb->hash[h]; /* chain new entry */
|
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;
|
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 */
|
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 step = (l>>5)+1; /* if string is too long, don't hash all its chars */
|
||||||
size_t l1;
|
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)) {
|
if (ts->tsv.len == l && (memcmp(str, getstr(ts), l) == 0)) {
|
||||||
/* string may be dead */
|
/* string may be dead */
|
||||||
if (isdead(G(L), o)) changewhite(o);
|
if (isdead(G(L), o)) changewhite(o);
|
||||||
|
if (testbits(type, TSTR_FIXED))
|
||||||
|
luaS_fix(ts);
|
||||||
return ts;
|
return ts;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return newlstr(L, str, l, h); /* not found */
|
return newlstr(L, str, l, h, type); /* not found */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -12,20 +12,29 @@
|
||||||
#include "lobject.h"
|
#include "lobject.h"
|
||||||
#include "lstate.h"
|
#include "lstate.h"
|
||||||
|
|
||||||
|
/* ROCKLUA ADDED */
|
||||||
#define sizestring(s) (sizeof(union TString)+((s)->len+1)*sizeof(char))
|
#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 sizeudata(u) (sizeof(union Udata)+(u)->len)
|
||||||
|
|
||||||
#define luaS_new(L, s) (luaS_newlstr(L, s, strlen(s)))
|
#define luaS_new(L, s) (luaS_newllocstr(L, s, 0, TSTR_INBLOB | TSTR_CHKSZ))
|
||||||
#define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \
|
#define luaS_newlstr(L, s, len) (luaS_newllocstr(L, s, len, TSTR_INBLOB))
|
||||||
(sizeof(s)/sizeof(char))-1))
|
#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)
|
#define luaS_fix(s) l_setbit((s)->tsv.marked, FIXEDBIT)
|
||||||
|
|
||||||
LUAI_FUNC void luaS_resize (lua_State *L, int newsize);
|
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 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
|
#endif
|
||||||
|
|
|
@ -36,10 +36,8 @@ void luaT_init (lua_State *L) {
|
||||||
"__concat", "__call"
|
"__concat", "__call"
|
||||||
};
|
};
|
||||||
int i;
|
int i;
|
||||||
for (i=0; i<TM_N; i++) {
|
for (i=0; i<TM_N; i++) /* never collect these names */
|
||||||
G(L)->tmname[i] = luaS_new(L, luaT_eventname[i]);
|
G(L)->tmname[i] = luaS_newlloc(L, luaT_eventname[i], TSTR_INBIN | TSTR_FIXED);
|
||||||
luaS_fix(G(L)->tmname[i]); /* never collect these names */
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
|
|
||||||
#undef LUA_PATH_DEFAULT
|
#undef LUA_PATH_DEFAULT
|
||||||
#define LUA_PATH_DEFAULT "$/?.lua;" "$/?/init.lua;" VIEWERS_DIR"/lua/?.lua;" VIEWERS_DIR"/lua/?/init.lua;"
|
#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 <setjmp.h>
|
#include <setjmp.h>
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#define LUA_LIB
|
#define LUA_LIB
|
||||||
|
|
||||||
#include "lua.h"
|
#include "lua.h"
|
||||||
|
#include "lstring.h"
|
||||||
|
|
||||||
#include "lauxlib.h"
|
#include "lauxlib.h"
|
||||||
#include "rocklib.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;
|
static const struct lua_int_reg* rlci = rlib_const_int;
|
||||||
for (; rlci->name; rlci++) {
|
for (; rlci->name; rlci++) {
|
||||||
lua_pushinteger(L, rlci->value);
|
lua_pushinteger(L, rlci->value);
|
||||||
|
luaS_newlloc(L, rlci->name, TSTR_INBIN);
|
||||||
lua_setfield(L, -2, rlci->name);
|
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;
|
static const struct lua_str_reg* rlcs = rlib_const_str;
|
||||||
for (; rlcs->name; rlcs++) {
|
for (; rlcs->name; rlcs++) {
|
||||||
|
luaS_newlloc(L, rlcs->value, TSTR_INBIN);
|
||||||
lua_pushstring(L, rlcs->value);
|
lua_pushstring(L, rlcs->value);
|
||||||
|
luaS_newlloc(L, rlcs->name, TSTR_INBIN);
|
||||||
lua_setfield(L, -2, rlcs->name);
|
lua_setfield(L, -2, rlcs->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue