// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details1// This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details2#pragma once34#include "lobject.h"5#include "ltm.h"67// registry8#define registry(L) (&L->global->registry)910// extra stack space to handle TM calls and some other extras11#define EXTRA_STACK 51213#define BASIC_CI_SIZE 81415#define BASIC_STACK_SIZE (2 * LUA_MINSTACK)1617// clang-format off18typedef struct stringtable19{20TString** hash;21uint32_t nuse; // number of elements22int size;23} stringtable;24// clang-format on2526/*27** informations about a call28**29** the general Lua stack frame structure is as follows:30** - each function gets a stack frame, with function "registers" being stack slots on the frame31** - function arguments are associated with registers 0+32** - function locals and temporaries follow after; usually locals are a consecutive block per scope, and temporaries are allocated after this, but33*this is up to the compiler34**35** when function doesn't have varargs, the stack layout is as follows:36** ^ (func) ^^ [fixed args] [locals + temporaries]37** where ^ is the 'func' pointer in CallInfo struct, and ^^ is the 'base' pointer (which is what registers are relative to)38**39** when function *does* have varargs, the stack layout is more complex - the runtime has to copy the fixed arguments so that the 0+ addressing still40*works as follows:41** ^ (func) [fixed args] [varargs] ^^ [fixed args] [locals + temporaries]42**43** computing the sizes of these individual blocks works as follows:44** - the number of fixed args is always matching the `numparams` in a function's Proto object; runtime adds `nil` during the call execution as45*necessary46** - the number of variadic args can be computed by evaluating (ci->base - ci->func - 1 - numparams)47**48** the CallInfo structures are allocated as an array, with each subsequent call being *appended* to this array (so if f calls g, CallInfo for g49*immediately follows CallInfo for f)50** the `nresults` field in CallInfo is set by the caller to tell the function how many arguments the caller is expecting on the stack after the51*function returns52** the `flags` field in CallInfo contains internal execution flags that are important for pcall/etc, see LUA_CALLINFO_*53*/54// clang-format off55typedef struct CallInfo56{57StkId base; // base for this function58StkId func; // function index in the stack59StkId top; // top for this function60const Instruction* savedpc;6162int nresults; // expected number of results from this function63unsigned int flags; // call frame flags, see LUA_CALLINFO_*64} CallInfo;65// clang-format on6667#define LUA_CALLINFO_RETURN (1 << 0) // should the interpreter return after returning from this callinfo? first frame must have this set68#define LUA_CALLINFO_HANDLE (1 << 1) // should the error thrown during execution get handled by continuation from this callinfo? func must be C69#define LUA_CALLINFO_NATIVE (1 << 2) // should this function be executed using execution callback for native code7071#define curr_func(L) (clvalue(L->ci->func))72#define ci_func(ci) (clvalue((ci)->func))73#define f_isLua(ci) (!ci_func(ci)->isC)74#define isLua(ci) (ttisfunction((ci)->func) && f_isLua(ci))7576struct GCStats77{78// data for proportional-integral controller of heap trigger value79int32_t triggerterms[32] = {0};80uint32_t triggertermpos = 0;81int32_t triggerintegral = 0;8283size_t atomicstarttotalsizebytes = 0;84size_t endtotalsizebytes = 0;85size_t heapgoalsizebytes = 0;8687double starttimestamp = 0;88double atomicstarttimestamp = 0;89double endtimestamp = 0;90};9192#ifdef LUAI_GCMETRICS93struct GCCycleMetrics94{95size_t starttotalsizebytes = 0;96size_t heaptriggersizebytes = 0;9798double pausetime = 0.0; // time from end of the last cycle to the start of a new one99100double starttimestamp = 0.0;101double endtimestamp = 0.0;102103double marktime = 0.0;104double markassisttime = 0.0;105double markmaxexplicittime = 0.0;106size_t markexplicitsteps = 0;107size_t markwork = 0;108109double atomicstarttimestamp = 0.0;110size_t atomicstarttotalsizebytes = 0;111double atomictime = 0.0;112113// specific atomic stage parts114double atomictimeupval = 0.0;115double atomictimeweak = 0.0;116double atomictimegray = 0.0;117double atomictimeclear = 0.0;118119double sweeptime = 0.0;120double sweepassisttime = 0.0;121double sweepmaxexplicittime = 0.0;122size_t sweepexplicitsteps = 0;123size_t sweepwork = 0;124125size_t assistwork = 0;126size_t explicitwork = 0;127128size_t propagatework = 0;129size_t propagateagainwork = 0;130131size_t endtotalsizebytes = 0;132};133134struct GCMetrics135{136double stepexplicittimeacc = 0.0;137double stepassisttimeacc = 0.0;138139// when cycle is completed, last cycle values are updated140uint64_t completedcycles = 0;141142GCCycleMetrics lastcycle;143GCCycleMetrics currcycle;144};145#endif146147// Callbacks that can be used to to redirect code execution from Luau bytecode VM to a custom implementation (AoT/JiT/sandboxing/...)148struct lua_ExecutionCallbacks149{150void* context;151void (*close)(lua_State* L); // called when global VM state is closed152void (*destroy)(lua_State* L, Proto* proto); // called when function is destroyed153int (*enter)(lua_State* L, Proto* proto); // called when function is about to start/resume (when execdata is present), return 0 to exit VM154void (*disable)(lua_State* L, Proto* proto); // called when function has to be switched from native to bytecode in the debugger155size_t (*getmemorysize)(lua_State* L, Proto* proto); // called to request the size of memory associated with native part of the Proto156uint8_t (*gettypemapping)(lua_State* L, const char* str, size_t len); // called to get the userdata type index157char* (*getcounterdata)(158lua_State* L,159Proto* proto,160size_t* count161); // called to get the execution counter data and count {uint32_t, uint32_t, uint64_t}162};163164/*165** `global state', shared by all threads of this state166*/167// clang-format off168typedef struct global_State169{170stringtable strt; // hash table for strings171172lua_Alloc frealloc; // function to reallocate memory173void* ud; // auxiliary data to `frealloc'174175uint8_t currentwhite;176uint8_t gcstate; // state of garbage collector177178GCObject* gray; // list of gray objects179GCObject* grayagain; // list of objects to be traversed atomically180GCObject* weak; // list of weak tables (to be cleared)181182size_t GCthreshold; // when totalbytes >= GCthreshold, run GC step183size_t totalbytes; // number of bytes currently allocated184185int gcgoal; // see LUAI_GCGOAL186int gcstepmul; // see LUAI_GCSTEPMUL187int gcstepsize; // see LUAI_GCSTEPSIZE188189struct lua_Page* freepages[LUA_SIZECLASSES]; // free page linked list for each size class for non-collectable objects190struct lua_Page* freegcopages[LUA_SIZECLASSES]; // free page linked list for each size class for collectable objects191struct lua_Page* allpages; // page linked list with all pages for all non-collectable object classes (available with LUAU_ASSERTENABLED)192struct lua_Page* allgcopages; // page linked list with all pages for all collectable object classes193struct lua_Page* sweepgcopage; // position of the sweep in `allgcopages'194195struct lua_State* mainthread;196UpVal uvhead; // head of double-linked list of all open upvalues197struct LuaTable* mt[LUA_T_COUNT]; // metatables for basic types198TString* ttname[LUA_T_COUNT]; // names for basic types199TString* tmname[TM_N]; // array with tag-method names200201TValue pseudotemp; // storage for temporary values used in pseudo2addr202203TValue registry; // registry table, used by lua_ref and LUA_REGISTRYINDEX204int registryfree; // next free slot in registry205206struct lua_jmpbuf* errorjmp; // jump buffer data for longjmp-style error handling207208uint64_t rngstate; // PCG random number generator state209uint64_t ptrenckey[4]; // pointer encoding key for display210211lua_Callbacks cb;212213lua_ExecutionCallbacks ecb;214215alignas(16) uint8_t ecbdata[LUA_EXECUTION_CALLBACK_STORAGE];216217size_t memcatbytes[LUA_MEMORY_CATEGORIES]; // total amount of memory used by each memory category218219void (*udatagc[LUA_UTAG_LIMIT])(lua_State*, void*); // for each userdata tag, a gc callback to be called immediately before freeing memory220LuaTable* udatamt[LUA_UTAG_LIMIT]; // metatables for tagged userdata221222TString* lightuserdataname[LUA_LUTAG_LIMIT]; // names for tagged lightuserdata223224GCStats gcstats;225226#ifdef LUAI_GCMETRICS227GCMetrics gcmetrics;228#endif229} global_State;230// clang-format on231232/*233** `per thread' state234*/235// clang-format off236struct lua_State237{238CommonHeader;239uint8_t status;240241uint8_t activememcat; // memory category that is used for new GC object allocations242243bool isactive; // thread is currently executing, stack may be mutated without barriers244bool singlestep; // call debugstep hook after each instruction245246StkId top; // first free slot in the stack247StkId base; // base of current function248global_State* global;249CallInfo* ci; // call info for current function250StkId stack_last; // last free slot in the stack251StkId stack; // stack base252253CallInfo* end_ci; // points after end of ci array254CallInfo* base_ci; // array of CallInfo's255256int stacksize;257int size_ci; // size of array `base_ci'258259unsigned short nCcalls; // number of nested C calls260unsigned short baseCcalls; // nested C calls when resuming coroutine261262int cachedslot; // when table operations or INDEX/NEWINDEX is invoked from Luau, what is the expected slot for lookup?263264LuaTable* gt; // table of globals265UpVal* openupval; // list of open upvalues in this stack266GCObject* gclist;267268TString* namecall; // when invoked from Luau using NAMECALL, what method do we need to invoke?269270void* userdata;271};272// clang-format on273274/*275** Union of all collectible objects276*/277union GCObject278{279GCheader gch;280struct TString ts;281struct Udata u;282struct Closure cl;283struct LuaTable h;284struct Proto p;285struct UpVal uv;286struct lua_State th; // thread287struct LuauBuffer buf;288};289290// macros to convert a GCObject into a specific value291#define gco2ts(o) check_exp((o)->gch.tt == LUA_TSTRING, &((o)->ts))292#define gco2u(o) check_exp((o)->gch.tt == LUA_TUSERDATA, &((o)->u))293#define gco2cl(o) check_exp((o)->gch.tt == LUA_TFUNCTION, &((o)->cl))294#define gco2h(o) check_exp((o)->gch.tt == LUA_TTABLE, &((o)->h))295#define gco2p(o) check_exp((o)->gch.tt == LUA_TPROTO, &((o)->p))296#define gco2uv(o) check_exp((o)->gch.tt == LUA_TUPVAL, &((o)->uv))297#define gco2th(o) check_exp((o)->gch.tt == LUA_TTHREAD, &((o)->th))298#define gco2buf(o) check_exp((o)->gch.tt == LUA_TBUFFER, &((o)->buf))299300// macro to convert any Lua object into a GCObject301#define obj2gco(v) check_exp(iscollectable(v), cast_to(GCObject*, (v) + 0))302303LUAI_FUNC lua_State* luaE_newthread(lua_State* L);304LUAI_FUNC void luaE_freethread(lua_State* L, lua_State* L1, struct lua_Page* page);305306307