v0.2.2+luau521

This commit is contained in:
Alex Orlenko 2022-03-31 23:20:58 +01:00
parent d9a2a46c68
commit 4e923b679b
No known key found for this signature in database
GPG Key ID: 4C150C250863B96D
23 changed files with 320 additions and 293 deletions

View File

@ -1,6 +1,6 @@
[package]
name = "luau0-src"
version = "0.2.1+luau519"
version = "0.2.2+luau521"
authors = ["Aleksandr Orlenko <zxteam@protonmail.com>"]
edition = "2018"
repository = "https://github.com/khvzak/luau-src-rs"

View File

@ -130,8 +130,8 @@ ThreadContext& getThreadContext();
struct Scope
{
explicit Scope(ThreadContext& context, uint16_t token)
: context(context)
explicit Scope(uint16_t token)
: context(getThreadContext())
{
if (!FFlag::DebugLuauTimeTracing)
return;
@ -152,8 +152,8 @@ struct Scope
struct OptionalTailScope
{
explicit OptionalTailScope(ThreadContext& context, uint16_t token, uint32_t threshold)
: context(context)
explicit OptionalTailScope(uint16_t token, uint32_t threshold)
: context(getThreadContext())
, token(token)
, threshold(threshold)
{
@ -188,27 +188,27 @@ struct OptionalTailScope
uint32_t pos;
};
LUAU_NOINLINE std::pair<uint16_t, Luau::TimeTrace::ThreadContext&> createScopeData(const char* name, const char* category);
LUAU_NOINLINE uint16_t createScopeData(const char* name, const char* category);
} // namespace TimeTrace
} // namespace Luau
// Regular scope
#define LUAU_TIMETRACE_SCOPE(name, category) \
static auto lttScopeStatic = Luau::TimeTrace::createScopeData(name, category); \
Luau::TimeTrace::Scope lttScope(lttScopeStatic.second, lttScopeStatic.first)
static uint16_t lttScopeStatic = Luau::TimeTrace::createScopeData(name, category); \
Luau::TimeTrace::Scope lttScope(lttScopeStatic)
// A scope without nested scopes that may be skipped if the time it took is less than the threshold
#define LUAU_TIMETRACE_OPTIONAL_TAIL_SCOPE(name, category, microsec) \
static auto lttScopeStaticOptTail = Luau::TimeTrace::createScopeData(name, category); \
Luau::TimeTrace::OptionalTailScope lttScope(lttScopeStaticOptTail.second, lttScopeStaticOptTail.first, microsec)
static uint16_t lttScopeStaticOptTail = Luau::TimeTrace::createScopeData(name, category); \
Luau::TimeTrace::OptionalTailScope lttScope(lttScopeStaticOptTail, microsec)
// Extra key/value data can be added to regular scopes
#define LUAU_TIMETRACE_ARGUMENT(name, value) \
do \
{ \
if (FFlag::DebugLuauTimeTracing) \
lttScopeStatic.second.eventArgument(name, value); \
lttScope.context.eventArgument(name, value); \
} while (false)
#else

View File

@ -6,6 +6,8 @@
#include <limits.h>
LUAU_FASTFLAGVARIABLE(LuauParseLocationIgnoreCommentSkip, false)
namespace Luau
{
@ -352,6 +354,8 @@ const Lexeme& Lexer::next()
const Lexeme& Lexer::next(bool skipComments)
{
bool first = true;
// in skipComments mode we reject valid comments
do
{
@ -359,9 +363,11 @@ const Lexeme& Lexer::next(bool skipComments)
while (isSpace(peekch()))
consume();
prevLocation = lexeme.location;
if (!FFlag::LuauParseLocationIgnoreCommentSkip || first)
prevLocation = lexeme.location;
lexeme = readNext();
first = false;
} while (skipComments && (lexeme.type == Lexeme::Comment || lexeme.type == Lexeme::BlockComment));
return lexeme;

View File

@ -10,8 +10,6 @@
// See docs/SyntaxChanges.md for an explanation.
LUAU_FASTINTVARIABLE(LuauRecursionLimit, 1000)
LUAU_FASTINTVARIABLE(LuauParseErrorLimit, 100)
LUAU_FASTFLAGVARIABLE(LuauParseSingletonTypes, false)
LUAU_FASTFLAGVARIABLE(LuauTableFieldFunctionDebugname, false)
namespace Luau
{
@ -1233,8 +1231,7 @@ AstType* Parser::parseTableTypeAnnotation()
while (lexer.current().type != '}')
{
if (FFlag::LuauParseSingletonTypes && lexer.current().type == '[' &&
(lexer.lookahead().type == Lexeme::RawString || lexer.lookahead().type == Lexeme::QuotedString))
if (lexer.current().type == '[' && (lexer.lookahead().type == Lexeme::RawString || lexer.lookahead().type == Lexeme::QuotedString))
{
const Lexeme begin = lexer.current();
nextLexeme(); // [
@ -1500,17 +1497,17 @@ AstTypeOrPack Parser::parseSimpleTypeAnnotation(bool allowPack)
nextLexeme();
return {allocator.alloc<AstTypeReference>(begin, std::nullopt, nameNil), {}};
}
else if (FFlag::LuauParseSingletonTypes && lexer.current().type == Lexeme::ReservedTrue)
else if (lexer.current().type == Lexeme::ReservedTrue)
{
nextLexeme();
return {allocator.alloc<AstTypeSingletonBool>(begin, true)};
}
else if (FFlag::LuauParseSingletonTypes && lexer.current().type == Lexeme::ReservedFalse)
else if (lexer.current().type == Lexeme::ReservedFalse)
{
nextLexeme();
return {allocator.alloc<AstTypeSingletonBool>(begin, false)};
}
else if (FFlag::LuauParseSingletonTypes && (lexer.current().type == Lexeme::RawString || lexer.current().type == Lexeme::QuotedString))
else if (lexer.current().type == Lexeme::RawString || lexer.current().type == Lexeme::QuotedString)
{
if (std::optional<AstArray<char>> value = parseCharArray())
{
@ -1520,7 +1517,7 @@ AstTypeOrPack Parser::parseSimpleTypeAnnotation(bool allowPack)
else
return {reportTypeAnnotationError(begin, {}, /*isMissing*/ false, "String literal contains malformed escape sequence")};
}
else if (FFlag::LuauParseSingletonTypes && lexer.current().type == Lexeme::BrokenString)
else if (lexer.current().type == Lexeme::BrokenString)
{
Location location = lexer.current().location;
nextLexeme();
@ -2189,11 +2186,8 @@ AstExpr* Parser::parseTableConstructor()
AstExpr* key = allocator.alloc<AstExprConstantString>(name.location, nameString);
AstExpr* value = parseExpr();
if (FFlag::LuauTableFieldFunctionDebugname)
{
if (AstExprFunction* func = value->as<AstExprFunction>())
func->debugname = name.name;
}
if (AstExprFunction* func = value->as<AstExprFunction>())
func->debugname = name.name;
items.push_back({AstExprTable::Item::Record, key, value});
}

View File

@ -246,10 +246,9 @@ ThreadContext& getThreadContext()
return context;
}
std::pair<uint16_t, Luau::TimeTrace::ThreadContext&> createScopeData(const char* name, const char* category)
uint16_t createScopeData(const char* name, const char* category)
{
uint16_t token = createToken(Luau::TimeTrace::getGlobalContext(), name, category);
return {token, Luau::TimeTrace::getThreadContext()};
return createToken(Luau::TimeTrace::getGlobalContext(), name, category);
}
} // namespace TimeTrace
} // namespace Luau

View File

@ -376,8 +376,7 @@ enum LuauOpcode
enum LuauBytecodeTag
{
// Bytecode version
LBC_VERSION = 1,
LBC_VERSION_FUTURE = 2, // TODO: This will be removed in favor of LBC_VERSION with LuauBytecodeV2Force
LBC_VERSION = 2,
// Types of constant table entries
LBC_CONSTANT_NIL = 0,
LBC_CONSTANT_BOOLEAN,

View File

@ -508,7 +508,7 @@ uint32_t BytecodeBuilder::getDebugPC() const
void BytecodeBuilder::finalize()
{
LUAU_ASSERT(bytecode.empty());
bytecode = char(LBC_VERSION_FUTURE);
bytecode = char(LBC_VERSION);
writeStringTable(bytecode);

View File

@ -14,8 +14,6 @@
#include <string.h>
LUAU_FASTFLAG(LuauGcAdditionalStats)
const char* lua_ident = "$Lua: Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio $\n"
"$Authors: R. Ierusalimschy, L. H. de Figueiredo & W. Celes $\n"
"$URL: www.lua.org $\n";
@ -1060,8 +1058,11 @@ int lua_gc(lua_State* L, int what, int data)
g->GCthreshold = 0;
bool waspaused = g->gcstate == GCSpause;
double startmarktime = g->gcstats.currcycle.marktime;
double startsweeptime = g->gcstats.currcycle.sweeptime;
#ifdef LUAI_GCMETRICS
double startmarktime = g->gcmetrics.currcycle.marktime;
double startsweeptime = g->gcmetrics.currcycle.sweeptime;
#endif
// track how much work the loop will actually perform
size_t actualwork = 0;
@ -1079,31 +1080,30 @@ int lua_gc(lua_State* L, int what, int data)
}
}
if (FFlag::LuauGcAdditionalStats)
#ifdef LUAI_GCMETRICS
// record explicit step statistics
GCCycleMetrics* cyclemetrics = g->gcstate == GCSpause ? &g->gcmetrics.lastcycle : &g->gcmetrics.currcycle;
double totalmarktime = cyclemetrics->marktime - startmarktime;
double totalsweeptime = cyclemetrics->sweeptime - startsweeptime;
if (totalmarktime > 0.0)
{
// record explicit step statistics
GCCycleStats* cyclestats = g->gcstate == GCSpause ? &g->gcstats.lastcycle : &g->gcstats.currcycle;
cyclemetrics->markexplicitsteps++;
double totalmarktime = cyclestats->marktime - startmarktime;
double totalsweeptime = cyclestats->sweeptime - startsweeptime;
if (totalmarktime > 0.0)
{
cyclestats->markexplicitsteps++;
if (totalmarktime > cyclestats->markmaxexplicittime)
cyclestats->markmaxexplicittime = totalmarktime;
}
if (totalsweeptime > 0.0)
{
cyclestats->sweepexplicitsteps++;
if (totalsweeptime > cyclestats->sweepmaxexplicittime)
cyclestats->sweepmaxexplicittime = totalsweeptime;
}
if (totalmarktime > cyclemetrics->markmaxexplicittime)
cyclemetrics->markmaxexplicittime = totalmarktime;
}
if (totalsweeptime > 0.0)
{
cyclemetrics->sweepexplicitsteps++;
if (totalsweeptime > cyclemetrics->sweepmaxexplicittime)
cyclemetrics->sweepmaxexplicittime = totalsweeptime;
}
#endif
// if cycle hasn't finished, advance threshold forward for the amount of extra work performed
if (g->gcstate != GCSpause)
{

View File

@ -11,8 +11,6 @@
#include <string.h>
LUAU_DYNAMIC_FASTFLAGVARIABLE(LuauMorePreciseLuaLTypeName, false)
/* convert a stack index to positive */
#define abs_index(L, i) ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : lua_gettop(L) + (i) + 1)
@ -337,15 +335,8 @@ const char* luaL_findtable(lua_State* L, int idx, const char* fname, int szhint)
const char* luaL_typename(lua_State* L, int idx)
{
if (DFFlag::LuauMorePreciseLuaLTypeName)
{
const TValue* obj = luaA_toobject(L, idx);
return luaT_objtypename(L, obj);
}
else
{
return lua_typename(L, lua_type(L, idx));
}
const TValue* obj = luaA_toobject(L, idx);
return luaT_objtypename(L, obj);
}
/*

View File

@ -11,8 +11,6 @@
#include <stdio.h>
#include <stdlib.h>
LUAU_DYNAMIC_FASTFLAG(LuauMorePreciseLuaLTypeName)
static void writestring(const char* s, size_t l)
{
fwrite(s, 1, l, stdout);
@ -189,31 +187,16 @@ static int luaB_gcinfo(lua_State* L)
static int luaB_type(lua_State* L)
{
luaL_checkany(L, 1);
if (DFFlag::LuauMorePreciseLuaLTypeName)
{
/* resulting name doesn't differentiate between userdata types */
lua_pushstring(L, lua_typename(L, lua_type(L, 1)));
}
else
{
lua_pushstring(L, luaL_typename(L, 1));
}
/* resulting name doesn't differentiate between userdata types */
lua_pushstring(L, lua_typename(L, lua_type(L, 1)));
return 1;
}
static int luaB_typeof(lua_State* L)
{
luaL_checkany(L, 1);
if (DFFlag::LuauMorePreciseLuaLTypeName)
{
/* resulting name returns __type if specified unless the input is a newproxy-created userdata */
lua_pushstring(L, luaL_typename(L, 1));
}
else
{
const TValue* obj = luaA_toobject(L, 1);
lua_pushstring(L, luaT_objtypename(L, obj));
}
/* resulting name returns __type if specified unless the input is a newproxy-created userdata */
lua_pushstring(L, luaL_typename(L, 1));
return 1;
}

View File

@ -12,8 +12,6 @@
#include <string.h>
#include <stdio.h>
LUAU_FASTFLAG(LuauBytecodeV2Force)
static const char* getfuncname(Closure* f);
static int currentpc(lua_State* L, CallInfo* ci)
@ -91,16 +89,6 @@ const char* lua_setlocal(lua_State* L, int level, int n)
return name;
}
static int getlinedefined(Proto* p)
{
if (FFlag::LuauBytecodeV2Force)
return p->linedefined;
else if (p->linedefined >= 0)
return p->linedefined;
else
return luaG_getline(p, 0);
}
static int auxgetinfo(lua_State* L, const char* what, lua_Debug* ar, Closure* f, CallInfo* ci)
{
int status = 1;
@ -120,7 +108,7 @@ static int auxgetinfo(lua_State* L, const char* what, lua_Debug* ar, Closure* f,
{
ar->source = getstr(f->l.p->source);
ar->what = "Lua";
ar->linedefined = getlinedefined(f->l.p);
ar->linedefined = f->l.p->linedefined;
}
luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE);
break;
@ -133,7 +121,7 @@ static int auxgetinfo(lua_State* L, const char* what, lua_Debug* ar, Closure* f,
}
else
{
ar->currentline = f->isC ? -1 : getlinedefined(f->l.p);
ar->currentline = f->isC ? -1 : f->l.p->linedefined;
}
break;
@ -424,7 +412,7 @@ static void getcoverage(Proto* p, int depth, int* buffer, size_t size, void* con
}
const char* debugname = p->debugname ? getstr(p->debugname) : NULL;
int linedefined = getlinedefined(p);
int linedefined = p->linedefined;
callback(context, debugname, linedefined, depth, buffer, size);

View File

@ -17,8 +17,6 @@
#include <string.h>
LUAU_FASTFLAG(LuauReduceStackReallocs)
/*
** {======================================================
** Error-recovery functions
@ -33,6 +31,15 @@ struct lua_jmpbuf
jmp_buf buf;
};
/* use POSIX versions of setjmp/longjmp if possible: they don't save/restore signal mask and are therefore faster */
#if defined(__linux__) || defined(__APPLE__)
#define LUAU_SETJMP(buf) _setjmp(buf)
#define LUAU_LONGJMP(buf, code) _longjmp(buf, code)
#else
#define LUAU_SETJMP(buf) setjmp(buf)
#define LUAU_LONGJMP(buf, code) longjmp(buf, code)
#endif
int luaD_rawrunprotected(lua_State* L, Pfunc f, void* ud)
{
lua_jmpbuf jb;
@ -40,7 +47,7 @@ int luaD_rawrunprotected(lua_State* L, Pfunc f, void* ud)
jb.status = 0;
L->global->errorjmp = &jb;
if (setjmp(jb.buf) == 0)
if (LUAU_SETJMP(jb.buf) == 0)
f(L, ud);
L->global->errorjmp = jb.prev;
@ -52,7 +59,7 @@ l_noret luaD_throw(lua_State* L, int errcode)
if (lua_jmpbuf* jb = L->global->errorjmp)
{
jb->status = errcode;
longjmp(jb->buf, 1);
LUAU_LONGJMP(jb->buf, 1);
}
if (L->global->cb.panic)
@ -165,8 +172,8 @@ static void correctstack(lua_State* L, TValue* oldstack)
void luaD_reallocstack(lua_State* L, int newsize)
{
TValue* oldstack = L->stack;
int realsize = newsize + (FFlag::LuauReduceStackReallocs ? EXTRA_STACK : 1 + EXTRA_STACK);
LUAU_ASSERT(L->stack_last - L->stack == L->stacksize - (FFlag::LuauReduceStackReallocs ? EXTRA_STACK : 1 + EXTRA_STACK));
int realsize = newsize + EXTRA_STACK;
LUAU_ASSERT(L->stack_last - L->stack == L->stacksize - EXTRA_STACK);
luaM_reallocarray(L, L->stack, L->stacksize, realsize, TValue, L->memcat);
TValue* newstack = L->stack;
for (int i = L->stacksize; i < realsize; i++)
@ -514,7 +521,7 @@ static void callerrfunc(lua_State* L, void* ud)
static void restore_stack_limit(lua_State* L)
{
LUAU_ASSERT(L->stack_last - L->stack == L->stacksize - (FFlag::LuauReduceStackReallocs ? EXTRA_STACK : 1 + EXTRA_STACK));
LUAU_ASSERT(L->stack_last - L->stack == L->stacksize - EXTRA_STACK);
if (L->size_ci > LUAI_MAXCALLS)
{ /* there was an overflow? */
int inuse = cast_int(L->ci - L->base_ci);

View File

@ -11,7 +11,7 @@
if ((char*)L->stack_last - (char*)L->top <= (n) * (int)sizeof(TValue)) \
luaD_growstack(L, n); \
else \
condhardstacktests(luaD_reallocstack(L, L->stacksize - (FFlag::LuauReduceStackReallocs ? EXTRA_STACK : 1 + EXTRA_STACK)));
condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK));
#define incr_top(L) \
{ \

View File

@ -11,8 +11,6 @@
#include "lmem.h"
#include "ludata.h"
LUAU_FASTFLAGVARIABLE(LuauGcAdditionalStats, false)
#include <string.h>
#define GC_SWEEPMAX 40
@ -48,7 +46,8 @@ LUAU_FASTFLAGVARIABLE(LuauGcAdditionalStats, false)
reallymarkobject(g, obj2gco(t)); \
}
static void recordGcStateTime(global_State* g, int startgcstate, double seconds, bool assist)
#ifdef LUAI_GCMETRICS
static void recordGcStateStep(global_State* g, int startgcstate, double seconds, bool assist, size_t work)
{
switch (startgcstate)
{
@ -56,58 +55,76 @@ static void recordGcStateTime(global_State* g, int startgcstate, double seconds,
// record root mark time if we have switched to next state
if (g->gcstate == GCSpropagate)
{
g->gcstats.currcycle.marktime += seconds;
g->gcmetrics.currcycle.marktime += seconds;
if (FFlag::LuauGcAdditionalStats && assist)
g->gcstats.currcycle.markassisttime += seconds;
if (assist)
g->gcmetrics.currcycle.markassisttime += seconds;
}
break;
case GCSpropagate:
case GCSpropagateagain:
g->gcstats.currcycle.marktime += seconds;
g->gcmetrics.currcycle.marktime += seconds;
g->gcmetrics.currcycle.markrequests += g->gcstepsize;
if (FFlag::LuauGcAdditionalStats && assist)
g->gcstats.currcycle.markassisttime += seconds;
if (assist)
g->gcmetrics.currcycle.markassisttime += seconds;
break;
case GCSatomic:
g->gcstats.currcycle.atomictime += seconds;
g->gcmetrics.currcycle.atomictime += seconds;
break;
case GCSsweep:
g->gcstats.currcycle.sweeptime += seconds;
g->gcmetrics.currcycle.sweeptime += seconds;
g->gcmetrics.currcycle.sweeprequests += g->gcstepsize;
if (FFlag::LuauGcAdditionalStats && assist)
g->gcstats.currcycle.sweepassisttime += seconds;
if (assist)
g->gcmetrics.currcycle.sweepassisttime += seconds;
break;
default:
LUAU_ASSERT(!"Unexpected GC state");
}
if (assist)
g->gcstats.stepassisttimeacc += seconds;
{
g->gcmetrics.stepassisttimeacc += seconds;
g->gcmetrics.currcycle.assistwork += work;
g->gcmetrics.currcycle.assistrequests += g->gcstepsize;
}
else
g->gcstats.stepexplicittimeacc += seconds;
{
g->gcmetrics.stepexplicittimeacc += seconds;
g->gcmetrics.currcycle.explicitwork += work;
g->gcmetrics.currcycle.explicitrequests += g->gcstepsize;
}
}
static void startGcCycleStats(global_State* g)
static double recordGcDeltaTime(double& timer)
{
g->gcstats.currcycle.starttimestamp = lua_clock();
g->gcstats.currcycle.pausetime = g->gcstats.currcycle.starttimestamp - g->gcstats.lastcycle.endtimestamp;
double now = lua_clock();
double delta = now - timer;
timer = now;
return delta;
}
static void finishGcCycleStats(global_State* g)
static void startGcCycleMetrics(global_State* g)
{
g->gcstats.currcycle.endtimestamp = lua_clock();
g->gcstats.currcycle.endtotalsizebytes = g->totalbytes;
g->gcstats.completedcycles++;
g->gcstats.lastcycle = g->gcstats.currcycle;
g->gcstats.currcycle = GCCycleStats();
g->gcstats.cyclestatsacc.marktime += g->gcstats.lastcycle.marktime;
g->gcstats.cyclestatsacc.atomictime += g->gcstats.lastcycle.atomictime;
g->gcstats.cyclestatsacc.sweeptime += g->gcstats.lastcycle.sweeptime;
g->gcmetrics.currcycle.starttimestamp = lua_clock();
g->gcmetrics.currcycle.pausetime = g->gcmetrics.currcycle.starttimestamp - g->gcmetrics.lastcycle.endtimestamp;
}
static void finishGcCycleMetrics(global_State* g)
{
g->gcmetrics.currcycle.endtimestamp = lua_clock();
g->gcmetrics.currcycle.endtotalsizebytes = g->totalbytes;
g->gcmetrics.completedcycles++;
g->gcmetrics.lastcycle = g->gcmetrics.currcycle;
g->gcmetrics.currcycle = GCCycleMetrics();
g->gcmetrics.currcycle.starttotalsizebytes = g->totalbytes;
g->gcmetrics.currcycle.heaptriggersizebytes = g->GCthreshold;
}
#endif
static void removeentry(LuaNode* n)
{
LUAU_ASSERT(ttisnil(gval(n)));
@ -598,20 +615,19 @@ static size_t atomic(lua_State* L)
LUAU_ASSERT(g->gcstate == GCSatomic);
size_t work = 0;
#ifdef LUAI_GCMETRICS
double currts = lua_clock();
double prevts = currts;
#endif
/* remark occasional upvalues of (maybe) dead threads */
work += remarkupvals(g);
/* traverse objects caught by write barrier and by 'remarkupvals' */
work += propagateall(g);
if (FFlag::LuauGcAdditionalStats)
{
currts = lua_clock();
g->gcstats.currcycle.atomictimeupval += currts - prevts;
prevts = currts;
}
#ifdef LUAI_GCMETRICS
g->gcmetrics.currcycle.atomictimeupval += recordGcDeltaTime(currts);
#endif
/* remark weak tables */
g->gray = g->weak;
@ -621,34 +637,26 @@ static size_t atomic(lua_State* L)
markmt(g); /* mark basic metatables (again) */
work += propagateall(g);
if (FFlag::LuauGcAdditionalStats)
{
currts = lua_clock();
g->gcstats.currcycle.atomictimeweak += currts - prevts;
prevts = currts;
}
#ifdef LUAI_GCMETRICS
g->gcmetrics.currcycle.atomictimeweak += recordGcDeltaTime(currts);
#endif
/* remark gray again */
g->gray = g->grayagain;
g->grayagain = NULL;
work += propagateall(g);
if (FFlag::LuauGcAdditionalStats)
{
currts = lua_clock();
g->gcstats.currcycle.atomictimegray += currts - prevts;
prevts = currts;
}
#ifdef LUAI_GCMETRICS
g->gcmetrics.currcycle.atomictimegray += recordGcDeltaTime(currts);
#endif
/* remove collected objects from weak tables */
work += cleartable(L, g->weak);
g->weak = NULL;
if (FFlag::LuauGcAdditionalStats)
{
currts = lua_clock();
g->gcstats.currcycle.atomictimeclear += currts - prevts;
}
#ifdef LUAI_GCMETRICS
g->gcmetrics.currcycle.atomictimeclear += recordGcDeltaTime(currts);
#endif
/* flip current white */
g->currentwhite = cast_byte(otherwhite(g));
@ -742,8 +750,9 @@ static size_t gcstep(lua_State* L, size_t limit)
if (!g->gray)
{
if (FFlag::LuauGcAdditionalStats)
g->gcstats.currcycle.propagatework = g->gcstats.currcycle.explicitwork + g->gcstats.currcycle.assistwork;
#ifdef LUAI_GCMETRICS
g->gcmetrics.currcycle.propagatework = g->gcmetrics.currcycle.explicitwork + g->gcmetrics.currcycle.assistwork;
#endif
// perform one iteration over 'gray again' list
g->gray = g->grayagain;
@ -762,9 +771,10 @@ static size_t gcstep(lua_State* L, size_t limit)
if (!g->gray) /* no more `gray' objects */
{
if (FFlag::LuauGcAdditionalStats)
g->gcstats.currcycle.propagateagainwork =
g->gcstats.currcycle.explicitwork + g->gcstats.currcycle.assistwork - g->gcstats.currcycle.propagatework;
#ifdef LUAI_GCMETRICS
g->gcmetrics.currcycle.propagateagainwork =
g->gcmetrics.currcycle.explicitwork + g->gcmetrics.currcycle.assistwork - g->gcmetrics.currcycle.propagatework;
#endif
g->gcstate = GCSatomic;
}
@ -772,8 +782,13 @@ static size_t gcstep(lua_State* L, size_t limit)
}
case GCSatomic:
{
g->gcstats.currcycle.atomicstarttimestamp = lua_clock();
g->gcstats.currcycle.atomicstarttotalsizebytes = g->totalbytes;
#ifdef LUAI_GCMETRICS
g->gcmetrics.currcycle.atomicstarttimestamp = lua_clock();
g->gcmetrics.currcycle.atomicstarttotalsizebytes = g->totalbytes;
#endif
g->gcstats.atomicstarttimestamp = lua_clock();
g->gcstats.atomicstarttotalsizebytes = g->totalbytes;
cost = atomic(L); /* finish mark phase */
@ -809,18 +824,20 @@ static size_t gcstep(lua_State* L, size_t limit)
return cost;
}
static int64_t getheaptriggererroroffset(GCHeapTriggerStats* triggerstats, GCCycleStats* cyclestats)
static int64_t getheaptriggererroroffset(global_State* g)
{
// adjust for error using Proportional-Integral controller
// https://en.wikipedia.org/wiki/PID_controller
int32_t errorKb = int32_t((cyclestats->atomicstarttotalsizebytes - cyclestats->heapgoalsizebytes) / 1024);
int32_t errorKb = int32_t((g->gcstats.atomicstarttotalsizebytes - g->gcstats.heapgoalsizebytes) / 1024);
// we use sliding window for the error integral to avoid error sum 'windup' when the desired target cannot be reached
int32_t* slot = &triggerstats->terms[triggerstats->termpos % triggerstats->termcount];
const size_t triggertermcount = sizeof(g->gcstats.triggerterms) / sizeof(g->gcstats.triggerterms[0]);
int32_t* slot = &g->gcstats.triggerterms[g->gcstats.triggertermpos % triggertermcount];
int32_t prev = *slot;
*slot = errorKb;
triggerstats->integral += errorKb - prev;
triggerstats->termpos++;
g->gcstats.triggerintegral += errorKb - prev;
g->gcstats.triggertermpos++;
// controller tuning
// https://en.wikipedia.org/wiki/Ziegler%E2%80%93Nichols_method
@ -832,7 +849,7 @@ static int64_t getheaptriggererroroffset(GCHeapTriggerStats* triggerstats, GCCyc
const double Ki = 0.54 * Ku / Ti; // integral gain
double proportionalTerm = Kp * errorKb;
double integralTerm = Ki * triggerstats->integral;
double integralTerm = Ki * g->gcstats.triggerintegral;
double totalTerm = proportionalTerm + integralTerm;
@ -841,23 +858,20 @@ static int64_t getheaptriggererroroffset(GCHeapTriggerStats* triggerstats, GCCyc
static size_t getheaptrigger(global_State* g, size_t heapgoal)
{
GCCycleStats* lastcycle = &g->gcstats.lastcycle;
GCCycleStats* currcycle = &g->gcstats.currcycle;
// adjust threshold based on a guess of how many bytes will be allocated between the cycle start and sweep phase
// our goal is to begin the sweep when used memory has reached the heap goal
const double durationthreshold = 1e-3;
double allocationduration = currcycle->atomicstarttimestamp - lastcycle->endtimestamp;
double allocationduration = g->gcstats.atomicstarttimestamp - g->gcstats.endtimestamp;
// avoid measuring intervals smaller than 1ms
if (allocationduration < durationthreshold)
return heapgoal;
double allocationrate = (currcycle->atomicstarttotalsizebytes - lastcycle->endtotalsizebytes) / allocationduration;
double markduration = currcycle->atomicstarttimestamp - currcycle->starttimestamp;
double allocationrate = (g->gcstats.atomicstarttotalsizebytes - g->gcstats.endtotalsizebytes) / allocationduration;
double markduration = g->gcstats.atomicstarttimestamp - g->gcstats.starttimestamp;
int64_t expectedgrowth = int64_t(markduration * allocationrate);
int64_t offset = getheaptriggererroroffset(&g->gcstats.triggerstats, currcycle);
int64_t offset = getheaptriggererroroffset(g);
int64_t heaptrigger = heapgoal - (expectedgrowth + offset);
// clamp the trigger between memory use at the end of the cycle and the heap goal
@ -868,11 +882,6 @@ void luaC_step(lua_State* L, bool assist)
{
global_State* g = L->global;
if (assist)
g->gcstats.currcycle.assistrequests += g->gcstepsize;
else
g->gcstats.currcycle.explicitrequests += g->gcstepsize;
int lim = (g->gcstepsize / 100) * g->gcstepmul; /* how much to work */
LUAU_ASSERT(g->totalbytes >= g->GCthreshold);
size_t debt = g->totalbytes - g->GCthreshold;
@ -881,24 +890,23 @@ void luaC_step(lua_State* L, bool assist)
// at the start of the new cycle
if (g->gcstate == GCSpause)
startGcCycleStats(g);
g->gcstats.starttimestamp = lua_clock();
#ifdef LUAI_GCMETRICS
if (g->gcstate == GCSpause)
startGcCycleMetrics(g);
double lasttimestamp = lua_clock();
#endif
int lastgcstate = g->gcstate;
double lasttimestamp = lua_clock();
size_t work = gcstep(L, lim);
(void)work;
if (assist)
g->gcstats.currcycle.assistwork += work;
else
g->gcstats.currcycle.explicitwork += work;
recordGcStateTime(g, lastgcstate, lua_clock() - lasttimestamp, assist);
if (lastgcstate == GCSpropagate)
g->gcstats.currcycle.markrequests += g->gcstepsize;
else if (lastgcstate == GCSsweep)
g->gcstats.currcycle.sweeprequests += g->gcstepsize;
#ifdef LUAI_GCMETRICS
recordGcStateStep(g, lastgcstate, lua_clock() - lasttimestamp, assist, work);
#endif
// at the end of the last cycle
if (g->gcstate == GCSpause)
@ -909,13 +917,13 @@ void luaC_step(lua_State* L, bool assist)
g->GCthreshold = heaptrigger;
finishGcCycleStats(g);
g->gcstats.heapgoalsizebytes = heapgoal;
g->gcstats.endtimestamp = lua_clock();
g->gcstats.endtotalsizebytes = g->totalbytes;
if (FFlag::LuauGcAdditionalStats)
g->gcstats.currcycle.starttotalsizebytes = g->totalbytes;
g->gcstats.currcycle.heapgoalsizebytes = heapgoal;
g->gcstats.currcycle.heaptriggersizebytes = heaptrigger;
#ifdef LUAI_GCMETRICS
finishGcCycleMetrics(g);
#endif
}
else
{
@ -933,8 +941,10 @@ void luaC_fullgc(lua_State* L)
{
global_State* g = L->global;
#ifdef LUAI_GCMETRICS
if (g->gcstate == GCSpause)
startGcCycleStats(g);
startGcCycleMetrics(g);
#endif
if (g->gcstate <= GCSatomic)
{
@ -954,11 +964,12 @@ void luaC_fullgc(lua_State* L)
gcstep(L, SIZE_MAX);
}
finishGcCycleStats(g);
#ifdef LUAI_GCMETRICS
finishGcCycleMetrics(g);
startGcCycleMetrics(g);
#endif
/* run a full collection cycle */
startGcCycleStats(g);
markroot(L);
while (g->gcstate != GCSpause)
{
@ -980,10 +991,11 @@ void luaC_fullgc(lua_State* L)
if (g->GCthreshold < g->totalbytes)
g->GCthreshold = g->totalbytes;
finishGcCycleStats(g);
g->gcstats.heapgoalsizebytes = heapgoalsizebytes;
g->gcstats.currcycle.heapgoalsizebytes = heapgoalsizebytes;
g->gcstats.currcycle.heaptriggersizebytes = g->GCthreshold;
#ifdef LUAI_GCMETRICS
finishGcCycleMetrics(g);
#endif
}
void luaC_barrierupval(lua_State* L, GCObject* v)
@ -1075,21 +1087,21 @@ int64_t luaC_allocationrate(lua_State* L)
if (g->gcstate <= GCSatomic)
{
double duration = lua_clock() - g->gcstats.lastcycle.endtimestamp;
double duration = lua_clock() - g->gcstats.endtimestamp;
if (duration < durationthreshold)
return -1;
return int64_t((g->totalbytes - g->gcstats.lastcycle.endtotalsizebytes) / duration);
return int64_t((g->totalbytes - g->gcstats.endtotalsizebytes) / duration);
}
// totalbytes is unstable during the sweep, use the rate measured at the end of mark phase
double duration = g->gcstats.currcycle.atomicstarttimestamp - g->gcstats.lastcycle.endtimestamp;
double duration = g->gcstats.atomicstarttimestamp - g->gcstats.endtimestamp;
if (duration < durationthreshold)
return -1;
return int64_t((g->gcstats.currcycle.atomicstarttotalsizebytes - g->gcstats.lastcycle.endtotalsizebytes) / duration);
return int64_t((g->gcstats.atomicstarttotalsizebytes - g->gcstats.endtotalsizebytes) / duration);
}
void luaC_wakethread(lua_State* L)

View File

@ -82,7 +82,7 @@
#define luaC_checkGC(L) \
{ \
condhardstacktests(luaD_reallocstack(L, L->stacksize - (FFlag::LuauReduceStackReallocs ? EXTRA_STACK : 1 + EXTRA_STACK))); \
condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK)); \
if (L->global->totalbytes >= L->global->GCthreshold) \
{ \
condhardmemtests(luaC_validate(L), 1); \

View File

@ -10,12 +10,12 @@ union GCObject;
#define luaM_newgco(L, t, size, memcat) cast_to(t*, luaM_newgco_(L, 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))
#define luaM_arraysize_(L, n, e) ((cast_to(size_t, (n)) <= SIZE_MAX / (e)) ? (n) * (e) : (luaM_toobig(L), SIZE_MAX))
#define luaM_newarray(L, n, t, memcat) cast_to(t*, luaM_new_(L, luaM_arraysize_(n, sizeof(t)), memcat))
#define luaM_newarray(L, n, t, memcat) cast_to(t*, luaM_new_(L, luaM_arraysize_(L, n, sizeof(t)), memcat))
#define luaM_freearray(L, b, n, t, memcat) luaM_free_(L, (b), (n) * sizeof(t), memcat)
#define luaM_reallocarray(L, v, oldn, n, t, memcat) \
((v) = cast_to(t*, luaM_realloc_(L, v, (oldn) * sizeof(t), luaM_arraysize_(n, sizeof(t)), memcat)))
((v) = cast_to(t*, luaM_realloc_(L, v, (oldn) * sizeof(t), luaM_arraysize_(L, n, sizeof(t)), memcat)))
LUAI_FUNC void* luaM_new_(lua_State* L, size_t nsize, uint8_t memcat);
LUAI_FUNC GCObject* luaM_newgco_(lua_State* L, size_t nsize, uint8_t memcat);

View File

@ -10,8 +10,6 @@
#include "ldo.h"
#include "ldebug.h"
LUAU_FASTFLAGVARIABLE(LuauReduceStackReallocs, false)
/*
** Main thread combines a thread state and the global state
*/
@ -35,7 +33,7 @@ static void stack_init(lua_State* L1, lua_State* L)
for (int i = 0; i < BASIC_STACK_SIZE + EXTRA_STACK; i++)
setnilvalue(stack + i); /* erase new stack */
L1->top = stack;
L1->stack_last = stack + (L1->stacksize - (FFlag::LuauReduceStackReallocs ? EXTRA_STACK : 1 + EXTRA_STACK));
L1->stack_last = stack + (L1->stacksize - EXTRA_STACK);
/* initialize first ci */
L1->ci->func = L1->top;
setnilvalue(L1->top++); /* `function' entry for this `ci' */
@ -141,30 +139,16 @@ void lua_resetthread(lua_State* L)
ci->top = ci->base + LUA_MINSTACK;
setnilvalue(ci->func);
L->ci = ci;
if (FFlag::LuauReduceStackReallocs)
{
if (L->size_ci != BASIC_CI_SIZE)
luaD_reallocCI(L, BASIC_CI_SIZE);
}
else
{
if (L->size_ci != BASIC_CI_SIZE)
luaD_reallocCI(L, BASIC_CI_SIZE);
}
/* clear thread state */
L->status = LUA_OK;
L->base = L->ci->base;
L->top = L->ci->base;
L->nCcalls = L->baseCcalls = 0;
/* clear thread stack */
if (FFlag::LuauReduceStackReallocs)
{
if (L->stacksize != BASIC_STACK_SIZE + EXTRA_STACK)
luaD_reallocstack(L, BASIC_STACK_SIZE);
}
else
{
if (L->stacksize != BASIC_STACK_SIZE + EXTRA_STACK)
luaD_reallocstack(L, BASIC_STACK_SIZE);
}
for (int i = 0; i < L->stacksize; i++)
setnilvalue(L->stack + i);
}
@ -234,6 +218,10 @@ lua_State* lua_newstate(lua_Alloc f, void* ud)
g->cb = lua_Callbacks();
g->gcstats = GCStats();
#ifdef LUAI_GCMETRICS
g->gcmetrics = GCMetrics();
#endif
if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0)
{
/* memory allocation error: free partial state */

View File

@ -75,10 +75,26 @@ typedef struct CallInfo
#define f_isLua(ci) (!ci_func(ci)->isC)
#define isLua(ci) (ttisfunction((ci)->func) && f_isLua(ci))
struct GCCycleStats
struct GCStats
{
// data for proportional-integral controller of heap trigger value
int32_t triggerterms[32] = {0};
uint32_t triggertermpos = 0;
int32_t triggerintegral = 0;
size_t atomicstarttotalsizebytes = 0;
size_t endtotalsizebytes = 0;
size_t heapgoalsizebytes = 0;
double starttimestamp = 0;
double atomicstarttimestamp = 0;
double endtimestamp = 0;
};
#ifdef LUAI_GCMETRICS
struct GCCycleMetrics
{
size_t starttotalsizebytes = 0;
size_t heapgoalsizebytes = 0;
size_t heaptriggersizebytes = 0;
double pausetime = 0.0; // time from end of the last cycle to the start of a new one
@ -120,16 +136,7 @@ struct GCCycleStats
size_t endtotalsizebytes = 0;
};
// data for proportional-integral controller of heap trigger value
struct GCHeapTriggerStats
{
static const unsigned termcount = 32;
int32_t terms[termcount] = {0};
uint32_t termpos = 0;
int32_t integral = 0;
};
struct GCStats
struct GCMetrics
{
double stepexplicittimeacc = 0.0;
double stepassisttimeacc = 0.0;
@ -137,14 +144,10 @@ struct GCStats
// when cycle is completed, last cycle values are updated
uint64_t completedcycles = 0;
GCCycleStats lastcycle;
GCCycleStats currcycle;
// only step count and their time is accumulated
GCCycleStats cyclestatsacc;
GCHeapTriggerStats triggerstats;
GCCycleMetrics lastcycle;
GCCycleMetrics currcycle;
};
#endif
/*
** `global state', shared by all threads of this state
@ -206,6 +209,9 @@ typedef struct global_State
GCStats gcstats;
#ifdef LUAI_GCMETRICS
GCMetrics gcmetrics;
#endif
} global_State;
// clang-format on

View File

@ -2,17 +2,26 @@
// This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details
/*
** Implementation of tables (aka arrays, objects, or hash tables).
** Tables keep its elements in two parts: an array part and a hash part.
** Non-negative integer keys are all candidates to be kept in the array
** part. The actual size of the array is the largest `n' such that at
** least half the slots between 0 and n are in use.
** Hash uses a mix of chained scatter table with Brent's variation.
** A main invariant of these tables is that, if an element is not
** in its main position (i.e. the `original' position that its hash gives
** to it), then the colliding element is in its own main position.
** Hence even when the load factor reaches 100%, performance remains good.
*/
* Implementation of tables (aka arrays, objects, or hash tables).
*
* Tables keep the elements in two parts: an array part and a hash part.
* Integer keys >=1 are all candidates to be kept in the array part. The actual size of the array is the
* largest n such that at least half the slots between 0 and n are in use.
* Hash uses a mix of chained scatter table with Brent's variation.
*
* A main invariant of these tables is that, if an element is not in its main position (i.e. the original
* position that its hash gives to it), then the colliding element is in its own main position.
* Hence even when the load factor reaches 100%, performance remains good.
*
* Table keys can be arbitrary values unless they contain NaN. Keys are hashed and compared using raw equality,
* so even if the key is a userdata with an overridden __eq, it's not used during hash lookups.
*
* Each table has a "boundary", defined as the index k where t[k] ~= nil and t[k+1] == nil. The boundary can be
* computed using a binary search and can be adjusted when the table is modified; crucially, Luau enforces an
* invariant where the boundary must be in the array part - this enforces a consistent iteration order through the
* prefix of the table when using pairs(), and allows to implement algorithms that access elements in 1..#t range
* more efficiently.
*/
#include "ltable.h"
@ -25,6 +34,7 @@
#include <string.h>
LUAU_FASTFLAGVARIABLE(LuauTableRehashRework, false)
LUAU_FASTFLAGVARIABLE(LuauTableNewBoundary, false)
// max size of both array and hash part is 2^MAXBITS
#define MAXBITS 26
@ -460,7 +470,20 @@ static void rehash(lua_State* L, Table* t, const TValue* ek)
totaluse++;
/* compute new size for array part */
int na = computesizes(nums, &nasize);
/* enforce the boundary invariant; for performance, only do hash lookups if we must */
if (FFlag::LuauTableNewBoundary)
{
bool tbound = t->node != dummynode || nasize < t->sizearray;
int ekindex = ttisnumber(ek) ? arrayindex(nvalue(ek)) : -1;
/* move the array size up until the boundary is guaranteed to be inside the array part */
while (nasize + 1 == ekindex || (tbound && !ttisnil(luaH_getnum(t, nasize + 1))))
{
nasize++;
na++;
}
}
/* resize the table to new computed sizes */
LUAU_ASSERT(na <= totaluse);
resize(L, t, nasize, totaluse - na);
}
@ -520,14 +543,22 @@ static LuaNode* getfreepos(Table* t)
*/
static TValue* newkey(lua_State* L, Table* t, const TValue* key)
{
/* enforce boundary invariant */
if (FFlag::LuauTableNewBoundary && ttisnumber(key) && nvalue(key) == t->sizearray + 1)
{
rehash(L, t, key); /* grow table */
// after rehash, numeric keys might be located in the new array part, but won't be found in the node part
return arrayornewkey(L, t, key);
}
LuaNode* mp = mainposition(t, key);
if (!ttisnil(gval(mp)) || mp == dummynode)
{
LuaNode* othern;
LuaNode* n = getfreepos(t); /* get a free place */
if (n == NULL)
{ /* cannot find a free place? */
rehash(L, t, key); /* grow table */
{ /* cannot find a free place? */
rehash(L, t, key); /* grow table */
if (!FFlag::LuauTableRehashRework)
{
@ -542,7 +573,7 @@ static TValue* newkey(lua_State* L, Table* t, const TValue* key)
LUAU_ASSERT(n != dummynode);
TValue mk;
getnodekey(L, &mk, mp);
othern = mainposition(t, &mk);
LuaNode* othern = mainposition(t, &mk);
if (othern != mp)
{ /* is colliding node out of its main position? */
/* yes; move colliding node into free position */
@ -704,6 +735,7 @@ TValue* luaH_setstr(lua_State* L, Table* t, TString* key)
static LUAU_NOINLINE int unbound_search(Table* t, unsigned int j)
{
LUAU_ASSERT(!FFlag::LuauTableNewBoundary);
unsigned int i = j; /* i is zero or a present index */
j++;
/* find `i' and `j' such that i is present and j is not */
@ -788,6 +820,12 @@ int luaH_getn(Table* t)
maybesetaboundary(t, boundary);
return boundary;
}
else if (FFlag::LuauTableNewBoundary)
{
/* validate boundary invariant */
LUAU_ASSERT(t->node == dummynode || ttisnil(luaH_getnum(t, j + 1)));
return j;
}
/* else must find a boundary in hash part */
else if (t->node == dummynode) /* hash part is empty? */
return j; /* that is easy... */

View File

@ -10,7 +10,9 @@
#include "ldebug.h"
#include "lvm.h"
LUAU_FASTFLAGVARIABLE(LuauTableClone, false)
LUAU_DYNAMIC_FASTFLAGVARIABLE(LuauTableMoveTelemetry2, false)
void (*lua_table_move_telemetry)(lua_State* L, int f, int e, int t, int nf, int nt);
static int foreachi(lua_State* L)
{
@ -197,6 +199,29 @@ static int tmove(lua_State* L)
int tt = !lua_isnoneornil(L, 5) ? 5 : 1; /* destination table */
luaL_checktype(L, tt, LUA_TTABLE);
void (*telemetrycb)(lua_State* L, int f, int e, int t, int nf, int nt) = lua_table_move_telemetry;
if (DFFlag::LuauTableMoveTelemetry2 && telemetrycb)
{
int nf = lua_objlen(L, 1);
int nt = lua_objlen(L, tt);
bool report = false;
// source index range must be in bounds in source table unless the table is empty (permits 1..#t moves)
if (!(f == 1 || (f >= 1 && f <= nf)))
report = true;
if (!(e == nf || (e >= 1 && e <= nf)))
report = true;
// destination index must be in bounds in dest table or be exactly at the first empty element (permits concats)
if (!(t == nt + 1 || (t >= 1 && t <= nt)))
report = true;
if (report)
telemetrycb(L, f, e, t, nf, nt);
}
if (e >= f)
{ /* otherwise, nothing to move */
luaL_argcheck(L, f > 0 || e < INT_MAX + f, 3, "too many elements to move");
@ -512,9 +537,6 @@ static int tisfrozen(lua_State* L)
static int tclone(lua_State* L)
{
if (!FFlag::LuauTableClone)
luaG_runerror(L, "table.clone is not available");
luaL_checktype(L, 1, LUA_TTABLE);
luaL_argcheck(L, !luaL_getmetafield(L, 1, "__metatable"), 1, "table has a protected metatable");

View File

@ -16,6 +16,8 @@
#include <string.h>
LUAU_FASTFLAG(LuauTableNewBoundary)
// Disable c99-designator to avoid the warning in CGOTO dispatch table
#ifdef __clang__
#if __has_warning("-Wc99-designator")
@ -2266,9 +2268,9 @@ static void luau_execute(lua_State* L)
VM_NEXT();
}
}
else if (h->lsizenode == 0 && ttisnil(gval(h->node)))
else if (FFlag::LuauTableNewBoundary || (h->lsizenode == 0 && ttisnil(gval(h->node))))
{
// hash part is empty: fallthrough to exit
// fallthrough to exit
VM_NEXT();
}
else

View File

@ -13,8 +13,6 @@
#include <string.h>
LUAU_FASTFLAGVARIABLE(LuauBytecodeV2Force, false)
// TODO: RAII deallocation doesn't work for longjmp builds if a memory error happens
template<typename T>
struct TempBuffer
@ -156,12 +154,11 @@ int luau_load(lua_State* L, const char* chunkname, const char* data, size_t size
return 1;
}
if (FFlag::LuauBytecodeV2Force ? (version != LBC_VERSION_FUTURE) : (version != LBC_VERSION && version != LBC_VERSION_FUTURE))
if (version != LBC_VERSION)
{
char chunkid[LUA_IDSIZE];
luaO_chunkid(chunkid, chunkname, LUA_IDSIZE);
lua_pushfstring(L, "%s: bytecode version mismatch (expected %d, got %d)", chunkid,
FFlag::LuauBytecodeV2Force ? LBC_VERSION_FUTURE : LBC_VERSION, version);
lua_pushfstring(L, "%s: bytecode version mismatch (expected %d, got %d)", chunkid, LBC_VERSION, version);
return 1;
}
@ -292,11 +289,7 @@ int luau_load(lua_State* L, const char* chunkname, const char* data, size_t size
p->p[j] = protos[fid];
}
if (FFlag::LuauBytecodeV2Force || version == LBC_VERSION_FUTURE)
p->linedefined = readVarInt(data, size, offset);
else
p->linedefined = -1;
p->linedefined = readVarInt(data, size, offset);
p->debugname = readString(strings, data, size, offset);
uint8_t lineinfo = read<uint8_t>(data, size, offset);

View File

@ -111,7 +111,6 @@ impl Build {
.clone()
.include(&vm_include_dir)
.define("LUA_API", "extern \"C\"")
// Works 9 times slower, see https://github.com/Roblox/luau/issues/425
// .define("LUA_USE_LONGJMP", "1")
.add_files_by_ext(&vm_source_dir, "cpp")
.out_dir(&lib_dir)