summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/lua/src/lstring.c
diff options
context:
space:
mode:
author Vas Crabb <vas@vastheman.com>2023-03-07 01:39:42 +1100
committer Vas Crabb <vas@vastheman.com>2023-03-07 01:39:42 +1100
commitb5475eb38b8b79a13a0a9e8a6cb68755b84f0c7b (patch)
tree005b70ffe81cab56d55873ac6ee68725e5ba9d36 /3rdparty/lua/src/lstring.c
parent2102c32d2f3f94e69e3baf60294be3c04ca8b09f (diff)
Various updates, mostly around Lua:
Compile Lua as C++. When Lua is compiled as C, it uses setjmp/longjmp for error handling, resulting in failure to unwind intermediate stack frames. Trying to ensure no objects with non-trivial destructors are in scope when raising a Lua error is error-prone. In particular, converting an exception to a Lua error becomes convoluted, and raising a Lua error from a constructor is effectively impossible. Updated Lua to 5.4.4 - this includes a brand-new garbage collector implementation with better performance. The main thing removed is the deprecated bitlib. Updated sol2 to version 3.3.0 - this adds support for Lua 5.4 and fixes a number of issues, including not correctly handling errors when Lua is built as C++. Updated LuaFileSystem to version 1.8.0 - this adds support for symbolic links on Windows, as well as Lua 5.4 compatibility. Updated LuaSQLite3 to version 0.9.5 - this fixes issues in multi-threaded environments, as well as Lua 5.4 compatibility. Fixed double-free after attempting to construct a debugger expression from Lua with an invalid string, and exposed expression error to Lua in a better way. Added warning level print function to Lua. Fixed saving cheats with shift operators in expressions, although this code isn't actually used as there's no cheat editor.
Diffstat (limited to '3rdparty/lua/src/lstring.c')
-rw-r--r--3rdparty/lua/src/lstring.c135
1 files changed, 80 insertions, 55 deletions
diff --git a/3rdparty/lua/src/lstring.c b/3rdparty/lua/src/lstring.c
index 9351766fd63..13dcaf4259b 100644
--- a/3rdparty/lua/src/lstring.c
+++ b/3rdparty/lua/src/lstring.c
@@ -1,5 +1,5 @@
/*
-** $Id: lstring.c,v 2.56 2015/11/23 11:32:51 roberto Exp $
+** $Id: lstring.c $
** String table (keeps all strings handled by Lua)
** See Copyright Notice in lua.h
*/
@@ -22,16 +22,10 @@
#include "lstring.h"
-#define MEMERRMSG "not enough memory"
-
-
/*
-** Lua will use at most ~(2^LUAI_HASHLIMIT) bytes from a string to
-** compute its hash
+** Maximum size for string table.
*/
-#if !defined(LUAI_HASHLIMIT)
-#define LUAI_HASHLIMIT 5
-#endif
+#define MAXSTRTB cast_int(luaM_limitN(MAX_INT, TString*))
/*
@@ -39,7 +33,7 @@
*/
int luaS_eqlngstr (TString *a, TString *b) {
size_t len = a->u.lnglen;
- lua_assert(a->tt == LUA_TLNGSTR && b->tt == LUA_TLNGSTR);
+ lua_assert(a->tt == LUA_VLNGSTR && b->tt == LUA_VLNGSTR);
return (a == b) || /* same instance or... */
((len == b->u.lnglen) && /* equal length and ... */
(memcmp(getstr(a), getstr(b), len) == 0)); /* equal contents */
@@ -47,52 +41,65 @@ int luaS_eqlngstr (TString *a, TString *b) {
unsigned int luaS_hash (const char *str, size_t l, unsigned int seed) {
- unsigned int h = seed ^ cast(unsigned int, l);
- size_t step = (l >> LUAI_HASHLIMIT) + 1;
- for (; l >= step; l -= step)
+ unsigned int h = seed ^ cast_uint(l);
+ for (; l > 0; l--)
h ^= ((h<<5) + (h>>2) + cast_byte(str[l - 1]));
return h;
}
unsigned int luaS_hashlongstr (TString *ts) {
- lua_assert(ts->tt == LUA_TLNGSTR);
+ lua_assert(ts->tt == LUA_VLNGSTR);
if (ts->extra == 0) { /* no hash? */
- ts->hash = luaS_hash(getstr(ts), ts->u.lnglen, ts->hash);
+ size_t len = ts->u.lnglen;
+ ts->hash = luaS_hash(getstr(ts), len, ts->hash);
ts->extra = 1; /* now it has its hash */
}
return ts->hash;
}
-/*
-** resizes the string table
-*/
-void luaS_resize (lua_State *L, int newsize) {
+static void tablerehash (TString **vect, int osize, int nsize) {
int i;
- stringtable *tb = &G(L)->strt;
- if (newsize > tb->size) { /* grow table if needed */
- luaM_reallocvector(L, tb->hash, tb->size, newsize, TString *);
- for (i = tb->size; i < newsize; i++)
- tb->hash[i] = NULL;
- }
- for (i = 0; i < tb->size; i++) { /* rehash */
- TString *p = tb->hash[i];
- tb->hash[i] = NULL;
- while (p) { /* for each node in the list */
+ for (i = osize; i < nsize; i++) /* clear new elements */
+ vect[i] = NULL;
+ for (i = 0; i < osize; i++) { /* rehash old part of the array */
+ TString *p = vect[i];
+ vect[i] = NULL;
+ while (p) { /* for each string in the list */
TString *hnext = p->u.hnext; /* save next */
- unsigned int h = lmod(p->hash, newsize); /* new position */
- p->u.hnext = tb->hash[h]; /* chain it */
- tb->hash[h] = p;
+ unsigned int h = lmod(p->hash, nsize); /* new position */
+ p->u.hnext = vect[h]; /* chain it into array */
+ vect[h] = p;
p = hnext;
}
}
- if (newsize < tb->size) { /* shrink table if needed */
- /* vanishing slice should be empty */
- lua_assert(tb->hash[newsize] == NULL && tb->hash[tb->size - 1] == NULL);
- luaM_reallocvector(L, tb->hash, tb->size, newsize, TString *);
+}
+
+
+/*
+** Resize the string table. If allocation fails, keep the current size.
+** (This can degrade performance, but any non-zero size should work
+** correctly.)
+*/
+void luaS_resize (lua_State *L, int nsize) {
+ stringtable *tb = &G(L)->strt;
+ int osize = tb->size;
+ TString **newvect;
+ if (nsize < osize) /* shrinking table? */
+ tablerehash(tb->hash, osize, nsize); /* depopulate shrinking part */
+ newvect = luaM_reallocvector(L, tb->hash, osize, nsize, TString*);
+ if (l_unlikely(newvect == NULL)) { /* reallocation failed? */
+ if (nsize < osize) /* was it shrinking table? */
+ tablerehash(tb->hash, nsize, osize); /* restore to original size */
+ /* leave table as it was */
+ }
+ else { /* allocation succeeded */
+ tb->hash = newvect;
+ tb->size = nsize;
+ if (nsize > osize)
+ tablerehash(newvect, osize, nsize); /* rehash for new size */
}
- tb->size = newsize;
}
@@ -104,8 +111,8 @@ void luaS_clearcache (global_State *g) {
int i, j;
for (i = 0; i < STRCACHE_N; i++)
for (j = 0; j < STRCACHE_M; j++) {
- if (iswhite(g->strcache[i][j])) /* will entry be collected? */
- g->strcache[i][j] = g->memerrmsg; /* replace it with something fixed */
+ if (iswhite(g->strcache[i][j])) /* will entry be collected? */
+ g->strcache[i][j] = g->memerrmsg; /* replace it with something fixed */
}
}
@@ -116,7 +123,10 @@ void luaS_clearcache (global_State *g) {
void luaS_init (lua_State *L) {
global_State *g = G(L);
int i, j;
- luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */
+ stringtable *tb = &G(L)->strt;
+ tb->hash = luaM_newvector(L, MINSTRTABSIZE, TString*);
+ tablerehash(tb->hash, 0, MINSTRTABSIZE); /* clear array */
+ tb->size = MINSTRTABSIZE;
/* pre-create memory-error message */
g->memerrmsg = luaS_newliteral(L, MEMERRMSG);
luaC_fix(L, obj2gco(g->memerrmsg)); /* it should never be collected */
@@ -145,7 +155,7 @@ static TString *createstrobj (lua_State *L, size_t l, int tag, unsigned int h) {
TString *luaS_createlngstrobj (lua_State *L, size_t l) {
- TString *ts = createstrobj(L, l, LUA_TLNGSTR, G(L)->seed);
+ TString *ts = createstrobj(L, l, LUA_VLNGSTR, G(L)->seed);
ts->u.lnglen = l;
return ts;
}
@@ -161,34 +171,46 @@ void luaS_remove (lua_State *L, TString *ts) {
}
+static void growstrtab (lua_State *L, stringtable *tb) {
+ if (l_unlikely(tb->nuse == MAX_INT)) { /* too many strings? */
+ luaC_fullgc(L, 1); /* try to free some... */
+ if (tb->nuse == MAX_INT) /* still too many? */
+ luaM_error(L); /* cannot even create a message... */
+ }
+ if (tb->size <= MAXSTRTB / 2) /* can grow string table? */
+ luaS_resize(L, tb->size * 2);
+}
+
+
/*
-** checks whether short string exists and reuses it or creates a new one
+** Checks whether short string exists and reuses it or creates a new one.
*/
static TString *internshrstr (lua_State *L, const char *str, size_t l) {
TString *ts;
global_State *g = G(L);
+ stringtable *tb = &g->strt;
unsigned int h = luaS_hash(str, l, g->seed);
- TString **list = &g->strt.hash[lmod(h, g->strt.size)];
+ TString **list = &tb->hash[lmod(h, tb->size)];
lua_assert(str != NULL); /* otherwise 'memcmp'/'memcpy' are undefined */
for (ts = *list; ts != NULL; ts = ts->u.hnext) {
- if (l == ts->shrlen &&
- (memcmp(str, getstr(ts), l * sizeof(char)) == 0)) {
+ if (l == ts->shrlen && (memcmp(str, getstr(ts), l * sizeof(char)) == 0)) {
/* found! */
if (isdead(g, ts)) /* dead (but not collected yet)? */
changewhite(ts); /* resurrect it */
return ts;
}
}
- if (g->strt.nuse >= g->strt.size && g->strt.size <= MAX_INT/2) {
- luaS_resize(L, g->strt.size * 2);
- list = &g->strt.hash[lmod(h, g->strt.size)]; /* recompute with new size */
+ /* else must create a new string */
+ if (tb->nuse >= tb->size) { /* need to grow string table? */
+ growstrtab(L, tb);
+ list = &tb->hash[lmod(h, tb->size)]; /* rehash with new size */
}
- ts = createstrobj(L, l, LUA_TSHRSTR, h);
+ ts = createstrobj(L, l, LUA_VSHRSTR, h);
memcpy(getstr(ts), str, l * sizeof(char));
ts->shrlen = cast_byte(l);
ts->u.hnext = *list;
*list = ts;
- g->strt.nuse++;
+ tb->nuse++;
return ts;
}
@@ -201,7 +223,7 @@ TString *luaS_newlstr (lua_State *L, const char *str, size_t l) {
return internshrstr(L, str, l);
else {
TString *ts;
- if (l >= (MAX_SIZE - sizeof(TString))/sizeof(char))
+ if (l_unlikely(l >= (MAX_SIZE - sizeof(TString))/sizeof(char)))
luaM_toobig(L);
ts = luaS_createlngstrobj(L, l);
memcpy(getstr(ts), str, l * sizeof(char));
@@ -233,16 +255,19 @@ TString *luaS_new (lua_State *L, const char *str) {
}
-Udata *luaS_newudata (lua_State *L, size_t s) {
+Udata *luaS_newudata (lua_State *L, size_t s, int nuvalue) {
Udata *u;
+ int i;
GCObject *o;
- if (s > MAX_SIZE - sizeof(Udata))
+ if (l_unlikely(s > MAX_SIZE - udatamemoffset(nuvalue)))
luaM_toobig(L);
- o = luaC_newobj(L, LUA_TUSERDATA, sizeludata(s));
+ o = luaC_newobj(L, LUA_VUSERDATA, sizeudata(nuvalue, s));
u = gco2u(o);
u->len = s;
+ u->nuvalue = nuvalue;
u->metatable = NULL;
- setuservalue(L, u, luaO_nilobject);
+ for (i = 0; i < nuvalue; i++)
+ setnilvalue(&u->uv[i].uv);
return u;
}