Skip to content
Closed
4 changes: 4 additions & 0 deletions gamedata/scripts/lua_help_ex.script
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,10 @@
jit.allocprof.resume() // re-arm and continue capturing
}

jit.util { // additions beyond stock jit.util
table jit.util.gcstat() // {total, threshold, estimate, debt} in bytes plus cycles = completed GC collections since start; read-only snapshot, values may be mid-cycle under parallel GC
}

globals {
string dik_to_keyname(number dik, boolean localize)
int get_modded_exes_version() // Returns modded exes version in integer format
Expand Down
32 changes: 31 additions & 1 deletion src/3rd party/luajit-2/src/lib_jit.c
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,12 @@ static void setintfield(lua_State *L, GCtab *t, const char *name, int32_t val)
setintV(lj_tab_setstr(L, t, lj_str_newz(L, name)), val);
}

/* GC counters are MSize (uint32); a double holds the full range without the int32 wrap. */
static void setnumfield(lua_State *L, GCtab *t, const char *name, lua_Number val)
{
setnumV(lj_tab_setstr(L, t, lj_str_newz(L, name)), val);
}

/* local info = jit.util.funcinfo(func [,pc]) */
LJLIB_CF(jit_util_funcinfo)
{
Expand Down Expand Up @@ -268,6 +274,29 @@ LJLIB_CF(jit_util_funcuvname)
return 0;
}

extern uint32_t lj_gc_cycles; /* Defined in lj_gc.c: completed GC cycles since start. */

/* local info = jit.util.gcstat() -- GC counters: total, threshold, estimate, debt (bytes) and cycles (completed collections) */
LJLIB_CF(jit_util_gcstat)
{
global_State *g = G(L);
/* Snapshot before allocating: lua_createtable/lj_str_newz can run a GC step that moves these. */
lua_Number total = (lua_Number)g->gc.total;
lua_Number threshold = (lua_Number)g->gc.threshold;
lua_Number estimate = (lua_Number)g->gc.estimate;
lua_Number debt = (lua_Number)g->gc.debt;
lua_Number cycles = (lua_Number)lj_gc_cycles;
GCtab *t;
lua_createtable(L, 0, 5);
t = tabV(L->top-1);
setnumfield(L, t, "total", total);
setnumfield(L, t, "threshold", threshold);
setnumfield(L, t, "estimate", estimate);
setnumfield(L, t, "debt", debt);
setnumfield(L, t, "cycles", cycles);
return 1;
}

/* -- Reflection API for traces ------------------------------------------- */

#if LJ_HASJIT
Expand Down Expand Up @@ -544,8 +573,9 @@ static void jit_profile_callback(lua_State *L2, lua_State *L, int samples,
setstrV(L2, L2->top++, lj_str_new(L2, &vmst, 1));
status = lua_pcall(L2, 3, 0, 0); /* callback(thread, samples, vmstate) */
if (status) {
/* Panic logs and returns; drop the sample and keep sampling, never exit the game. */
if (G(L2)->panic) G(L2)->panic(L2);
exit(EXIT_FAILURE);
lua_settop(L2, 0);
}
lj_trace_abort(G(L2));
}
Expand Down
35 changes: 27 additions & 8 deletions src/3rd party/luajit-2/src/lj_allocprof.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "luajit.h"

#include <string.h>
#include <stdlib.h>
#include <math.h>

#define ALLOCPROF_LEAF_SLOTS 4096
Expand All @@ -37,8 +38,8 @@ static struct {
uint8_t saved_mask;
int32_t saved_count;
int32_t saved_cstart;
AllocProfEntry leaf[ALLOCPROF_LEAF_SLOTS];
AllocProfEntry stack[ALLOCPROF_STACK_SLOTS];
AllocProfEntry *leaf; /* Heap, first start; kept so dump reads work after stop. */
AllocProfEntry *stack;
} AS;

