aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2024-12-17 11:23:22 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2024-12-17 11:23:22 -0300
commit1c40ff9faafed620aa0458b397bcbfbe19e0f663 (patch)
treeedfb96022feb99244a7a6c4c9d28525e141b783e
parent7538f3886dfa091d661c56e48ebb1578ced8e467 (diff)
downloadlua-1c40ff9faafed620aa0458b397bcbfbe19e0f663.tar.gz
lua-1c40ff9faafed620aa0458b397bcbfbe19e0f663.tar.bz2
lua-1c40ff9faafed620aa0458b397bcbfbe19e0f663.zip
Scanner and parser use different tables for constants
Moreover, each function being parsed has its own table. The code is cleaner when each table is used for one specific purpose: The scanner uses its table to anchor and unify strings, mapping strings to themselves; the parser uses it to reuse constants in the code, mapping constants to their indices in the constant table. A different table for each task avoids false collisions.
-rw-r--r--lcode.c12
-rw-r--r--llex.c15
-rw-r--r--lparser.c7
-rw-r--r--lparser.h1
-rw-r--r--ltable.c11
-rw-r--r--ltable.h2
6 files changed, 20 insertions, 28 deletions
diff --git a/lcode.c b/lcode.c
index e6a98bb6..8f08302e 100644
--- a/lcode.c
+++ b/lcode.c
@@ -563,13 +563,13 @@ static int addk (FuncState *fs, Proto *f, TValue *v) {
563static int k2proto (FuncState *fs, TValue *key, TValue *v) { 563static int k2proto (FuncState *fs, TValue *key, TValue *v) {
564 TValue val; 564 TValue val;
565 Proto *f = fs->f; 565 Proto *f = fs->f;
566 int tag = luaH_get(fs->ls->h, key, &val); /* query scanner table */ 566 int tag = luaH_get(fs->kcache, key, &val); /* query scanner table */
567 int k; 567 int k;
568 if (tag == LUA_VNUMINT) { /* is there an index there? */ 568 if (!tagisempty(tag)) { /* is there an index there? */
569 k = cast_int(ivalue(&val)); 569 k = cast_int(ivalue(&val));
570 lua_assert(k < fs->nk);
570 /* correct value? (warning: must distinguish floats from integers!) */ 571 /* correct value? (warning: must distinguish floats from integers!) */
571 if (k < fs->nk && ttypetag(&f->k[k]) == ttypetag(v) && 572 if (ttypetag(&f->k[k]) == ttypetag(v) && luaV_rawequalobj(&f->k[k], v))
572 luaV_rawequalobj(&f->k[k], v))
573 return k; /* reuse index */ 573 return k; /* reuse index */
574 } 574 }
575 /* constant not found; create a new entry */ 575 /* constant not found; create a new entry */
@@ -577,7 +577,7 @@ static int k2proto (FuncState *fs, TValue *key, TValue *v) {
577 /* cache for reuse; numerical value does not need GC barrier; 577 /* cache for reuse; numerical value does not need GC barrier;
578 table has no metatable, so it does not need to invalidate cache */ 578 table has no metatable, so it does not need to invalidate cache */
579 setivalue(&val, k); 579 setivalue(&val, k);
580 luaH_set(fs->ls->L, fs->ls->h, key, &val); 580 luaH_set(fs->ls->L, fs->kcache, key, &val);
581 return k; 581 return k;
582} 582}
583 583
@@ -659,7 +659,7 @@ static int nilK (FuncState *fs) {
659 TValue k, v; 659 TValue k, v;
660 setnilvalue(&v); 660 setnilvalue(&v);
661 /* cannot use nil as key; instead use table itself to represent nil */ 661 /* cannot use nil as key; instead use table itself to represent nil */
662 sethvalue(fs->ls->L, &k, fs->ls->h); 662 sethvalue(fs->ls->L, &k, fs->kcache);
663 return k2proto(fs, &k, &v); 663 return k2proto(fs, &k, &v);
664} 664}
665 665
diff --git a/llex.c b/llex.c
index b2e77c9c..d913db17 100644
--- a/llex.c
+++ b/llex.c
@@ -130,18 +130,15 @@ l_noret luaX_syntaxerror (LexState *ls, const char *msg) {
130** Creates a new string and anchors it in scanner's table so that it 130** Creates a new string and anchors it in scanner's table so that it
131** will not be collected until the end of the compilation; by that time 131** will not be collected until the end of the compilation; by that time
132** it should be anchored somewhere. It also internalizes long strings, 132** it should be anchored somewhere. It also internalizes long strings,
133** ensuring there is only one copy of each unique string. The table 133** ensuring there is only one copy of each unique string.
134** here is used as a set: the string enters as the key, while its value
135** is irrelevant. We use the string itself as the value only because it
136** is a TValue readily available. Later, the code generation can change
137** this value.
138*/ 134*/
139TString *luaX_newstring (LexState *ls, const char *str, size_t l) { 135TString *luaX_newstring (LexState *ls, const char *str, size_t l) {
140 lua_State *L = ls->L; 136 lua_State *L = ls->L;
141 TString *ts = luaS_newlstr(L, str, l); /* create new string */ 137 TString *ts = luaS_newlstr(L, str, l); /* create new string */
142 TString *oldts = luaH_getstrkey(ls->h, ts); 138 TValue oldts;
143 if (oldts != NULL) /* string already present? */ 139 int tag = luaH_getstr(ls->h, ts, &oldts);
144 return oldts; /* use it */ 140 if (!tagisempty(tag)) /* string already present? */
141 return tsvalue(&oldts); /* use stored value */
145 else { /* create a new entry */ 142 else { /* create a new entry */
146 TValue *stv = s2v(L->top.p++); /* reserve stack space for string */ 143 TValue *stv = s2v(L->top.p++); /* reserve stack space for string */
147 setsvalue(L, stv, ts); /* temporarily anchor the string */ 144 setsvalue(L, stv, ts); /* temporarily anchor the string */
@@ -149,8 +146,8 @@ TString *luaX_newstring (LexState *ls, const char *str, size_t l) {
149 /* table is not a metatable, so it does not need to invalidate cache */ 146 /* table is not a metatable, so it does not need to invalidate cache */
150 luaC_checkGC(L); 147 luaC_checkGC(L);
151 L->top.p--; /* remove string from stack */ 148 L->top.p--; /* remove string from stack */
149 return ts;
152 } 150 }
153 return ts;
154} 151}
155 152
156 153
diff --git a/lparser.c b/lparser.c
index 3db7df4c..642e43b7 100644
--- a/lparser.c
+++ b/lparser.c
@@ -737,6 +737,7 @@ static void codeclosure (LexState *ls, expdesc *v) {
737 737
738 738
739static void open_func (LexState *ls, FuncState *fs, BlockCnt *bl) { 739static void open_func (LexState *ls, FuncState *fs, BlockCnt *bl) {
740 lua_State *L = ls->L;
740 Proto *f = fs->f; 741 Proto *f = fs->f;
741 fs->prev = ls->fs; /* linked list of funcstates */ 742 fs->prev = ls->fs; /* linked list of funcstates */
742 fs->ls = ls; 743 fs->ls = ls;
@@ -757,8 +758,11 @@ static void open_func (LexState *ls, FuncState *fs, BlockCnt *bl) {
757 fs->firstlabel = ls->dyd->label.n; 758 fs->firstlabel = ls->dyd->label.n;
758 fs->bl = NULL; 759 fs->bl = NULL;
759 f->source = ls->source; 760 f->source = ls->source;
760 luaC_objbarrier(ls->L, f, f->source); 761 luaC_objbarrier(L, f, f->source);
761 f->maxstacksize = 2; /* registers 0/1 are always valid */ 762 f->maxstacksize = 2; /* registers 0/1 are always valid */
763 fs->kcache = luaH_new(L); /* create table for function */
764 sethvalue2s(L, L->top.p, fs->kcache); /* anchor it */
765 luaD_inctop(L);
762 enterblock(fs, bl, 0); 766 enterblock(fs, bl, 0);
763} 767}
764 768
@@ -780,6 +784,7 @@ static void close_func (LexState *ls) {
780 luaM_shrinkvector(L, f->locvars, f->sizelocvars, fs->ndebugvars, LocVar); 784 luaM_shrinkvector(L, f->locvars, f->sizelocvars, fs->ndebugvars, LocVar);
781 luaM_shrinkvector(L, f->upvalues, f->sizeupvalues, fs->nups, Upvaldesc); 785 luaM_shrinkvector(L, f->upvalues, f->sizeupvalues, fs->nups, Upvaldesc);
782 ls->fs = fs->prev; 786 ls->fs = fs->prev;
787 L->top.p--; /* pop kcache table */
783 luaC_checkGC(L); 788 luaC_checkGC(L);
784} 789}
785 790
diff --git a/lparser.h b/lparser.h
index 8a87776d..589befdb 100644
--- a/lparser.h
+++ b/lparser.h
@@ -146,6 +146,7 @@ typedef struct FuncState {
146 struct FuncState *prev; /* enclosing function */ 146 struct FuncState *prev; /* enclosing function */
147 struct LexState *ls; /* lexical state */ 147 struct LexState *ls; /* lexical state */
148 struct BlockCnt *bl; /* chain of current blocks */ 148 struct BlockCnt *bl; /* chain of current blocks */
149 Table *kcache; /* cache for reusing constants */
149 int pc; /* next position to code (equivalent to 'ncode') */ 150 int pc; /* next position to code (equivalent to 'ncode') */
150 int lasttarget; /* 'label' of last 'jump label' */ 151 int lasttarget; /* 'label' of last 'jump label' */
151 int previousline; /* last line that was saved in 'lineinfo' */ 152 int previousline; /* last line that was saved in 'lineinfo' */
diff --git a/ltable.c b/ltable.c
index 052e005e..eb5abf9f 100644
--- a/ltable.c
+++ b/ltable.c
@@ -962,7 +962,7 @@ lu_byte luaH_getint (Table *t, lua_Integer key, TValue *res) {
962*/ 962*/
963const TValue *luaH_Hgetshortstr (Table *t, TString *key) { 963const TValue *luaH_Hgetshortstr (Table *t, TString *key) {
964 Node *n = hashstr(t, key); 964 Node *n = hashstr(t, key);
965 lua_assert(key->tt == LUA_VSHRSTR); 965 lua_assert(strisshr(key));
966 for (;;) { /* check whether 'key' is somewhere in the chain */ 966 for (;;) { /* check whether 'key' is somewhere in the chain */
967 if (keyisshrstr(n) && eqshrstr(keystrval(n), key)) 967 if (keyisshrstr(n) && eqshrstr(keystrval(n), key))
968 return gval(n); /* that's it */ 968 return gval(n); /* that's it */
@@ -997,15 +997,6 @@ lu_byte luaH_getstr (Table *t, TString *key, TValue *res) {
997} 997}
998 998
999 999
1000TString *luaH_getstrkey (Table *t, TString *key) {
1001 const TValue *o = Hgetstr(t, key);
1002 if (!isabstkey(o)) /* string already present? */
1003 return keystrval(nodefromval(o)); /* get saved copy */
1004 else
1005 return NULL;
1006}
1007
1008
1009/* 1000/*
1010** main search function 1001** main search function
1011*/ 1002*/
diff --git a/ltable.h b/ltable.h
index e4aa98f0..ca21e692 100644
--- a/ltable.h
+++ b/ltable.h
@@ -154,8 +154,6 @@ LUAI_FUNC lu_byte luaH_getint (Table *t, lua_Integer key, TValue *res);
154/* Special get for metamethods */ 154/* Special get for metamethods */
155LUAI_FUNC const TValue *luaH_Hgetshortstr (Table *t, TString *key); 155LUAI_FUNC const TValue *luaH_Hgetshortstr (Table *t, TString *key);
156 156
157LUAI_FUNC TString *luaH_getstrkey (Table *t, TString *key);
158
159LUAI_FUNC int luaH_psetint (Table *t, lua_Integer key, TValue *val); 157LUAI_FUNC int luaH_psetint (Table *t, lua_Integer key, TValue *val);
160LUAI_FUNC int luaH_psetshortstr (Table *t, TString *key, TValue *val); 158LUAI_FUNC int luaH_psetshortstr (Table *t, TString *key, TValue *val);
161LUAI_FUNC int luaH_psetstr (Table *t, TString *key, TValue *val); 159LUAI_FUNC int luaH_psetstr (Table *t, TString *key, TValue *val);