Add arrays to Lua (#222)

You can now have O(1) length and append.
This commit is contained in:
Paul Kulchenko 2021-08-06 04:55:01 -07:00 committed by GitHub
parent b142ea7176
commit 55a15c204e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 557 additions and 20 deletions

39
third_party/lua/lvm.c vendored
View file

@ -17,6 +17,7 @@
#include "third_party/lua/lstate.h"
#include "third_party/lua/lstring.h"
#include "third_party/lua/ltable.h"
#include "third_party/lua/larray.h"
#include "third_party/lua/ltm.h"
#include "third_party/lua/lua.h"
#include "third_party/lua/lvm.h"
@ -283,6 +284,11 @@ void luaV_finishget (lua_State *L, const TValue *t, TValue *key, StkId val,
for (loop = 0; loop < MAXTAGLOOP; loop++) {
if (slot == NULL) { /* 't' is not a table? */
lua_assert(!ttistable(t));
if (ttisarray(t)) {
/* get array value */
setobj2s(L, val, luaA_get(L, avalue(t), key));
return;
}
tm = luaT_gettmbyobj(L, t, TM_INDEX);
if (l_unlikely(notm(tm)))
luaG_typeerror(L, t, "index"); /* no metamethod */
@ -331,12 +337,17 @@ void luaV_finishset (lua_State *L, const TValue *t, TValue *key,
if (tm == NULL) { /* no metamethod? */
luaH_finishset(L, h, key, slot, val); /* set new value */
invalidateTMcache(h);
/* enlarge array length when necessary */
/* this should be quite fast as fields of h and key have already been loaded to CPU cache at this point */
h->sizeused += (val_(key).i > h->sizeused) & ttisinteger(key) & 1;
luaC_barrierback(L, obj2gco(h), val);
return;
}
/* else will try the metamethod */
}
else { /* not a table; check metamethod */
if(ttisarray(t))
luaG_typeerror(L, t, "set non-integer index of");
tm = luaT_gettmbyobj(L, t, TM_NEWINDEX);
if (l_unlikely(notm(tm)))
luaG_typeerror(L, t, "index");
@ -682,6 +693,11 @@ void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) {
setivalue(s2v(ra), luaH_getn(h)); /* else primitive len */
return;
}
case LUA_TARRAY: {
Array *a = avalue(rb);
setivalue(s2v(ra), a->alimit);
return;
}
case LUA_VSHRSTR: {
setivalue(s2v(ra), tsvalue(rb)->shrlen);
return;
@ -1241,7 +1257,10 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
const TValue *slot;
TValue *rb = vRB(i);
int c = GETARG_C(i);
if (luaV_fastgeti(L, rb, c, slot)) {
if(ttisarray(rb)) {
setobj2s(L, ra, luaA_getint(L, avalue(rb), c));
}
else if (luaV_fastgeti(L, rb, c, slot)) {
setobj2s(L, ra, slot);
}
else {
@ -1294,7 +1313,10 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
const TValue *slot;
int c = GETARG_B(i);
TValue *rc = RKC(i);
if (luaV_fastgeti(L, s2v(ra), c, slot)) {
if(ttisarray(s2v(ra))) {
luaA_setint(L, avalue(s2v(ra)), c, rc);
}
else if (luaV_fastgeti(L, s2v(ra), c, slot)) {
luaV_finishfastset(L, s2v(ra), slot, rc);
}
else {
@ -1319,6 +1341,8 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
vmcase(OP_NEWTABLE) {
int b = GETARG_B(i); /* log2(hash size) + 1 */
int c = GETARG_C(i); /* array size */
/* decode arrayness */
int array = (b == 255);
Table *t;
if (b > 0)
b = 1 << (b - 1); /* size is 2^(b - 1) */
@ -1328,9 +1352,16 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
pc++; /* skip extra argument */
L->top = ra + 1; /* correct top in case of emergency GC */
t = luaH_new(L); /* memory allocation */
t->truearray = array;
t->sizeused = c;
sethvalue2s(L, ra, t);
if (b != 0 || c != 0)
luaH_resize(L, t, c, b); /* idem */
if (b != 0 || c != 0) {
if (array) {
luaH_resizearray(L, t, c); /* idem */
} else {
luaH_resize(L, t, c, b); /* idem */
}
}
checkGC(L, ra + 1);
vmbreak;
}