Full abstraction for representation of array values
This commit is contained in:
31
lapi.c
31
lapi.c
@@ -653,21 +653,17 @@ l_sinline int auxgetstr (lua_State *L, const TValue *t, const char *k) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
static void getGlobalTable (lua_State *L, TValue *gt) {
|
||||||
** Get the global table in the registry. Since all predefined
|
Table *registry = hvalue(&G(L)->l_registry);
|
||||||
** indices in the registry were inserted right when the registry
|
luaH_getint(registry, LUA_RIDX_GLOBALS, gt);
|
||||||
** was created and never removed, they must always be in the array
|
}
|
||||||
** part of the registry.
|
|
||||||
*/
|
|
||||||
#define getGtable(L) \
|
|
||||||
(&hvalue(&G(L)->l_registry)->array[LUA_RIDX_GLOBALS - 1])
|
|
||||||
|
|
||||||
|
|
||||||
LUA_API int lua_getglobal (lua_State *L, const char *name) {
|
LUA_API int lua_getglobal (lua_State *L, const char *name) {
|
||||||
const TValue *G;
|
TValue gt;
|
||||||
lua_lock(L);
|
lua_lock(L);
|
||||||
G = getGtable(L);
|
getGlobalTable(L, >);
|
||||||
return auxgetstr(L, G, name);
|
return auxgetstr(L, >, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -840,10 +836,10 @@ static void auxsetstr (lua_State *L, const TValue *t, const char *k) {
|
|||||||
|
|
||||||
|
|
||||||
LUA_API void lua_setglobal (lua_State *L, const char *name) {
|
LUA_API void lua_setglobal (lua_State *L, const char *name) {
|
||||||
const TValue *G;
|
TValue gt;
|
||||||
lua_lock(L); /* unlock done in 'auxsetstr' */
|
lua_lock(L); /* unlock done in 'auxsetstr' */
|
||||||
G = getGtable(L);
|
getGlobalTable(L, >);
|
||||||
auxsetstr(L, G, name);
|
auxsetstr(L, >, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1093,10 +1089,11 @@ LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data,
|
|||||||
LClosure *f = clLvalue(s2v(L->top.p - 1)); /* get new function */
|
LClosure *f = clLvalue(s2v(L->top.p - 1)); /* get new function */
|
||||||
if (f->nupvalues >= 1) { /* does it have an upvalue? */
|
if (f->nupvalues >= 1) { /* does it have an upvalue? */
|
||||||
/* get global table from registry */
|
/* get global table from registry */
|
||||||
const TValue *gt = getGtable(L);
|
TValue gt;
|
||||||
|
getGlobalTable(L, >);
|
||||||
/* set global table as 1st upvalue of 'f' (may be LUA_ENV) */
|
/* set global table as 1st upvalue of 'f' (may be LUA_ENV) */
|
||||||
setobj(L, f->upvals[0]->v.p, gt);
|
setobj(L, f->upvals[0]->v.p, >);
|
||||||
luaC_barrier(L, f->upvals[0], gt);
|
luaC_barrier(L, f->upvals[0], >);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lua_unlock(L);
|
lua_unlock(L);
|
||||||
|
|||||||
25
lgc.c
25
lgc.c
@@ -91,6 +91,13 @@
|
|||||||
#define gcvalueN(o) (iscollectable(o) ? gcvalue(o) : NULL)
|
#define gcvalueN(o) (iscollectable(o) ? gcvalue(o) : NULL)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Access to collectable objects in array part of tables
|
||||||
|
*/
|
||||||
|
#define gcvalarr(t,i) \
|
||||||
|
((*getArrTag(t,i) & BIT_ISCOLLECTABLE) ? getArrVal(t,i)->gc : NULL)
|
||||||
|
|
||||||
|
|
||||||
#define markvalue(g,o) { checkliveness(g->mainthread,o); \
|
#define markvalue(g,o) { checkliveness(g->mainthread,o); \
|
||||||
if (valiswhite(o)) reallymarkobject(g,gcvalue(o)); }
|
if (valiswhite(o)) reallymarkobject(g,gcvalue(o)); }
|
||||||
|
|
||||||
@@ -486,9 +493,10 @@ static int traverseephemeron (global_State *g, Table *h, int inv) {
|
|||||||
unsigned int nsize = sizenode(h);
|
unsigned int nsize = sizenode(h);
|
||||||
/* traverse array part */
|
/* traverse array part */
|
||||||
for (i = 0; i < asize; i++) {
|
for (i = 0; i < asize; i++) {
|
||||||
if (valiswhite(&h->array[i])) {
|
GCObject *o = gcvalarr(h, i + 1);
|
||||||
|
if (o != NULL && iswhite(o)) {
|
||||||
marked = 1;
|
marked = 1;
|
||||||
reallymarkobject(g, gcvalue(&h->array[i]));
|
reallymarkobject(g, o);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* traverse hash part; if 'inv', traverse descending
|
/* traverse hash part; if 'inv', traverse descending
|
||||||
@@ -524,8 +532,11 @@ static void traversestrongtable (global_State *g, Table *h) {
|
|||||||
Node *n, *limit = gnodelast(h);
|
Node *n, *limit = gnodelast(h);
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
unsigned int asize = luaH_realasize(h);
|
unsigned int asize = luaH_realasize(h);
|
||||||
for (i = 0; i < asize; i++) /* traverse array part */
|
for (i = 0; i < asize; i++) { /* traverse array part */
|
||||||
markvalue(g, &h->array[i]);
|
GCObject *o = gcvalarr(h, i + 1);
|
||||||
|
if (o != NULL && iswhite(o))
|
||||||
|
reallymarkobject(g, o);
|
||||||
|
}
|
||||||
for (n = gnode(h, 0); n < limit; n++) { /* traverse hash part */
|
for (n = gnode(h, 0); n < limit; n++) { /* traverse hash part */
|
||||||
if (isempty(gval(n))) /* entry is empty? */
|
if (isempty(gval(n))) /* entry is empty? */
|
||||||
clearkey(n); /* clear its key */
|
clearkey(n); /* clear its key */
|
||||||
@@ -746,9 +757,9 @@ static void clearbyvalues (global_State *g, GCObject *l, GCObject *f) {
|
|||||||
unsigned int i;
|
unsigned int i;
|
||||||
unsigned int asize = luaH_realasize(h);
|
unsigned int asize = luaH_realasize(h);
|
||||||
for (i = 0; i < asize; i++) {
|
for (i = 0; i < asize; i++) {
|
||||||
TValue *o = &h->array[i];
|
GCObject *o = gcvalarr(h, i + 1);
|
||||||
if (iscleared(g, gcvalueN(o))) /* value was collected? */
|
if (iscleared(g, o)) /* value was collected? */
|
||||||
setempty(o); /* remove entry */
|
*getArrTag(h, i + 1) = LUA_VEMPTY; /* remove entry */
|
||||||
}
|
}
|
||||||
for (n = gnode(h, 0); n < limit; n++) {
|
for (n = gnode(h, 0); n < limit; n++) {
|
||||||
if (iscleared(g, gcvalueN(gval(n)))) /* unmarked value? */
|
if (iscleared(g, gcvalueN(gval(n)))) /* unmarked value? */
|
||||||
|
|||||||
@@ -736,12 +736,15 @@ typedef union Node {
|
|||||||
#define setnorealasize(t) ((t)->flags |= BITRAS)
|
#define setnorealasize(t) ((t)->flags |= BITRAS)
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct ArrayCell ArrayCell;
|
||||||
|
|
||||||
|
|
||||||
typedef struct Table {
|
typedef struct Table {
|
||||||
CommonHeader;
|
CommonHeader;
|
||||||
lu_byte flags; /* 1<<p means tagmethod(p) is not present */
|
lu_byte flags; /* 1<<p means tagmethod(p) is not present */
|
||||||
lu_byte lsizenode; /* log2 of size of 'node' array */
|
lu_byte lsizenode; /* log2 of size of 'node' array */
|
||||||
unsigned int alimit; /* "limit" of 'array' array */
|
unsigned int alimit; /* "limit" of 'array' array */
|
||||||
TValue *array; /* array part */
|
ArrayCell *array; /* array part */
|
||||||
Node *node;
|
Node *node;
|
||||||
Node *lastfree; /* any free position is before this position */
|
Node *lastfree; /* any free position is before this position */
|
||||||
struct Table *metatable;
|
struct Table *metatable;
|
||||||
|
|||||||
7
lstate.c
7
lstate.c
@@ -215,13 +215,16 @@ static void freestack (lua_State *L) {
|
|||||||
*/
|
*/
|
||||||
static void init_registry (lua_State *L, global_State *g) {
|
static void init_registry (lua_State *L, global_State *g) {
|
||||||
/* create registry */
|
/* create registry */
|
||||||
|
TValue aux;
|
||||||
Table *registry = luaH_new(L);
|
Table *registry = luaH_new(L);
|
||||||
sethvalue(L, &g->l_registry, registry);
|
sethvalue(L, &g->l_registry, registry);
|
||||||
luaH_resize(L, registry, LUA_RIDX_LAST, 0);
|
luaH_resize(L, registry, LUA_RIDX_LAST, 0);
|
||||||
/* registry[LUA_RIDX_MAINTHREAD] = L */
|
/* registry[LUA_RIDX_MAINTHREAD] = L */
|
||||||
setthvalue(L, ®istry->array[LUA_RIDX_MAINTHREAD - 1], L);
|
setthvalue(L, &aux, L);
|
||||||
|
luaH_setint(L, registry, LUA_RIDX_MAINTHREAD, &aux);
|
||||||
/* registry[LUA_RIDX_GLOBALS] = new table (table of globals) */
|
/* registry[LUA_RIDX_GLOBALS] = new table (table of globals) */
|
||||||
sethvalue(L, ®istry->array[LUA_RIDX_GLOBALS - 1], luaH_new(L));
|
sethvalue(L, &aux, luaH_new(L));
|
||||||
|
luaH_setint(L, registry, LUA_RIDX_GLOBALS, &aux);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
116
ltable.c
116
ltable.c
@@ -350,9 +350,10 @@ int luaH_next (lua_State *L, Table *t, StkId key) {
|
|||||||
unsigned int asize = luaH_realasize(t);
|
unsigned int asize = luaH_realasize(t);
|
||||||
unsigned int i = findindex(L, t, s2v(key), asize); /* find original key */
|
unsigned int i = findindex(L, t, s2v(key), asize); /* find original key */
|
||||||
for (; i < asize; i++) { /* try first array part */
|
for (; i < asize; i++) { /* try first array part */
|
||||||
if (!isempty(&t->array[i])) { /* a non-empty entry? */
|
int tag = *getArrTag(t, i + 1);
|
||||||
|
if (!tagisempty(tag)) { /* a non-empty entry? */
|
||||||
setivalue(s2v(key), i + 1);
|
setivalue(s2v(key), i + 1);
|
||||||
setobj2s(L, key + 1, &t->array[i]);
|
farr2val(t, i + 1, tag, s2v(key + 1));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -374,6 +375,41 @@ static void freehash (lua_State *L, Table *t) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Check whether an integer key is in the array part. If 'alimit' is
|
||||||
|
** not the real size of the array, the key still can be in the array
|
||||||
|
** part. In this case, do the "Xmilia trick" to check whether 'key-1'
|
||||||
|
** is smaller than the real size.
|
||||||
|
** The trick works as follow: let 'p' be an integer such that
|
||||||
|
** '2^(p+1) >= alimit > 2^p', or '2^(p+1) > alimit-1 >= 2^p'.
|
||||||
|
** That is, 2^(p+1) is the real size of the array, and 'p' is the highest
|
||||||
|
** bit on in 'alimit-1'. What we have to check becomes 'key-1 < 2^(p+1)'.
|
||||||
|
** We compute '(key-1) & ~(alimit-1)', which we call 'res'; it will
|
||||||
|
** have the 'p' bit cleared. If the key is outside the array, that is,
|
||||||
|
** 'key-1 >= 2^(p+1)', then 'res' will have some 1-bit higher than 'p',
|
||||||
|
** therefore it will be larger or equal to 'alimit', and the check
|
||||||
|
** will fail. If 'key-1 < 2^(p+1)', then 'res' has no 1-bit higher than
|
||||||
|
** 'p', and as the bit 'p' itself was cleared, 'res' will be smaller
|
||||||
|
** than 2^p, therefore smaller than 'alimit', and the check succeeds.
|
||||||
|
** As special cases, when 'alimit' is 0 the condition is trivially false,
|
||||||
|
** and when 'alimit' is 1 the condition simplifies to 'key-1 < alimit'.
|
||||||
|
** If key is 0 or negative, 'res' will have its higher bit on, so that
|
||||||
|
** if cannot be smaller than alimit.
|
||||||
|
*/
|
||||||
|
static int keyinarray (Table *t, lua_Integer key) {
|
||||||
|
lua_Unsigned alimit = t->alimit;
|
||||||
|
if (l_castS2U(key) - 1u < alimit) /* 'key' in [1, t->alimit]? */
|
||||||
|
return 1;
|
||||||
|
else if (!isrealasize(t) && /* key still may be in the array part? */
|
||||||
|
(((l_castS2U(key) - 1u) & ~(alimit - 1u)) < alimit)) {
|
||||||
|
t->alimit = cast_uint(key); /* probably '#t' is here now */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** {=============================================================
|
** {=============================================================
|
||||||
** Rehash
|
** Rehash
|
||||||
@@ -421,6 +457,12 @@ static int countint (lua_Integer key, unsigned int *nums) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
l_sinline int arraykeyisempty (const Table *t, lua_Integer key) {
|
||||||
|
int tag = *getArrTag(t, key);
|
||||||
|
return tagisempty(tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Count keys in array part of table 't': Fill 'nums[i]' with
|
** Count keys in array part of table 't': Fill 'nums[i]' with
|
||||||
** number of keys that will go into corresponding slice and return
|
** number of keys that will go into corresponding slice and return
|
||||||
@@ -443,7 +485,7 @@ static unsigned int numusearray (const Table *t, unsigned int *nums) {
|
|||||||
}
|
}
|
||||||
/* count elements in range (2^(lg - 1), 2^lg] */
|
/* count elements in range (2^(lg - 1), 2^lg] */
|
||||||
for (; i <= lim; i++) {
|
for (; i <= lim; i++) {
|
||||||
if (!isempty(&t->array[i-1]))
|
if (!arraykeyisempty(t, i))
|
||||||
lc++;
|
lc++;
|
||||||
}
|
}
|
||||||
nums[lg] += lc;
|
nums[lg] += lc;
|
||||||
@@ -555,7 +597,7 @@ void luaH_resize (lua_State *L, Table *t, unsigned int newasize,
|
|||||||
unsigned int i;
|
unsigned int i;
|
||||||
Table newt; /* to keep the new hash part */
|
Table newt; /* to keep the new hash part */
|
||||||
unsigned int oldasize = setlimittosize(t);
|
unsigned int oldasize = setlimittosize(t);
|
||||||
TValue *newarray;
|
ArrayCell *newarray;
|
||||||
/* create new hash part with appropriate size into 'newt' */
|
/* create new hash part with appropriate size into 'newt' */
|
||||||
setnodevector(L, &newt, nhsize);
|
setnodevector(L, &newt, nhsize);
|
||||||
if (newasize < oldasize) { /* will array shrink? */
|
if (newasize < oldasize) { /* will array shrink? */
|
||||||
@@ -563,14 +605,18 @@ void luaH_resize (lua_State *L, Table *t, unsigned int newasize,
|
|||||||
exchangehashpart(t, &newt); /* and new hash */
|
exchangehashpart(t, &newt); /* and new hash */
|
||||||
/* re-insert into the new hash the elements from vanishing slice */
|
/* re-insert into the new hash the elements from vanishing slice */
|
||||||
for (i = newasize; i < oldasize; i++) {
|
for (i = newasize; i < oldasize; i++) {
|
||||||
if (!isempty(&t->array[i]))
|
int tag = *getArrTag(t, i + 1);
|
||||||
luaH_setint(L, t, i + 1, &t->array[i]);
|
if (!tagisempty(tag)) { /* a non-empty entry? */
|
||||||
|
TValue aux;
|
||||||
|
farr2val(t, i + 1, tag, &aux);
|
||||||
|
luaH_setint(L, t, i + 1, &aux);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
t->alimit = oldasize; /* restore current size... */
|
t->alimit = oldasize; /* restore current size... */
|
||||||
exchangehashpart(t, &newt); /* and hash (in case of errors) */
|
exchangehashpart(t, &newt); /* and hash (in case of errors) */
|
||||||
}
|
}
|
||||||
/* allocate new array */
|
/* allocate new array */
|
||||||
newarray = luaM_reallocvector(L, t->array, oldasize, newasize, TValue);
|
newarray = luaM_reallocvector(L, t->array, oldasize, newasize, ArrayCell);
|
||||||
if (l_unlikely(newarray == NULL && newasize > 0)) { /* allocation failed? */
|
if (l_unlikely(newarray == NULL && newasize > 0)) { /* allocation failed? */
|
||||||
freehash(L, &newt); /* release new hash part */
|
freehash(L, &newt); /* release new hash part */
|
||||||
luaM_error(L); /* raise error (with array unchanged) */
|
luaM_error(L); /* raise error (with array unchanged) */
|
||||||
@@ -580,7 +626,7 @@ void luaH_resize (lua_State *L, Table *t, unsigned int newasize,
|
|||||||
t->array = newarray; /* set new array part */
|
t->array = newarray; /* set new array part */
|
||||||
t->alimit = newasize;
|
t->alimit = newasize;
|
||||||
for (i = oldasize; i < newasize; i++) /* clear new slice of the array */
|
for (i = oldasize; i < newasize; i++) /* clear new slice of the array */
|
||||||
setempty(&t->array[i]);
|
*getArrTag(t, i + 1) = LUA_VEMPTY;
|
||||||
/* re-insert elements from old hash part into new parts */
|
/* re-insert elements from old hash part into new parts */
|
||||||
reinsert(L, &newt, t); /* 'newt' now has the old hash */
|
reinsert(L, &newt, t); /* 'newt' now has the old hash */
|
||||||
freehash(L, &newt); /* free old hash part */
|
freehash(L, &newt); /* free old hash part */
|
||||||
@@ -719,41 +765,6 @@ void luaH_newkey (lua_State *L, Table *t, const TValue *key, TValue *value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Check whether key is in the array part. If 'alimit' is not the real
|
|
||||||
** size of the array, the key still can be in the array part. In this
|
|
||||||
** case, do the "Xmilia trick" to check whether 'key-1' is smaller than
|
|
||||||
** the real size.
|
|
||||||
** The trick works as follow: let 'p' be an integer such that
|
|
||||||
** '2^(p+1) >= alimit > 2^p', or '2^(p+1) > alimit-1 >= 2^p'.
|
|
||||||
** That is, 2^(p+1) is the real size of the array, and 'p' is the highest
|
|
||||||
** bit on in 'alimit-1'. What we have to check becomes 'key-1 < 2^(p+1)'.
|
|
||||||
** We compute '(key-1) & ~(alimit-1)', which we call 'res'; it will
|
|
||||||
** have the 'p' bit cleared. If the key is outside the array, that is,
|
|
||||||
** 'key-1 >= 2^(p+1)', then 'res' will have some 1-bit higher than 'p',
|
|
||||||
** therefore it will be larger or equal to 'alimit', and the check
|
|
||||||
** will fail. If 'key-1 < 2^(p+1)', then 'res' has no 1-bit higher than
|
|
||||||
** 'p', and as the bit 'p' itself was cleared, 'res' will be smaller
|
|
||||||
** than 2^p, therefore smaller than 'alimit', and the check succeeds.
|
|
||||||
** As special cases, when 'alimit' is 0 the condition is trivially false,
|
|
||||||
** and when 'alimit' is 1 the condition simplifies to 'key-1 < alimit'.
|
|
||||||
** If key is 0 or negative, 'res' will have its higher bit on, so that
|
|
||||||
** if cannot be smaller than alimit.
|
|
||||||
*/
|
|
||||||
static int keyinarray (Table *t, lua_Integer key) {
|
|
||||||
lua_Unsigned alimit = t->alimit;
|
|
||||||
if (l_castS2U(key) - 1u < alimit) /* 'key' in [1, t->alimit]? */
|
|
||||||
return 1;
|
|
||||||
else if (!isrealasize(t) && /* key still may be in the array part? */
|
|
||||||
(((l_castS2U(key) - 1u) & ~(alimit - 1u)) < alimit)) {
|
|
||||||
t->alimit = cast_uint(key); /* probably '#t' is here now */
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static const TValue *getintfromhash (Table *t, lua_Integer key) {
|
static const TValue *getintfromhash (Table *t, lua_Integer key) {
|
||||||
Node *n = hashint(t, key);
|
Node *n = hashint(t, key);
|
||||||
lua_assert(l_castS2U(key) - 1u >= luaH_realasize(t));
|
lua_assert(l_castS2U(key) - 1u >= luaH_realasize(t));
|
||||||
@@ -770,15 +781,8 @@ static const TValue *getintfromhash (Table *t, lua_Integer key) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
l_sinline int arraykeyisempty (Table *t, lua_Integer key) {
|
|
||||||
int tag = *getArrTag(t, key);
|
|
||||||
return tagisempty(tag);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int hashkeyisempty (Table *t, lua_Integer key) {
|
static int hashkeyisempty (Table *t, lua_Integer key) {
|
||||||
const TValue *val = getintfromhash(t, key);
|
const TValue *val = getintfromhash(t, key);
|
||||||
lua_assert(!keyinarray(t, key));
|
|
||||||
return isempty(val);
|
return isempty(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -797,7 +801,7 @@ int luaH_getint (Table *t, lua_Integer key, TValue *res) {
|
|||||||
if (keyinarray(t, key)) {
|
if (keyinarray(t, key)) {
|
||||||
int tag = *getArrTag(t, key);
|
int tag = *getArrTag(t, key);
|
||||||
if (!tagisempty(tag)) {
|
if (!tagisempty(tag)) {
|
||||||
arr2val(t, key, tag, res);
|
farr2val(t, key, tag, res);
|
||||||
return HOK; /* success */
|
return HOK; /* success */
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -900,7 +904,7 @@ int luaH_psetint (Table *t, lua_Integer key, TValue *val) {
|
|||||||
if (keyinarray(t, key)) {
|
if (keyinarray(t, key)) {
|
||||||
lu_byte *tag = getArrTag(t, key);
|
lu_byte *tag = getArrTag(t, key);
|
||||||
if (!tagisempty(*tag)) {
|
if (!tagisempty(*tag)) {
|
||||||
val2arr(t, key, tag, val);
|
fval2arr(t, key, tag, val);
|
||||||
return HOK; /* success */
|
return HOK; /* success */
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -956,7 +960,7 @@ void luaH_finishset (lua_State *L, Table *t, const TValue *key,
|
|||||||
}
|
}
|
||||||
else { /* array entry */
|
else { /* array entry */
|
||||||
hres = ~hres; /* real index */
|
hres = ~hres; /* real index */
|
||||||
val2arr(t, hres, getArrTag(t, hres), value);
|
fval2arr(t, hres, getArrTag(t, hres), value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1087,11 +1091,11 @@ lua_Unsigned luaH_getn (Table *t) {
|
|||||||
/* 'limit' is zero or present in table */
|
/* 'limit' is zero or present in table */
|
||||||
if (!limitequalsasize(t)) { /* (2)? */
|
if (!limitequalsasize(t)) { /* (2)? */
|
||||||
/* 'limit' > 0 and array has more elements after 'limit' */
|
/* 'limit' > 0 and array has more elements after 'limit' */
|
||||||
if (isempty(&t->array[limit])) /* 'limit + 1' is empty? */
|
if (arraykeyisempty(t, limit + 1)) /* 'limit + 1' is empty? */
|
||||||
return limit; /* this is the boundary */
|
return limit; /* this is the boundary */
|
||||||
/* else, try last element in the array */
|
/* else, try last element in the array */
|
||||||
limit = luaH_realasize(t);
|
limit = luaH_realasize(t);
|
||||||
if (isempty(&t->array[limit - 1])) { /* empty? */
|
if (arraykeyisempty(t, limit)) { /* empty? */
|
||||||
/* there must be a boundary in the array after old limit,
|
/* there must be a boundary in the array after old limit,
|
||||||
and it must be a valid new limit */
|
and it must be a valid new limit */
|
||||||
unsigned int boundary = binsearch(t, t->alimit, limit);
|
unsigned int boundary = binsearch(t, t->alimit, limit);
|
||||||
@@ -1102,7 +1106,7 @@ lua_Unsigned luaH_getn (Table *t) {
|
|||||||
}
|
}
|
||||||
/* (3) 'limit' is the last element and either is zero or present in table */
|
/* (3) 'limit' is the last element and either is zero or present in table */
|
||||||
lua_assert(limit == luaH_realasize(t) &&
|
lua_assert(limit == luaH_realasize(t) &&
|
||||||
(limit == 0 || !isempty(&t->array[limit - 1])));
|
(limit == 0 || !arraykeyisempty(t, limit)));
|
||||||
if (isdummy(t) || hashkeyisempty(t, cast(lua_Integer, limit + 1)))
|
if (isdummy(t) || hashkeyisempty(t, cast(lua_Integer, limit + 1)))
|
||||||
return limit; /* 'limit + 1' is absent */
|
return limit; /* 'limit + 1' is absent */
|
||||||
else /* 'limit + 1' is also present */
|
else /* 'limit + 1' is also present */
|
||||||
|
|||||||
21
ltable.h
21
ltable.h
@@ -51,20 +51,33 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
struct ArrayCell {
|
||||||
|
lu_byte tt;
|
||||||
|
Value value;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/* fast access to components of array values */
|
/* fast access to components of array values */
|
||||||
#define getArrTag(t,k) (&(t)->array[k - 1].tt_)
|
#define getArrTag(t,k) (&(t)->array[k - 1].tt)
|
||||||
#define getArrVal(t,k) (&(t)->array[k - 1].value_)
|
#define getArrVal(t,k) (&(t)->array[k - 1].value)
|
||||||
|
|
||||||
#define tagisempty(tag) (novariant(tag) == LUA_TNIL)
|
#define tagisempty(tag) (novariant(tag) == LUA_TNIL)
|
||||||
|
|
||||||
#define arr2val(h,k,tag,res) \
|
|
||||||
|
#define farr2val(h,k,tag,res) \
|
||||||
((res)->tt_ = tag, (res)->value_ = *getArrVal(h,k))
|
((res)->tt_ = tag, (res)->value_ = *getArrVal(h,k))
|
||||||
|
|
||||||
#define val2arr(h,k,tag,val) \
|
#define fval2arr(h,k,tag,val) \
|
||||||
(*tag = (val)->tt_, *getArrVal(h,k) = (val)->value_)
|
(*tag = (val)->tt_, *getArrVal(h,k) = (val)->value_)
|
||||||
|
|
||||||
|
|
||||||
|
#define obj2arr(h,k,val) \
|
||||||
|
(*getArrTag(h,k) = (val)->tt_, *getArrVal(h,k) = (val)->value_)
|
||||||
|
|
||||||
|
#define arr2obj(h,k,val) \
|
||||||
|
((val)->tt_ = *getArrTag(h,k), (val)->value_ = *getArrVal(h,k))
|
||||||
|
|
||||||
|
|
||||||
LUAI_FUNC int luaH_getshortstr (Table *t, TString *key, TValue *res);
|
LUAI_FUNC int luaH_getshortstr (Table *t, TString *key, TValue *res);
|
||||||
LUAI_FUNC int luaH_getstr (Table *t, TString *key, TValue *res);
|
LUAI_FUNC int luaH_getstr (Table *t, TString *key, TValue *res);
|
||||||
LUAI_FUNC int luaH_get (Table *t, const TValue *key, TValue *res);
|
LUAI_FUNC int luaH_get (Table *t, const TValue *key, TValue *res);
|
||||||
|
|||||||
10
ltests.c
10
ltests.c
@@ -362,8 +362,11 @@ static void checktable (global_State *g, Table *h) {
|
|||||||
Node *n, *limit = gnode(h, sizenode(h));
|
Node *n, *limit = gnode(h, sizenode(h));
|
||||||
GCObject *hgc = obj2gco(h);
|
GCObject *hgc = obj2gco(h);
|
||||||
checkobjrefN(g, hgc, h->metatable);
|
checkobjrefN(g, hgc, h->metatable);
|
||||||
for (i = 0; i < asize; i++)
|
for (i = 0; i < asize; i++) {
|
||||||
checkvalref(g, hgc, &h->array[i]);
|
TValue aux;
|
||||||
|
arr2obj(h, i + 1, &aux);
|
||||||
|
checkvalref(g, hgc, &aux);
|
||||||
|
}
|
||||||
for (n = gnode(h, 0); n < limit; n++) {
|
for (n = gnode(h, 0); n < limit; n++) {
|
||||||
if (!isempty(gval(n))) {
|
if (!isempty(gval(n))) {
|
||||||
TValue k;
|
TValue k;
|
||||||
@@ -1005,7 +1008,8 @@ static int table_query (lua_State *L) {
|
|||||||
}
|
}
|
||||||
else if ((unsigned int)i < asize) {
|
else if ((unsigned int)i < asize) {
|
||||||
lua_pushinteger(L, i);
|
lua_pushinteger(L, i);
|
||||||
pushobject(L, &t->array[i]);
|
arr2obj(t, i + 1, s2v(L->top.p));
|
||||||
|
api_incr_top(L);
|
||||||
lua_pushnil(L);
|
lua_pushnil(L);
|
||||||
}
|
}
|
||||||
else if ((i -= asize) < sizenode(t)) {
|
else if ((i -= asize) < sizenode(t)) {
|
||||||
|
|||||||
2
lvm.c
2
lvm.c
@@ -1845,7 +1845,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
|
|||||||
luaH_resizearray(L, h, last); /* preallocate it at once */
|
luaH_resizearray(L, h, last); /* preallocate it at once */
|
||||||
for (; n > 0; n--) {
|
for (; n > 0; n--) {
|
||||||
TValue *val = s2v(ra + n);
|
TValue *val = s2v(ra + n);
|
||||||
setobj2t(L, &h->array[last - 1], val);
|
obj2arr(h, last, val);
|
||||||
last--;
|
last--;
|
||||||
luaC_barrierback(L, obj2gco(h), val);
|
luaC_barrierback(L, obj2gco(h), val);
|
||||||
}
|
}
|
||||||
|
|||||||
4
lvm.h
4
lvm.h
@@ -92,7 +92,7 @@ typedef enum {
|
|||||||
if ((u - 1u < h->alimit)) { \
|
if ((u - 1u < h->alimit)) { \
|
||||||
int tag = *getArrTag(h,u); \
|
int tag = *getArrTag(h,u); \
|
||||||
if (tagisempty(tag)) aux = HNOTFOUND; \
|
if (tagisempty(tag)) aux = HNOTFOUND; \
|
||||||
else { arr2val(h, u, tag, res); aux = HOK; }} \
|
else { farr2val(h, u, tag, res); aux = HOK; }} \
|
||||||
else { aux = luaH_getint(h, u, res); }}
|
else { aux = luaH_getint(h, u, res); }}
|
||||||
|
|
||||||
|
|
||||||
@@ -105,7 +105,7 @@ typedef enum {
|
|||||||
if ((u - 1u < h->alimit)) { \
|
if ((u - 1u < h->alimit)) { \
|
||||||
lu_byte *tag = getArrTag(h,u); \
|
lu_byte *tag = getArrTag(h,u); \
|
||||||
if (tagisempty(*tag)) aux = ~cast_int(u); \
|
if (tagisempty(*tag)) aux = ~cast_int(u); \
|
||||||
else { val2arr(h, u, tag, val); aux = HOK; }} \
|
else { fval2arr(h, u, tag, val); aux = HOK; }} \
|
||||||
else { aux = luaH_psetint(h, u, val); }}
|
else { aux = luaH_psetint(h, u, val); }}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user