Compare commits

...
21 Commits
Author SHA1 Message Date
indev 33554dc14e Update bluajit to support non-gcc compilers 2025-08-15 20:13:15 +03:00
Alug c7d4c28f01 pass our compiler and ldflags to bluajit 2025-08-15 08:02:10 +02:00
Alug c8929b8c77 dont compile with bluajit by default
add HAVE_BLUAJIT=1 to compile with it
2025-08-05 23:21:44 +02:00
indev 7ee0fe1c1f Reapply lug's bluajit changes :3 2025-08-05 21:55:33 +03:00
indev ce11589f84 Change bluajit submodule branch to bluajit-install 2025-08-05 21:38:20 +03:00
indev c34ec52159 Convert libs/bluajit into git submodule 2025-08-05 21:31:20 +03:00
indev 50d9826e74 Always try to rebuild bluajit in case something is changed in it's sources 2025-08-05 16:04:30 +03:00
Alug 4444d35985 actually pass our compiler flags to jit
and supress all warnings for jit (idk how else to handle it lmao)
2025-08-04 20:23:36 +02:00
Alug 78a597543c readd ref system compat 2025-08-04 19:29:16 +02:00
Alug 78999ebcfa remove unused goto parse function 2025-08-04 19:29:16 +02:00
Alug b049475dd6 Remove goto stuff from bluajit
this wasnt in the main repo
but kart does not have goto so we dont allow modders to screw things up
2025-08-04 19:29:16 +02:00
Alug 477b6567e7 pass our main CFLAGS to bluajit
otherwise it would compile with O2 and stuff becoming super slow lol
no clue if we also should pass linker flags aswell
2025-08-04 19:29:16 +02:00
indev ba67d870a2 Automatically build bluajit 2025-08-04 19:42:11 +03:00
indev f4019ad5ea Move bluajit into libs 2025-08-04 19:10:37 +03:00
Alug 098779c924 fixup bluajit merge
this is the last state this had before wiping it
2025-08-04 15:15:32 +02:00
Alug 54b9c86d9d Merge remote-tracking branch 'origin/ljtest' into ljtest2 2025-08-04 15:06:23 +02:00
GenericHeroGuy 744dc87c16 In rehashtab, do counthash before adding asize
Thanks alug!
2025-01-29 22:25:24 +01:00
GenericHeroGuy b400655f3c Add cleanjit target
Recompiling the whole game after changing a single flag is pretty tiring
2025-01-06 00:02:11 +01:00
GenericHeroGuy 314ab9e9f0 Fix some functions leaking doubles in INTONLY 2025-01-05 23:48:40 +01:00
GenericHeroGuy 0fbc448013 Use references instead of upvalues for original I/O functions
No more unrestricted I/O through debug.getupvalue
2025-01-03 22:16:11 +01:00
GenericHeroGuy eb9d1982fa Update to BLUAJIT 449b76f 2025-01-03 20:12:26 +01:00
14 changed files with 307 additions and 100 deletions

No files matched your search

