Skip to content
Permalink
Browse files
table constants
  • Loading branch information
cloudwu committed Apr 12, 2016
1 parent d86205e commit a940a40
Show file tree
Hide file tree
Showing 9 changed files with 161 additions and 10 deletions.
@@ -336,6 +336,53 @@ static int addk (FuncState *fs, TValue *key, TValue *v) {
return k;
}

void luaK_tableK (FuncState *fs, Table *t, int pc) {
lua_State *L = fs->ls->L;
Proto *f = fs->f;
int array = 1;
int i,j,k,oldsize;
for (i = pc+1; i< fs->pc; i++) {
OpCode o = GET_OPCODE(f->code[i]);
switch(o) {
case OP_LOADK:
luaH_setint(L, t, array++, &f->k[GETARG_Bx(f->code[i])]);
break;
case OP_LOADKX:
/* should be OP_EXTRAARG next */
++i;
lua_assert(i< fs->pc && GET_OPCODE(f->code[i]) == OP_EXTRAARG);
luaH_setint(L, t, array++, &f->k[GETARG_Ax(f->code[i])]);
break;
case OP_LOADNIL:
for (j = 0; j <= GETARG_B(f->code[i]); j++) {
TValue nil;
setnilvalue(&nil);
luaH_setint(L, t, array++, &nil);
}
break;
case OP_SETTABLE:
setobj2t(L, luaH_set(L, t, &f->k[INDEXK(GETARG_B(f->code[i]))]), &f->k[INDEXK(GETARG_B(f->code[i]))]);
break;
default:
lua_assert(o == OP_SETLIST);
break;
}
}
k = oldsize = f->sizek;
luaM_growvector(L, f->k, k, f->sizek, TValue, MAXARG_Ax, "table constants");
while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]);
k = fs->nk++;
sethvalue(L, &f->k[k], t);
fs->pc = pc + 1;
if (k <= MAXARG_Bx) {
SET_OPCODE(fs->f->code[pc], OP_NEWTABLEK);
SETARG_Bx(fs->f->code[pc], k);
} else {
SET_OPCODE(fs->f->code[pc], OP_NEWTABLEKX);
codeextraarg(fs, k);
}
luaC_objbarrier(L, f, t);
}

