Skip to content

Commit

Permalink
Support loading of Lua 5.4 bytecode, bump Pluto bytecode version to m…
Browse files Browse the repository at this point in the history
…ark it as incompatible for older versions
  • Loading branch information
Sainan committed Mar 2, 2024
1 parent 46f9b35 commit 1a95fb1
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 32 deletions.
2 changes: 1 addition & 1 deletion src/lcode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1337,7 +1337,7 @@ void luaK_goifnil (FuncState *fs, expdesc *e) {
discharge2anyreg(fs, e);
freeexp(fs, e);
luaK_codeABCk(fs, OP_TESTSET, NO_REG, e->u.reg, NULL_COALESCE, 1);
fs->f->onPlutoOpUsed(0);
fs->f->lua_vm_compatible = false;
pc = luaK_jump(fs); /* jump if nil */
}
luaK_concat(fs, &e->t, pc); /* insert new jump in 't' list */
Expand Down
19 changes: 8 additions & 11 deletions src/ldump.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ typedef struct {
Table *h; /* table to track saved strings */
lua_Integer nstr; /* counter to number saved strings */
bool lua_vm_compatible;
lu_byte min_required_version;
} DumpState;


Expand Down Expand Up @@ -255,7 +254,7 @@ static void dumpHeader (DumpState *D) {
dumpByte(D, LUAC_FORMAT);
}
else {
dumpByte(D, D->min_required_version);
dumpByte(D, 1);
dumpByte(D, 'P');
}
dumpLiteral(D, LUAC_DATA);
Expand All @@ -267,15 +266,14 @@ static void dumpHeader (DumpState *D) {
}


