#pragma once
#include "lobject.h"
#include "ltm.h"
#define gt(L) (&L->l_gt)
#define registry(L) (&L->global->registry)
#define EXTRA_STACK 5
#define BASIC_CI_SIZE 8
#define BASIC_STACK_SIZE (2 * LUA_MINSTACK)
typedef struct stringtable
{
GCObject** hash;
uint32_t nuse;
int size;
} stringtable;
typedef struct CallInfo
{
StkId base;
StkId func;
StkId top;
const Instruction* savedpc;
int nresults;
unsigned int flags;
} CallInfo;
#define LUA_CALLINFO_RETURN (1 << 0)
#define LUA_CALLINFO_HANDLE (1 << 1)
#define curr_func(L) (clvalue(L->ci->func))
#define ci_func(ci) (clvalue((ci)->func))
#define f_isLua(ci) (!ci_func(ci)->isC)
#define isLua(ci) (ttisfunction((ci)->func) && f_isLua(ci))
struct GCCycleStats
{
size_t heapgoalsizebytes = 0;
size_t heaptriggersizebytes = 0;
double waittime = 0.0;
double starttimestamp = 0.0;
double endtimestamp = 0.0;
double marktime = 0.0;
double atomicstarttimestamp = 0.0;
size_t atomicstarttotalsizebytes = 0;
double atomictime = 0.0;
double sweeptime = 0.0;
size_t markitems = 0;
size_t sweepitems = 0;
size_t assistwork = 0;
size_t explicitwork = 0;
size_t endtotalsizebytes = 0;
};
struct GCHeapTriggerStats
{
static const unsigned termcount = 32;
int32_t terms[termcount] = {0};
uint32_t termpos = 0;
int32_t integral = 0;
};
struct GCStats
{
double stepexplicittimeacc = 0.0;
double stepassisttimeacc = 0.0;
uint64_t completedcycles = 0;
GCCycleStats lastcycle;
GCCycleStats currcycle;
GCCycleStats cyclestatsacc;
GCHeapTriggerStats triggerstats;
};
typedef struct global_State
{
stringtable strt;
lua_Alloc frealloc;
void* ud;
uint8_t currentwhite;
uint8_t gcstate;
int sweepstrgc;
GCObject* rootgc;
GCObject** sweepgc;
GCObject* gray;
GCObject* grayagain;
GCObject* weak;
GCObject* strbufgc;
size_t GCthreshold; size_t totalbytes; int gcgoal; int gcstepmul; int gcstepsize;
struct lua_Page* freepages[LUA_SIZECLASSES];
size_t memcatbytes[LUA_MEMORY_CATEGORIES];
struct lua_State* mainthread;
UpVal uvhead;
struct Table* mt[LUA_T_COUNT];
TString* ttname[LUA_T_COUNT];
TString* tmname[TM_N];
TValue registry;
int registryfree;
struct lua_jmpbuf* errorjmp;
uint64_t rngstate;
uint64_t ptrenckey[4];
void (*udatagc[LUA_UTAG_LIMIT])(void*);
lua_Callbacks cb;
GCStats gcstats;
} global_State;
struct lua_State
{
CommonHeader;
uint8_t status;
uint8_t activememcat;
uint8_t stackstate;
bool singlestep;
StkId top;
StkId base;
global_State* global;
CallInfo* ci;
StkId stack_last;
StkId stack;
CallInfo* end_ci;
CallInfo* base_ci;
int stacksize;
int size_ci;
unsigned short nCcalls;
unsigned short baseCcalls;
int cachedslot;
TValue l_gt;
TValue env;
GCObject* openupval;
GCObject* gclist;
TString* namecall;
void* userdata;
};
union GCObject
{
GCheader gch;
struct TString ts;
struct Udata u;
struct Closure cl;
struct Table h;
struct Proto p;
struct UpVal uv;
struct lua_State th;
};
#define gco2ts(o) check_exp((o)->gch.tt == LUA_TSTRING, &((o)->ts))
#define gco2u(o) check_exp((o)->gch.tt == LUA_TUSERDATA, &((o)->u))
#define gco2cl(o) check_exp((o)->gch.tt == LUA_TFUNCTION, &((o)->cl))
#define gco2h(o) check_exp((o)->gch.tt == LUA_TTABLE, &((o)->h))
#define gco2p(o) check_exp((o)->gch.tt == LUA_TPROTO, &((o)->p))
#define gco2uv(o) check_exp((o)->gch.tt == LUA_TUPVAL, &((o)->uv))
#define gco2th(o) check_exp((o)->gch.tt == LUA_TTHREAD, &((o)->th))
#define obj2gco(v) check_exp(iscollectable(v), cast_to(GCObject*, (v) + 0))
LUAI_FUNC lua_State* luaE_newthread(lua_State* L);
LUAI_FUNC void luaE_freethread(lua_State* L, lua_State* L1);