diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2020-12-04 11:08:42 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2020-12-04 11:08:42 -0300 |
commit | 23051e830a8b212f831443eb888e93e30fa8bb19 (patch) | |
tree | 782f56415ad3a8799c4dea8d6d329f1550d3d7c3 | |
parent | f15589f3b0da477e5dda8863cbf4c0b36469e36d (diff) | |
download | lua-23051e830a8b212f831443eb888e93e30fa8bb19.tar.gz lua-23051e830a8b212f831443eb888e93e30fa8bb19.tar.bz2 lua-23051e830a8b212f831443eb888e93e30fa8bb19.zip |
Changes in the API of 'luaH_set' and related functions
Functions to set values in a table (luaH_set, luaH_newkey, etc.) receive
the new value, instead of returning a slot where to put the value.
-rw-r--r-- | lapi.c | 4 | ||||
-rw-r--r-- | lcode.c | 8 | ||||
-rw-r--r-- | llex.c | 31 | ||||
-rw-r--r-- | ltable.c | 42 | ||||
-rw-r--r-- | ltable.h | 8 | ||||
-rw-r--r-- | lvm.c | 5 |
6 files changed, 58 insertions, 40 deletions
@@ -871,12 +871,10 @@ LUA_API void lua_seti (lua_State *L, int idx, lua_Integer n) { | |||
871 | 871 | ||
872 | static void aux_rawset (lua_State *L, int idx, TValue *key, int n) { | 872 | static void aux_rawset (lua_State *L, int idx, TValue *key, int n) { |
873 | Table *t; | 873 | Table *t; |
874 | TValue *slot; | ||
875 | lua_lock(L); | 874 | lua_lock(L); |
876 | api_checknelems(L, n); | 875 | api_checknelems(L, n); |
877 | t = gettable(L, idx); | 876 | t = gettable(L, idx); |
878 | slot = luaH_set(L, t, key); | 877 | luaH_set(L, t, key, s2v(L->top - 1)); |
879 | setobj2t(L, slot, s2v(L->top - 1)); | ||
880 | invalidateTMcache(t); | 878 | invalidateTMcache(t); |
881 | luaC_barrierback(L, obj2gco(t), s2v(L->top - 1)); | 879 | luaC_barrierback(L, obj2gco(t), s2v(L->top - 1)); |
882 | L->top -= n; | 880 | L->top -= n; |
@@ -545,11 +545,14 @@ static void freeexps (FuncState *fs, expdesc *e1, expdesc *e2) { | |||
545 | ** and try to reuse constants. Because some values should not be used | 545 | ** and try to reuse constants. Because some values should not be used |
546 | ** as keys (nil cannot be a key, integer keys can collapse with float | 546 | ** as keys (nil cannot be a key, integer keys can collapse with float |
547 | ** keys), the caller must provide a useful 'key' for indexing the cache. | 547 | ** keys), the caller must provide a useful 'key' for indexing the cache. |
548 | ** Note that all functions share the same table, so entering or exiting | ||
549 | ** a function can make some indices wrong. | ||
548 | */ | 550 | */ |
549 | static int addk (FuncState *fs, TValue *key, TValue *v) { | 551 | static int addk (FuncState *fs, TValue *key, TValue *v) { |
552 | TValue val; | ||
550 | lua_State *L = fs->ls->L; | 553 | lua_State *L = fs->ls->L; |
551 | Proto *f = fs->f; | 554 | Proto *f = fs->f; |
552 | TValue *idx = luaH_set(L, fs->ls->h, key); /* index scanner table */ | 555 | const TValue *idx = luaH_get(fs->ls->h, key); /* query scanner table */ |
553 | int k, oldsize; | 556 | int k, oldsize; |
554 | if (ttisinteger(idx)) { /* is there an index there? */ | 557 | if (ttisinteger(idx)) { /* is there an index there? */ |
555 | k = cast_int(ivalue(idx)); | 558 | k = cast_int(ivalue(idx)); |
@@ -563,7 +566,8 @@ static int addk (FuncState *fs, TValue *key, TValue *v) { | |||
563 | k = fs->nk; | 566 | k = fs->nk; |
564 | /* numerical value does not need GC barrier; | 567 | /* numerical value does not need GC barrier; |
565 | table has no metatable, so it does not need to invalidate cache */ | 568 | table has no metatable, so it does not need to invalidate cache */ |
566 | setivalue(idx, k); | 569 | setivalue(&val, k); |
570 | luaH_finishset(L, fs->ls->h, key, idx, &val); | ||
567 | luaM_growvector(L, f->k, k, f->sizek, TValue, MAXARG_Ax, "constants"); | 571 | luaM_growvector(L, f->k, k, f->sizek, TValue, MAXARG_Ax, "constants"); |
568 | while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]); | 572 | while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]); |
569 | setobj(L, &f->k[k], v); | 573 | setobj(L, &f->k[k], v); |
@@ -122,26 +122,29 @@ l_noret luaX_syntaxerror (LexState *ls, const char *msg) { | |||
122 | 122 | ||
123 | 123 | ||
124 | /* | 124 | /* |
125 | ** creates a new string and anchors it in scanner's table so that | 125 | ** Creates a new string and anchors it in scanner's table so that it |
126 | ** it will not be collected until the end of the compilation | 126 | ** will not be collected until the end of the compilation; by that time |
127 | ** (by that time it should be anchored somewhere) | 127 | ** it should be anchored somewhere. It also internalizes long strings, |
128 | ** ensuring there is only one copy of each unique string. The table | ||
129 | ** here is used as a set: the string enters as the key, while its value | ||
130 | ** is irrelevant. We use the string itself as the value only because it | ||
131 | ** is a TValue readly available. Later, the code generation can change | ||
132 | ** this value. | ||
128 | */ | 133 | */ |
129 | TString *luaX_newstring (LexState *ls, const char *str, size_t l) { | 134 | TString *luaX_newstring (LexState *ls, const char *str, size_t l) { |
130 | lua_State *L = ls->L; | 135 | lua_State *L = ls->L; |
131 | TValue *o; /* entry for 'str' */ | ||
132 | TString *ts = luaS_newlstr(L, str, l); /* create new string */ | 136 | TString *ts = luaS_newlstr(L, str, l); /* create new string */ |
133 | setsvalue2s(L, L->top++, ts); /* temporarily anchor it in stack */ | 137 | const TValue *o = luaH_getstr(ls->h, ts); |
134 | o = luaH_set(L, ls->h, s2v(L->top - 1)); | 138 | if (!ttisnil(o)) /* string already present? */ |
135 | if (isempty(o)) { /* not in use yet? */ | 139 | ts = keystrval(nodefromval(o)); /* get saved copy */ |
136 | /* boolean value does not need GC barrier; | 140 | else { /* not in use yet */ |
137 | table is not a metatable, so it does not need to invalidate cache */ | 141 | TValue *stv = s2v(L->top++); /* reserve stack space for string */ |
138 | setbtvalue(o); /* t[string] = true */ | 142 | setsvalue(L, stv, ts); /* temporarily anchor the string */ |
143 | luaH_finishset(L, ls->h, stv, o, stv); /* t[string] = string */ | ||
144 | /* table is not a metatable, so it does not need to invalidate cache */ | ||
139 | luaC_checkGC(L); | 145 | luaC_checkGC(L); |
146 | L->top--; /* remove string from stack */ | ||
140 | } | 147 | } |
141 | else { /* string already present */ | ||
142 | ts = keystrval(nodefromval(o)); /* re-use value previously stored */ | ||
143 | } | ||
144 | L->top--; /* remove string from stack */ | ||
145 | return ts; | 148 | return ts; |
146 | } | 149 | } |
147 | 150 | ||
@@ -485,7 +485,7 @@ static void reinsert (lua_State *L, Table *ot, Table *t) { | |||
485 | already present in the table */ | 485 | already present in the table */ |
486 | TValue k; | 486 | TValue k; |
487 | getnodekey(L, &k, old); | 487 | getnodekey(L, &k, old); |
488 | setobjt2t(L, luaH_set(L, t, &k), gval(old)); | 488 | luaH_set(L, t, &k, gval(old)); |
489 | } | 489 | } |
490 | } | 490 | } |
491 | } | 491 | } |
@@ -632,7 +632,7 @@ static Node *getfreepos (Table *t) { | |||
632 | ** put new key in its main position; otherwise (colliding node is in its main | 632 | ** put new key in its main position; otherwise (colliding node is in its main |
633 | ** position), new key goes to an empty position. | 633 | ** position), new key goes to an empty position. |
634 | */ | 634 | */ |
635 | TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) { | 635 | void luaH_newkey (lua_State *L, Table *t, const TValue *key, TValue *value) { |
636 | Node *mp; | 636 | Node *mp; |
637 | TValue aux; | 637 | TValue aux; |
638 | if (unlikely(ttisnil(key))) | 638 | if (unlikely(ttisnil(key))) |
@@ -654,7 +654,8 @@ TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) { | |||
654 | if (f == NULL) { /* cannot find a free place? */ | 654 | if (f == NULL) { /* cannot find a free place? */ |
655 | rehash(L, t, key); /* grow table */ | 655 | rehash(L, t, key); /* grow table */ |
656 | /* whatever called 'newkey' takes care of TM cache */ | 656 | /* whatever called 'newkey' takes care of TM cache */ |
657 | return luaH_set(L, t, key); /* insert key into grown table */ | 657 | luaH_set(L, t, key, value); /* insert key into grown table */ |
658 | return; | ||
658 | } | 659 | } |
659 | lua_assert(!isdummy(t)); | 660 | lua_assert(!isdummy(t)); |
660 | othern = mainposition(t, keytt(mp), &keyval(mp)); | 661 | othern = mainposition(t, keytt(mp), &keyval(mp)); |
@@ -682,7 +683,7 @@ TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) { | |||
682 | setnodekey(L, mp, key); | 683 | setnodekey(L, mp, key); |
683 | luaC_barrierback(L, obj2gco(t), key); | 684 | luaC_barrierback(L, obj2gco(t), key); |
684 | lua_assert(isempty(gval(mp))); | 685 | lua_assert(isempty(gval(mp))); |
685 | return gval(mp); | 686 | setobj2t(L, gval(mp), value); |
686 | } | 687 | } |
687 | 688 | ||
688 | 689 | ||
@@ -770,28 +771,39 @@ const TValue *luaH_get (Table *t, const TValue *key) { | |||
770 | 771 | ||
771 | 772 | ||
772 | /* | 773 | /* |
774 | ** Finish a raw "set table" operation, where 'slot' is where the value | ||
775 | ** should have been (the result of a previous "get table"). | ||
776 | ** Beware: when using this function you probably need to check a GC | ||
777 | ** barrier and invalidate the TM cache. | ||
778 | */ | ||
779 | void luaH_finishset (lua_State *L, Table *t, const TValue *key, | ||
780 | const TValue *slot, TValue *value) { | ||
781 | if (isabstkey(slot)) | ||
782 | luaH_newkey(L, t, key, value); | ||
783 | else | ||
784 | setobj2t(L, cast(TValue *, slot), value); | ||
785 | } | ||
786 | |||
787 | |||
788 | /* | ||
773 | ** beware: when using this function you probably need to check a GC | 789 | ** beware: when using this function you probably need to check a GC |
774 | ** barrier and invalidate the TM cache. | 790 | ** barrier and invalidate the TM cache. |
775 | */ | 791 | */ |
776 | TValue *luaH_set (lua_State *L, Table *t, const TValue *key) { | 792 | void luaH_set (lua_State *L, Table *t, const TValue *key, TValue *value) { |
777 | const TValue *p = luaH_get(t, key); | 793 | const TValue *slot = luaH_get(t, key); |
778 | if (!isabstkey(p)) | 794 | luaH_finishset(L, t, key, slot, value); |
779 | return cast(TValue *, p); | ||
780 | else return luaH_newkey(L, t, key); | ||
781 | } | 795 | } |
782 | 796 | ||
783 | 797 | ||
784 | void luaH_setint (lua_State *L, Table *t, lua_Integer key, TValue *value) { | 798 | void luaH_setint (lua_State *L, Table *t, lua_Integer key, TValue *value) { |
785 | const TValue *p = luaH_getint(t, key); | 799 | const TValue *p = luaH_getint(t, key); |
786 | TValue *cell; | 800 | if (isabstkey(p)) { |
787 | if (!isabstkey(p)) | ||
788 | cell = cast(TValue *, p); | ||
789 | else { | ||
790 | TValue k; | 801 | TValue k; |
791 | setivalue(&k, key); | 802 | setivalue(&k, key); |
792 | cell = luaH_newkey(L, t, &k); | 803 | luaH_newkey(L, t, &k, value); |
793 | } | 804 | } |
794 | setobj2t(L, cell, value); | 805 | else |
806 | setobj2t(L, cast(TValue *, p), value); | ||
795 | } | 807 | } |
796 | 808 | ||
797 | 809 | ||
@@ -41,8 +41,12 @@ LUAI_FUNC void luaH_setint (lua_State *L, Table *t, lua_Integer key, | |||
41 | LUAI_FUNC const TValue *luaH_getshortstr (Table *t, TString *key); | 41 | LUAI_FUNC const TValue *luaH_getshortstr (Table *t, TString *key); |
42 | LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key); | 42 | LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key); |
43 | LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key); | 43 | LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key); |
44 | LUAI_FUNC TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key); | 44 | LUAI_FUNC void luaH_newkey (lua_State *L, Table *t, const TValue *key, |
45 | LUAI_FUNC TValue *luaH_set (lua_State *L, Table *t, const TValue *key); | 45 | TValue *value); |
46 | LUAI_FUNC void luaH_set (lua_State *L, Table *t, const TValue *key, | ||
47 | TValue *value); | ||
48 | LUAI_FUNC void luaH_finishset (lua_State *L, Table *t, const TValue *key, | ||
49 | const TValue *slot, TValue *value); | ||
46 | LUAI_FUNC Table *luaH_new (lua_State *L); | 50 | LUAI_FUNC Table *luaH_new (lua_State *L); |
47 | LUAI_FUNC void luaH_resize (lua_State *L, Table *t, unsigned int nasize, | 51 | LUAI_FUNC void luaH_resize (lua_State *L, Table *t, unsigned int nasize, |
48 | unsigned int nhsize); | 52 | unsigned int nhsize); |
@@ -337,10 +337,7 @@ void luaV_finishset (lua_State *L, const TValue *t, TValue *key, | |||
337 | lua_assert(isempty(slot)); /* slot must be empty */ | 337 | lua_assert(isempty(slot)); /* slot must be empty */ |
338 | tm = fasttm(L, h->metatable, TM_NEWINDEX); /* get metamethod */ | 338 | tm = fasttm(L, h->metatable, TM_NEWINDEX); /* get metamethod */ |
339 | if (tm == NULL) { /* no metamethod? */ | 339 | if (tm == NULL) { /* no metamethod? */ |
340 | if (isabstkey(slot)) /* no previous entry? */ | 340 | luaH_finishset(L, h, key, slot, val); /* set new value */ |
341 | slot = luaH_newkey(L, h, key); /* create one */ | ||
342 | /* no metamethod and (now) there is an entry with given key */ | ||
343 | setobj2t(L, cast(TValue *, slot), val); /* set its new value */ | ||
344 | invalidateTMcache(h); | 341 | invalidateTMcache(h); |
345 | luaC_barrierback(L, obj2gco(h), val); | 342 | luaC_barrierback(L, obj2gco(h), val); |
346 | return; | 343 | return; |