Change version to `0.1.0+luau516`
This commit is contained in:
parent
5dbdb036dd
commit
1a8f5dcfcf
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "luau0-src"
|
||||
version = "1.0.0+luau515"
|
||||
version = "0.1.0+luau516"
|
||||
authors = ["Aleksandr Orlenko <zxteam@protonmail.com>"]
|
||||
edition = "2018"
|
||||
repository = "https://github.com/khvzak/luau-src-rs"
|
||||
|
|
|
@ -12,7 +12,6 @@ LUAU_FASTINTVARIABLE(LuauRecursionLimit, 1000)
|
|||
LUAU_FASTINTVARIABLE(LuauParseErrorLimit, 100)
|
||||
LUAU_FASTFLAGVARIABLE(LuauParseSingletonTypes, false)
|
||||
LUAU_FASTFLAGVARIABLE(LuauParseTypeAliasDefaults, false)
|
||||
LUAU_FASTFLAGVARIABLE(LuauParseRecoverTypePackEllipsis, false)
|
||||
LUAU_FASTFLAGVARIABLE(LuauParseAllHotComments, false)
|
||||
LUAU_FASTFLAGVARIABLE(LuauTableFieldFunctionDebugname, false)
|
||||
|
||||
|
@ -2372,11 +2371,11 @@ std::pair<AstArray<AstGenericType>, AstArray<AstGenericTypePack>> Parser::parseG
|
|||
{
|
||||
Location nameLocation = lexer.current().location;
|
||||
AstName name = parseName().name;
|
||||
if (lexer.current().type == Lexeme::Dot3 || (FFlag::LuauParseRecoverTypePackEllipsis && seenPack))
|
||||
if (lexer.current().type == Lexeme::Dot3 || seenPack)
|
||||
{
|
||||
seenPack = true;
|
||||
|
||||
if (FFlag::LuauParseRecoverTypePackEllipsis && lexer.current().type != Lexeme::Dot3)
|
||||
if (lexer.current().type != Lexeme::Dot3)
|
||||
report(lexer.current().location, "Generic types come before generic type packs");
|
||||
else
|
||||
nextLexeme();
|
||||
|
@ -2414,9 +2413,6 @@ std::pair<AstArray<AstGenericType>, AstArray<AstGenericTypePack>> Parser::parseG
|
|||
}
|
||||
else
|
||||
{
|
||||
if (!FFlag::LuauParseRecoverTypePackEllipsis && seenPack)
|
||||
report(lexer.current().location, "Generic types come before generic type packs");
|
||||
|
||||
if (withDefaultValues && lexer.current().type == '=')
|
||||
{
|
||||
seenDefault = true;
|
||||
|
|
|
@ -44,7 +44,7 @@ typedef int (*lua_Continuation)(lua_State* L, int status);
|
|||
** prototype for memory-allocation functions
|
||||
*/
|
||||
|
||||
typedef void* (*lua_Alloc)(lua_State* L, void* ud, void* ptr, size_t osize, size_t nsize);
|
||||
typedef void* (*lua_Alloc)(void* ud, void* ptr, size_t osize, size_t nsize);
|
||||
|
||||
/* non-return type */
|
||||
#define l_noret void LUA_NORETURN
|
||||
|
@ -178,11 +178,11 @@ LUA_API int lua_pushthread(lua_State* L);
|
|||
/*
|
||||
** get functions (Lua -> stack)
|
||||
*/
|
||||
LUA_API void lua_gettable(lua_State* L, int idx);
|
||||
LUA_API void lua_getfield(lua_State* L, int idx, const char* k);
|
||||
LUA_API void lua_rawgetfield(lua_State* L, int idx, const char* k);
|
||||
LUA_API void lua_rawget(lua_State* L, int idx);
|
||||
LUA_API void lua_rawgeti(lua_State* L, int idx, int n);
|
||||
LUA_API int lua_gettable(lua_State* L, int idx);
|
||||
LUA_API int lua_getfield(lua_State* L, int idx, const char* k);
|
||||
LUA_API int lua_rawgetfield(lua_State* L, int idx, const char* k);
|
||||
LUA_API int lua_rawget(lua_State* L, int idx);
|
||||
LUA_API int lua_rawgeti(lua_State* L, int idx, int n);
|
||||
LUA_API void lua_createtable(lua_State* L, int narr, int nrec);
|
||||
|
||||
LUA_API void lua_setreadonly(lua_State* L, int idx, int enabled);
|
||||
|
|
|
@ -659,16 +659,16 @@ int lua_pushthread(lua_State* L)
|
|||
** get functions (Lua -> stack)
|
||||
*/
|
||||
|
||||
void lua_gettable(lua_State* L, int idx)
|
||||
int lua_gettable(lua_State* L, int idx)
|
||||
{
|
||||
luaC_checkthreadsleep(L);
|
||||
StkId t = index2addr(L, idx);
|
||||
api_checkvalidindex(L, t);
|
||||
luaV_gettable(L, t, L->top - 1, L->top - 1);
|
||||
return;
|
||||
return ttype(L->top - 1);
|
||||
}
|
||||
|
||||
void lua_getfield(lua_State* L, int idx, const char* k)
|
||||
int lua_getfield(lua_State* L, int idx, const char* k)
|
||||
{
|
||||
luaC_checkthreadsleep(L);
|
||||
StkId t = index2addr(L, idx);
|
||||
|
@ -677,10 +677,10 @@ void lua_getfield(lua_State* L, int idx, const char* k)
|
|||
setsvalue(L, &key, luaS_new(L, k));
|
||||
luaV_gettable(L, t, &key, L->top);
|
||||
api_incr_top(L);
|
||||
return;
|
||||
return ttype(L->top - 1);
|
||||
}
|
||||
|
||||
void lua_rawgetfield(lua_State* L, int idx, const char* k)
|
||||
int lua_rawgetfield(lua_State* L, int idx, const char* k)
|
||||
{
|
||||
luaC_checkthreadsleep(L);
|
||||
StkId t = index2addr(L, idx);
|
||||
|
@ -689,26 +689,26 @@ void lua_rawgetfield(lua_State* L, int idx, const char* k)
|
|||
setsvalue(L, &key, luaS_new(L, k));
|
||||
setobj2s(L, L->top, luaH_getstr(hvalue(t), tsvalue(&key)));
|
||||
api_incr_top(L);
|
||||
return;
|
||||
return ttype(L->top - 1);
|
||||
}
|
||||
|
||||
void lua_rawget(lua_State* L, int idx)
|
||||
int lua_rawget(lua_State* L, int idx)
|
||||
{
|
||||
luaC_checkthreadsleep(L);
|
||||
StkId t = index2addr(L, idx);
|
||||
api_check(L, ttistable(t));
|
||||
setobj2s(L, L->top - 1, luaH_get(hvalue(t), L->top - 1));
|
||||
return;
|
||||
return ttype(L->top - 1);
|
||||
}
|
||||
|
||||
void lua_rawgeti(lua_State* L, int idx, int n)
|
||||
int lua_rawgeti(lua_State* L, int idx, int n)
|
||||
{
|
||||
luaC_checkthreadsleep(L);
|
||||
StkId t = index2addr(L, idx);
|
||||
api_check(L, ttistable(t));
|
||||
setobj2s(L, L->top, luaH_getnum(hvalue(t), n));
|
||||
api_incr_top(L);
|
||||
return;
|
||||
return ttype(L->top - 1);
|
||||
}
|
||||
|
||||
void lua_createtable(lua_State* L, int narray, int nrec)
|
||||
|
|
|
@ -151,8 +151,7 @@ l_noret luaD_throw(lua_State* L, int errcode)
|
|||
static void correctstack(lua_State* L, TValue* oldstack)
|
||||
{
|
||||
L->top = (L->top - oldstack) + L->stack;
|
||||
// TODO (FFlagLuauGcPagedSweep): 'next' type will change after removal of the flag and the cast will not be required
|
||||
for (UpVal* up = L->openupval; up != NULL; up = (UpVal*)up->next)
|
||||
for (UpVal* up = L->openupval; up != NULL; up = up->u.l.threadnext)
|
||||
up->v = (up->v - oldstack) + L->stack;
|
||||
for (CallInfo* ci = L->base_ci; ci <= L->ci; ci++)
|
||||
{
|
||||
|
|
|
@ -6,13 +6,10 @@
|
|||
#include "lmem.h"
|
||||
#include "lgc.h"
|
||||
|
||||
LUAU_FASTFLAGVARIABLE(LuauNoDirectUpvalRemoval, false)
|
||||
LUAU_FASTFLAG(LuauGcPagedSweep)
|
||||
|
||||
Proto* luaF_newproto(lua_State* L)
|
||||
{
|
||||
Proto* f = luaM_newgco(L, Proto, sizeof(Proto), L->activememcat);
|
||||
luaC_link(L, f, LUA_TPROTO);
|
||||
luaC_init(L, f, LUA_TPROTO);
|
||||
f->k = NULL;
|
||||
f->sizek = 0;
|
||||
f->p = NULL;
|
||||
|
@ -40,7 +37,7 @@ Proto* luaF_newproto(lua_State* L)
|
|||
Closure* luaF_newLclosure(lua_State* L, int nelems, Table* e, Proto* p)
|
||||
{
|
||||
Closure* c = luaM_newgco(L, Closure, sizeLclosure(nelems), L->activememcat);
|
||||
luaC_link(L, c, LUA_TFUNCTION);
|
||||
luaC_init(L, c, LUA_TFUNCTION);
|
||||
c->isC = 0;
|
||||
c->env = e;
|
||||
c->nupvalues = cast_byte(nelems);
|
||||
|
@ -55,7 +52,7 @@ Closure* luaF_newLclosure(lua_State* L, int nelems, Table* e, Proto* p)
|
|||
Closure* luaF_newCclosure(lua_State* L, int nelems, Table* e)
|
||||
{
|
||||
Closure* c = luaM_newgco(L, Closure, sizeCclosure(nelems), L->activememcat);
|
||||
luaC_link(L, c, LUA_TFUNCTION);
|
||||
luaC_init(L, c, LUA_TFUNCTION);
|
||||
c->isC = 1;
|
||||
c->env = e;
|
||||
c->nupvalues = cast_byte(nelems);
|
||||
|
@ -82,8 +79,7 @@ UpVal* luaF_findupval(lua_State* L, StkId level)
|
|||
return p;
|
||||
}
|
||||
|
||||
// TODO (FFlagLuauGcPagedSweep): 'next' type will change after removal of the flag and the cast will not be required
|
||||
pp = (UpVal**)&p->next;
|
||||
pp = &p->u.l.threadnext;
|
||||
}
|
||||
|
||||
UpVal* uv = luaM_newgco(L, UpVal, sizeof(UpVal), L->activememcat); /* not found: create a new one */
|
||||
|
@ -94,19 +90,10 @@ UpVal* luaF_findupval(lua_State* L, StkId level)
|
|||
|
||||
// chain the upvalue in the threads open upvalue list at the proper position
|
||||
UpVal* next = *pp;
|
||||
|
||||
// TODO (FFlagLuauGcPagedSweep): 'next' type will change after removal of the flag and the cast will not be required
|
||||
uv->next = (GCObject*)next;
|
||||
|
||||
if (FFlag::LuauGcPagedSweep)
|
||||
{
|
||||
uv->u.l.threadprev = pp;
|
||||
if (next)
|
||||
{
|
||||
// TODO (FFlagLuauGcPagedSweep): 'next' type will change after removal of the flag and the cast will not be required
|
||||
next->u.l.threadprev = (UpVal**)&uv->next;
|
||||
}
|
||||
}
|
||||
uv->u.l.threadnext = next;
|
||||
uv->u.l.threadprev = pp;
|
||||
if (next)
|
||||
next->u.l.threadprev = &uv->u.l.threadnext;
|
||||
|
||||
*pp = uv;
|
||||
|
||||
|
@ -125,15 +112,11 @@ void luaF_unlinkupval(UpVal* uv)
|
|||
uv->u.l.next->u.l.prev = uv->u.l.prev;
|
||||
uv->u.l.prev->u.l.next = uv->u.l.next;
|
||||
|
||||
if (FFlag::LuauGcPagedSweep)
|
||||
{
|
||||
// unlink upvalue from the thread open upvalue list
|
||||
// TODO (FFlagLuauGcPagedSweep): 'next' type will change after removal of the flag and this and the following cast will not be required
|
||||
*uv->u.l.threadprev = (UpVal*)uv->next;
|
||||
// unlink upvalue from the thread open upvalue list
|
||||
*uv->u.l.threadprev = uv->u.l.threadnext;
|
||||
|
||||
if (UpVal* next = (UpVal*)uv->next)
|
||||
next->u.l.threadprev = uv->u.l.threadprev;
|
||||
}
|
||||
if (UpVal* next = uv->u.l.threadnext)
|
||||
next->u.l.threadprev = uv->u.l.threadprev;
|
||||
}
|
||||
|
||||
void luaF_freeupval(lua_State* L, UpVal* uv, lua_Page* page)
|
||||
|
@ -145,34 +128,27 @@ void luaF_freeupval(lua_State* L, UpVal* uv, lua_Page* page)
|
|||
|
||||
void luaF_close(lua_State* L, StkId level)
|
||||
{
|
||||
global_State* g = L->global; // TODO: remove with FFlagLuauNoDirectUpvalRemoval
|
||||
global_State* g = L->global;
|
||||
UpVal* uv;
|
||||
while (L->openupval != NULL && (uv = L->openupval)->v >= level)
|
||||
{
|
||||
GCObject* o = obj2gco(uv);
|
||||
LUAU_ASSERT(!isblack(o) && uv->v != &uv->u.value);
|
||||
|
||||
if (!FFlag::LuauGcPagedSweep)
|
||||
L->openupval = (UpVal*)uv->next; /* remove from `open' list */
|
||||
// by removing the upvalue from global/thread open upvalue lists, L->openupval will be pointing to the next upvalue
|
||||
luaF_unlinkupval(uv);
|
||||
|
||||
if (FFlag::LuauGcPagedSweep && isdead(g, o))
|
||||
if (isdead(g, o))
|
||||
{
|
||||
// by removing the upvalue from global/thread open upvalue lists, L->openupval will be pointing to the next upvalue
|
||||
luaF_unlinkupval(uv);
|
||||
// close the upvalue without copying the dead data so that luaF_freeupval will not unlink again
|
||||
uv->v = &uv->u.value;
|
||||
}
|
||||
else if (!FFlag::LuauNoDirectUpvalRemoval && isdead(g, o))
|
||||
{
|
||||
luaF_freeupval(L, uv, NULL); /* free upvalue */
|
||||
}
|
||||
else
|
||||
{
|
||||
// by removing the upvalue from global/thread open upvalue lists, L->openupval will be pointing to the next upvalue
|
||||
luaF_unlinkupval(uv);
|
||||
setobj(L, &uv->u.value, uv->v);
|
||||
uv->v = &uv->u.value; /* now current value lives here */
|
||||
luaC_linkupval(L, uv); /* link upvalue into `gcroot' list */
|
||||
uv->v = &uv->u.value;
|
||||
// GC state of a new closed upvalue has to be initialized
|
||||
luaC_initupval(L, uv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,8 +13,6 @@
|
|||
|
||||
#include <string.h>
|
||||
|
||||
LUAU_FASTFLAGVARIABLE(LuauGcPagedSweep, false)
|
||||
|
||||
#define GC_SWEEPMAX 40
|
||||
#define GC_SWEEPCOST 10
|
||||
#define GC_SWEEPPAGESTEPCOST 4
|
||||
|
@ -64,7 +62,6 @@ static void recordGcStateTime(global_State* g, int startgcstate, double seconds,
|
|||
case GCSatomic:
|
||||
g->gcstats.currcycle.atomictime += seconds;
|
||||
break;
|
||||
case GCSsweepstring:
|
||||
case GCSsweep:
|
||||
g->gcstats.currcycle.sweeptime += seconds;
|
||||
break;
|
||||
|
@ -490,65 +487,6 @@ static void freeobj(lua_State* L, GCObject* o, lua_Page* page)
|
|||
}
|
||||
}
|
||||
|
||||
#define sweepwholelist(L, p) sweeplist(L, p, SIZE_MAX)
|
||||
|
||||
static GCObject** sweeplist(lua_State* L, GCObject** p, size_t count)
|
||||
{
|
||||
LUAU_ASSERT(!FFlag::LuauGcPagedSweep);
|
||||
|
||||
GCObject* curr;
|
||||
global_State* g = L->global;
|
||||
int deadmask = otherwhite(g);
|
||||
LUAU_ASSERT(testbit(deadmask, FIXEDBIT)); /* make sure we never sweep fixed objects */
|
||||
while ((curr = *p) != NULL && count-- > 0)
|
||||
{
|
||||
int alive = (curr->gch.marked ^ WHITEBITS) & deadmask;
|
||||
if (curr->gch.tt == LUA_TTHREAD)
|
||||
{
|
||||
sweepwholelist(L, (GCObject**)&gco2th(curr)->openupval); /* sweep open upvalues */
|
||||
|
||||
lua_State* th = gco2th(curr);
|
||||
|
||||
if (alive)
|
||||
{
|
||||
resetbit(th->stackstate, THREAD_SLEEPINGBIT);
|
||||
shrinkstack(th);
|
||||
}
|
||||
}
|
||||
if (alive)
|
||||
{ /* not dead? */
|
||||
LUAU_ASSERT(!isdead(g, curr));
|
||||
makewhite(g, curr); /* make it white (for next cycle) */
|
||||
p = &curr->gch.next;
|
||||
}
|
||||
else
|
||||
{ /* must erase `curr' */
|
||||
LUAU_ASSERT(isdead(g, curr));
|
||||
*p = curr->gch.next;
|
||||
if (curr == g->rootgc) /* is the first element of the list? */
|
||||
g->rootgc = curr->gch.next; /* adjust first */
|
||||
freeobj(L, curr, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
static void deletelist(lua_State* L, GCObject** p, GCObject* limit)
|
||||
{
|
||||
LUAU_ASSERT(!FFlag::LuauGcPagedSweep);
|
||||
|
||||
GCObject* curr;
|
||||
while ((curr = *p) != limit)
|
||||
{
|
||||
if (curr->gch.tt == LUA_TTHREAD) /* delete open upvalues of each thread */
|
||||
deletelist(L, (GCObject**)&gco2th(curr)->openupval, NULL);
|
||||
|
||||
*p = curr->gch.next;
|
||||
freeobj(L, curr, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void shrinkbuffers(lua_State* L)
|
||||
{
|
||||
global_State* g = L->global;
|
||||
|
@ -570,8 +508,6 @@ static void shrinkbuffersfull(lua_State* L)
|
|||
|
||||
static bool deletegco(void* context, lua_Page* page, GCObject* gco)
|
||||
{
|
||||
LUAU_ASSERT(FFlag::LuauGcPagedSweep);
|
||||
|
||||
// we are in the process of deleting everything
|
||||
// threads with open upvalues will attempt to close them all on removal
|
||||
// but those upvalues might point to stack values that were already deleted
|
||||
|
@ -598,32 +534,13 @@ void luaC_freeall(lua_State* L)
|
|||
|
||||
LUAU_ASSERT(L == g->mainthread);
|
||||
|
||||
if (FFlag::LuauGcPagedSweep)
|
||||
{
|
||||
luaM_visitgco(L, L, deletegco);
|
||||
luaM_visitgco(L, L, deletegco);
|
||||
|
||||
for (int i = 0; i < g->strt.size; i++) /* free all string lists */
|
||||
LUAU_ASSERT(g->strt.hash[i] == NULL);
|
||||
for (int i = 0; i < g->strt.size; i++) /* free all string lists */
|
||||
LUAU_ASSERT(g->strt.hash[i] == NULL);
|
||||
|
||||
LUAU_ASSERT(L->global->strt.nuse == 0);
|
||||
LUAU_ASSERT(g->strbufgc == NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
LUAU_ASSERT(L->next == NULL); /* mainthread is at the end of rootgc list */
|
||||
|
||||
deletelist(L, &g->rootgc, obj2gco(L));
|
||||
|
||||
for (int i = 0; i < g->strt.size; i++) /* free all string lists */
|
||||
deletelist(L, (GCObject**)&g->strt.hash[i], NULL);
|
||||
|
||||
LUAU_ASSERT(L->global->strt.nuse == 0);
|
||||
deletelist(L, (GCObject**)&g->strbufgc, NULL);
|
||||
|
||||
// unfortunately, when string objects are freed, the string table use count is decremented
|
||||
// even when the string is a buffer that wasn't placed into the table
|
||||
L->global->strt.nuse = 0;
|
||||
}
|
||||
LUAU_ASSERT(L->global->strt.nuse == 0);
|
||||
LUAU_ASSERT(g->strbufgc == NULL);
|
||||
}
|
||||
|
||||
static void markmt(global_State* g)
|
||||
|
@ -687,26 +604,13 @@ static size_t atomic(lua_State* L)
|
|||
g->weak = NULL;
|
||||
/* flip current white */
|
||||
g->currentwhite = cast_byte(otherwhite(g));
|
||||
g->sweepstrgc = 0;
|
||||
|
||||
if (FFlag::LuauGcPagedSweep)
|
||||
{
|
||||
g->sweepgcopage = g->allgcopages;
|
||||
g->gcstate = GCSsweep;
|
||||
}
|
||||
else
|
||||
{
|
||||
g->sweepgc = &g->rootgc;
|
||||
g->gcstate = GCSsweepstring;
|
||||
}
|
||||
|
||||
g->sweepgcopage = g->allgcopages;
|
||||
g->gcstate = GCSsweep;
|
||||
return work;
|
||||
}
|
||||
|
||||
static bool sweepgco(lua_State* L, lua_Page* page, GCObject* gco)
|
||||
{
|
||||
LUAU_ASSERT(FFlag::LuauGcPagedSweep);
|
||||
|
||||
global_State* g = L->global;
|
||||
|
||||
int deadmask = otherwhite(g);
|
||||
|
@ -740,8 +644,6 @@ static bool sweepgco(lua_State* L, lua_Page* page, GCObject* gco)
|
|||
// a version of generic luaM_visitpage specialized for the main sweep stage
|
||||
static int sweepgcopage(lua_State* L, lua_Page* page)
|
||||
{
|
||||
LUAU_ASSERT(FFlag::LuauGcPagedSweep);
|
||||
|
||||
char* start;
|
||||
char* end;
|
||||
int busyBlocks;
|
||||
|
@ -819,75 +721,29 @@ static size_t gcstep(lua_State* L, size_t limit)
|
|||
|
||||
cost = atomic(L); /* finish mark phase */
|
||||
|
||||
if (FFlag::LuauGcPagedSweep)
|
||||
LUAU_ASSERT(g->gcstate == GCSsweep);
|
||||
else
|
||||
LUAU_ASSERT(g->gcstate == GCSsweepstring);
|
||||
break;
|
||||
}
|
||||
case GCSsweepstring:
|
||||
{
|
||||
LUAU_ASSERT(!FFlag::LuauGcPagedSweep);
|
||||
|
||||
while (g->sweepstrgc < g->strt.size && cost < limit)
|
||||
{
|
||||
sweepwholelist(L, (GCObject**)&g->strt.hash[g->sweepstrgc++]);
|
||||
|
||||
cost += GC_SWEEPCOST;
|
||||
}
|
||||
|
||||
// nothing more to sweep?
|
||||
if (g->sweepstrgc >= g->strt.size)
|
||||
{
|
||||
// sweep string buffer list and preserve used string count
|
||||
uint32_t nuse = L->global->strt.nuse;
|
||||
|
||||
sweepwholelist(L, (GCObject**)&g->strbufgc);
|
||||
|
||||
L->global->strt.nuse = nuse;
|
||||
|
||||
g->gcstate = GCSsweep; // end sweep-string phase
|
||||
}
|
||||
LUAU_ASSERT(g->gcstate == GCSsweep);
|
||||
break;
|
||||
}
|
||||
case GCSsweep:
|
||||
{
|
||||
if (FFlag::LuauGcPagedSweep)
|
||||
while (g->sweepgcopage && cost < limit)
|
||||
{
|
||||
while (g->sweepgcopage && cost < limit)
|
||||
{
|
||||
lua_Page* next = luaM_getnextgcopage(g->sweepgcopage); // page sweep might destroy the page
|
||||
lua_Page* next = luaM_getnextgcopage(g->sweepgcopage); // page sweep might destroy the page
|
||||
|
||||
int steps = sweepgcopage(L, g->sweepgcopage);
|
||||
int steps = sweepgcopage(L, g->sweepgcopage);
|
||||
|
||||
g->sweepgcopage = next;
|
||||
cost += steps * GC_SWEEPPAGESTEPCOST;
|
||||
}
|
||||
|
||||
// nothing more to sweep?
|
||||
if (g->sweepgcopage == NULL)
|
||||
{
|
||||
// don't forget to visit main thread
|
||||
sweepgco(L, NULL, obj2gco(g->mainthread));
|
||||
|
||||
shrinkbuffers(L);
|
||||
g->gcstate = GCSpause; /* end collection */
|
||||
}
|
||||
g->sweepgcopage = next;
|
||||
cost += steps * GC_SWEEPPAGESTEPCOST;
|
||||
}
|
||||
else
|
||||
|
||||
// nothing more to sweep?
|
||||
if (g->sweepgcopage == NULL)
|
||||
{
|
||||
while (*g->sweepgc && cost < limit)
|
||||
{
|
||||
g->sweepgc = sweeplist(L, g->sweepgc, GC_SWEEPMAX);
|
||||
// don't forget to visit main thread
|
||||
sweepgco(L, NULL, obj2gco(g->mainthread));
|
||||
|
||||
cost += GC_SWEEPMAX * GC_SWEEPCOST;
|
||||
}
|
||||
|
||||
if (*g->sweepgc == NULL)
|
||||
{ /* nothing more to sweep? */
|
||||
shrinkbuffers(L);
|
||||
g->gcstate = GCSpause; /* end collection */
|
||||
}
|
||||
shrinkbuffers(L);
|
||||
g->gcstate = GCSpause; /* end collection */
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1013,26 +869,18 @@ void luaC_fullgc(lua_State* L)
|
|||
if (g->gcstate <= GCSatomic)
|
||||
{
|
||||
/* reset sweep marks to sweep all elements (returning them to white) */
|
||||
g->sweepstrgc = 0;
|
||||
if (FFlag::LuauGcPagedSweep)
|
||||
g->sweepgcopage = g->allgcopages;
|
||||
else
|
||||
g->sweepgc = &g->rootgc;
|
||||
g->sweepgcopage = g->allgcopages;
|
||||
/* reset other collector lists */
|
||||
g->gray = NULL;
|
||||
g->grayagain = NULL;
|
||||
g->weak = NULL;
|
||||
|
||||
if (FFlag::LuauGcPagedSweep)
|
||||
g->gcstate = GCSsweep;
|
||||
else
|
||||
g->gcstate = GCSsweepstring;
|
||||
g->gcstate = GCSsweep;
|
||||
}
|
||||
LUAU_ASSERT(g->gcstate == GCSsweepstring || g->gcstate == GCSsweep);
|
||||
LUAU_ASSERT(g->gcstate == GCSsweep);
|
||||
/* finish any pending sweep phase */
|
||||
while (g->gcstate != GCSpause)
|
||||
{
|
||||
LUAU_ASSERT(g->gcstate == GCSsweepstring || g->gcstate == GCSsweep);
|
||||
LUAU_ASSERT(g->gcstate == GCSsweep);
|
||||
gcstep(L, SIZE_MAX);
|
||||
}
|
||||
|
||||
|
@ -1120,30 +968,19 @@ void luaC_barrierback(lua_State* L, Table* t)
|
|||
g->grayagain = o;
|
||||
}
|
||||
|
||||
void luaC_linkobj(lua_State* L, GCObject* o, uint8_t tt)
|
||||
void luaC_initobj(lua_State* L, GCObject* o, uint8_t tt)
|
||||
{
|
||||
global_State* g = L->global;
|
||||
if (!FFlag::LuauGcPagedSweep)
|
||||
{
|
||||
o->gch.next = g->rootgc;
|
||||
g->rootgc = o;
|
||||
}
|
||||
o->gch.marked = luaC_white(g);
|
||||
o->gch.tt = tt;
|
||||
o->gch.memcat = L->activememcat;
|
||||
}
|
||||
|
||||
void luaC_linkupval(lua_State* L, UpVal* uv)
|
||||
void luaC_initupval(lua_State* L, UpVal* uv)
|
||||
{
|
||||
global_State* g = L->global;
|
||||
GCObject* o = obj2gco(uv);
|
||||
|
||||
if (!FFlag::LuauGcPagedSweep)
|
||||
{
|
||||
o->gch.next = g->rootgc; /* link upvalue into `rootgc' list */
|
||||
g->rootgc = o;
|
||||
}
|
||||
|
||||
if (isgray(o))
|
||||
{
|
||||
if (keepinvariant(g))
|
||||
|
@ -1221,9 +1058,6 @@ const char* luaC_statename(int state)
|
|||
case GCSatomic:
|
||||
return "atomic";
|
||||
|
||||
case GCSsweepstring:
|
||||
return "sweepstring";
|
||||
|
||||
case GCSsweep:
|
||||
return "sweep";
|
||||
|
||||
|
|
|
@ -13,9 +13,7 @@
|
|||
#define GCSpropagate 1
|
||||
#define GCSpropagateagain 2
|
||||
#define GCSatomic 3
|
||||
// TODO: remove with FFlagLuauGcPagedSweep
|
||||
#define GCSsweepstring 4
|
||||
#define GCSsweep 5
|
||||
#define GCSsweep 4
|
||||
|
||||
/*
|
||||
** macro to tell when main invariant (white objects cannot point to black
|
||||
|
@ -132,13 +130,13 @@
|
|||
luaC_wakethread(L); \
|
||||
}
|
||||
|
||||
#define luaC_link(L, o, tt) luaC_linkobj(L, cast_to(GCObject*, (o)), tt)
|
||||
#define luaC_init(L, o, tt) luaC_initobj(L, cast_to(GCObject*, (o)), tt)
|
||||
|
||||
LUAI_FUNC void luaC_freeall(lua_State* L);
|
||||
LUAI_FUNC void luaC_step(lua_State* L, bool assist);
|
||||
LUAI_FUNC void luaC_fullgc(lua_State* L);
|
||||
LUAI_FUNC void luaC_linkobj(lua_State* L, GCObject* o, uint8_t tt);
|
||||
LUAI_FUNC void luaC_linkupval(lua_State* L, UpVal* uv);
|
||||
LUAI_FUNC void luaC_initobj(lua_State* L, GCObject* o, uint8_t tt);
|
||||
LUAI_FUNC void luaC_initupval(lua_State* L, UpVal* uv);
|
||||
LUAI_FUNC void luaC_barrierupval(lua_State* L, GCObject* v);
|
||||
LUAI_FUNC void luaC_barrierf(lua_State* L, GCObject* o, GCObject* v);
|
||||
LUAI_FUNC void luaC_barriertable(lua_State* L, Table* t, GCObject* v);
|
||||
|
|
|
@ -13,8 +13,6 @@
|
|||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
LUAU_FASTFLAG(LuauGcPagedSweep)
|
||||
|
||||
static void validateobjref(global_State* g, GCObject* f, GCObject* t)
|
||||
{
|
||||
LUAU_ASSERT(!isdead(g, t));
|
||||
|
@ -104,8 +102,7 @@ static void validatestack(global_State* g, lua_State* l)
|
|||
if (l->namecall)
|
||||
validateobjref(g, obj2gco(l), obj2gco(l->namecall));
|
||||
|
||||
// TODO (FFlagLuauGcPagedSweep): 'next' type will change after removal of the flag and the cast will not be required
|
||||
for (UpVal* uv = l->openupval; uv; uv = (UpVal*)uv->next)
|
||||
for (UpVal* uv = l->openupval; uv; uv = uv->u.l.threadnext)
|
||||
{
|
||||
LUAU_ASSERT(uv->tt == LUA_TUPVAL);
|
||||
LUAU_ASSERT(uv->v != &uv->u.value);
|
||||
|
@ -141,7 +138,7 @@ static void validateobj(global_State* g, GCObject* o)
|
|||
/* dead objects can only occur during sweep */
|
||||
if (isdead(g, o))
|
||||
{
|
||||
LUAU_ASSERT(g->gcstate == GCSsweepstring || g->gcstate == GCSsweep);
|
||||
LUAU_ASSERT(g->gcstate == GCSsweep);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -180,18 +177,6 @@ static void validateobj(global_State* g, GCObject* o)
|
|||
}
|
||||
}
|
||||
|
||||
static void validatelist(global_State* g, GCObject* o)
|
||||
{
|
||||
LUAU_ASSERT(!FFlag::LuauGcPagedSweep);
|
||||
|
||||
while (o)
|
||||
{
|
||||
validateobj(g, o);
|
||||
|
||||
o = o->gch.next;
|
||||
}
|
||||
}
|
||||
|
||||
static void validategraylist(global_State* g, GCObject* o)
|
||||
{
|
||||
if (!keepinvariant(g))
|
||||
|
@ -224,8 +209,6 @@ static void validategraylist(global_State* g, GCObject* o)
|
|||
|
||||
static bool validategco(void* context, lua_Page* page, GCObject* gco)
|
||||
{
|
||||
LUAU_ASSERT(FFlag::LuauGcPagedSweep);
|
||||
|
||||
lua_State* L = (lua_State*)context;
|
||||
global_State* g = L->global;
|
||||
|
||||
|
@ -248,20 +231,9 @@ void luaC_validate(lua_State* L)
|
|||
validategraylist(g, g->gray);
|
||||
validategraylist(g, g->grayagain);
|
||||
|
||||
if (FFlag::LuauGcPagedSweep)
|
||||
{
|
||||
validategco(L, NULL, obj2gco(g->mainthread));
|
||||
validategco(L, NULL, obj2gco(g->mainthread));
|
||||
|
||||
luaM_visitgco(L, L, validategco);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < g->strt.size; ++i)
|
||||
validatelist(g, (GCObject*)(g->strt.hash[i]));
|
||||
|
||||
validatelist(g, g->rootgc);
|
||||
validatelist(g, (GCObject*)(g->strbufgc));
|
||||
}
|
||||
luaM_visitgco(L, L, validategco);
|
||||
|
||||
for (UpVal* uv = g->uvhead.u.l.next; uv != &g->uvhead; uv = uv->u.l.next)
|
||||
{
|
||||
|
@ -521,30 +493,8 @@ static void dumpobj(FILE* f, GCObject* o)
|
|||
}
|
||||
}
|
||||
|
||||
static void dumplist(FILE* f, GCObject* o)
|
||||
{
|
||||
LUAU_ASSERT(!FFlag::LuauGcPagedSweep);
|
||||
|
||||
while (o)
|
||||
{
|
||||
dumpref(f, o);
|
||||
fputc(':', f);
|
||||
dumpobj(f, o);
|
||||
fputc(',', f);
|
||||
fputc('\n', f);
|
||||
|
||||
// thread has additional list containing collectable objects that are not present in rootgc
|
||||
if (o->gch.tt == LUA_TTHREAD)
|
||||
dumplist(f, (GCObject*)gco2th(o)->openupval);
|
||||
|
||||
o = o->gch.next;
|
||||
}
|
||||
}
|
||||
|
||||
static bool dumpgco(void* context, lua_Page* page, GCObject* gco)
|
||||
{
|
||||
LUAU_ASSERT(FFlag::LuauGcPagedSweep);
|
||||
|
||||
FILE* f = (FILE*)context;
|
||||
|
||||
dumpref(f, gco);
|
||||
|
@ -563,19 +513,9 @@ void luaC_dump(lua_State* L, void* file, const char* (*categoryName)(lua_State*
|
|||
|
||||
fprintf(f, "{\"objects\":{\n");
|
||||
|
||||
if (FFlag::LuauGcPagedSweep)
|
||||
{
|
||||
dumpgco(f, NULL, obj2gco(g->mainthread));
|
||||
dumpgco(f, NULL, obj2gco(g->mainthread));
|
||||
|
||||
luaM_visitgco(L, f, dumpgco);
|
||||
}
|
||||
else
|
||||
{
|
||||
dumplist(f, g->rootgc);
|
||||
dumplist(f, (GCObject*)(g->strbufgc));
|
||||
for (int i = 0; i < g->strt.size; ++i)
|
||||
dumplist(f, (GCObject*)(g->strt.hash[i]));
|
||||
}
|
||||
luaM_visitgco(L, f, dumpgco);
|
||||
|
||||
fprintf(f, "\"0\":{\"type\":\"userdata\",\"cat\":0,\"size\":0}\n"); // to avoid issues with trailing ,
|
||||
fprintf(f, "},\"roots\":{\n");
|
||||
|
|
|
@ -68,7 +68,7 @@ void luaL_sandboxthread(lua_State* L)
|
|||
lua_setsafeenv(L, LUA_GLOBALSINDEX, true);
|
||||
}
|
||||
|
||||
static void* l_alloc(lua_State* L, void* ud, void* ptr, size_t osize, size_t nsize)
|
||||
static void* l_alloc(void* ud, void* ptr, size_t osize, size_t nsize)
|
||||
{
|
||||
(void)ud;
|
||||
(void)osize;
|
||||
|
|
|
@ -78,8 +78,6 @@
|
|||
* allocated pages.
|
||||
*/
|
||||
|
||||
LUAU_FASTFLAG(LuauGcPagedSweep)
|
||||
|
||||
#ifndef __has_feature
|
||||
#define __has_feature(x) 0
|
||||
#endif
|
||||
|
@ -98,8 +96,10 @@ LUAU_FASTFLAG(LuauGcPagedSweep)
|
|||
* To prevent some of them accidentally growing and us losing memory without realizing it, we're going to lock
|
||||
* the sizes of all critical structures down.
|
||||
*/
|
||||
#if defined(__APPLE__) && !defined(__MACH__)
|
||||
#if defined(__APPLE__)
|
||||
#define ABISWITCH(x64, ms32, gcc32) (sizeof(void*) == 8 ? x64 : gcc32)
|
||||
#elif defined(__i386__)
|
||||
#define ABISWITCH(x64, ms32, gcc32) (gcc32)
|
||||
#else
|
||||
// Android somehow uses a similar ABI to MSVC, *not* to iOS...
|
||||
#define ABISWITCH(x64, ms32, gcc32) (sizeof(void*) == 8 ? x64 : ms32)
|
||||
|
@ -114,14 +114,8 @@ static_assert(sizeof(LuaNode) == ABISWITCH(32, 32, 32), "size mismatch for table
|
|||
#endif
|
||||
|
||||
static_assert(offsetof(TString, data) == ABISWITCH(24, 20, 20), "size mismatch for string header");
|
||||
// TODO (FFlagLuauGcPagedSweep): this will become ABISWITCH(16, 16, 16)
|
||||
static_assert(offsetof(Udata, data) == ABISWITCH(24, 16, 16), "size mismatch for userdata header");
|
||||
// TODO (FFlagLuauGcPagedSweep): this will become ABISWITCH(48, 32, 32)
|
||||
static_assert(sizeof(Table) == ABISWITCH(56, 36, 36), "size mismatch for table header");
|
||||
|
||||
// TODO (FFlagLuauGcPagedSweep): new code with old 'next' pointer requires that GCObject start at the same point as TString/UpVal
|
||||
static_assert(offsetof(GCObject, uv) == 0, "UpVal data must be located at the start of the GCObject");
|
||||
static_assert(offsetof(GCObject, ts) == 0, "TString data must be located at the start of the GCObject");
|
||||
static_assert(offsetof(Udata, data) == ABISWITCH(16, 16, 12), "size mismatch for userdata header");
|
||||
static_assert(sizeof(Table) == ABISWITCH(48, 32, 32), "size mismatch for table header");
|
||||
|
||||
const size_t kSizeClasses = LUA_SIZECLASSES;
|
||||
const size_t kMaxSmallSize = 512;
|
||||
|
@ -208,53 +202,13 @@ l_noret luaM_toobig(lua_State* L)
|
|||
luaG_runerror(L, "memory allocation error: block too big");
|
||||
}
|
||||
|
||||
static lua_Page* newpageold(lua_State* L, uint8_t sizeClass)
|
||||
{
|
||||
LUAU_ASSERT(!FFlag::LuauGcPagedSweep);
|
||||
|
||||
global_State* g = L->global;
|
||||
lua_Page* page = (lua_Page*)(*g->frealloc)(L, g->ud, NULL, 0, kPageSize);
|
||||
if (!page)
|
||||
luaD_throw(L, LUA_ERRMEM);
|
||||
|
||||
int blockSize = kSizeClassConfig.sizeOfClass[sizeClass] + kBlockHeader;
|
||||
int blockCount = (kPageSize - offsetof(lua_Page, data)) / blockSize;
|
||||
|
||||
ASAN_POISON_MEMORY_REGION(page->data, blockSize * blockCount);
|
||||
|
||||
// setup page header
|
||||
page->prev = NULL;
|
||||
page->next = NULL;
|
||||
|
||||
page->gcolistprev = NULL;
|
||||
page->gcolistnext = NULL;
|
||||
|
||||
page->pageSize = kPageSize;
|
||||
page->blockSize = blockSize;
|
||||
|
||||
// note: we start with the last block in the page and move downward
|
||||
// either order would work, but that way we don't need to store the block count in the page
|
||||
// additionally, GC stores objects in singly linked lists, and this way the GC lists end up in increasing pointer order
|
||||
page->freeList = NULL;
|
||||
page->freeNext = (blockCount - 1) * blockSize;
|
||||
page->busyBlocks = 0;
|
||||
|
||||
// prepend a page to page freelist (which is empty because we only ever allocate a new page when it is!)
|
||||
LUAU_ASSERT(!g->freepages[sizeClass]);
|
||||
g->freepages[sizeClass] = page;
|
||||
|
||||
return page;
|
||||
}
|
||||
|
||||
static lua_Page* newpage(lua_State* L, lua_Page** gcopageset, int pageSize, int blockSize, int blockCount)
|
||||
{
|
||||
LUAU_ASSERT(FFlag::LuauGcPagedSweep);
|
||||
|
||||
global_State* g = L->global;
|
||||
|
||||
LUAU_ASSERT(pageSize - int(offsetof(lua_Page, data)) >= blockSize * blockCount);
|
||||
|
||||
lua_Page* page = (lua_Page*)(*g->frealloc)(L, g->ud, NULL, 0, pageSize);
|
||||
lua_Page* page = (lua_Page*)(*g->frealloc)(g->ud, NULL, 0, pageSize);
|
||||
if (!page)
|
||||
luaD_throw(L, LUA_ERRMEM);
|
||||
|
||||
|
@ -290,8 +244,6 @@ static lua_Page* newpage(lua_State* L, lua_Page** gcopageset, int pageSize, int
|
|||
|
||||
static lua_Page* newclasspage(lua_State* L, lua_Page** freepageset, lua_Page** gcopageset, uint8_t sizeClass, bool storeMetadata)
|
||||
{
|
||||
LUAU_ASSERT(FFlag::LuauGcPagedSweep);
|
||||
|
||||
int blockSize = kSizeClassConfig.sizeOfClass[sizeClass] + (storeMetadata ? kBlockHeader : 0);
|
||||
int blockCount = (kPageSize - offsetof(lua_Page, data)) / blockSize;
|
||||
|
||||
|
@ -304,29 +256,8 @@ static lua_Page* newclasspage(lua_State* L, lua_Page** freepageset, lua_Page** g
|
|||
return page;
|
||||
}
|
||||
|
||||
static void freepageold(lua_State* L, lua_Page* page, uint8_t sizeClass)
|
||||
{
|
||||
LUAU_ASSERT(!FFlag::LuauGcPagedSweep);
|
||||
|
||||
global_State* g = L->global;
|
||||
|
||||
// remove page from freelist
|
||||
if (page->next)
|
||||
page->next->prev = page->prev;
|
||||
|
||||
if (page->prev)
|
||||
page->prev->next = page->next;
|
||||
else if (g->freepages[sizeClass] == page)
|
||||
g->freepages[sizeClass] = page->next;
|
||||
|
||||
// so long
|
||||
(*g->frealloc)(L, g->ud, page, kPageSize, 0);
|
||||
}
|
||||
|
||||
static void freepage(lua_State* L, lua_Page** gcopageset, lua_Page* page)
|
||||
{
|
||||
LUAU_ASSERT(FFlag::LuauGcPagedSweep);
|
||||
|
||||
global_State* g = L->global;
|
||||
|
||||
if (gcopageset)
|
||||
|
@ -342,13 +273,11 @@ static void freepage(lua_State* L, lua_Page** gcopageset, lua_Page* page)
|
|||
}
|
||||
|
||||
// so long
|
||||
(*g->frealloc)(L, g->ud, page, page->pageSize, 0);
|
||||
(*g->frealloc)(g->ud, page, page->pageSize, 0);
|
||||
}
|
||||
|
||||
static void freeclasspage(lua_State* L, lua_Page** freepageset, lua_Page** gcopageset, lua_Page* page, uint8_t sizeClass)
|
||||
{
|
||||
LUAU_ASSERT(FFlag::LuauGcPagedSweep);
|
||||
|
||||
// remove page from freelist
|
||||
if (page->next)
|
||||
page->next->prev = page->prev;
|
||||
|
@ -368,12 +297,7 @@ static void* newblock(lua_State* L, int sizeClass)
|
|||
|
||||
// slow path: no page in the freelist, allocate a new one
|
||||
if (!page)
|
||||
{
|
||||
if (FFlag::LuauGcPagedSweep)
|
||||
page = newclasspage(L, g->freepages, NULL, sizeClass, true);
|
||||
else
|
||||
page = newpageold(L, sizeClass);
|
||||
}
|
||||
page = newclasspage(L, g->freepages, NULL, sizeClass, true);
|
||||
|
||||
LUAU_ASSERT(!page->prev);
|
||||
LUAU_ASSERT(page->freeList || page->freeNext >= 0);
|
||||
|
@ -416,8 +340,6 @@ static void* newblock(lua_State* L, int sizeClass)
|
|||
|
||||
static void* newgcoblock(lua_State* L, int sizeClass)
|
||||
{
|
||||
LUAU_ASSERT(FFlag::LuauGcPagedSweep);
|
||||
|
||||
global_State* g = L->global;
|
||||
lua_Page* page = g->freegcopages[sizeClass];
|
||||
|
||||
|
@ -496,17 +418,11 @@ static void freeblock(lua_State* L, int sizeClass, void* block)
|
|||
|
||||
// if it's the last block in the page, we don't need the page
|
||||
if (page->busyBlocks == 0)
|
||||
{
|
||||
if (FFlag::LuauGcPagedSweep)
|
||||
freeclasspage(L, g->freepages, NULL, page, sizeClass);
|
||||
else
|
||||
freepageold(L, page, sizeClass);
|
||||
}
|
||||
freeclasspage(L, g->freepages, NULL, page, sizeClass);
|
||||
}
|
||||
|
||||
static void freegcoblock(lua_State* L, int sizeClass, void* block, lua_Page* page)
|
||||
{
|
||||
LUAU_ASSERT(FFlag::LuauGcPagedSweep);
|
||||
LUAU_ASSERT(page && page->busyBlocks > 0);
|
||||
LUAU_ASSERT(page->blockSize == kSizeClassConfig.sizeOfClass[sizeClass]);
|
||||
LUAU_ASSERT(block >= page->data && block < (char*)page + page->pageSize);
|
||||
|
@ -544,7 +460,7 @@ void* luaM_new_(lua_State* L, size_t nsize, uint8_t memcat)
|
|||
|
||||
int nclass = sizeclass(nsize);
|
||||
|
||||
void* block = nclass >= 0 ? newblock(L, nclass) : (*g->frealloc)(L, g->ud, NULL, 0, nsize);
|
||||
void* block = nclass >= 0 ? newblock(L, nclass) : (*g->frealloc)(g->ud, NULL, 0, nsize);
|
||||
if (block == NULL && nsize > 0)
|
||||
luaD_throw(L, LUA_ERRMEM);
|
||||
|
||||
|
@ -556,9 +472,6 @@ void* luaM_new_(lua_State* L, size_t nsize, uint8_t memcat)
|
|||
|
||||
GCObject* luaM_newgco_(lua_State* L, size_t nsize, uint8_t memcat)
|
||||
{
|
||||
if (!FFlag::LuauGcPagedSweep)
|
||||
return (GCObject*)luaM_new_(L, nsize, memcat);
|
||||
|
||||
// we need to accommodate space for link for free blocks (freegcolink)
|
||||
LUAU_ASSERT(nsize >= kGCOLinkOffset + sizeof(void*));
|
||||
|
||||
|
@ -602,7 +515,7 @@ void luaM_free_(lua_State* L, void* block, size_t osize, uint8_t memcat)
|
|||
if (oclass >= 0)
|
||||
freeblock(L, oclass, block);
|
||||
else
|
||||
(*g->frealloc)(L, g->ud, block, osize, 0);
|
||||
(*g->frealloc)(g->ud, block, osize, 0);
|
||||
|
||||
g->totalbytes -= osize;
|
||||
g->memcatbytes[memcat] -= osize;
|
||||
|
@ -610,12 +523,6 @@ void luaM_free_(lua_State* L, void* block, size_t osize, uint8_t memcat)
|
|||
|
||||
void luaM_freegco_(lua_State* L, GCObject* block, size_t osize, uint8_t memcat, lua_Page* page)
|
||||
{
|
||||
if (!FFlag::LuauGcPagedSweep)
|
||||
{
|
||||
luaM_free_(L, block, osize, memcat);
|
||||
return;
|
||||
}
|
||||
|
||||
global_State* g = L->global;
|
||||
LUAU_ASSERT((osize == 0) == (block == NULL));
|
||||
|
||||
|
@ -652,7 +559,7 @@ void* luaM_realloc_(lua_State* L, void* block, size_t osize, size_t nsize, uint8
|
|||
// if either block needs to be allocated using a block allocator, we can't use realloc directly
|
||||
if (nclass >= 0 || oclass >= 0)
|
||||
{
|
||||
result = nclass >= 0 ? newblock(L, nclass) : (*g->frealloc)(L, g->ud, NULL, 0, nsize);
|
||||
result = nclass >= 0 ? newblock(L, nclass) : (*g->frealloc)(g->ud, NULL, 0, nsize);
|
||||
if (result == NULL && nsize > 0)
|
||||
luaD_throw(L, LUA_ERRMEM);
|
||||
|
||||
|
@ -662,11 +569,11 @@ void* luaM_realloc_(lua_State* L, void* block, size_t osize, size_t nsize, uint8
|
|||
if (oclass >= 0)
|
||||
freeblock(L, oclass, block);
|
||||
else
|
||||
(*g->frealloc)(L, g->ud, block, osize, 0);
|
||||
(*g->frealloc)(g->ud, block, osize, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = (*g->frealloc)(L, g->ud, block, osize, nsize);
|
||||
result = (*g->frealloc)(g->ud, block, osize, nsize);
|
||||
if (result == NULL && nsize > 0)
|
||||
luaD_throw(L, LUA_ERRMEM);
|
||||
}
|
||||
|
@ -679,8 +586,6 @@ void* luaM_realloc_(lua_State* L, void* block, size_t osize, size_t nsize, uint8
|
|||
|
||||
void luaM_getpagewalkinfo(lua_Page* page, char** start, char** end, int* busyBlocks, int* blockSize)
|
||||
{
|
||||
LUAU_ASSERT(FFlag::LuauGcPagedSweep);
|
||||
|
||||
int blockCount = (page->pageSize - offsetof(lua_Page, data)) / page->blockSize;
|
||||
|
||||
LUAU_ASSERT(page->freeNext >= -page->blockSize && page->freeNext <= (blockCount - 1) * page->blockSize);
|
||||
|
@ -700,8 +605,6 @@ lua_Page* luaM_getnextgcopage(lua_Page* page)
|
|||
|
||||
void luaM_visitpage(lua_Page* page, void* context, bool (*visitor)(void* context, lua_Page* page, GCObject* gco))
|
||||
{
|
||||
LUAU_ASSERT(FFlag::LuauGcPagedSweep);
|
||||
|
||||
char* start;
|
||||
char* end;
|
||||
int busyBlocks;
|
||||
|
@ -730,8 +633,6 @@ void luaM_visitpage(lua_Page* page, void* context, bool (*visitor)(void* context
|
|||
|
||||
void luaM_visitgco(lua_State* L, void* context, bool (*visitor)(void* context, lua_Page* page, GCObject* gco))
|
||||
{
|
||||
LUAU_ASSERT(FFlag::LuauGcPagedSweep);
|
||||
|
||||
global_State* g = L->global;
|
||||
|
||||
for (lua_Page* curr = g->allgcopages; curr;)
|
||||
|
|
|
@ -7,11 +7,7 @@
|
|||
struct lua_Page;
|
||||
union GCObject;
|
||||
|
||||
// TODO: remove with FFlagLuauGcPagedSweep and rename luaM_newgco to luaM_new
|
||||
#define luaM_new(L, t, size, memcat) cast_to(t*, luaM_new_(L, size, memcat))
|
||||
#define luaM_newgco(L, t, size, memcat) cast_to(t*, luaM_newgco_(L, size, memcat))
|
||||
// TODO: remove with FFlagLuauGcPagedSweep and rename luaM_freegco to luaM_free
|
||||
#define luaM_free(L, p, size, memcat) luaM_free_(L, (p), size, memcat)
|
||||
#define luaM_freegco(L, p, size, memcat, page) luaM_freegco_(L, obj2gco(p), size, memcat, page)
|
||||
|
||||
#define luaM_arraysize_(n, e) ((cast_to(size_t, (n)) <= SIZE_MAX / (e)) ? (n) * (e) : (luaM_toobig(L), SIZE_MAX))
|
||||
|
|
|
@ -15,7 +15,6 @@ typedef union GCObject GCObject;
|
|||
*/
|
||||
// clang-format off
|
||||
#define CommonHeader \
|
||||
GCObject* next; /* TODO: remove with FFlagLuauGcPagedSweep */ \
|
||||
uint8_t tt; uint8_t marked; uint8_t memcat
|
||||
// clang-format on
|
||||
|
||||
|
@ -233,6 +232,8 @@ typedef struct TString
|
|||
int16_t atom;
|
||||
// 2 byte padding
|
||||
|
||||
TString* next; // next string in the hash table bucket or the string buffer linked list
|
||||
|
||||
unsigned int hash;
|
||||
unsigned int len;
|
||||
|
||||
|
@ -327,7 +328,7 @@ typedef struct UpVal
|
|||
struct UpVal* next;
|
||||
|
||||
/* thread double linked list (when open) */
|
||||
// TODO: when FFlagLuauGcPagedSweep is removed, old outer 'next' value will be placed here
|
||||
struct UpVal* threadnext;
|
||||
/* note: this is the location of a pointer to this upvalue in the previous element that can be either an UpVal or a lua_State */
|
||||
struct UpVal** threadprev;
|
||||
} l;
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
#include "ldo.h"
|
||||
#include "ldebug.h"
|
||||
|
||||
LUAU_FASTFLAG(LuauGcPagedSweep)
|
||||
LUAU_FASTFLAGVARIABLE(LuauReduceStackReallocs, false)
|
||||
|
||||
/*
|
||||
|
@ -90,8 +89,6 @@ static void close_state(lua_State* L)
|
|||
global_State* g = L->global;
|
||||
luaF_close(L, L->stack); /* close all upvalues for this thread */
|
||||
luaC_freeall(L); /* collect all objects */
|
||||
if (!FFlag::LuauGcPagedSweep)
|
||||
LUAU_ASSERT(g->rootgc == obj2gco(L));
|
||||
LUAU_ASSERT(g->strbufgc == NULL);
|
||||
LUAU_ASSERT(g->strt.nuse == 0);
|
||||
luaM_freearray(L, L->global->strt.hash, L->global->strt.size, TString*, 0);
|
||||
|
@ -99,22 +96,20 @@ static void close_state(lua_State* L)
|
|||
for (int i = 0; i < LUA_SIZECLASSES; i++)
|
||||
{
|
||||
LUAU_ASSERT(g->freepages[i] == NULL);
|
||||
if (FFlag::LuauGcPagedSweep)
|
||||
LUAU_ASSERT(g->freegcopages[i] == NULL);
|
||||
LUAU_ASSERT(g->freegcopages[i] == NULL);
|
||||
}
|
||||
if (FFlag::LuauGcPagedSweep)
|
||||
LUAU_ASSERT(g->allgcopages == NULL);
|
||||
LUAU_ASSERT(g->allgcopages == NULL);
|
||||
LUAU_ASSERT(g->totalbytes == sizeof(LG));
|
||||
LUAU_ASSERT(g->memcatbytes[0] == sizeof(LG));
|
||||
for (int i = 1; i < LUA_MEMORY_CATEGORIES; i++)
|
||||
LUAU_ASSERT(g->memcatbytes[i] == 0);
|
||||
(*g->frealloc)(L, g->ud, L, sizeof(LG), 0);
|
||||
(*g->frealloc)(g->ud, L, sizeof(LG), 0);
|
||||
}
|
||||
|
||||
lua_State* luaE_newthread(lua_State* L)
|
||||
{
|
||||
lua_State* L1 = luaM_newgco(L, lua_State, sizeof(lua_State), L->activememcat);
|
||||
luaC_link(L, L1, LUA_TTHREAD);
|
||||
luaC_init(L, L1, LUA_TTHREAD);
|
||||
preinit_state(L1, L->global);
|
||||
L1->activememcat = L->activememcat; // inherit the active memory category
|
||||
stack_init(L1, L); /* init stack */
|
||||
|
@ -184,13 +179,11 @@ lua_State* lua_newstate(lua_Alloc f, void* ud)
|
|||
int i;
|
||||
lua_State* L;
|
||||
global_State* g;
|
||||
void* l = (*f)(NULL, ud, NULL, 0, sizeof(LG));
|
||||
void* l = (*f)(ud, NULL, 0, sizeof(LG));
|
||||
if (l == NULL)
|
||||
return NULL;
|
||||
L = (lua_State*)l;
|
||||
g = &((LG*)L)->g;
|
||||
if (!FFlag::LuauGcPagedSweep)
|
||||
L->next = NULL;
|
||||
L->tt = LUA_TTHREAD;
|
||||
L->marked = g->currentwhite = bit2mask(WHITE0BIT, FIXEDBIT);
|
||||
L->memcat = 0;
|
||||
|
@ -214,11 +207,6 @@ lua_State* lua_newstate(lua_Alloc f, void* ud)
|
|||
setnilvalue(&g->pseudotemp);
|
||||
setnilvalue(registry(L));
|
||||
g->gcstate = GCSpause;
|
||||
if (!FFlag::LuauGcPagedSweep)
|
||||
g->rootgc = obj2gco(L);
|
||||
g->sweepstrgc = 0;
|
||||
if (!FFlag::LuauGcPagedSweep)
|
||||
g->sweepgc = &g->rootgc;
|
||||
g->gray = NULL;
|
||||
g->grayagain = NULL;
|
||||
g->weak = NULL;
|
||||
|
@ -230,14 +218,10 @@ lua_State* lua_newstate(lua_Alloc f, void* ud)
|
|||
for (i = 0; i < LUA_SIZECLASSES; i++)
|
||||
{
|
||||
g->freepages[i] = NULL;
|
||||
if (FFlag::LuauGcPagedSweep)
|
||||
g->freegcopages[i] = NULL;
|
||||
}
|
||||
if (FFlag::LuauGcPagedSweep)
|
||||
{
|
||||
g->allgcopages = NULL;
|
||||
g->sweepgcopage = NULL;
|
||||
g->freegcopages[i] = NULL;
|
||||
}
|
||||
g->allgcopages = NULL;
|
||||
g->sweepgcopage = NULL;
|
||||
for (i = 0; i < LUA_T_COUNT; i++)
|
||||
g->mt[i] = NULL;
|
||||
for (i = 0; i < LUA_UTAG_LIMIT; i++)
|
||||
|
|
|
@ -142,11 +142,6 @@ typedef struct global_State
|
|||
uint8_t gcstate; /* state of garbage collector */
|
||||
|
||||
|
||||
int sweepstrgc; /* position of sweep in `strt' */
|
||||
// TODO: remove with FFlagLuauGcPagedSweep
|
||||
GCObject* rootgc; /* list of all collectable objects */
|
||||
// TODO: remove with FFlagLuauGcPagedSweep
|
||||
GCObject** sweepgc; /* position of sweep in `rootgc' */
|
||||
GCObject* gray; /* list of gray objects */
|
||||
GCObject* grayagain; /* list of objects to be traversed atomically */
|
||||
GCObject* weak; /* list of weak tables (to be cleared) */
|
||||
|
|
|
@ -7,8 +7,6 @@
|
|||
|
||||
#include <string.h>
|
||||
|
||||
LUAU_FASTFLAG(LuauGcPagedSweep)
|
||||
|
||||
unsigned int luaS_hash(const char* str, size_t len)
|
||||
{
|
||||
// Note that this hashing algorithm is replicated in BytecodeBuilder.cpp, BytecodeBuilder::getStringHash
|
||||
|
@ -46,8 +44,6 @@ unsigned int luaS_hash(const char* str, size_t len)
|
|||
|
||||
void luaS_resize(lua_State* L, int newsize)
|
||||
{
|
||||
if (L->global->gcstate == GCSsweepstring)
|
||||
return; /* cannot resize during GC traverse */
|
||||
TString** newhash = luaM_newarray(L, newsize, TString*, 0);
|
||||
stringtable* tb = &L->global->strt;
|
||||
for (int i = 0; i < newsize; i++)
|
||||
|
@ -58,13 +54,11 @@ void luaS_resize(lua_State* L, int newsize)
|
|||
TString* p = tb->hash[i];
|
||||
while (p)
|
||||
{ /* for each node in the list */
|
||||
// TODO (FFlagLuauGcPagedSweep): 'next' type will change after removal of the flag and the cast will not be required
|
||||
TString* next = (TString*)p->next; /* save next */
|
||||
TString* next = p->next; /* save next */
|
||||
unsigned int h = p->hash;
|
||||
int h1 = lmod(h, newsize); /* new position */
|
||||
LUAU_ASSERT(cast_int(h % newsize) == lmod(h, newsize));
|
||||
// TODO (FFlagLuauGcPagedSweep): 'next' type will change after removal of the flag and the cast will not be required
|
||||
p->next = (GCObject*)newhash[h1]; /* chain it */
|
||||
p->next = newhash[h1]; /* chain it */
|
||||
newhash[h1] = p;
|
||||
p = next;
|
||||
}
|
||||
|
@ -91,8 +85,7 @@ static TString* newlstr(lua_State* L, const char* str, size_t l, unsigned int h)
|
|||
ts->atom = L->global->cb.useratom ? L->global->cb.useratom(ts->data, l) : -1;
|
||||
tb = &L->global->strt;
|
||||
h = lmod(h, tb->size);
|
||||
// TODO (FFlagLuauGcPagedSweep): 'next' type will change after removal of the flag and the case will not be required
|
||||
ts->next = (GCObject*)tb->hash[h]; /* chain new entry */
|
||||
ts->next = tb->hash[h]; /* chain new entry */
|
||||
tb->hash[h] = ts;
|
||||
tb->nuse++;
|
||||
if (tb->nuse > cast_to(uint32_t, tb->size) && tb->size <= INT_MAX / 2)
|
||||
|
@ -104,20 +97,9 @@ static void linkstrbuf(lua_State* L, TString* ts)
|
|||
{
|
||||
global_State* g = L->global;
|
||||
|
||||
if (FFlag::LuauGcPagedSweep)
|
||||
{
|
||||
// TODO (FFlagLuauGcPagedSweep): 'next' type will change after removal of the flag and the cast will not be required
|
||||
ts->next = (GCObject*)g->strbufgc;
|
||||
g->strbufgc = ts;
|
||||
ts->marked = luaC_white(g);
|
||||
}
|
||||
else
|
||||
{
|
||||
GCObject* o = obj2gco(ts);
|
||||
o->gch.next = (GCObject*)g->strbufgc;
|
||||
g->strbufgc = gco2ts(o);
|
||||
o->gch.marked = luaC_white(g);
|
||||
}
|
||||
ts->next = g->strbufgc;
|
||||
g->strbufgc = ts;
|
||||
ts->marked = luaC_white(g);
|
||||
}
|
||||
|
||||
static void unlinkstrbuf(lua_State* L, TString* ts)
|
||||
|
@ -130,14 +112,12 @@ static void unlinkstrbuf(lua_State* L, TString* ts)
|
|||
{
|
||||
if (curr == ts)
|
||||
{
|
||||
// TODO (FFlagLuauGcPagedSweep): 'next' type will change after removal of the flag and the cast will not be required
|
||||
*p = (TString*)curr->next;
|
||||
*p = curr->next;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO (FFlagLuauGcPagedSweep): 'next' type will change after removal of the flag and the cast will not be required
|
||||
p = (TString**)&curr->next;
|
||||
p = &curr->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -167,8 +147,7 @@ TString* luaS_buffinish(lua_State* L, TString* ts)
|
|||
int bucket = lmod(h, tb->size);
|
||||
|
||||
// search if we already have this string in the hash table
|
||||
// TODO (FFlagLuauGcPagedSweep): 'next' type will change after removal of the flag and the cast will not be required
|
||||
for (TString* el = tb->hash[bucket]; el != NULL; el = (TString*)el->next)
|
||||
for (TString* el = tb->hash[bucket]; el != NULL; el = el->next)
|
||||
{
|
||||
if (el->len == ts->len && memcmp(el->data, ts->data, ts->len) == 0)
|
||||
{
|
||||
|
@ -187,8 +166,7 @@ TString* luaS_buffinish(lua_State* L, TString* ts)
|
|||
|
||||
// Complete string object
|
||||
ts->atom = L->global->cb.useratom ? L->global->cb.useratom(ts->data, ts->len) : -1;
|
||||
// TODO (FFlagLuauGcPagedSweep): 'next' type will change after removal of the flag and the cast will not be required
|
||||
ts->next = (GCObject*)tb->hash[bucket]; // chain new entry
|
||||
ts->next = tb->hash[bucket]; // chain new entry
|
||||
tb->hash[bucket] = ts;
|
||||
|
||||
tb->nuse++;
|
||||
|
@ -201,8 +179,7 @@ TString* luaS_buffinish(lua_State* L, TString* ts)
|
|||
TString* luaS_newlstr(lua_State* L, const char* str, size_t l)
|
||||
{
|
||||
unsigned int h = luaS_hash(str, l);
|
||||
// TODO (FFlagLuauGcPagedSweep): 'next' type will change after removal of the flag and the cast will not be required
|
||||
for (TString* el = L->global->strt.hash[lmod(h, L->global->strt.size)]; el != NULL; el = (TString*)el->next)
|
||||
for (TString* el = L->global->strt.hash[lmod(h, L->global->strt.size)]; el != NULL; el = el->next)
|
||||
{
|
||||
if (el->len == l && (memcmp(str, getstr(el), l) == 0))
|
||||
{
|
||||
|
@ -217,8 +194,6 @@ TString* luaS_newlstr(lua_State* L, const char* str, size_t l)
|
|||
|
||||
static bool unlinkstr(lua_State* L, TString* ts)
|
||||
{
|
||||
LUAU_ASSERT(FFlag::LuauGcPagedSweep);
|
||||
|
||||
global_State* g = L->global;
|
||||
|
||||
TString** p = &g->strt.hash[lmod(ts->hash, g->strt.size)];
|
||||
|
@ -227,14 +202,12 @@ static bool unlinkstr(lua_State* L, TString* ts)
|
|||
{
|
||||
if (curr == ts)
|
||||
{
|
||||
// TODO (FFlagLuauGcPagedSweep): 'next' type will change after removal of the flag and the cast will not be required
|
||||
*p = (TString*)curr->next;
|
||||
*p = curr->next;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO (FFlagLuauGcPagedSweep): 'next' type will change after removal of the flag and the cast will not be required
|
||||
p = (TString**)&curr->next;
|
||||
p = &curr->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -243,20 +216,11 @@ static bool unlinkstr(lua_State* L, TString* ts)
|
|||
|
||||
void luaS_free(lua_State* L, TString* ts, lua_Page* page)
|
||||
{
|
||||
if (FFlag::LuauGcPagedSweep)
|
||||
{
|
||||
// Unchain from the string table
|
||||
if (!unlinkstr(L, ts))
|
||||
unlinkstrbuf(L, ts); // An unlikely scenario when we have a string buffer on our hands
|
||||
else
|
||||
L->global->strt.nuse--;
|
||||
|
||||
luaM_freegco(L, ts, sizestring(ts->len), ts->memcat, page);
|
||||
}
|
||||
// Unchain from the string table
|
||||
if (!unlinkstr(L, ts))
|
||||
unlinkstrbuf(L, ts); // An unlikely scenario when we have a string buffer on our hands
|
||||
else
|
||||
{
|
||||
L->global->strt.nuse--;
|
||||
|
||||
luaM_free(L, ts, sizestring(ts->len), ts->memcat);
|
||||
}
|
||||
luaM_freegco(L, ts, sizestring(ts->len), ts->memcat, page);
|
||||
}
|
||||
|
|
|
@ -425,7 +425,7 @@ static void rehash(lua_State* L, Table* t, const TValue* ek)
|
|||
Table* luaH_new(lua_State* L, int narray, int nhash)
|
||||
{
|
||||
Table* t = luaM_newgco(L, Table, sizeof(Table), L->activememcat);
|
||||
luaC_link(L, t, LUA_TTABLE);
|
||||
luaC_init(L, t, LUA_TTABLE);
|
||||
t->metatable = NULL;
|
||||
t->flags = cast_byte(~0);
|
||||
t->array = NULL;
|
||||
|
@ -742,7 +742,7 @@ int luaH_getn(Table* t)
|
|||
Table* luaH_clone(lua_State* L, Table* tt)
|
||||
{
|
||||
Table* t = luaM_newgco(L, Table, sizeof(Table), L->activememcat);
|
||||
luaC_link(L, t, LUA_TTABLE);
|
||||
luaC_init(L, t, LUA_TTABLE);
|
||||
t->metatable = tt->metatable;
|
||||
t->flags = tt->flags;
|
||||
t->array = NULL;
|
||||
|
|
|
@ -12,7 +12,7 @@ Udata* luaU_newudata(lua_State* L, size_t s, int tag)
|
|||
if (s > INT_MAX - sizeof(Udata))
|
||||
luaM_toobig(L);
|
||||
Udata* u = luaM_newgco(L, Udata, sizeudata(s), L->activememcat);
|
||||
luaC_link(L, u, LUA_TUSERDATA);
|
||||
luaC_init(L, u, LUA_TUSERDATA);
|
||||
u->len = int(s);
|
||||
u->metatable = NULL;
|
||||
LUAU_ASSERT(tag >= 0 && tag <= 255);
|
||||
|
|
|
@ -16,7 +16,7 @@ extern "C" {
|
|||
|
||||
pub fn luaL_newstate() -> *mut c_void;
|
||||
pub fn luaL_openlibs(state: *mut c_void);
|
||||
pub fn lua_getfield(state: *mut c_void, index: c_int, k: *const c_char);
|
||||
pub fn lua_getfield(state: *mut c_void, index: c_int, k: *const c_char) -> c_int;
|
||||
pub fn lua_tolstring(state: *mut c_void, index: c_int, len: *mut c_long) -> *const c_char;
|
||||
|
||||
pub fn luau_compile(
|
||||
|
|
Loading…
Reference in New Issue