aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2023-11-24 14:41:07 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2023-11-24 14:41:07 -0300
commit52b899d60d8c61b8affe0206014173912de94940 (patch)
tree5e6f9116b2c70a5ebd4c1bdea49f283cca5cb3fb
parent25cd3d377ec13176a6701d9d21a278ba8f2bc3d6 (diff)
downloadlua-52b899d60d8c61b8affe0206014173912de94940.tar.gz
lua-52b899d60d8c61b8affe0206014173912de94940.tar.bz2
lua-52b899d60d8c61b8affe0206014173912de94940.zip
Simpler coding for new representation for arrays
With the tags comming first in a cell, we can define the whole cell as a C type and let C do part of the address computations.
-rw-r--r--lobject.h2
-rw-r--r--ltable.c46
-rw-r--r--ltable.h38
3 files changed, 36 insertions, 50 deletions
diff --git a/lobject.h b/lobject.h
index 8688a842..6da50215 100644
--- a/lobject.h
+++ b/lobject.h
@@ -762,7 +762,7 @@ typedef union Node {
762#define setnorealasize(t) ((t)->flags |= BITRAS) 762#define setnorealasize(t) ((t)->flags |= BITRAS)
763 763
764 764
765typedef union ArrayCell ArrayCell; 765typedef struct ArrayCell ArrayCell;
766 766
767 767
768typedef struct Table { 768typedef struct Table {
diff --git a/ltable.c b/ltable.c
index c9f66b3c..d3e90696 100644
--- a/ltable.c
+++ b/ltable.c
@@ -541,29 +541,28 @@ static int numusehash (const Table *t, unsigned int *nums, unsigned int *pna) {
541 541
542 542
543/* 543/*
544** Convert an "abstract size" (number of values in an array) to 544** Convert an "abstract size" (number of slots in an array) to
545** "concrete size" (number of cell elements in the array). Cells 545** "concrete size" (number of bytes in the array).
546** do not need to be full; we only must make sure it has the values 546** If the abstract size is not a multiple of NM, the last cell is
547** needed and its 'tag' element. So, we compute the concrete tag index 547** incomplete, so we don't need to allocate memory for the whole cell.
548** and the concrete value index of the last element, get their maximum 548** 'extra' computes how many values are not needed in that last cell.
549** and adds 1. 549** It will be zero when 'size' is a multiple of NM, and from there it
550** increases as 'size' decreases, up to (NM - 1).
550*/ 551*/
551static unsigned int concretesize (unsigned int size) { 552static size_t concretesize (unsigned int size) {
552 if (size == 0) return 0; 553 unsigned int numcells = (size + NM - 1) / NM; /* (size / NM) rounded up */
553 else { 554 unsigned int extra = NM - 1 - ((size + NM - 1) % NM);
554 unsigned int ts = TagIndex(size - 1); 555 return numcells * sizeof(ArrayCell) - extra * sizeof(Value);
555 unsigned int vs = ValueIndex(size - 1);
556 return ((ts >= vs) ? ts : vs) + 1;
557 }
558} 556}
559 557
560 558
561static ArrayCell *resizearray (lua_State *L , Table *t, 559static ArrayCell *resizearray (lua_State *L , Table *t,
562 unsigned int oldasize, 560 unsigned int oldasize,
563 unsigned int newasize) { 561 unsigned int newasize) {
564 oldasize = concretesize(oldasize); 562 size_t oldasizeb = concretesize(oldasize);
565 newasize = concretesize(newasize); 563 size_t newasizeb = concretesize(newasize);
566 return luaM_reallocvector(L, t->array, oldasize, newasize, ArrayCell); 564 void *a = luaM_reallocvector(L, t->array, oldasizeb, newasizeb, lu_byte);
565 return cast(ArrayCell*, a);
567} 566}
568 567
569 568
@@ -747,10 +746,19 @@ Table *luaH_new (lua_State *L) {
747} 746}
748 747
749 748
749/*
750** Frees a table. The assert ensures the correctness of 'concretesize',
751** checking its result against the address of the last element in the
752** array part of the table, computed abstractly.
753*/
750void luaH_free (lua_State *L, Table *t) { 754void luaH_free (lua_State *L, Table *t) {
751 unsigned ps = concretesize(luaH_realasize(t)); 755 unsigned int realsize = luaH_realasize(t);
756 size_t sizeb = concretesize(realsize);
757 lua_assert((sizeb == 0 && realsize == 0) ||
758 cast_charp(t->array) + sizeb - sizeof(Value) ==
759 cast_charp(getArrVal(t, realsize - 1)));
752 freehash(L, t); 760 freehash(L, t);
753 luaM_freearray(L, t->array, ps); 761 luaM_freemem(L, t->array, sizeb);
754 luaM_free(L, t); 762 luaM_free(L, t);
755} 763}
756 764
@@ -944,7 +952,7 @@ TString *luaH_getstrkey (Table *t, TString *key) {
944** main search function 952** main search function
945*/ 953*/
946int luaH_get (Table *t, const TValue *key, TValue *res) { 954int luaH_get (Table *t, const TValue *key, TValue *res) {
947 const TValue *slot; 955 const TValue *slot;
948 switch (ttypetag(key)) { 956 switch (ttypetag(key)) {
949 case LUA_VSHRSTR: 957 case LUA_VSHRSTR:
950 slot = luaH_Hgetshortstr(t, tsvalue(key)); 958 slot = luaH_Hgetshortstr(t, tsvalue(key));
diff --git a/ltable.h b/ltable.h
index d488a1f7..5581efb1 100644
--- a/ltable.h
+++ b/ltable.h
@@ -69,44 +69,22 @@
69 69
70/* 70/*
71** The array part of a table is represented by an array of cells. 71** The array part of a table is represented by an array of cells.
72** Each cell is composed of (NM + 1) elements, and each element has the 72** Each cell is composed of NM tags followed by NM values, so that
73** type 'ArrayCell'. In each cell, only one element has the variant 73** no space is wasted in padding.
74** 'tag', while the other NM elements have the variant 'value'. The
75** array in the 'tag' element holds the tags of the other elements in
76** that cell.
77*/ 74*/
78#define NM ((unsigned int)sizeof(Value)) 75#define NM cast_uint(sizeof(Value))
79 76
80union ArrayCell { 77struct ArrayCell {
81 unsigned char tag[NM]; 78 lu_byte tag[NM];
82 Value value; 79 Value value[NM];
83}; 80};
84 81
85 82
86/*
87** 'NMTag' defines which cell element has the tags; that could be any
88** value between 0 (tags come before all values) and NM (tags come after
89** all values).
90*/
91#define NMTag 0
92
93
94/*
95** Computes the concrete index that holds the tag of abstract index 'i'
96*/
97#define TagIndex(i) (((i)/NM * (NM + 1u)) + NMTag)
98
99/*
100** Computes the concrete index that holds the value of abstract index 'i'
101*/
102#define ValueIndex(i) ((i) + (((i) + (NM - NMTag))/NM))
103
104
105/* Computes the address of the tag for the abstract index 'k' */ 83/* Computes the address of the tag for the abstract index 'k' */
106#define getArrTag(t,k) (&(t)->array[TagIndex(k)].tag[(k)%NM]) 84#define getArrTag(t,k) (&(t)->array[(k)/NM].tag[(k)%NM])
107 85
108/* Computes the address of the value for the abstract index 'k' */ 86/* Computes the address of the value for the abstract index 'k' */
109#define getArrVal(t,k) (&(t)->array[ValueIndex(k)].value) 87#define getArrVal(t,k) (&(t)->array[(k)/NM].value[(k)%NM])
110 88
111 89
112/* 90/*