+5
View File
@@ -0,0 +1,5 @@
[submodule "libs/bluajit"]
path = libs/bluajit
url = https://github.com/Indev450/bluajit
[submodule "libs/bluajit/"]
branch = bluajit-install
Submodule
+1
Submodule libs/bluajit added at 14f5b60567.
+23 -1
View File
@@ -64,6 +64,10 @@
# DEBUGMODE=1 - Enable various debugging capabilities.
# Also disables optimizations.
#
# Potentially Unsafe
# ------------------
# HAVE_BLUAJIT=1 - Enable compiling with BluaJIT instead of blua, can have potential bugs
#
# Development flags:
#
# VALGRIND=1 - Enable Valgrind memory debugging support.
@@ -184,8 +188,14 @@ sources+=\
$(call List,Sourcefile)\
$(call List,core/Sourcefile)
ifndef HAVE_BLUAJIT
lualib:=
sources+=\
$(call List,blua/Sourcefile)
else
opts+=-DLUAJIT_INTONLY
lualib:=../libs/bluajit/src/libbluajit.a
endif
depends:=$(basename $(filter %.c %.cpp %.s,$(sources)))
objects:=$(basename $(filter %.c %.cpp %.s %.nas,$(sources)))
@@ -357,10 +367,15 @@ ifdef UPX
endif
# original executable with debugging symbols
$(dbg) : $(objects) | $$(@D)/
$(dbg) : $(objects) $(lualib) | $$(@D)/
$(call Echo,Linking $(@F)...)
$(.)$(LD) -o $@ $^ $(libs)
ifdef HAVE_BLUAJIT
$(lualib) ::
@$(MAKE) -C ../libs/bluajit $(MAKECMDGOALS) CC="$(CC)" CCOPT="$(opts)" LDFLAGS="$(LDFLAGS)"
endif
# disassembly of executable
$(dbg).txt : $(dbg)
$(call Echo,Dumping debugging info...)
@@ -423,6 +438,13 @@ clean :
distclean :
$(call _rm,../bin ../objs ../dep ../make comptime.h)
ifdef HAVE_BLUAJIT
$(call _rm,$(objdir)/buildvm* $(objdir)/minilua* $(objdir)/lj_vm*)
cleanjit:
$(call _rm,$(objdir)/buildvm* $(objdir)/minilua* $(objdir)/lj_vm* $(ALL_HDRGEN) $(LJVMCORE_O) $(ALL_GEN))
endif
info:
ifdef WINDOWSHELL
@REM
+2 -1
View File
@@ -6,7 +6,8 @@ passthru_opts+=\
NOHW NOMD5 NOPOSTPROCESSING\
MOBJCONSISTANCY PACKETDROP ZDEBUG\
HAVE_MINIUPNPC\
HAVE_DISCORDRPC DEVELOP
HAVE_DISCORDRPC DEVELOP\
HAVE_BLUAJIT
# build with debugging information
ifdef DEBUGMODE
+5
View File
@@ -26,6 +26,11 @@ ifeq (${DEDICATED},1)
EXENAME?=lsrb2kartd
endif
ifdef HAVE_BLUAJIT
libs+=-L../libs/bluajit/src/ -l:libbluajit.a
opts+=-I../libs/bluajit/src/
endif
# In common usage.
ifdef LINUX
libs+=-lrt
+5
View File
@@ -69,6 +69,11 @@ LIBOPENMPT_opts:=-I$(lib)/inc
LIBOPENMPT_libs:=-L$(lib)/lib/$(x86) -lopenmpt
$(eval $(call _set,LIBOPENMPT))
lib:=../libs/bluajit
BLUAJIT_opts:=-I$(lib)/src
BLUAJIT_libs:=-L$(lib)/lib/$(x86) -lbluajit
$(eval $(call _set,BLUAJIT))
lib:=../libs/SDL2_mixer/$(mingw)
ifdef SDL
+5 -70
View File
@@ -17,27 +17,14 @@
#include "lauxlib.h"
#include "lualib.h"
#include "../i_system.h"
#include "../doomdef.h"
#include "../d_main.h"
#include "../m_misc.h"
#define IO_INPUT 1
#define IO_OUTPUT 2
#define FILELIMIT 1024*1024 // Size limit for reading/writing files
static const char *const fnames[] = {"input", "output"};
static const char *whitelist[] = { // Allow scripters to write files of these types to SRB2's folder
".txt",
".sav2",
".cfg",
".png",
".bmp"
};
static int pushresult (lua_State *L, int i, const char *filename) {
@@ -159,59 +146,12 @@ static int io_tostring (lua_State *L) {
return 1;
}
static int StartsWith(const char *a, const char *b) // this is wolfs being lazy yet again
{
if(strncmp(a, b, strlen(b)) == 0) return 1;
return 0;
}
static int io_open (lua_State *L) {
FILE **pf;
const char *filename = luaL_checkstring(L, 1);
int pass = 0;
size_t i;
int length = strlen(filename);
char *splitter, *forward, *backward;
char *destFilename;
const char *mode = luaL_optstring(L, 2, "r");
for (i = 0; i < (sizeof (whitelist) / sizeof(const char *)); i++)
{
if (!stricmp(&filename[length - strlen(whitelist[i])], whitelist[i]))
{
pass = 1;
break;
}
}
if (l_unlikely(strstr(filename, "..") || strchr(filename, ':') || StartsWith(filename, "\\")
|| StartsWith(filename, "/") || !pass))
{
luaL_error(L,"access denied to %s", filename);
return pushresult(L,0,filename);
}
destFilename = va("%s"PATHSEP"luafiles"PATHSEP"%s", srb2home, filename);
// Make directories as needed
splitter = destFilename;
forward = strchr(splitter, '/');
backward = strchr(splitter, '\\');
while ((splitter = (forward && backward) ? min(forward, backward) : (forward ?: backward)))
{
*splitter = 0;
I_mkdir(destFilename, 0755);
*splitter = '/';
splitter++;
forward = strchr(splitter, '/');
backward = strchr(splitter, '\\');
}
pf = newfile(L);
*pf = fopen(destFilename, mode);
return (*pf == NULL) ? pushresult(L, 0, filename) : 1;
const char *filename = luaL_checkstring(L, 1);
const char *mode = luaL_optstring(L, 2, "r");
FILE **pf = newfile(L);
*pf = fopen(filename, mode);
return (*pf == NULL) ? pushresult(L, 0, filename) : 1;
}
@@ -454,11 +394,6 @@ static int g_write (lua_State *L, FILE *f, int arg) {
else {
size_t l;
const char *s = luaL_checklstring(L, arg, &l);
if (l_unlikely(ftell(f) + l > FILELIMIT))
{
luaL_error(L,"write limit bypassed in file. Changes have been discarded.");
break;
}
status = status && (fwrite(s, sizeof(char), l, f) == l);
}
}
+4
View File
@@ -777,6 +777,10 @@ void D_RegisterServerCommands(void)
CV_RegisterVar(&cv_netdemosyncquality);
CV_RegisterVar(&cv_maxdemosize);
CV_RegisterVar(&cv_demochangemap);
#ifdef HAVE_BLUAJIT
CV_RegisterVar(&cv_luajit);
#endif
}
// =========================================================================
+139
View File
@@ -42,6 +42,123 @@ boolean luaL_checkboolean(lua_State *L, int narg) {
return lua_toboolean(L, narg);
}
static int ref_open, ref_iowrite, ref_fwrite; // original versions of io functions
#define FILELIMIT 1024*1024 // Size limit for reading/writing files
static const char *whitelist[] = { // Allow scripters to write files of these types to SRB2's folder
".txt",
".sav2",
".cfg",
".png",
".bmp"
};
static int StartsWith(const char *a, const char *b) // this is wolfs being lazy yet again
{
if(strncmp(a, b, strlen(b)) == 0) return 1;
return 0;
};
// Wrapper for opening files
static int lib_open(lua_State *L)
{
const char *filename = luaL_checkstring(L, 1);
int pass = 0;
size_t i;
int length = strlen(filename);
char *splitter, *forward, *backward;
char *destFilename;
for (i = 0; i < (sizeof (whitelist) / sizeof(const char *)); i++)
{
if (!stricmp(&filename[length - strlen(whitelist[i])], whitelist[i]))
{
pass = 1;
break;
}
}
if (strstr(filename, "..") || strchr(filename, ':') || StartsWith(filename, "\\")
|| StartsWith(filename, "/") || !pass)
{
return luaL_error(L,"access denied to %s", filename);
}
destFilename = va("%s"PATHSEP"luafiles"PATHSEP"%s", srb2home, filename);
// Make directories as needed
splitter = destFilename;
forward = strchr(splitter, '/');
backward = strchr(splitter, '\\');
while ((splitter = (forward && backward) ? min(forward, backward) : (forward ?: backward)))
{
*splitter = 0;
I_mkdir(destFilename, 0755);
*splitter = '/';
splitter++;
forward = strchr(splitter, '/');
backward = strchr(splitter, '\\');
}
// replace the filename string
lua_pushstring(L, destFilename);
lua_replace(L, 1);
// now call the real io.open
lua_rawgeti(L, LUA_REGISTRYINDEX, ref_open);
lua_insert(L, 1);
lua_call(L, lua_gettop(L)-1, LUA_MULTRET);
return lua_gettop(L);
}
// Wrapper for writing to files
static int lib_write(lua_State *L, int arg)
{
int top = lua_gettop(L);
boolean error = true;
size_t len, size = 0;
int ogref = ref_iowrite;
if (arg != 1) {
ogref = ref_fwrite;
FILE *fp = *(FILE **)luaL_checkudata(L, 1, LUA_FILEHANDLE);
if (fp == NULL) goto call; // real file:write will throw
size = ftell(fp);
}
// check the size of each argument. if there's too much data,
// cut off the stack and print an error
for (; arg <= top; arg++) {
if (lua_tolstring(L, arg, &len) == NULL) goto call;
if ((size += len) > FILELIMIT) {
// oops! too many bytes!
lua_settop(L, arg-1);
goto call;
}
}
error = false;
call:
lua_rawgeti(L, LUA_REGISTRYINDEX, ogref);
lua_insert(L, 1);
lua_call(L, lua_gettop(L)-1, LUA_MULTRET);
if (error)
return luaL_error(L,"write limit bypassed in file. Changes have been discarded.");
return lua_gettop(L);
}
static int lib_write_f(lua_State *L)
{
return lib_write(L, 2);
}
static int lib_write_io(lua_State *L)
{
return lib_write(L, 1);
}
// String concatination
static int lib_concat(lua_State *L)
{
@@ -3348,6 +3465,28 @@ int LUA_BaseLib(lua_State *L)
lua_setfield(L,-2,"__add"); // ... store it as mathematical addition
lua_pop(L, 2); // pop metatable and dummy string
// replaces an existing function with another,
// saving the original as a reference
#define REPLACE(name, func, ref) \
lua_pushliteral(L, name); \
lua_rawget(L, -2); \
ref = luaL_ref(L, LUA_REGISTRYINDEX); \
lua_pushliteral(L, name); \
lua_pushcclosure(L, &func, 0); \
lua_rawset(L, -3);
// replace io.open
lua_getglobal(L, "io");
REPLACE("open", lib_open, ref_open)
REPLACE("write", lib_write_io, ref_iowrite)
lua_pop(L, 1);
// replace file:write
luaL_getmetatable(L, LUA_FILEHANDLE);
REPLACE("write", lib_write_f, ref_fwrite)
lua_pop(L, 1);
#undef REPLACE
lua_newtable(L);
lua_setfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS);
+41 -27
View File
@@ -324,13 +324,14 @@ static int lib_cvRegisterVar(lua_State *L)
const char* category = NULL;
const char* menu_name = NULL;
boolean hasfunc = false;
int funcref = 0;
luaL_checktype(L, 1, LUA_TTABLE);
lua_settop(L, 1); // Clear out all other possible arguments, leaving only the first one.
NOHUD
cvar = lua_newuserdata(L, sizeof(consvar_t));
luaL_getmetatable(L, META_CVAR);
lua_setmetatable(L, -2);
cvar = ZZ_Calloc(sizeof(consvar_t));
LUA_PushUserdata(L, cvar, META_CVAR);
#define FIELDERROR(f, e) luaL_error(L, "bad value for " LUA_QL(f) " in table passed to " LUA_QL("CV_RegisterVar") " (%s)", e);
#define TYPEERROR(f, t) FIELDERROR(f, va("%s expected, got %s", lua_typename(L, t), luaL_typename(L, -1)))
@@ -404,27 +405,38 @@ static int lib_cvRegisterVar(lua_State *L)
cvpv[i].value = 0;
cvpv[i].strvalue = NULL;
cvar->PossibleValue = cvpv;
// MIN and MAX are expected to be at hardcoded indices apparently
// so, sigh, here goes...
#define SWAP(from, to) \
INT32 val = cvpv[from].value; \
const char *strval = cvpv[from].strvalue; \
cvpv[from].value = cvpv[to].value; \
cvpv[from].strvalue = cvpv[to].strvalue; \
cvpv[to].value = val; \
cvpv[to].strvalue = strval;
for (int j = 0; j < i; j++) {
if (!strcmp(cvpv[j].strvalue, "MIN") && j != 0) {
SWAP(j, 0)
} else if (!strcmp(cvpv[j].strvalue, "MAX") && j != 1) {
SWAP(j, 1)
}
}
} else
FIELDERROR("PossibleValue", va("%s or CV_PossibleValue_t expected, got %s", lua_typename(L, LUA_TTABLE), luaL_typename(L, -1)))
} else if (i == 5 || (k && fasticmp(k, "func"))) {
if (!lua_isfunction(L, 4))
TYPEERROR("func", LUA_TFUNCTION)
lua_getfield(L, LUA_REGISTRYINDEX, "CV_OnChange");
I_Assert(lua_istable(L, 5));
lua_pushvalue(L, 4);
lua_setfield(L, 5, cvar->name);
lua_pop(L, 1);
cvar->func = Lua_OnChange;
if (hasfunc)
luaL_unref(L, LUA_REGISTRYINDEX, funcref); // real clever, huh?
funcref = luaL_ref(L, LUA_REGISTRYINDEX);
hasfunc = true;
continue;
}
else if (((i == 5 && !(cvar->flags & CV_CALL))
|| (cvar->flags & CV_CALL && i == 6))
|| (k && fasticmp(k, "category")))
else if (i == 6 || (k && fasticmp(k, "category")))
{
category = lua_isnoneornil(L, 4) ? NULL : lua_tostring(L, 4);
}
else if (((i == 6 && !(cvar->flags & CV_CALL))
|| (cvar->flags & CV_CALL && i == 7))
|| (k && fasticmp(k, "menuname")))
else if (i == 7 || (k && fasticmp(k, "menuname")))
{
menu_name = lua_isnoneornil(L, 4) ? NULL : lua_tostring(L, 4);
}
@@ -434,6 +446,16 @@ static int lib_cvRegisterVar(lua_State *L)
#undef TYPEERROR
// stack: cvar table, cvar userdata
if (hasfunc) {
lua_getfield(L, LUA_REGISTRYINDEX, "CV_OnChange");
I_Assert(lua_istable(L, 3));
lua_rawgeti(L, LUA_REGISTRYINDEX, funcref);
lua_setfield(L, 3, cvar->name);
lua_pop(L, 1);
cvar->func = Lua_OnChange;
luaL_unref(L, LUA_REGISTRYINDEX, funcref);
}
lua_getfield(L, LUA_REGISTRYINDEX, "CV_Vars");
I_Assert(lua_istable(L, 3));
@@ -479,15 +501,7 @@ static int lib_cvFindVar(lua_State *L)
consvar_t *cv;
if (( cv = CV_FindVar(luaL_checkstring(L,1)) ))
{
lua_settop(L,1);/* We only want one argument in the stack. */
lua_pushlightuserdata(L, cv);/* Now the second value on stack. */
luaL_getmetatable(L, META_CVAR);
/*
The metatable is the last value on the stack, so this
applies it to the second value, which is the cvar.
*/
lua_setmetatable(L,2);
lua_pushvalue(L,2);
LUA_PushUserdata(L, cv, META_CVAR);
return 1;
}
else
@@ -500,7 +514,7 @@ static int CVarSetFunction
void (*Set)(consvar_t *, const char *),
void (*SetValue)(consvar_t *, INT32)
){
consvar_t *cvar = (consvar_t *)luaL_checkudata(L, 1, META_CVAR);
consvar_t *cvar = *((consvar_t **)luaL_checkudata(L, 1, META_CVAR));
switch (lua_type(L, 2))
{
@@ -529,7 +543,7 @@ static int lib_cvStealthSet(lua_State *L)
static int lib_cvAddValue(lua_State *L)
{
consvar_t *cvar = (consvar_t *)luaL_checkudata(L, 1, META_CVAR);
consvar_t *cvar = *((consvar_t **)luaL_checkudata(L, 1, META_CVAR));
CV_AddValue(cvar, (INT32)luaL_checknumber(L, 2));
return 0;
}
@@ -604,7 +618,7 @@ static int cvar_fields_ref = LUA_NOREF;
static int cvar_get(lua_State *L)
{
consvar_t *cvar = (consvar_t *)luaL_checkudata(L, 1, META_CVAR);
consvar_t *cvar = *((consvar_t **)luaL_checkudata(L, 1, META_CVAR));
enum cvar_e field = Lua_optoption(L, 2, -1, cvar_fields_ref);
switch (field)
+12 -1
View File
@@ -12,7 +12,11 @@
#include "lua_hudlib_drawlist.h"
#include "lua_hud.h"
#ifndef HAVE_BLUAJIT
#include "blua/lstate.h" // shhhhhh
#else
#include "lua_script.h"
#endif
#include "lua_libs.h"
#include <string.h>
@@ -328,8 +332,15 @@ static UINT64 GetItemId(void)
if (!hud_interpolate)
return 0;
#ifndef HAVE_BLUAJIT
UINT64 id = (uintptr_t)gL->savedpc;
#else
// he who controls the JIT controls the API
const void *p = lua_getpc(gL, 1);
UINT64 id = (uintptr_t)p;
#endif
// leave bits 0 and 1 free for the string mode
UINT64 id = ((UINT64)(uintptr_t)gL->savedpc << 32) | (hud_interpcounter << 10) | (hud_interptag << 2);
id = (id << 32) | (hud_interpcounter << 10) | (hud_interptag << 2);
if (hud_interplatch)
{
+5
View File
@@ -11,7 +11,12 @@
/// \brief libraries for Lua scripting
#include "doomtype.h"
#ifndef HAVE_BLUAJIT
#include "blua/lua.h"
#else
#include <lua.h>
#endif
extern lua_State *gL;
+50
View File
@@ -35,6 +35,14 @@
#include "doomstat.h"
#ifdef HAVE_BLUAJIT
#include "d_main.h"
#include "i_system.h"
static void LuaJit_OnChange(void);
static void print_jit_status(boolean verbose);
consvar_t cv_luajit = {"luajit", "On", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, LuaJit_OnChange, 0, NULL, NULL, 0, 0, NULL};
#endif
lua_State *gL = NULL;
// Mathlib global state
@@ -61,6 +69,21 @@ static lua_CFunction liblist[] = {
NULL
};
#ifdef HAVE_BLUAJIT
static void LuaJit_OnChange(void)
{
if (!gL)
LUA_ClearState();
lua_getfield(gL, LUA_REGISTRYINDEX, "_LOADED");
lua_getfield(gL, -1, "jit");
lua_remove(gL, -2);
lua_getfield(gL, -1, cv_luajit.value ? "on" : "off");
lua_remove(gL, -2);
lua_call(gL, 0, 0);
print_jit_status(false);
}
#endif
// Lua asks for memory using this.
static void *LUA_Alloc(void *ud, void *ptr, size_t osize, size_t nsize)
{
@@ -185,6 +208,29 @@ static int noglobals(lua_State *L)
return luaL_error(L, "Implicit global " LUA_QS " prevented. Create a local variable instead.", csname);
}
#ifdef HAVE_BLUAJIT
// print all the ISA extensions because it looks cool!
// absolutely not stolen from luajit.c
static void print_jit_status(boolean verbose)
{
int n;
const char *s;
lua_getfield(gL, LUA_REGISTRYINDEX, "_LOADED");
lua_getfield(gL, -1, "jit"); /* Get jit.* module table. */
lua_remove(gL, -2);
lua_getfield(gL, -1, "status");
lua_remove(gL, -2);
n = lua_gettop(gL);
lua_call(gL, 0, LUA_MULTRET);
CONS_Printf(lua_toboolean(gL, n) ? "JIT: ON" : "JIT: OFF");
if (verbose)
for (n++; (s = lua_tostring(gL, n)); n++)
CONS_Printf(" %s", s);
CONS_Printf("\n");
lua_settop(gL, 0); /* clear stack */
}
#endif
// Clear and create a new Lua state, laddo!
// There's SCRIPTIN to be had!
void LUA_ClearState(void)
@@ -227,6 +273,10 @@ void LUA_ClearState(void)
// lua state is ready!
gL = L;
#ifdef HAVE_BLUAJIT
print_jit_status(true);
#endif
}
#ifdef _DEBUG
+10
View File
@@ -18,9 +18,19 @@
#include "d_player.h"
#include "p_saveg.h"
#ifndef HAVE_BLUAJIT
#include "blua/lua.h"
#include "blua/lualib.h"
#include "blua/lauxlib.h"
#else
#include "command.h"
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
#define abs_index(L, i) ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : \
lua_gettop(L) + (i) + 1)
extern consvar_t cv_luajit;
#endif
#define lua_optboolean(L, i) (!lua_isnoneornil(L, i) && lua_toboolean(L, i))
#define lua_opttrueboolean(L, i) (lua_isnoneornil(L, i) || lua_toboolean(L, i))