static void check_vm_compatibility (const Proto *f, bool& lua_vm_compatible, lu_byte& min_required_version) {
if (!f->lua_vm_compatible) {
lua_vm_compatible = false;
if (f->min_required_version > min_required_version)
min_required_version = f->min_required_version;
}
static bool is_lua_vm_compatible (const Proto *f) {
if (!f->lua_vm_compatible)
return false;
for (int i = 0; i != f->sizep; ++i) {
check_vm_compatibility(f->p[i], lua_vm_compatible, min_required_version);
if (!is_lua_vm_compatible(f->p[i]))
return false;
}
return true;
}


Expand All @@ -295,8 +293,7 @@ int luaU_dump (lua_State *L, const Proto *f, lua_Writer w, void *data,
D.strip = strip;
D.status = 0;
D.nstr = 0;
D.lua_vm_compatible = true;
check_vm_compatibility(f, D.lua_vm_compatible, D.min_required_version);
D.lua_vm_compatible = is_lua_vm_compatible(f);
dumpHeader(&D);
dumpByte(&D, f->sizeupvalues);
dumpFunction(&D, f);
Expand Down
8 changes: 0 additions & 8 deletions src/lobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -596,14 +596,6 @@ typedef struct Proto {
TString *source; /* used for debug information */
GCObject *gclist;
bool lua_vm_compatible;
lu_byte min_required_version;

void onPlutoOpUsed(lu_byte min_required_version) noexcept {
if (lua_vm_compatible || min_required_version > this->min_required_version) {
lua_vm_compatible = false;
this->min_required_version = min_required_version;
}
}
} Proto;

/* }================================================================== */
Expand Down
2 changes: 1 addition & 1 deletion src/lparser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3438,7 +3438,7 @@ static void inexpr (LexState *ls, expdesc *v) {
luaK_dischargevars(ls->fs, &v2);
luaK_exp2nextreg(ls->fs, &v2);
luaK_codeABC(ls->fs, OP_IN, v->u.reg, v2.u.reg, 0);
ls->fs->f->onPlutoOpUsed(0);
ls->fs->f->lua_vm_compatible = false;
ls->fs->freereg = base + 1;
}

Expand Down
52 changes: 41 additions & 11 deletions src/lundump.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "lfunc.h"
#include "lmem.h"
#include "lobject.h"
#include "lopcodes.h" // GET_OPCODE
#include "lstring.h"
#include "ltable.h"
#include "lundump.h"
Expand All @@ -39,6 +40,7 @@ typedef struct {
size_t offset; /* current position relative to beginning of dump */
lua_Integer nstr; /* number of strings in the list */
lu_byte fixed; /* dump is fixed in memory */
bool lua54; /* we're loading bytecode generated by Lua 5.4 (Pluto 0.8.x and below) */
} LoadState;


Expand All @@ -62,6 +64,8 @@ static void loadBlock (LoadState *S, void *b, size_t size) {


static void loadAlign (LoadState *S, int align) {
if (S->lua54)
return;
int padding = align - (S->offset % align);
if (padding < align) { /* apd == align means no padding */
lua_Integer paddingContent;
Expand Down Expand Up @@ -148,17 +152,20 @@ static void loadString (LoadState *S, Proto *p, TString **sl) {
lua_assert(*sl == NULL); /* must be prefilled */
return;
}
else if (size == 1) { /* previously saved string? */
else if (size == 1 && !S->lua54) { /* previously saved string? */
int idx = loadInt(S); /* get its index */
TValue stv;
luaH_getint(S->h, idx, &stv);
*sl = ts = tsvalue(&stv);
luaC_objbarrier(L, p, ts);
return; /* do not save it again */
}
else if ((size -= 2) <= LUAI_MAXSHORTLEN) { /* short string? */
else if ((size -= (S->lua54 ? 1 : 2)) <= LUAI_MAXSHORTLEN) { /* short string? */
char buff[LUAI_MAXSHORTLEN + 1]; /* extra space for '\0' */
loadVector(S, buff, size + 1); /* load string into buffer */
if (S->lua54)
loadVector(S, buff, size); /* load string into buffer */
else
loadVector(S, buff, size + 1); /* load string into buffer */
*sl = ts = luaS_newlstr(L, buff, size); /* create string */
luaC_objbarrier(L, p, ts);
}
Expand All @@ -170,7 +177,9 @@ static void loadString (LoadState *S, Proto *p, TString **sl) {
else { /* create internal copy */
*sl = ts = luaS_createlngstrobj(L, size); /* create string */
luaC_objbarrier(L, p, ts);
loadVector(S, getlngstr(ts), size + 1); /* load directly in final place */
if (!S->lua54)
++size;
loadVector(S, getlngstr(ts), size); /* load directly in final place */
}
/* add string to list of saved strings */
S->nstr++;
Expand All @@ -191,6 +200,12 @@ static void loadCode (LoadState *S, Proto *f) {
f->code = luaM_newvectorchecked(S->L, n, Instruction);
f->sizecode = n;
loadVector(S, f->code, n);
if (S->lua54) {
for (int i = 0; i != n; ++i) {
if (GET_OPCODE(f->code[i]) == OP_FORPREP || GET_OPCODE(f->code[i]) == OP_TFORPREP || GET_OPCODE(f->code[i]) == OP_TFORCALL || GET_OPCODE(f->code[i]) == OP_TFORLOOP)
error(S, "incompatible Lua 5.4 instructions");
}
}
}
}

Expand Down Expand Up @@ -298,7 +313,14 @@ static void loadDebug (LoadState *S, Proto *f) {
else {
f->abslineinfo = luaM_newvectorchecked(S->L, n, AbsLineInfo);
f->sizeabslineinfo = n;
loadVector(S, f->abslineinfo, n);
if (S->lua54) {
for (i = 0; i < n; i++) {
f->abslineinfo[i].pc = loadInt(S);
f->abslineinfo[i].line = loadInt(S);
}
}
else
loadVector(S, f->abslineinfo, n);
}
}
n = loadInt(S);
Expand All @@ -320,6 +342,8 @@ static void loadDebug (LoadState *S, Proto *f) {


static void loadFunction (LoadState *S, Proto *f) {
if (S->lua54)
loadString(S, f, &f->source);
f->linedefined = loadInt(S);
f->lastlinedefined = loadInt(S);
f->numparams = loadByte(S);
Expand All @@ -331,7 +355,8 @@ static void loadFunction (LoadState *S, Proto *f) {
loadConstants(S, f);
loadUpvalues(S, f);
loadProtos(S, f);
loadString(S, f, &f->source);
if (!S->lua54)
loadString(S, f, &f->source);
loadDebug(S, f);
}

Expand All @@ -358,12 +383,16 @@ static void checkHeader (LoadState *S) {
checkliteral(S, &LUA_SIGNATURE[1], "not a binary chunk");
auto version = loadByte(S);
auto format = loadByte(S);
if (format == LUAC_FORMAT) {
if (version != LUAC_VERSION)
error(S, "version mismatch");
if (format == LUAC_FORMAT) { /* Lua bytecode? (or Lua-compatible Pluto bytecode) */
if (version == 0x54)
S->lua54 = true;
else if (version != LUAC_VERSION)
error(S, "version mismatch");
}
else if (format == 'P') {
if (version > 0)
else if (format == 'P') { /* Pluto bytecode? */
if (version == 0)
S->lua54 = true; /* This was generated by Pluto 0.8.x, which is based on Lua 5.4. */
else if (version != 1)
error(S, "version mismatch");
}
else
Expand Down Expand Up @@ -395,6 +424,7 @@ LClosure *luaU_undump (lua_State *L, ZIO *Z, const char *name, int fixed) {
S.Z = Z;
S.fixed = fixed;
S.offset = 1; /* fist byte was already read */
S.lua54 = false;
checkHeader(&S);
cl = luaF_newLclosure(L, loadByte(&S));
setclLvalue2s(L, L->top.p, cl);
Expand Down

0 comments on commit 1a95fb1

Please sign in to comment.