[WIP] Patch enumlib to be a bit faster. #53

Merged
utkumaden merged 9 commits from patch-enumlib-fast into Saturn-Next-EnumLib 2023-10-30 13:06:20 +01:00
6 changed files with 1280 additions and 423 deletions

No files matched your search

+2
View File
@@ -242,6 +242,7 @@ if(${SRB2_CONFIG_HAVE_BLUA})
lua_skinlib.c
lua_thinkerlib.c
lua_udatalib.c
lua_glib.c
)
set(SRB2_LUA_HEADERS
lua_hook.h
@@ -250,6 +251,7 @@ if(${SRB2_CONFIG_HAVE_BLUA})
lua_libs.h
lua_script.h
lua_udatalib.h
lua_glib.h
)
prepend_sources(SRB2_LUA_SOURCES)
+2 -1
View File
@@ -52,4 +52,5 @@ OBJS:=$(OBJS) \
$(OBJDIR)/lua_maplib.o \
$(OBJDIR)/lua_hudlib.o \
$(OBJDIR)/lua_hudlib_drawlist.o \
$(OBJDIR)/lua_udatalib.o
$(OBJDIR)/lua_udatalib.o \
$(OBJDIR)/lua_glib.o
+710 -413
View File
File diff suppressed because it is too large. Load diff
+381
View File
@@ -0,0 +1,381 @@
#include "lua_glib.h"
#define GLIB_DATABASE_GUID "{cf75e032-00c8-4887-b15f-87b755784ad3}"
#define GLIB_DATABASE_GETTERS "getters" /* Table of getter functions. */
#define GLIB_DATABASE_SETTERS "setters" /* Table of setter functions. */
#define GLIB_DATABASE_ENUMS "enums" /* Table of enum fallback functions. */
#define GLIB_DATABASE_CACHE "cache" /* Table of cached enum values. */
#define GLIB_DATABASE_MTABLE "metatable" /* Metatable.*/
#define GLIB_DATABASE_PROXY "proxy" /* Proxy table for the library that isn't the global table. */
static inline void lua_glib_push_db(lua_State *L)
{
lua_pushliteral(L, GLIB_DATABASE_GUID);
lua_gettable(L, LUA_REGISTRYINDEX);
}
void lua_glib_get_proxy(lua_State *L)
{
lua_pushliteral(L, GLIB_DATABASE_GUID);
lua_gettable(L, LUA_REGISTRYINDEX);
lua_pushliteral(L, GLIB_DATABASE_PROXY);
lua_gettable(L, -2);
lua_remove(L, -2);
}
/**
* Copy table contents to another.
* @param L[1] Destination table.
* @param L[2] Source table.
*/
static int lua_glib_copy_table(lua_State *L)
{
luaL_checktype(L, 1, LUA_TTABLE);
luaL_checktype(L, 2, LUA_TTABLE);
lua_pushnil(L);
while (lua_next(L, 2))
{
lua_pushvalue(L, -2); /* Push key. */
lua_pushvalue(L, -2); /* Push value. */
lua_settable(L, 1); /* Store at dst. */
lua_pop(L, 1); /* Pop the value. */
}
return 0;
}
static int lua_glib___index(lua_State *L)
{
/* function mt:__index(key) */
const int CACHE = lua_upvalueindex(1); /* Enum cache. */
const int GETTERS = lua_upvalueindex(2); /* Storage for getters. */
const int ENUMS = lua_upvalueindex(3); /* Enum fallback cache. */
if (!lua_isstring(L, 2))
{
/* A non string key should not happen. But somebody might really want it. */
return 0;
}
/* Attempt cache lookup. */
lua_pushvalue(L, 2);
lua_gettable(L, CACHE);
if (!lua_isnil(L, -1))
{
return 1;
}
lua_pop(L, 1);
/* Attempt a get property. */
lua_pushvalue(L, 2);
lua_gettable(L, GETTERS);
if (lua_isfunction(L, -1))
{
lua_call(L, 0, 1);
return 1;
}
/* Try finding a the relevant enum fallback function. */
const char *str = lua_tostring(L, 2);
int sz = lua_strlen(L, 2);
for (int i = 1; i < sz; i++)
{
lua_pushlstring(L, str, i);
lua_gettable(L, ENUMS);
if (lua_isfunction(L, -1))
{
lua_pushvalue(L, 2);
lua_call(L, 1, 1);
/* Store value in cache. */
lua_pushvalue(L, 2);
lua_pushvalue(L, -2);
lua_settable(L, CACHE);
/* Return it. */
return 1;
}
else
{
lua_pop(L, 1);
}
}
/* This really does not exist. Returns nil. */
return 0;
}
static int lua_glib___newindex(lua_State *L)
{
/* function mt:__newindex(key, value) */
const int SETTERS = lua_upvalueindex(1);
lua_pushvalue(L, 2);
lua_gettable(L, SETTERS);
if (!lua_isfunction(L, -1))
{
return luaL_error(L, "You cannot set the global table except known writeable properties. If this isn't a mistake use `rawset(_G, k, v)`.");
}
/* Set the property. */
lua_pushvalue(L, 3);
lua_call(L, 1, 0);
return 0;
}
int lua_glib_append_cache(lua_State *L)
{
luaL_checktype(L, 1, LUA_TTABLE);
lua_glib_push_db(L);
lua_pushcfunction(L, lua_glib_copy_table);
lua_pushliteral(L, GLIB_DATABASE_CACHE);
lua_gettable(L, -3);
lua_pushvalue(L, 1);
lua_call(L, 2, 0);
return 0;
}
int lua_glib_require(lua_State *L)
{
if (!lua_isboolean(L, 1))
{
/* Request loading the metatable by default. */
lua_pushboolean(L, 1);
}
lua_pushliteral(L, GLIB_DATABASE_GUID);
lua_newtable(L);
/* Standard functions. */
lua_pushliteral(L, GLIB_DATABASE_GETTERS);
lua_newtable(L);
lua_settable(L, -3);
lua_pushliteral(L, GLIB_DATABASE_SETTERS);
lua_newtable(L);
lua_settable(L, -3);
lua_pushliteral(L, GLIB_DATABASE_ENUMS);
lua_newtable(L);
lua_settable(L, -3);
lua_pushliteral(L, GLIB_DATABASE_CACHE);
lua_newtable(L);
lua_settable(L, -3);
lua_pushliteral(L, GLIB_DATABASE_MTABLE);
lua_newtable(L);
lua_pushliteral(L, "__index");
lua_pushliteral(L, GLIB_DATABASE_CACHE);
lua_gettable(L, -5);
lua_pushliteral(L, GLIB_DATABASE_GETTERS);
lua_gettable(L, -6);
lua_pushliteral(L, GLIB_DATABASE_ENUMS);
lua_gettable(L, -7);
lua_pushcclosure(L, lua_glib___index, 3);
lua_settable(L, -3); /* __index */
lua_pushliteral(L, "__newindex");
lua_pushliteral(L, GLIB_DATABASE_SETTERS);
lua_gettable(L, -5);
lua_pushcclosure(L, lua_glib___newindex, 1);
lua_settable(L, -3); /* __newindex */
lua_settable(L, -3); /* GLIB_DATABASE_MTABLE. */
lua_pushliteral(L, GLIB_DATABASE_PROXY);
lua_newtable(L);
lua_pushliteral(L, GLIB_DATABASE_MTABLE);
lua_gettable(L, -4);
lua_setmetatable(L, -2); /* get GLIB_DATABASE_MTABLE. */
lua_settable(L, -3); /* GLIB_DATABASE_PROXY. */
lua_settable(L, LUA_REGISTRYINDEX); /* GLIB_DATABASE_GUID. */
/* Set global metatable. */
if (lua_toboolean(L, 1))
{
lua_glib_push_db(L);
lua_pushliteral(L, GLIB_DATABASE_MTABLE);
lua_gettable(L, -2);
lua_setmetatable(L, LUA_GLOBALSINDEX);
}
return 0;
}
int lua_glib_new_enum(lua_State *L)
{
lua_glib_push_db(L);
if (lua_istable(L, 1))
{
/* copy_table(dst, src) */
lua_pushcfunction(L, lua_glib_copy_table);
lua_pushliteral(L, GLIB_DATABASE_CACHE);
lua_gettable(L, -3); /* dst */
lua_pushvalue(L, 1); /* src */
lua_call(L, 2, 0);
}
if (lua_isstring(L, 2) && lua_isfunction(L, 3))
{
lua_pushliteral(L, GLIB_DATABASE_ENUMS);
lua_gettable(L, -2);
lua_pushvalue(L, 2); /* prefix */
lua_pushvalue(L, 3); /* fallback */
lua_settable(L, -3);
}
return 0;
}
int lua_glib_new_getter(lua_State *L)
{
luaL_checktype(L, 1, LUA_TSTRING);
luaL_checktype(L, 2, LUA_TFUNCTION);
lua_glib_push_db(L);
lua_pushliteral(L, GLIB_DATABASE_GETTERS);
lua_gettable(L, -2);
lua_pushvalue(L, 1);
lua_pushvalue(L, 2);
lua_settable(L, -3);
return 0;
}
int lua_glib_new_setter(lua_State *L)
{
luaL_checktype(L, 1, LUA_TSTRING);
luaL_checktype(L, 2, LUA_TFUNCTION);
lua_glib_push_db(L);
lua_pushliteral(L, GLIB_DATABASE_SETTERS);
lua_gettable(L, -2);
lua_pushvalue(L, 1);
lua_pushvalue(L, 2);
lua_settable(L, -3);
return 0;
}
#define _GLIB_DECL_INT_GETTER(T, name) \
int lua_glib_getter_##name(lua_State *L) { \
const T* ptr = (const T*)lua_topointer(L, lua_upvalueindex(1)); \
lua_pushinteger(L, (lua_Integer)*ptr); \
return 1; \
}
#define _GLIB_DECL_INT_SETTER(T, name) \
int lua_glib_setter_##name(lua_State *L) { \
luaL_checktype(L, 1, LUA_TNUMBER); \
T* ptr = (T*)lua_topointer(L, lua_upvalueindex(1)); \
*ptr = (T)lua_tointeger(L, 1); \
return 0; \
}
#define _GLIB_DECL_BOOL_GETTER(T, name) \
int lua_glib_getter_##name(lua_State *L) { \
const T* ptr = (const T*)lua_topointer(L, lua_upvalueindex(1)); \
lua_pushboolean(L, *ptr != 0); \
return 1; \
}
#define _GLIB_DECL_FLOAT_GETTER(T, name) \
int lua_glib_getter_##name(lua_State *L) { \
const T* ptr = (const T*)lua_topointer(L, lua_upvalueindex(1)); \
lua_pushnumber(L, (lua_Number)*ptr); \
return 1; \
}
#define _GLIB_DECL_FLOAT_SETTER(T, name) \
int lua_glib_setter_##name(lua_State *L) { \
luaL_checktype(L, 1, LUA_TNUMBER); \
T* ptr = (T*)lua_topointer(L, lua_upvalueindex(1)); \
*ptr = (T)lua_tonumber(L, 1); \
return 0; \
}
#define _GLIB_DECL_BOOL_SETTER(T, name) \
int lua_glib_setter_##name(lua_State *L) { \
T* ptr = (T*)lua_topointer(L, lua_upvalueindex(1)); \
*ptr = (T)lua_toboolean(L, 1); \
return 0; \
}
_GLIB_DECL_INT_GETTER(int8_t, i8);
_GLIB_DECL_INT_GETTER(int16_t, i16);
_GLIB_DECL_INT_GETTER(int32_t, i32);
_GLIB_DECL_INT_GETTER(int64_t, i64);
_GLIB_DECL_INT_GETTER(uint8_t, u8);
_GLIB_DECL_INT_GETTER(uint16_t, u16);
_GLIB_DECL_INT_GETTER(uint32_t, u32);
_GLIB_DECL_INT_GETTER(uint64_t, u64);
_GLIB_DECL_FLOAT_GETTER(float, f32);
_GLIB_DECL_FLOAT_GETTER(double, f64);
_GLIB_DECL_BOOL_GETTER(uint8_t, b8);
_GLIB_DECL_BOOL_GETTER(uint16_t, b16);
_GLIB_DECL_BOOL_GETTER(uint32_t, b32);
_GLIB_DECL_BOOL_GETTER(uint64_t, b64);
_GLIB_DECL_INT_SETTER(int8_t, i8);
_GLIB_DECL_INT_SETTER(int16_t, i16);
_GLIB_DECL_INT_SETTER(int32_t, i32);
_GLIB_DECL_INT_SETTER(int64_t, i64);
_GLIB_DECL_INT_SETTER(uint8_t, u8);
_GLIB_DECL_INT_SETTER(uint16_t, u16);
_GLIB_DECL_INT_SETTER(uint32_t, u32);
_GLIB_DECL_INT_SETTER(uint64_t, u64);
_GLIB_DECL_FLOAT_SETTER(float, f32);
_GLIB_DECL_FLOAT_SETTER(double, f64);
_GLIB_DECL_BOOL_SETTER(uint8_t, b8);
_GLIB_DECL_BOOL_SETTER(uint16_t, b16);
_GLIB_DECL_BOOL_SETTER(uint32_t, b32);
_GLIB_DECL_BOOL_SETTER(uint64_t, b64);
int lua_glib_setter_fxp(lua_State *L)
{
fixed_t *fxp = (fixed_t*)lua_topointer(L, lua_upvalueindex(1));
*fxp = lua_tointeger(L, 1);
return 0;
}
int lua_glib_getter_fxp(lua_State *L)
{
const fixed_t *fxp = (const fixed_t*)lua_topointer(L, lua_upvalueindex(1));
lua_pushfixed(L, *fxp);
return 1;
}
int lua_glib_getter_str(lua_State *L)
{
const char *str = (const char*)lua_topointer(L, lua_upvalueindex(1));
lua_pushstring(L, str);
return 1;
}
int lua_glib_getter_ptr(lua_State *L)
{
lua_pushvalue(L, lua_upvalueindex(1));
return 1;
}
+175
View File
@@ -0,0 +1,175 @@
/**
* @file lua_glib.h Lua global table field management library.
*/
#ifndef _LUA_GLIB_H_
#define _LUA_GLIB_H_
#include "doomdef.h"
#include "lua_script.h"
/**
* Feed a list of items to append to the enum cache.
* @param L[1] The table of tiems to add to the enum cache.
* @returns Nothing.
*/
int lua_glib_append_cache(lua_State *L);
/**
* Create a new enum.
* @param L[1] The cache table for the enum.
* @param L[2] The prefix for the enum.
* @param L[3] The fallback function for the enum. Can be nil.
* @returns Nothing.
*/
int lua_glib_new_enum(lua_State *L);
/**
* Create a new getter.
* @param L[1] The name of the getter.
* @param L[2] The getter() function.
* @returns Nothing.
*/
int lua_glib_new_getter(lua_State *L);
/**
* Create a new setter.
* @param L[1] The name of the setter.
* @param L[2] The setter(value) function.
*/
int lua_glib_new_setter(lua_State *L);
/**
* Require the globals library.
* @param L[1] (optional) False to inhibit setting the global metatable.
* @remarks This is a standard Lua require function.
*/
int lua_glib_require(lua_State *L);
/**
* Get the proxy table that can be used to get globals.
*/
void lua_glib_get_proxy(lua_State *L);
/**
* Helper function to push a linear enum cache.
* @param L The Lua state.
* @param prefix enum prefix.
* @param list Enum list.
* @param count Number of elements in list. INT_MAX for NULL termination.
*/
inline static void lua_glib_push_linear_cache(lua_State *L, const char *prefix, const char * const *list, lua_Integer count)
{
lua_newtable(L);
for (lua_Integer i = 0; i < count && list[i]; i++)
{
lua_pushfstring(L, "%s%s", prefix, list[i]);
lua_pushinteger(L, i);
lua_settable(L, -3);
}
}
/**
* Helper function to push a bitfield enum cache.
* @param L The Lua state.
* @param prefix enum prefix.
* @param list Enum list.
* @param count Number of elements in list. INT_MAX for NULL termination.
*/
inline static void lua_glib_push_bitfield_cache(lua_State *L, const char *prefix, const char * const *list, lua_Integer count)
{
lua_newtable(L);
for (lua_Integer i = 0; i < count && list[i]; i++)
{
lua_pushfstring(L, "%s%s", prefix, list[i]);
lua_pushinteger(L, (lua_Integer)1 << i);
lua_settable(L, -3);
}
}
/* Base getters. */
int lua_glib_getter_i8(lua_State *L);
int lua_glib_getter_i16(lua_State *L);
int lua_glib_getter_i32(lua_State *L);
int lua_glib_getter_i64(lua_State *L);
int lua_glib_getter_u8(lua_State *L);
int lua_glib_getter_u16(lua_State *L);
int lua_glib_getter_u32(lua_State *L);
int lua_glib_getter_u64(lua_State *L);
int lua_glib_getter_f32(lua_State *L);
int lua_glib_getter_f64(lua_State *L);
int lua_glib_getter_b8(lua_State *L);
int lua_glib_getter_b16(lua_State *L);
int lua_glib_getter_b32(lua_State *L);
int lua_glib_getter_b64(lua_State *L);
int lua_glib_getter_fxp(lua_State *L);
int lua_glib_getter_str(lua_State *L);
int lua_glib_getter_ptr(lua_State *L);
/* Base setters. */
int lua_glib_setter_i8(lua_State *L);
int lua_glib_setter_i16(lua_State *L);
int lua_glib_setter_i32(lua_State *L);
int lua_glib_setter_i64(lua_State *L);
int lua_glib_setter_u8(lua_State *L);
int lua_glib_setter_u16(lua_State *L);
int lua_glib_setter_u32(lua_State *L);
int lua_glib_setter_u64(lua_State *L);
int lua_glib_setter_f32(lua_State *L);
int lua_glib_setter_f64(lua_State *L);
int lua_glib_setter_b8(lua_State *L);
int lua_glib_setter_b16(lua_State *L);
int lua_glib_setter_b32(lua_State *L);
int lua_glib_setter_b64(lua_State *L);
int lua_glib_setter_fxp(lua_State *L);
#define _LUA_GLIB_DECL_PGETTER(T, name) \
static inline void lua_glib_push_##name##_getter(lua_State *L, const T* ptr) { \
lua_pushlightuserdata(L, (void*)ptr); \
lua_pushcclosure(L, lua_glib_getter_##name, 1); \
}
_LUA_GLIB_DECL_PGETTER(int8_t, i8);
_LUA_GLIB_DECL_PGETTER(int16_t, i16);
_LUA_GLIB_DECL_PGETTER(int32_t, i32);
_LUA_GLIB_DECL_PGETTER(int64_t, i64);
_LUA_GLIB_DECL_PGETTER(uint8_t, u8);
_LUA_GLIB_DECL_PGETTER(uint16_t, u16);
_LUA_GLIB_DECL_PGETTER(uint32_t, u32);
_LUA_GLIB_DECL_PGETTER(uint64_t, u64);
_LUA_GLIB_DECL_PGETTER(float, f32);
_LUA_GLIB_DECL_PGETTER(double, f64);
_LUA_GLIB_DECL_PGETTER(char, str);
_LUA_GLIB_DECL_PGETTER(void, ptr);
_LUA_GLIB_DECL_PGETTER(uint8_t, b8);
_LUA_GLIB_DECL_PGETTER(uint16_t, b16);
_LUA_GLIB_DECL_PGETTER(uint32_t, b32);
_LUA_GLIB_DECL_PGETTER(uint64_t, b64);
_LUA_GLIB_DECL_PGETTER(fixed_t, fxp);
#undef _LUA_GLIB_DECL_PGETTER
#define _LUA_GLIB_DECL_PSETTER(T, name) \
static inline void lua_glib_push_##name##_setter(lua_State *L, T* ptr) { \
lua_pushlightuserdata(L, ptr); \
lua_pushcclosure(L, lua_glib_setter_##name, 1); \
}
_LUA_GLIB_DECL_PSETTER(int8_t, i8);
_LUA_GLIB_DECL_PSETTER(int16_t, i16);
_LUA_GLIB_DECL_PSETTER(int32_t, i32);
_LUA_GLIB_DECL_PSETTER(int64_t, i64);
_LUA_GLIB_DECL_PSETTER(uint8_t, u8);
_LUA_GLIB_DECL_PSETTER(uint16_t, u16);
_LUA_GLIB_DECL_PSETTER(uint32_t, u32);
_LUA_GLIB_DECL_PSETTER(uint64_t, u64);
_LUA_GLIB_DECL_PSETTER(float, f32);
_LUA_GLIB_DECL_PSETTER(double, f64);
_LUA_GLIB_DECL_PSETTER(uint8_t, b8);
_LUA_GLIB_DECL_PSETTER(uint16_t, b16);
_LUA_GLIB_DECL_PSETTER(uint32_t, b32);
_LUA_GLIB_DECL_PSETTER(uint64_t, b64);
_LUA_GLIB_DECL_PSETTER(fixed_t, fxp);
#undef _LUA_GLIB_DECL_PSETTER
#endif
+10 -9
View File
@@ -358,20 +358,23 @@ void LUA_DumpFile(const char *filename)
fixed_t LUA_EvalMath(const char *word)
{
lua_State *L = NULL;
static lua_State *L = NULL;
char buf[1024], *b;
const char *p;
fixed_t res = 0;
// make a new state so SOC can't interefere with scripts
// allocate state
L = lua_newstate(LUA_Alloc, NULL);
lua_atpanic(L, LUA_Panic);
if (L == NULL)
{
L = lua_newstate(LUA_Alloc, NULL);
lua_atpanic(L, LUA_Panic);
// open only enum lib
lua_pushcfunction(L, LUA_EnumLib);
lua_pushboolean(L, true);
lua_call(L, 1, 0);
// open only enum lib
lua_pushcfunction(L, LUA_EnumLib);
lua_pushboolean(L, true);
lua_call(L, 1, 0);
}
// change ^ into ^^ for Lua.
strcpy(buf, "return ");
@@ -396,8 +399,6 @@ fixed_t LUA_EvalMath(const char *word)
else
res = lua_tointeger(L, -1);
// clean up and return.
lua_close(L);
return res;
}