static uint32_t allocprof_hash(const char *s, size_t n)
Expand All @@ -54,7 +55,12 @@ static void allocprof_record(AllocProfEntry *tab, int slots, int *used,
{
size_t n = strlen(key);
uint32_t h, i;
if (n >= sizeof(tab->key)) n = sizeof(tab->key) - 1;
if (n >= sizeof(tab->key)) {
/* Cut at the last ';' so a partial frame drops whole, never mid-name. */
size_t j = sizeof(tab->key) - 1;
while (j > 0 && key[j] != ';') j--;
n = j > 0 ? j : sizeof(tab->key) - 1;
}
h = allocprof_hash(key, n) & (uint32_t)(slots - 1);
for (i = 0; i < (uint32_t)slots; i++) {
AllocProfEntry *e = &tab[(h + i) & (uint32_t)(slots - 1)];
Expand Down Expand Up @@ -123,7 +129,20 @@ void lj_allocprof_start(lua_State *L, int depth)
}
if (depth < 1) depth = 1;
if (depth > ALLOCPROF_MAX_DEPTH) depth = ALLOCPROF_MAX_DEPTH;
memset(&AS, 0, sizeof(AS));
if (!AS.leaf) {
AS.leaf = (AllocProfEntry *)calloc(ALLOCPROF_LEAF_SLOTS, sizeof(AllocProfEntry));
AS.stack = (AllocProfEntry *)calloc(ALLOCPROF_STACK_SLOTS, sizeof(AllocProfEntry));
if (!AS.leaf || !AS.stack) {
free(AS.leaf); free(AS.stack);
AS.leaf = NULL; AS.stack = NULL;
return;
}
} else {
memset(AS.leaf, 0, ALLOCPROF_LEAF_SLOTS * sizeof(AllocProfEntry));
memset(AS.stack, 0, ALLOCPROF_STACK_SLOTS * sizeof(AllocProfEntry));
}
AS.leaf_used = 0;
AS.stack_used = 0;
AS.g = g;
AS.depth = depth;
AS.saved_mask = g->hookmask;
Expand Down Expand Up @@ -157,9 +176,9 @@ void lj_allocprof_stop(lua_State *L)

void lj_allocprof_reset(void)
{
if (!AS.g) return;
memset(AS.leaf, 0, sizeof(AS.leaf));
memset(AS.stack, 0, sizeof(AS.stack));
if (!(AS.g && AS.leaf)) return;
memset(AS.leaf, 0, ALLOCPROF_LEAF_SLOTS * sizeof(AllocProfEntry));
memset(AS.stack, 0, ALLOCPROF_STACK_SLOTS * sizeof(AllocProfEntry));
AS.leaf_used = 0;
AS.stack_used = 0;
lj_allocprof_dropped = 0;
Expand Down Expand Up @@ -208,7 +227,7 @@ int lj_allocprof_slots(int stacks)
const AllocProfEntry *lj_allocprof_slot(int stacks, int k)
{
AllocProfEntry *tab = stacks ? AS.stack : AS.leaf;
return tab[k].bytes ? &tab[k] : NULL;
return (tab && tab[k].bytes) ? &tab[k] : NULL;
}

#endif
2 changes: 1 addition & 1 deletion src/3rd party/luajit-2/src/lj_allocprof.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#if LJ_HASPROFILE

typedef struct AllocProfEntry {
char key[512];
char key[4096];
uint64_t bytes;
} AllocProfEntry;

Expand Down
6 changes: 6 additions & 0 deletions src/3rd party/luajit-2/src/lj_gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -603,6 +603,10 @@ static void atomic(global_State *g, lua_State *L)
}

/* GC state machine. Returns a cost estimate for each step performed. */
/* Completed GC cycles since process start, read via jit.util.gcstat. A file-scope
** global, not a GCState field, so it does not shift global_State layout. */
uint32_t lj_gc_cycles = 0;

static size_t gc_onestep(lua_State *L)
{
global_State *g = G(L);
Expand Down Expand Up @@ -646,6 +650,7 @@ static size_t gc_onestep(lua_State *L)
} else { /* Otherwise skip this phase to help the JIT. */
g->gc.state = GCSpause; /* End of GC cycle. */
g->gc.debt = 0;
lj_gc_cycles++;
}
}
return GCSWEEPMAX*GCSWEEPCOST;
Expand All @@ -664,6 +669,7 @@ static size_t gc_onestep(lua_State *L)
#endif
g->gc.state = GCSpause; /* End of GC cycle. */
g->gc.debt = 0;
lj_gc_cycles++;
return 0;
default:
lua_assert(0);
Expand Down
21 changes: 18 additions & 3 deletions src/3rd party/luajit-2/src/lj_profile.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "lua.h"

#include <stdio.h>
#include <math.h>

#if LJ_PROFILE_SIGPROF

Expand Down Expand Up @@ -249,14 +250,28 @@ static void profile_timer_stop(ProfileState *ps)

#elif LJ_PROFILE_WTHREAD

static uint64_t profile_rng = 0x2545f4914f6cdd1dull;

/* Randomized sleep from exp(interval): breaks phase-lock so periodic work cannot alias the sampler. */
static int profile_jitter(int interval)
{
uint64_t x = profile_rng;
double u, d;
x ^= x << 13; x ^= x >> 7; x ^= x << 17;
profile_rng = x;
u = ((double)(x >> 11) + 1.0) / 9007199254740993.0;
d = -(double)interval * log(u);
return d < 1.0 ? 1 : (int)d;
}

/* Windows timer thread. */
static DWORD WINAPI profile_thread(void *psx)
{
ProfileState *ps = (ProfileState *)psx;
int interval = ps->interval;
if (ps->wmm_tbp) ps->wmm_tbp(interval);
while (1) {
Sleep(interval);
Sleep((DWORD)profile_jitter(interval));
if (ps->abort) break;
profile_trigger(ps);
}
Expand Down Expand Up @@ -342,8 +357,8 @@ LUA_API void luaJIT_profile_stop(lua_State *L)
ProfileState *ps = &profile_state;
global_State *g = ps->g;
if (G(L) == g) { /* Only stop profiler if started by this VM. */
profile_timer_stop(ps); /* Join the timer thread first: no profile_trigger can read a cleared g. */
ps->g = NULL;
profile_timer_stop(ps);
g->hookmask &= (uint8_t)~(HOOK_PROFILE |
(ps->added_maskline ? LUA_MASKLINE : 0));
g->hookcount = ps->saved_count;
Expand All @@ -356,7 +371,7 @@ LUA_API void luaJIT_profile_stop(lua_State *L)
LUA_API const char *luaJIT_profile_dumpstack(lua_State *L, const char *fmt,
int depth, size_t *len)
{
static char buf[2048];
static char buf[8192];
size_t n = 0;
int level;
int maxd = depth < 0 ? -depth : depth;
Expand Down
Loading