int luaK_stringK (FuncState *fs, TString *s) {
TValue o;
@@ -55,6 +55,7 @@ LUAI_FUNC void luaK_fixline (FuncState *fs, int line);
LUAI_FUNC void luaK_nil (FuncState *fs, int from, int n);
LUAI_FUNC void luaK_reserveregs (FuncState *fs, int n);
LUAI_FUNC void luaK_checkstack (FuncState *fs, int n);
LUAI_FUNC void luaK_tableK (FuncState *fs, Table *t, int pc);
LUAI_FUNC int luaK_stringK (FuncState *fs, TString *s);
LUAI_FUNC int luaK_intK (FuncState *fs, lua_Integer n);
LUAI_FUNC void luaK_dischargevars (FuncState *fs, expdesc *e);
@@ -452,6 +452,7 @@ static lu_mem traversetable (global_State *g, Table *h) {
const char *weakkey, *weakvalue;
const TValue *mode = gfasttm(g, h->metatable, TM_MODE);
markobjectN(g, h->metatable);
markobjectN(g, h->constant);
if (mode && ttisstring(mode) && /* is there a weak mode? */
((weakkey = strchr(svalue(mode), 'k')),
(weakvalue = strchr(svalue(mode), 'v')),
@@ -504,6 +504,7 @@ typedef struct Table {
Node *lastfree; /* any free position is before this position */
struct Table *metatable;
GCObject *gclist;
struct Table * constant;
} Table;


@@ -30,6 +30,8 @@ LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1] = {
"SETUPVAL",
"SETTABLE",
"NEWTABLE",
"NEWTABLEK",
"NEWTABLEKX",
"SELF",
"ADD",
"SUB",
@@ -85,6 +87,8 @@ LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = {
,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_SETUPVAL */
,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABLE */
,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_NEWTABLE */
,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_NEWTABLEK */
,opmode(0, 1, OpArgN, OpArgN, iABx) /* OP_NEWTABLEKX */
,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_SELF */
,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_ADD */
,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_SUB */
@@ -181,6 +181,8 @@ OP_SETUPVAL,/* A B UpValue[B] := R(A) */
OP_SETTABLE,/* A B C R(A)[RK(B)] := RK(C) */

OP_NEWTABLE,/* A B C R(A) := {} (size = B,C) */
OP_NEWTABLEK,/* A Bx R(A) := Kst(Bx) */
OP_NEWTABLEKX,/* A R(A) := Kst(extra arg) */

OP_SELF,/* A B C R(A+1) := R(B); R(A) := R(B)[RK(C)] */

@@ -714,6 +714,28 @@ static void field (LexState *ls, struct ConsControl *cc) {
}
}

static int isconsttable(FuncState *fs, int pc) {
int i;
if (pc == fs->pc)
return 0; /* empty table */
for (i=pc; i < fs->pc; i++) {
OpCode o=GET_OPCODE(fs->f->code[i]);
if (o != OP_LOADK &&
o != OP_SETTABLE &&
o != OP_LOADKX &&
o != OP_EXTRAARG &&
o != OP_LOADNIL &&
o != OP_LOADBOOL &&
o != OP_SETLIST)
return 0;
if (o == OP_SETTABLE) {
if (!ISK(GETARG_B(fs->f->code[i])) ||
!ISK(GETARG_C(fs->f->code[i])))
return 0;
}
}
return 1; /* all field is const */
}

static void constructor (LexState *ls, expdesc *t) {
/* constructor -> '{' [ field { sep field } [sep] ] '}'
@@ -736,8 +758,15 @@ static void constructor (LexState *ls, expdesc *t) {
} while (testnext(ls, ',') || testnext(ls, ';'));
check_match(ls, '}', '{', line);
lastlistfield(fs, &cc);
SETARG_B(fs->f->code[pc], luaO_int2fb(cc.na)); /* set initial array size */
SETARG_C(fs->f->code[pc], luaO_int2fb(cc.nh)); /* set initial table size */
if (isconsttable(fs, pc+1)) {
lua_State *L = ls->L;
Table *t = luaH_new(L);
luaH_resize(L, t, cc.na, cc.nh);
luaK_tableK(fs, t, pc);
} else {
SETARG_B(fs->f->code[pc], luaO_int2fb(cc.na)); /* set initial array size */
SETARG_C(fs->f->code[pc], luaO_int2fb(cc.nh)); /* set initial table size */
}
}

/* }====================================================================== */
@@ -25,6 +25,7 @@

#include <math.h>
#include <limits.h>
#include <string.h>

#include "lua.h"

@@ -186,7 +187,10 @@ static unsigned int findindex (lua_State *L, Table *t, StkId key) {


int luaH_next (lua_State *L, Table *t, StkId key) {
unsigned int i = findindex(L, t, key); /* find original element */
unsigned int i;
if (t->constant)
t = t->constant;
i = findindex(L, t, key); /* find original element */
for (; i < t->sizearray; i++) { /* try first array part */
if (!ttisnil(&t->array[i])) { /* a non-nil value? */
setivalue(key, i + 1);
@@ -331,14 +335,32 @@ static void setnodevector (lua_State *L, Table *t, unsigned int size) {
t->lastfree = gnode(t, size); /* all positions are free */
}

static void makemutable (lua_State *L, Table *t) {
Table *from = t->constant;
int sizearray = from->sizearray;
int sizenode = twoto(from->lsizenode);
setarrayvector(L, t, sizearray);
memcpy(t->array, from->array, sizearray * sizeof(TValue));
setnodevector(L, t, sizenode);
memcpy(t->node, from->node, sizenode * sizeof(Node));
t->lastfree = t->node + (from->lastfree - from->node);
t->constant = NULL;
}

void luaH_resize (lua_State *L, Table *t, unsigned int nasize,
unsigned int nhsize) {
unsigned int i;
int j;
unsigned int oldasize = t->sizearray;
int oldhsize = t->lsizenode;
Node *nold = t->node; /* save old hash ... */
unsigned int oldasize;
int oldhsize;
Node *nold;

if (t->constant)
makemutable(L, t);
oldasize = t->sizearray;
oldhsize = t->lsizenode;

nold = t->node; /* save old hash ... */
if (nasize > oldasize) /* array part must grow? */
setarrayvector(L, t, nasize);
/* create new hash part with appropriate size */
@@ -368,7 +390,10 @@ void luaH_resize (lua_State *L, Table *t, unsigned int nasize,


void luaH_resizearray (lua_State *L, Table *t, unsigned int nasize) {
int nsize = isdummy(t->node) ? 0 : sizenode(t);
int nsize;
if (t->constant)
makemutable(L, t);
nsize = isdummy(t->node) ? 0 : sizenode(t);
luaH_resize(L, t, nasize, nsize);
}

@@ -408,6 +433,7 @@ Table *luaH_new (lua_State *L) {
t->flags = cast_byte(~0);
t->array = NULL;
t->sizearray = 0;
t->constant = NULL;
setnodevector(L, t, 0);
return t;
}
@@ -442,6 +468,8 @@ static Node *getfreepos (Table *t) {
TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) {
Node *mp;
TValue aux;
if (t->constant)
makemutable(L, t);
if (ttisnil(key)) luaG_runerror(L, "table index is nil");
else if (ttisfloat(key)) {
lua_Integer k;
@@ -495,6 +523,8 @@ TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) {
** search function for integers
*/
const TValue *luaH_getint (Table *t, lua_Integer key) {
if (t->constant)
t = t->constant;
/* (1 <= key && key <= t->sizearray) */
if (l_castS2U(key) - 1 < t->sizearray)
return &t->array[key - 1];
@@ -518,7 +548,10 @@ const TValue *luaH_getint (Table *t, lua_Integer key) {
** search function for short strings
*/
const TValue *luaH_getshortstr (Table *t, TString *key) {
Node *n = hashstr(t, key);
Node *n;
if (t->constant)
t = t->constant;
n = hashstr(t, key);
lua_assert(key->tt == LUA_TSHRSTR);
for (;;) { /* check whether 'key' is somewhere in the chain */
const TValue *k = gkey(n);
@@ -558,6 +591,8 @@ const TValue *luaH_getstr (Table *t, TString *key) {
return luaH_getshortstr(t, key);
else { /* for long strings, use generic case */
TValue ko;
if (t->constant)
t = t->constant;
setsvalue(cast(lua_State *, NULL), &ko, key);
return getgeneric(t, &ko);
}
@@ -579,6 +614,8 @@ const TValue *luaH_get (Table *t, const TValue *key) {
/* else... */
} /* FALLTHROUGH */
default:
if (t->constant)
t = t->constant;
return getgeneric(t, key);
}
}
@@ -589,6 +626,8 @@ const TValue *luaH_get (Table *t, const TValue *key) {
** barrier and invalidate the TM cache.
*/
TValue *luaH_set (lua_State *L, Table *t, const TValue *key) {
if (t->constant)
makemutable(L, t);
const TValue *p = luaH_get(t, key);
if (p != luaO_nilobject)
return cast(TValue *, p);
@@ -597,8 +636,11 @@ TValue *luaH_set (lua_State *L, Table *t, const TValue *key) {


void luaH_setint (lua_State *L, Table *t, lua_Integer key, TValue *value) {
const TValue *p = luaH_getint(t, key);
const TValue *p;
TValue *cell;
if (t->constant)
makemutable(L, t);
p = luaH_getint(t, key);
if (p != luaO_nilobject)
cell = cast(TValue *, p);
else {
@@ -639,7 +681,10 @@ static int unbound_search (Table *t, unsigned int j) {
** such that t[i] is non-nil and t[i+1] is nil (and 0 if t[1] is nil).
*/
int luaH_getn (Table *t) {
unsigned int j = t->sizearray;
unsigned int j;
if (t->constant)
t = t->constant;
j = t->sizearray;
if (j > 0 && ttisnil(&t->array[j - 1])) {
/* there is a boundary in the array part: (binary) search for it */
unsigned int i = 0;
@@ -661,6 +706,8 @@ int luaH_getn (Table *t) {
#if defined(LUA_DEBUG)

Node *luaH_mainposition (const Table *t, const TValue *key) {
if (t->constant)
t = t->constant;
return mainposition(t, key);
}

@@ -855,6 +855,25 @@ void luaV_execute (lua_State *L) {
checkGC(L, ra + 1);
vmbreak;
}
vmcase(OP_NEWTABLEK) {
TValue *rb = k + GETARG_Bx(i);
Table *t = luaH_new(L);
t->constant = hvalue(rb);
sethvalue(L, ra, t);
checkGC(L, ra + 1);
vmbreak;
}
vmcase(OP_NEWTABLEKX) {
TValue *rb;
Table *t;
lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_EXTRAARG);
rb = k + GETARG_Ax(*ci->u.l.savedpc++);
t = luaH_new(L);
t->constant = hvalue(rb);
sethvalue(L, ra, t);
checkGC(L, ra + 1);
vmbreak;
}
vmcase(OP_SELF) {
const TValue *aux;
StkId rb = RB(i);

0 comments on commit a940a40

Please sign in to comment.