diff options
author | Li Jin <dragon-fly@qq.com> | 2021-01-05 16:48:53 +0800 |
---|---|---|
committer | Li Jin <dragon-fly@qq.com> | 2021-01-05 16:48:53 +0800 |
commit | 71b9532659abb531bd1597d88451426dcc895824 (patch) | |
tree | c9b50856b37f759c9a31e1a6e761e77b51996fa6 | |
parent | e3a31f9945053d8e8d9e4ef3d2e4c9abe563cff2 (diff) | |
download | yuescript-71b9532659abb531bd1597d88451426dcc895824.tar.gz yuescript-71b9532659abb531bd1597d88451426dcc895824.tar.bz2 yuescript-71b9532659abb531bd1597d88451426dcc895824.zip |
update Lua.
-rw-r--r-- | src/lua/lapi.c | 29 | ||||
-rw-r--r-- | src/lua/lauxlib.c | 96 | ||||
-rw-r--r-- | src/lua/lauxlib.h | 16 | ||||
-rw-r--r-- | src/lua/lcode.c | 28 | ||||
-rw-r--r-- | src/lua/ldblib.c | 4 | ||||
-rw-r--r-- | src/lua/ldo.c | 18 | ||||
-rw-r--r-- | src/lua/lgc.c | 4 | ||||
-rw-r--r-- | src/lua/liolib.c | 18 | ||||
-rw-r--r-- | src/lua/llex.c | 56 | ||||
-rw-r--r-- | src/lua/llimits.h | 3 | ||||
-rw-r--r-- | src/lua/lobject.c | 2 | ||||
-rw-r--r-- | src/lua/lparser.c | 104 | ||||
-rw-r--r-- | src/lua/lparser.h | 11 | ||||
-rw-r--r-- | src/lua/lstate.c | 11 | ||||
-rw-r--r-- | src/lua/ltable.c | 69 | ||||
-rw-r--r-- | src/lua/ltable.h | 8 | ||||
-rw-r--r-- | src/lua/lualib.h | 6 | ||||
-rw-r--r-- | src/lua/lvm.c | 5 |
18 files changed, 270 insertions, 218 deletions
diff --git a/src/lua/lapi.c b/src/lua/lapi.c index c824da2..03e756d 100644 --- a/src/lua/lapi.c +++ b/src/lua/lapi.c | |||
@@ -629,11 +629,21 @@ static int auxgetstr (lua_State *L, const TValue *t, const char *k) { | |||
629 | } | 629 | } |
630 | 630 | ||
631 | 631 | ||
632 | /* | ||
633 | ** Get the global table in the registry. Since all predefined | ||
634 | ** indices in the registry were inserted right when the registry | ||
635 | ** was created and never removed, they must always be in the array | ||
636 | ** part of the registry. | ||
637 | */ | ||
638 | #define getGtable(L) \ | ||
639 | (&hvalue(&G(L)->l_registry)->array[LUA_RIDX_GLOBALS - 1]) | ||
640 | |||
641 | |||
632 | LUA_API int lua_getglobal (lua_State *L, const char *name) { | 642 | LUA_API int lua_getglobal (lua_State *L, const char *name) { |
633 | Table *reg; | 643 | const TValue *G; |
634 | lua_lock(L); | 644 | lua_lock(L); |
635 | reg = hvalue(&G(L)->l_registry); | 645 | G = getGtable(L); |
636 | return auxgetstr(L, luaH_getint(reg, LUA_RIDX_GLOBALS), name); | 646 | return auxgetstr(L, G, name); |
637 | } | 647 | } |
638 | 648 | ||
639 | 649 | ||
@@ -811,10 +821,10 @@ static void auxsetstr (lua_State *L, const TValue *t, const char *k) { | |||
811 | 821 | ||
812 | 822 | ||
813 | LUA_API void lua_setglobal (lua_State *L, const char *name) { | 823 | LUA_API void lua_setglobal (lua_State *L, const char *name) { |
814 | Table *reg; | 824 | const TValue *G; |
815 | lua_lock(L); /* unlock done in 'auxsetstr' */ | 825 | lua_lock(L); /* unlock done in 'auxsetstr' */ |
816 | reg = hvalue(&G(L)->l_registry); | 826 | G = getGtable(L); |
817 | auxsetstr(L, luaH_getint(reg, LUA_RIDX_GLOBALS), name); | 827 | auxsetstr(L, G, name); |
818 | } | 828 | } |
819 | 829 | ||
820 | 830 | ||
@@ -861,12 +871,10 @@ LUA_API void lua_seti (lua_State *L, int idx, lua_Integer n) { | |||
861 | 871 | ||
862 | 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) { |
863 | Table *t; | 873 | Table *t; |
864 | TValue *slot; | ||
865 | lua_lock(L); | 874 | lua_lock(L); |
866 | api_checknelems(L, n); | 875 | api_checknelems(L, n); |
867 | t = gettable(L, idx); | 876 | t = gettable(L, idx); |
868 | slot = luaH_set(L, t, key); | 877 | luaH_set(L, t, key, s2v(L->top - 1)); |
869 | setobj2t(L, slot, s2v(L->top - 1)); | ||
870 | invalidateTMcache(t); | 878 | invalidateTMcache(t); |
871 | luaC_barrierback(L, obj2gco(t), s2v(L->top - 1)); | 879 | luaC_barrierback(L, obj2gco(t), s2v(L->top - 1)); |
872 | L->top -= n; | 880 | L->top -= n; |
@@ -1063,8 +1071,7 @@ LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data, | |||
1063 | LClosure *f = clLvalue(s2v(L->top - 1)); /* get newly created function */ | 1071 | LClosure *f = clLvalue(s2v(L->top - 1)); /* get newly created function */ |
1064 | if (f->nupvalues >= 1) { /* does it have an upvalue? */ | 1072 | if (f->nupvalues >= 1) { /* does it have an upvalue? */ |
1065 | /* get global table from registry */ | 1073 | /* get global table from registry */ |
1066 | Table *reg = hvalue(&G(L)->l_registry); | 1074 | const TValue *gt = getGtable(L); |
1067 | const TValue *gt = luaH_getint(reg, LUA_RIDX_GLOBALS); | ||
1068 | /* set global table as 1st upvalue of 'f' (may be LUA_ENV) */ | 1075 | /* set global table as 1st upvalue of 'f' (may be LUA_ENV) */ |
1069 | setobj(L, f->upvals[0]->v, gt); | 1076 | setobj(L, f->upvals[0]->v, gt); |
1070 | luaC_barrier(L, f->upvals[0], gt); | 1077 | luaC_barrier(L, f->upvals[0], gt); |
diff --git a/src/lua/lauxlib.c b/src/lua/lauxlib.c index cbe9ed3..074ff08 100644 --- a/src/lua/lauxlib.c +++ b/src/lua/lauxlib.c | |||
@@ -283,10 +283,10 @@ LUALIB_API int luaL_fileresult (lua_State *L, int stat, const char *fname) { | |||
283 | 283 | ||
284 | 284 | ||
285 | LUALIB_API int luaL_execresult (lua_State *L, int stat) { | 285 | LUALIB_API int luaL_execresult (lua_State *L, int stat) { |
286 | const char *what = "exit"; /* type of termination */ | ||
287 | if (stat != 0 && errno != 0) /* error with an 'errno'? */ | 286 | if (stat != 0 && errno != 0) /* error with an 'errno'? */ |
288 | return luaL_fileresult(L, 0, NULL); | 287 | return luaL_fileresult(L, 0, NULL); |
289 | else { | 288 | else { |
289 | const char *what = "exit"; /* type of termination */ | ||
290 | l_inspectstat(stat, what); /* interpret result */ | 290 | l_inspectstat(stat, what); /* interpret result */ |
291 | if (*what == 'e' && stat == 0) /* successful termination? */ | 291 | if (*what == 'e' && stat == 0) /* successful termination? */ |
292 | lua_pushboolean(L, 1); | 292 | lua_pushboolean(L, 1); |
@@ -639,10 +639,14 @@ LUALIB_API char *luaL_buffinitsize (lua_State *L, luaL_Buffer *B, size_t sz) { | |||
639 | ** ======================================================= | 639 | ** ======================================================= |
640 | */ | 640 | */ |
641 | 641 | ||
642 | /* index of free-list header */ | 642 | /* index of free-list header (after the predefined values) */ |
643 | #define freelist 0 | 643 | #define freelist (LUA_RIDX_LAST + 1) |
644 | |||
645 | 644 | ||
645 | /* | ||
646 | ** The previously freed references form a linked list: | ||
647 | ** t[freelist] is the index of a first free index, or zero if list is | ||
648 | ** empty; t[t[freelist]] is the index of the second element; etc. | ||
649 | */ | ||
646 | LUALIB_API int luaL_ref (lua_State *L, int t) { | 650 | LUALIB_API int luaL_ref (lua_State *L, int t) { |
647 | int ref; | 651 | int ref; |
648 | if (lua_isnil(L, -1)) { | 652 | if (lua_isnil(L, -1)) { |
@@ -650,9 +654,16 @@ LUALIB_API int luaL_ref (lua_State *L, int t) { | |||
650 | return LUA_REFNIL; /* 'nil' has a unique fixed reference */ | 654 | return LUA_REFNIL; /* 'nil' has a unique fixed reference */ |
651 | } | 655 | } |
652 | t = lua_absindex(L, t); | 656 | t = lua_absindex(L, t); |
653 | lua_rawgeti(L, t, freelist); /* get first free element */ | 657 | if (lua_rawgeti(L, t, freelist) == LUA_TNIL) { /* first access? */ |
654 | ref = (int)lua_tointeger(L, -1); /* ref = t[freelist] */ | 658 | ref = 0; /* list is empty */ |
655 | lua_pop(L, 1); /* remove it from stack */ | 659 | lua_pushinteger(L, 0); /* initialize as an empty list */ |
660 | lua_rawseti(L, t, freelist); /* ref = t[freelist] = 0 */ | ||
661 | } | ||
662 | else { /* already initialized */ | ||
663 | lua_assert(lua_isinteger(L, -1)); | ||
664 | ref = (int)lua_tointeger(L, -1); /* ref = t[freelist] */ | ||
665 | } | ||
666 | lua_pop(L, 1); /* remove element from stack */ | ||
656 | if (ref != 0) { /* any free element? */ | 667 | if (ref != 0) { /* any free element? */ |
657 | lua_rawgeti(L, t, ref); /* remove it from list */ | 668 | lua_rawgeti(L, t, ref); /* remove it from list */ |
658 | lua_rawseti(L, t, freelist); /* (t[freelist] = t[ref]) */ | 669 | lua_rawseti(L, t, freelist); /* (t[freelist] = t[ref]) */ |
@@ -668,6 +679,7 @@ LUALIB_API void luaL_unref (lua_State *L, int t, int ref) { | |||
668 | if (ref >= 0) { | 679 | if (ref >= 0) { |
669 | t = lua_absindex(L, t); | 680 | t = lua_absindex(L, t); |
670 | lua_rawgeti(L, t, freelist); | 681 | lua_rawgeti(L, t, freelist); |
682 | lua_assert(lua_isinteger(L, -1)); | ||
671 | lua_rawseti(L, t, ref); /* t[ref] = t[freelist] */ | 683 | lua_rawseti(L, t, ref); /* t[ref] = t[freelist] */ |
672 | lua_pushinteger(L, ref); | 684 | lua_pushinteger(L, ref); |
673 | lua_rawseti(L, t, freelist); /* t[freelist] = ref */ | 685 | lua_rawseti(L, t, freelist); /* t[freelist] = ref */ |
@@ -1006,43 +1018,67 @@ static int panic (lua_State *L) { | |||
1006 | 1018 | ||
1007 | 1019 | ||
1008 | /* | 1020 | /* |
1009 | ** Emit a warning. '*warnstate' means: | 1021 | ** Warning functions: |
1010 | ** 0 - warning system is off; | 1022 | ** warnfoff: warning system is off |
1011 | ** 1 - ready to start a new message; | 1023 | ** warnfon: ready to start a new message |
1012 | ** 2 - previous message is to be continued. | 1024 | ** warnfcont: previous message is to be continued |
1013 | */ | 1025 | */ |
1014 | static void warnf (void *ud, const char *message, int tocont) { | 1026 | static void warnfoff (void *ud, const char *message, int tocont); |
1015 | int *warnstate = (int *)ud; | 1027 | static void warnfon (void *ud, const char *message, int tocont); |
1016 | if (*warnstate != 2 && !tocont && *message == '@') { /* control message? */ | 1028 | static void warnfcont (void *ud, const char *message, int tocont); |
1017 | if (strcmp(message, "@off") == 0) | 1029 | |
1018 | *warnstate = 0; | 1030 | |
1019 | else if (strcmp(message, "@on") == 0) | 1031 | /* |
1020 | *warnstate = 1; | 1032 | ** Check whether message is a control message. If so, execute the |
1021 | return; | 1033 | ** control or ignore it if unknown. |
1034 | */ | ||
1035 | static int checkcontrol (lua_State *L, const char *message, int tocont) { | ||
1036 | if (tocont || *(message++) != '@') /* not a control message? */ | ||
1037 | return 0; | ||
1038 | else { | ||
1039 | if (strcmp(message, "off") == 0) | ||
1040 | lua_setwarnf(L, warnfoff, L); /* turn warnings off */ | ||
1041 | else if (strcmp(message, "on") == 0) | ||
1042 | lua_setwarnf(L, warnfon, L); /* turn warnings on */ | ||
1043 | return 1; /* it was a control message */ | ||
1022 | } | 1044 | } |
1023 | else if (*warnstate == 0) /* warnings off? */ | 1045 | } |
1024 | return; | 1046 | |
1025 | if (*warnstate == 1) /* previous message was the last? */ | 1047 | |
1026 | lua_writestringerror("%s", "Lua warning: "); /* start a new warning */ | 1048 | static void warnfoff (void *ud, const char *message, int tocont) { |
1049 | checkcontrol((lua_State *)ud, message, tocont); | ||
1050 | } | ||
1051 | |||
1052 | |||
1053 | /* | ||
1054 | ** Writes the message and handle 'tocont', finishing the message | ||
1055 | ** if needed and setting the next warn function. | ||
1056 | */ | ||
1057 | static void warnfcont (void *ud, const char *message, int tocont) { | ||
1058 | lua_State *L = (lua_State *)ud; | ||
1027 | lua_writestringerror("%s", message); /* write message */ | 1059 | lua_writestringerror("%s", message); /* write message */ |
1028 | if (tocont) /* not the last part? */ | 1060 | if (tocont) /* not the last part? */ |
1029 | *warnstate = 2; /* to be continued */ | 1061 | lua_setwarnf(L, warnfcont, L); /* to be continued */ |
1030 | else { /* last part */ | 1062 | else { /* last part */ |
1031 | lua_writestringerror("%s", "\n"); /* finish message with end-of-line */ | 1063 | lua_writestringerror("%s", "\n"); /* finish message with end-of-line */ |
1032 | *warnstate = 1; /* ready to start a new message */ | 1064 | lua_setwarnf(L, warnfon, L); /* next call is a new message */ |
1033 | } | 1065 | } |
1034 | } | 1066 | } |
1035 | 1067 | ||
1036 | 1068 | ||
1069 | static void warnfon (void *ud, const char *message, int tocont) { | ||
1070 | if (checkcontrol((lua_State *)ud, message, tocont)) /* control message? */ | ||
1071 | return; /* nothing else to be done */ | ||
1072 | lua_writestringerror("%s", "Lua warning: "); /* start a new warning */ | ||
1073 | warnfcont(ud, message, tocont); /* finish processing */ | ||
1074 | } | ||
1075 | |||
1076 | |||
1037 | LUALIB_API lua_State *luaL_newstate (void) { | 1077 | LUALIB_API lua_State *luaL_newstate (void) { |
1038 | lua_State *L = lua_newstate(l_alloc, NULL); | 1078 | lua_State *L = lua_newstate(l_alloc, NULL); |
1039 | if (L) { | 1079 | if (L) { |
1040 | int *warnstate; /* space for warning state */ | ||
1041 | lua_atpanic(L, &panic); | 1080 | lua_atpanic(L, &panic); |
1042 | warnstate = (int *)lua_newuserdatauv(L, sizeof(int), 0); | 1081 | lua_setwarnf(L, warnfoff, L); /* default is warnings off */ |
1043 | luaL_ref(L, LUA_REGISTRYINDEX); /* make sure it won't be collected */ | ||
1044 | *warnstate = 0; /* default is warnings off */ | ||
1045 | lua_setwarnf(L, warnf, warnstate); | ||
1046 | } | 1082 | } |
1047 | return L; | 1083 | return L; |
1048 | } | 1084 | } |
diff --git a/src/lua/lauxlib.h b/src/lua/lauxlib.h index 59fef6a..6571491 100644 --- a/src/lua/lauxlib.h +++ b/src/lua/lauxlib.h | |||
@@ -158,6 +158,22 @@ LUALIB_API void (luaL_requiref) (lua_State *L, const char *modname, | |||
158 | 158 | ||
159 | 159 | ||
160 | /* | 160 | /* |
161 | ** Internal assertions for in-house debugging | ||
162 | */ | ||
163 | #if !defined(lua_assert) | ||
164 | |||
165 | #if defined LUAI_ASSERT | ||
166 | #include <assert.h> | ||
167 | #define lua_assert(c) assert(c) | ||
168 | #else | ||
169 | #define lua_assert(c) ((void)0) | ||
170 | #endif | ||
171 | |||
172 | #endif | ||
173 | |||
174 | |||
175 | |||
176 | /* | ||
161 | ** {====================================================== | 177 | ** {====================================================== |
162 | ** Generic Buffer manipulation | 178 | ** Generic Buffer manipulation |
163 | ** ======================================================= | 179 | ** ======================================================= |
diff --git a/src/lua/lcode.c b/src/lua/lcode.c index 6f241c9..d8d353f 100644 --- a/src/lua/lcode.c +++ b/src/lua/lcode.c | |||
@@ -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); |
@@ -753,7 +757,7 @@ void luaK_setoneret (FuncState *fs, expdesc *e) { | |||
753 | 757 | ||
754 | 758 | ||
755 | /* | 759 | /* |
756 | ** Ensure that expression 'e' is not a variable (nor a constant). | 760 | ** Ensure that expression 'e' is not a variable (nor a <const>). |
757 | ** (Expression still may have jump lists.) | 761 | ** (Expression still may have jump lists.) |
758 | */ | 762 | */ |
759 | void luaK_dischargevars (FuncState *fs, expdesc *e) { | 763 | void luaK_dischargevars (FuncState *fs, expdesc *e) { |
@@ -763,7 +767,7 @@ void luaK_dischargevars (FuncState *fs, expdesc *e) { | |||
763 | break; | 767 | break; |
764 | } | 768 | } |
765 | case VLOCAL: { /* already in a register */ | 769 | case VLOCAL: { /* already in a register */ |
766 | e->u.info = e->u.var.sidx; | 770 | e->u.info = e->u.var.ridx; |
767 | e->k = VNONRELOC; /* becomes a non-relocatable value */ | 771 | e->k = VNONRELOC; /* becomes a non-relocatable value */ |
768 | break; | 772 | break; |
769 | } | 773 | } |
@@ -805,8 +809,8 @@ void luaK_dischargevars (FuncState *fs, expdesc *e) { | |||
805 | 809 | ||
806 | 810 | ||
807 | /* | 811 | /* |
808 | ** Ensures expression value is in register 'reg' (and therefore | 812 | ** Ensure expression value is in register 'reg', making 'e' a |
809 | ** 'e' will become a non-relocatable expression). | 813 | ** non-relocatable expression. |
810 | ** (Expression still may have jump lists.) | 814 | ** (Expression still may have jump lists.) |
811 | */ | 815 | */ |
812 | static void discharge2reg (FuncState *fs, expdesc *e, int reg) { | 816 | static void discharge2reg (FuncState *fs, expdesc *e, int reg) { |
@@ -860,7 +864,8 @@ static void discharge2reg (FuncState *fs, expdesc *e, int reg) { | |||
860 | 864 | ||
861 | 865 | ||
862 | /* | 866 | /* |
863 | ** Ensures expression value is in any register. | 867 | ** Ensure expression value is in a register, making 'e' a |
868 | ** non-relocatable expression. | ||
864 | ** (Expression still may have jump lists.) | 869 | ** (Expression still may have jump lists.) |
865 | */ | 870 | */ |
866 | static void discharge2anyreg (FuncState *fs, expdesc *e) { | 871 | static void discharge2anyreg (FuncState *fs, expdesc *e) { |
@@ -946,8 +951,11 @@ int luaK_exp2anyreg (FuncState *fs, expdesc *e) { | |||
946 | exp2reg(fs, e, e->u.info); /* put final result in it */ | 951 | exp2reg(fs, e, e->u.info); /* put final result in it */ |
947 | return e->u.info; | 952 | return e->u.info; |
948 | } | 953 | } |
954 | /* else expression has jumps and cannot change its register | ||
955 | to hold the jump values, because it is a local variable. | ||
956 | Go through to the default case. */ | ||
949 | } | 957 | } |
950 | luaK_exp2nextreg(fs, e); /* otherwise, use next available register */ | 958 | luaK_exp2nextreg(fs, e); /* default: use next available register */ |
951 | return e->u.info; | 959 | return e->u.info; |
952 | } | 960 | } |
953 | 961 | ||
@@ -1032,7 +1040,7 @@ void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) { | |||
1032 | switch (var->k) { | 1040 | switch (var->k) { |
1033 | case VLOCAL: { | 1041 | case VLOCAL: { |
1034 | freeexp(fs, ex); | 1042 | freeexp(fs, ex); |
1035 | exp2reg(fs, ex, var->u.var.sidx); /* compute 'ex' into proper place */ | 1043 | exp2reg(fs, ex, var->u.var.ridx); /* compute 'ex' into proper place */ |
1036 | return; | 1044 | return; |
1037 | } | 1045 | } |
1038 | case VUPVAL: { | 1046 | case VUPVAL: { |
@@ -1272,7 +1280,7 @@ void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { | |||
1272 | } | 1280 | } |
1273 | else { | 1281 | else { |
1274 | /* register index of the table */ | 1282 | /* register index of the table */ |
1275 | t->u.ind.t = (t->k == VLOCAL) ? t->u.var.sidx: t->u.info; | 1283 | t->u.ind.t = (t->k == VLOCAL) ? t->u.var.ridx: t->u.info; |
1276 | if (isKstr(fs, k)) { | 1284 | if (isKstr(fs, k)) { |
1277 | t->u.ind.idx = k->u.info; /* literal string */ | 1285 | t->u.ind.idx = k->u.info; /* literal string */ |
1278 | t->k = VINDEXSTR; | 1286 | t->k = VINDEXSTR; |
diff --git a/src/lua/ldblib.c b/src/lua/ldblib.c index 5a326ad..15593bf 100644 --- a/src/lua/ldblib.c +++ b/src/lua/ldblib.c | |||
@@ -377,7 +377,7 @@ static int db_sethook (lua_State *L) { | |||
377 | } | 377 | } |
378 | if (!luaL_getsubtable(L, LUA_REGISTRYINDEX, HOOKKEY)) { | 378 | if (!luaL_getsubtable(L, LUA_REGISTRYINDEX, HOOKKEY)) { |
379 | /* table just created; initialize it */ | 379 | /* table just created; initialize it */ |
380 | lua_pushstring(L, "k"); | 380 | lua_pushliteral(L, "k"); |
381 | lua_setfield(L, -2, "__mode"); /** hooktable.__mode = "k" */ | 381 | lua_setfield(L, -2, "__mode"); /** hooktable.__mode = "k" */ |
382 | lua_pushvalue(L, -1); | 382 | lua_pushvalue(L, -1); |
383 | lua_setmetatable(L, -2); /* metatable(hooktable) = hooktable */ | 383 | lua_setmetatable(L, -2); /* metatable(hooktable) = hooktable */ |
@@ -420,7 +420,7 @@ static int db_debug (lua_State *L) { | |||
420 | for (;;) { | 420 | for (;;) { |
421 | char buffer[250]; | 421 | char buffer[250]; |
422 | lua_writestringerror("%s", "lua_debug> "); | 422 | lua_writestringerror("%s", "lua_debug> "); |
423 | if (fgets(buffer, sizeof(buffer), stdin) == 0 || | 423 | if (fgets(buffer, sizeof(buffer), stdin) == NULL || |
424 | strcmp(buffer, "cont\n") == 0) | 424 | strcmp(buffer, "cont\n") == 0) |
425 | return 0; | 425 | return 0; |
426 | if (luaL_loadbuffer(L, buffer, strlen(buffer), "=(debug command)") || | 426 | if (luaL_loadbuffer(L, buffer, strlen(buffer), "=(debug command)") || |
diff --git a/src/lua/ldo.c b/src/lua/ldo.c index 5729b19..4b55c31 100644 --- a/src/lua/ldo.c +++ b/src/lua/ldo.c | |||
@@ -192,7 +192,7 @@ int luaD_reallocstack (lua_State *L, int newsize, int raiseerror) { | |||
192 | else return 0; /* do not raise an error */ | 192 | else return 0; /* do not raise an error */ |
193 | } | 193 | } |
194 | for (; lim < newsize; lim++) | 194 | for (; lim < newsize; lim++) |
195 | setnilvalue(s2v(newstack + lim)); /* erase new segment */ | 195 | setnilvalue(s2v(newstack + lim + EXTRA_STACK)); /* erase new segment */ |
196 | correctstack(L, L->stack, newstack); | 196 | correctstack(L, L->stack, newstack); |
197 | L->stack = newstack; | 197 | L->stack = newstack; |
198 | L->stack_last = L->stack + newsize; | 198 | L->stack_last = L->stack + newsize; |
@@ -534,11 +534,11 @@ CallInfo *luaD_precall (lua_State *L, StkId func, int nresults) { | |||
534 | 534 | ||
535 | 535 | ||
536 | /* | 536 | /* |
537 | ** Call a function (C or Lua). 'inc' can be 1 (increment number | 537 | ** Call a function (C or Lua) through C. 'inc' can be 1 (increment |
538 | ** of recursive invocations in the C stack) or nyci (the same plus | 538 | ** number of recursive invocations in the C stack) or nyci (the same |
539 | ** increment number of non-yieldable calls). | 539 | ** plus increment number of non-yieldable calls). |
540 | */ | 540 | */ |
541 | static void docall (lua_State *L, StkId func, int nResults, int inc) { | 541 | static void ccall (lua_State *L, StkId func, int nResults, int inc) { |
542 | CallInfo *ci; | 542 | CallInfo *ci; |
543 | L->nCcalls += inc; | 543 | L->nCcalls += inc; |
544 | if (unlikely(getCcalls(L) >= LUAI_MAXCCALLS)) | 544 | if (unlikely(getCcalls(L) >= LUAI_MAXCCALLS)) |
@@ -552,10 +552,10 @@ static void docall (lua_State *L, StkId func, int nResults, int inc) { | |||
552 | 552 | ||
553 | 553 | ||
554 | /* | 554 | /* |
555 | ** External interface for 'docall' | 555 | ** External interface for 'ccall' |
556 | */ | 556 | */ |
557 | void luaD_call (lua_State *L, StkId func, int nResults) { | 557 | void luaD_call (lua_State *L, StkId func, int nResults) { |
558 | return docall(L, func, nResults, 1); | 558 | ccall(L, func, nResults, 1); |
559 | } | 559 | } |
560 | 560 | ||
561 | 561 | ||
@@ -563,7 +563,7 @@ void luaD_call (lua_State *L, StkId func, int nResults) { | |||
563 | ** Similar to 'luaD_call', but does not allow yields during the call. | 563 | ** Similar to 'luaD_call', but does not allow yields during the call. |
564 | */ | 564 | */ |
565 | void luaD_callnoyield (lua_State *L, StkId func, int nResults) { | 565 | void luaD_callnoyield (lua_State *L, StkId func, int nResults) { |
566 | return docall(L, func, nResults, nyci); | 566 | ccall(L, func, nResults, nyci); |
567 | } | 567 | } |
568 | 568 | ||
569 | 569 | ||
@@ -678,7 +678,7 @@ static void resume (lua_State *L, void *ud) { | |||
678 | StkId firstArg = L->top - n; /* first argument */ | 678 | StkId firstArg = L->top - n; /* first argument */ |
679 | CallInfo *ci = L->ci; | 679 | CallInfo *ci = L->ci; |
680 | if (L->status == LUA_OK) /* starting a coroutine? */ | 680 | if (L->status == LUA_OK) /* starting a coroutine? */ |
681 | docall(L, firstArg - 1, LUA_MULTRET, 1); /* just call its body */ | 681 | ccall(L, firstArg - 1, LUA_MULTRET, 1); /* just call its body */ |
682 | else { /* resuming from previous yield */ | 682 | else { /* resuming from previous yield */ |
683 | lua_assert(L->status == LUA_YIELD); | 683 | lua_assert(L->status == LUA_YIELD); |
684 | L->status = LUA_OK; /* mark that it is running (again) */ | 684 | L->status = LUA_OK; /* mark that it is running (again) */ |
diff --git a/src/lua/lgc.c b/src/lua/lgc.c index 5dba56f..bab9beb 100644 --- a/src/lua/lgc.c +++ b/src/lua/lgc.c | |||
@@ -632,8 +632,8 @@ static int traversethread (global_State *g, lua_State *th) { | |||
632 | for (uv = th->openupval; uv != NULL; uv = uv->u.open.next) | 632 | for (uv = th->openupval; uv != NULL; uv = uv->u.open.next) |
633 | markobject(g, uv); /* open upvalues cannot be collected */ | 633 | markobject(g, uv); /* open upvalues cannot be collected */ |
634 | if (g->gcstate == GCSatomic) { /* final traversal? */ | 634 | if (g->gcstate == GCSatomic) { /* final traversal? */ |
635 | for (; o < th->stack_last; o++) /* clear not-marked stack slice */ | 635 | for (; o < th->stack_last + EXTRA_STACK; o++) |
636 | setnilvalue(s2v(o)); | 636 | setnilvalue(s2v(o)); /* clear dead stack slice */ |
637 | /* 'remarkupvals' may have removed thread from 'twups' list */ | 637 | /* 'remarkupvals' may have removed thread from 'twups' list */ |
638 | if (!isintwups(th) && th->openupval != NULL) { | 638 | if (!isintwups(th) && th->openupval != NULL) { |
639 | th->twups = g->twups; /* link it back to the list */ | 639 | th->twups = g->twups; /* link it back to the list */ |
diff --git a/src/lua/liolib.c b/src/lua/liolib.c index 60ab1bf..7951672 100644 --- a/src/lua/liolib.c +++ b/src/lua/liolib.c | |||
@@ -52,12 +52,6 @@ static int l_checkmode (const char *mode) { | |||
52 | ** ======================================================= | 52 | ** ======================================================= |
53 | */ | 53 | */ |
54 | 54 | ||
55 | #if !defined(l_checkmodep) | ||
56 | /* By default, Lua accepts only "r" or "w" as mode */ | ||
57 | #define l_checkmodep(m) ((m[0] == 'r' || m[0] == 'w') && m[1] == '\0') | ||
58 | #endif | ||
59 | |||
60 | |||
61 | #if !defined(l_popen) /* { */ | 55 | #if !defined(l_popen) /* { */ |
62 | 56 | ||
63 | #if defined(LUA_USE_POSIX) /* { */ | 57 | #if defined(LUA_USE_POSIX) /* { */ |
@@ -70,6 +64,12 @@ static int l_checkmode (const char *mode) { | |||
70 | #define l_popen(L,c,m) (_popen(c,m)) | 64 | #define l_popen(L,c,m) (_popen(c,m)) |
71 | #define l_pclose(L,file) (_pclose(file)) | 65 | #define l_pclose(L,file) (_pclose(file)) |
72 | 66 | ||
67 | #if !defined(l_checkmodep) | ||
68 | /* Windows accepts "[rw][bt]?" as valid modes */ | ||
69 | #define l_checkmodep(m) ((m[0] == 'r' || m[0] == 'w') && \ | ||
70 | (m[1] == '\0' || ((m[1] == 'b' || m[1] == 't') && m[2] == '\0'))) | ||
71 | #endif | ||
72 | |||
73 | #else /* }{ */ | 73 | #else /* }{ */ |
74 | 74 | ||
75 | /* ISO C definitions */ | 75 | /* ISO C definitions */ |
@@ -83,6 +83,12 @@ static int l_checkmode (const char *mode) { | |||
83 | 83 | ||
84 | #endif /* } */ | 84 | #endif /* } */ |
85 | 85 | ||
86 | |||
87 | #if !defined(l_checkmodep) | ||
88 | /* By default, Lua accepts only "r" or "w" as valid modes */ | ||
89 | #define l_checkmodep(m) ((m[0] == 'r' || m[0] == 'w') && m[1] == '\0') | ||
90 | #endif | ||
91 | |||
86 | /* }====================================================== */ | 92 | /* }====================================================== */ |
87 | 93 | ||
88 | 94 | ||
diff --git a/src/lua/llex.c b/src/lua/llex.c index 3d6b2b9..e991517 100644 --- a/src/lua/llex.c +++ b/src/lua/llex.c | |||
@@ -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 | ||
@@ -254,9 +257,10 @@ static int read_numeral (LexState *ls, SemInfo *seminfo) { | |||
254 | 257 | ||
255 | 258 | ||
256 | /* | 259 | /* |
257 | ** reads a sequence '[=*[' or ']=*]', leaving the last bracket. | 260 | ** read a sequence '[=*[' or ']=*]', leaving the last bracket. If |
258 | ** If sequence is well formed, return its number of '='s + 2; otherwise, | 261 | ** sequence is well formed, return its number of '='s + 2; otherwise, |
259 | ** return 1 if there is no '='s or 0 otherwise (an unfinished '[==...'). | 262 | ** return 1 if it is a single bracket (no '='s and no 2nd bracket); |
263 | ** otherwise (an unfinished '[==...') return 0. | ||
260 | */ | 264 | */ |
261 | static size_t skip_sep (LexState *ls) { | 265 | static size_t skip_sep (LexState *ls) { |
262 | size_t count = 0; | 266 | size_t count = 0; |
@@ -481,34 +485,34 @@ static int llex (LexState *ls, SemInfo *seminfo) { | |||
481 | } | 485 | } |
482 | case '=': { | 486 | case '=': { |
483 | next(ls); | 487 | next(ls); |
484 | if (check_next1(ls, '=')) return TK_EQ; | 488 | if (check_next1(ls, '=')) return TK_EQ; /* '==' */ |
485 | else return '='; | 489 | else return '='; |
486 | } | 490 | } |
487 | case '<': { | 491 | case '<': { |
488 | next(ls); | 492 | next(ls); |
489 | if (check_next1(ls, '=')) return TK_LE; | 493 | if (check_next1(ls, '=')) return TK_LE; /* '<=' */ |
490 | else if (check_next1(ls, '<')) return TK_SHL; | 494 | else if (check_next1(ls, '<')) return TK_SHL; /* '<<' */ |
491 | else return '<'; | 495 | else return '<'; |
492 | } | 496 | } |
493 | case '>': { | 497 | case '>': { |
494 | next(ls); | 498 | next(ls); |
495 | if (check_next1(ls, '=')) return TK_GE; | 499 | if (check_next1(ls, '=')) return TK_GE; /* '>=' */ |
496 | else if (check_next1(ls, '>')) return TK_SHR; | 500 | else if (check_next1(ls, '>')) return TK_SHR; /* '>>' */ |
497 | else return '>'; | 501 | else return '>'; |
498 | } | 502 | } |
499 | case '/': { | 503 | case '/': { |
500 | next(ls); | 504 | next(ls); |
501 | if (check_next1(ls, '/')) return TK_IDIV; | 505 | if (check_next1(ls, '/')) return TK_IDIV; /* '//' */ |
502 | else return '/'; | 506 | else return '/'; |
503 | } | 507 | } |
504 | case '~': { | 508 | case '~': { |
505 | next(ls); | 509 | next(ls); |
506 | if (check_next1(ls, '=')) return TK_NE; | 510 | if (check_next1(ls, '=')) return TK_NE; /* '~=' */ |
507 | else return '~'; | 511 | else return '~'; |
508 | } | 512 | } |
509 | case ':': { | 513 | case ':': { |
510 | next(ls); | 514 | next(ls); |
511 | if (check_next1(ls, ':')) return TK_DBCOLON; | 515 | if (check_next1(ls, ':')) return TK_DBCOLON; /* '::' */ |
512 | else return ':'; | 516 | else return ':'; |
513 | } | 517 | } |
514 | case '"': case '\'': { /* short literal strings */ | 518 | case '"': case '\'': { /* short literal strings */ |
@@ -547,7 +551,7 @@ static int llex (LexState *ls, SemInfo *seminfo) { | |||
547 | return TK_NAME; | 551 | return TK_NAME; |
548 | } | 552 | } |
549 | } | 553 | } |
550 | else { /* single-char tokens (+ - / ...) */ | 554 | else { /* single-char tokens ('+', '*', '%', '{', '}', ...) */ |
551 | int c = ls->current; | 555 | int c = ls->current; |
552 | next(ls); | 556 | next(ls); |
553 | return c; | 557 | return c; |
diff --git a/src/lua/llimits.h b/src/lua/llimits.h index a76c13e..d039483 100644 --- a/src/lua/llimits.h +++ b/src/lua/llimits.h | |||
@@ -326,7 +326,8 @@ typedef l_uint32 Instruction; | |||
326 | 326 | ||
327 | /* exponentiation */ | 327 | /* exponentiation */ |
328 | #if !defined(luai_numpow) | 328 | #if !defined(luai_numpow) |
329 | #define luai_numpow(L,a,b) ((void)L, l_mathop(pow)(a,b)) | 329 | #define luai_numpow(L,a,b) \ |
330 | ((void)L, (b == 2) ? (a)*(a) : l_mathop(pow)(a,b)) | ||
330 | #endif | 331 | #endif |
331 | 332 | ||
332 | /* the others are quite standard operations */ | 333 | /* the others are quite standard operations */ |
diff --git a/src/lua/lobject.c b/src/lua/lobject.c index f8ea917..0e504be 100644 --- a/src/lua/lobject.c +++ b/src/lua/lobject.c | |||
@@ -258,7 +258,7 @@ static const char *l_str2d (const char *s, lua_Number *result) { | |||
258 | if (endptr == NULL) { /* failed? may be a different locale */ | 258 | if (endptr == NULL) { /* failed? may be a different locale */ |
259 | char buff[L_MAXLENNUM + 1]; | 259 | char buff[L_MAXLENNUM + 1]; |
260 | const char *pdot = strchr(s, '.'); | 260 | const char *pdot = strchr(s, '.'); |
261 | if (strlen(s) > L_MAXLENNUM || pdot == NULL) | 261 | if (pdot == NULL || strlen(s) > L_MAXLENNUM) |
262 | return NULL; /* string too long or no dot; fail */ | 262 | return NULL; /* string too long or no dot; fail */ |
263 | strcpy(buff, s); /* copy string to buffer */ | 263 | strcpy(buff, s); /* copy string to buffer */ |
264 | buff[pdot - s] = lua_getlocaledecpoint(); /* correct decimal point */ | 264 | buff[pdot - s] = lua_getlocaledecpoint(); /* correct decimal point */ |
diff --git a/src/lua/lparser.c b/src/lua/lparser.c index bcdcfb6..249ba9a 100644 --- a/src/lua/lparser.c +++ b/src/lua/lparser.c | |||
@@ -222,26 +222,26 @@ static Vardesc *getlocalvardesc (FuncState *fs, int vidx) { | |||
222 | 222 | ||
223 | 223 | ||
224 | /* | 224 | /* |
225 | ** Convert 'nvar', a compiler index level, to it corresponding | 225 | ** Convert 'nvar', a compiler index level, to its corresponding |
226 | ** stack index level. For that, search for the highest variable | 226 | ** register. For that, search for the highest variable below that level |
227 | ** below that level that is in the stack and uses its stack | 227 | ** that is in a register and uses its register index ('ridx') plus one. |
228 | ** index ('sidx'). | ||
229 | */ | 228 | */ |
230 | static int stacklevel (FuncState *fs, int nvar) { | 229 | static int reglevel (FuncState *fs, int nvar) { |
231 | while (nvar-- > 0) { | 230 | while (nvar-- > 0) { |
232 | Vardesc *vd = getlocalvardesc(fs, nvar); /* get variable */ | 231 | Vardesc *vd = getlocalvardesc(fs, nvar); /* get previous variable */ |
233 | if (vd->vd.kind != RDKCTC) /* is in the stack? */ | 232 | if (vd->vd.kind != RDKCTC) /* is in a register? */ |
234 | return vd->vd.sidx + 1; | 233 | return vd->vd.ridx + 1; |
235 | } | 234 | } |
236 | return 0; /* no variables in the stack */ | 235 | return 0; /* no variables in registers */ |
237 | } | 236 | } |
238 | 237 | ||
239 | 238 | ||
240 | /* | 239 | /* |
241 | ** Return the number of variables in the stack for function 'fs' | 240 | ** Return the number of variables in the register stack for the given |
241 | ** function. | ||
242 | */ | 242 | */ |
243 | int luaY_nvarstack (FuncState *fs) { | 243 | int luaY_nvarstack (FuncState *fs) { |
244 | return stacklevel(fs, fs->nactvar); | 244 | return reglevel(fs, fs->nactvar); |
245 | } | 245 | } |
246 | 246 | ||
247 | 247 | ||
@@ -267,7 +267,7 @@ static void init_var (FuncState *fs, expdesc *e, int vidx) { | |||
267 | e->f = e->t = NO_JUMP; | 267 | e->f = e->t = NO_JUMP; |
268 | e->k = VLOCAL; | 268 | e->k = VLOCAL; |
269 | e->u.var.vidx = vidx; | 269 | e->u.var.vidx = vidx; |
270 | e->u.var.sidx = getlocalvardesc(fs, vidx)->vd.sidx; | 270 | e->u.var.ridx = getlocalvardesc(fs, vidx)->vd.ridx; |
271 | } | 271 | } |
272 | 272 | ||
273 | 273 | ||
@@ -310,12 +310,12 @@ static void check_readonly (LexState *ls, expdesc *e) { | |||
310 | */ | 310 | */ |
311 | static void adjustlocalvars (LexState *ls, int nvars) { | 311 | static void adjustlocalvars (LexState *ls, int nvars) { |
312 | FuncState *fs = ls->fs; | 312 | FuncState *fs = ls->fs; |
313 | int stklevel = luaY_nvarstack(fs); | 313 | int reglevel = luaY_nvarstack(fs); |
314 | int i; | 314 | int i; |
315 | for (i = 0; i < nvars; i++) { | 315 | for (i = 0; i < nvars; i++) { |
316 | int vidx = fs->nactvar++; | 316 | int vidx = fs->nactvar++; |
317 | Vardesc *var = getlocalvardesc(fs, vidx); | 317 | Vardesc *var = getlocalvardesc(fs, vidx); |
318 | var->vd.sidx = stklevel++; | 318 | var->vd.ridx = reglevel++; |
319 | var->vd.pidx = registerlocalvar(ls, fs, var->vd.name); | 319 | var->vd.pidx = registerlocalvar(ls, fs, var->vd.name); |
320 | } | 320 | } |
321 | } | 321 | } |
@@ -366,7 +366,7 @@ static int newupvalue (FuncState *fs, TString *name, expdesc *v) { | |||
366 | FuncState *prev = fs->prev; | 366 | FuncState *prev = fs->prev; |
367 | if (v->k == VLOCAL) { | 367 | if (v->k == VLOCAL) { |
368 | up->instack = 1; | 368 | up->instack = 1; |
369 | up->idx = v->u.var.sidx; | 369 | up->idx = v->u.var.ridx; |
370 | up->kind = getlocalvardesc(prev, v->u.var.vidx)->vd.kind; | 370 | up->kind = getlocalvardesc(prev, v->u.var.vidx)->vd.kind; |
371 | lua_assert(eqstr(name, getlocalvardesc(prev, v->u.var.vidx)->vd.name)); | 371 | lua_assert(eqstr(name, getlocalvardesc(prev, v->u.var.vidx)->vd.name)); |
372 | } | 372 | } |
@@ -620,7 +620,7 @@ static void movegotosout (FuncState *fs, BlockCnt *bl) { | |||
620 | for (i = bl->firstgoto; i < gl->n; i++) { /* for each pending goto */ | 620 | for (i = bl->firstgoto; i < gl->n; i++) { /* for each pending goto */ |
621 | Labeldesc *gt = &gl->arr[i]; | 621 | Labeldesc *gt = &gl->arr[i]; |
622 | /* leaving a variable scope? */ | 622 | /* leaving a variable scope? */ |
623 | if (stacklevel(fs, gt->nactvar) > stacklevel(fs, bl->nactvar)) | 623 | if (reglevel(fs, gt->nactvar) > reglevel(fs, bl->nactvar)) |
624 | gt->close |= bl->upval; /* jump may need a close */ | 624 | gt->close |= bl->upval; /* jump may need a close */ |
625 | gt->nactvar = bl->nactvar; /* update goto level */ | 625 | gt->nactvar = bl->nactvar; /* update goto level */ |
626 | } | 626 | } |
@@ -661,7 +661,7 @@ static void leaveblock (FuncState *fs) { | |||
661 | BlockCnt *bl = fs->bl; | 661 | BlockCnt *bl = fs->bl; |
662 | LexState *ls = fs->ls; | 662 | LexState *ls = fs->ls; |
663 | int hasclose = 0; | 663 | int hasclose = 0; |
664 | int stklevel = stacklevel(fs, bl->nactvar); /* level outside the block */ | 664 | int stklevel = reglevel(fs, bl->nactvar); /* level outside the block */ |
665 | if (bl->isloop) /* fix pending breaks? */ | 665 | if (bl->isloop) /* fix pending breaks? */ |
666 | hasclose = createlabel(ls, luaS_newliteral(ls->L, "break"), 0, 0); | 666 | hasclose = createlabel(ls, luaS_newliteral(ls->L, "break"), 0, 0); |
667 | if (!hasclose && bl->previous && bl->upval) | 667 | if (!hasclose && bl->previous && bl->upval) |
@@ -945,7 +945,7 @@ static void setvararg (FuncState *fs, int nparams) { | |||
945 | 945 | ||
946 | 946 | ||
947 | static void parlist (LexState *ls) { | 947 | static void parlist (LexState *ls) { |
948 | /* parlist -> [ param { ',' param } ] */ | 948 | /* parlist -> [ {NAME ','} (NAME | '...') ] */ |
949 | FuncState *fs = ls->fs; | 949 | FuncState *fs = ls->fs; |
950 | Proto *f = fs->f; | 950 | Proto *f = fs->f; |
951 | int nparams = 0; | 951 | int nparams = 0; |
@@ -953,12 +953,12 @@ static void parlist (LexState *ls) { | |||
953 | if (ls->t.token != ')') { /* is 'parlist' not empty? */ | 953 | if (ls->t.token != ')') { /* is 'parlist' not empty? */ |
954 | do { | 954 | do { |
955 | switch (ls->t.token) { | 955 | switch (ls->t.token) { |
956 | case TK_NAME: { /* param -> NAME */ | 956 | case TK_NAME: { |
957 | new_localvar(ls, str_checkname(ls)); | 957 | new_localvar(ls, str_checkname(ls)); |
958 | nparams++; | 958 | nparams++; |
959 | break; | 959 | break; |
960 | } | 960 | } |
961 | case TK_DOTS: { /* param -> '...' */ | 961 | case TK_DOTS: { |
962 | luaX_next(ls); | 962 | luaX_next(ls); |
963 | isvararg = 1; | 963 | isvararg = 1; |
964 | break; | 964 | break; |
@@ -1330,13 +1330,13 @@ static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) { | |||
1330 | } | 1330 | } |
1331 | } | 1331 | } |
1332 | else { /* table is a register */ | 1332 | else { /* table is a register */ |
1333 | if (v->k == VLOCAL && lh->v.u.ind.t == v->u.var.sidx) { | 1333 | if (v->k == VLOCAL && lh->v.u.ind.t == v->u.var.ridx) { |
1334 | conflict = 1; /* table is the local being assigned now */ | 1334 | conflict = 1; /* table is the local being assigned now */ |
1335 | lh->v.u.ind.t = extra; /* assignment will use safe copy */ | 1335 | lh->v.u.ind.t = extra; /* assignment will use safe copy */ |
1336 | } | 1336 | } |
1337 | /* is index the local being assigned? */ | 1337 | /* is index the local being assigned? */ |
1338 | if (lh->v.k == VINDEXED && v->k == VLOCAL && | 1338 | if (lh->v.k == VINDEXED && v->k == VLOCAL && |
1339 | lh->v.u.ind.idx == v->u.var.sidx) { | 1339 | lh->v.u.ind.idx == v->u.var.ridx) { |
1340 | conflict = 1; | 1340 | conflict = 1; |
1341 | lh->v.u.ind.idx = extra; /* previous assignment will use safe copy */ | 1341 | lh->v.u.ind.idx = extra; /* previous assignment will use safe copy */ |
1342 | } | 1342 | } |
@@ -1346,7 +1346,7 @@ static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) { | |||
1346 | if (conflict) { | 1346 | if (conflict) { |
1347 | /* copy upvalue/local value to a temporary (in position 'extra') */ | 1347 | /* copy upvalue/local value to a temporary (in position 'extra') */ |
1348 | if (v->k == VLOCAL) | 1348 | if (v->k == VLOCAL) |
1349 | luaK_codeABC(fs, OP_MOVE, extra, v->u.var.sidx, 0); | 1349 | luaK_codeABC(fs, OP_MOVE, extra, v->u.var.ridx, 0); |
1350 | else | 1350 | else |
1351 | luaK_codeABC(fs, OP_GETUPVAL, extra, v->u.info, 0); | 1351 | luaK_codeABC(fs, OP_GETUPVAL, extra, v->u.info, 0); |
1352 | luaK_reserveregs(fs, 1); | 1352 | luaK_reserveregs(fs, 1); |
@@ -1411,7 +1411,7 @@ static void gotostat (LexState *ls) { | |||
1411 | newgotoentry(ls, name, line, luaK_jump(fs)); | 1411 | newgotoentry(ls, name, line, luaK_jump(fs)); |
1412 | else { /* found a label */ | 1412 | else { /* found a label */ |
1413 | /* backward jump; will be resolved here */ | 1413 | /* backward jump; will be resolved here */ |
1414 | int lblevel = stacklevel(fs, lb->nactvar); /* label level */ | 1414 | int lblevel = reglevel(fs, lb->nactvar); /* label level */ |
1415 | if (luaY_nvarstack(fs) > lblevel) /* leaving the scope of a variable? */ | 1415 | if (luaY_nvarstack(fs) > lblevel) /* leaving the scope of a variable? */ |
1416 | luaK_codeABC(fs, OP_CLOSE, lblevel, 0, 0); | 1416 | luaK_codeABC(fs, OP_CLOSE, lblevel, 0, 0); |
1417 | /* create jump and link it to the label */ | 1417 | /* create jump and link it to the label */ |
@@ -1488,7 +1488,7 @@ static void repeatstat (LexState *ls, int line) { | |||
1488 | if (bl2.upval) { /* upvalues? */ | 1488 | if (bl2.upval) { /* upvalues? */ |
1489 | int exit = luaK_jump(fs); /* normal exit must jump over fix */ | 1489 | int exit = luaK_jump(fs); /* normal exit must jump over fix */ |
1490 | luaK_patchtohere(fs, condexit); /* repetition must close upvalues */ | 1490 | luaK_patchtohere(fs, condexit); /* repetition must close upvalues */ |
1491 | luaK_codeABC(fs, OP_CLOSE, stacklevel(fs, bl2.nactvar), 0, 0); | 1491 | luaK_codeABC(fs, OP_CLOSE, reglevel(fs, bl2.nactvar), 0, 0); |
1492 | condexit = luaK_jump(fs); /* repeat after closing upvalues */ | 1492 | condexit = luaK_jump(fs); /* repeat after closing upvalues */ |
1493 | luaK_patchtohere(fs, exit); /* normal exit comes to here */ | 1493 | luaK_patchtohere(fs, exit); /* normal exit comes to here */ |
1494 | } | 1494 | } |
@@ -1623,59 +1623,21 @@ static void forstat (LexState *ls, int line) { | |||
1623 | } | 1623 | } |
1624 | 1624 | ||
1625 | 1625 | ||
1626 | /* | ||
1627 | ** Check whether next instruction is a single jump (a 'break', a 'goto' | ||
1628 | ** to a forward label, or a 'goto' to a backward label with no variable | ||
1629 | ** to close). If so, set the name of the 'label' it is jumping to | ||
1630 | ** ("break" for a 'break') or to where it is jumping to ('target') and | ||
1631 | ** return true. If not a single jump, leave input unchanged, to be | ||
1632 | ** handled as a regular statement. | ||
1633 | */ | ||
1634 | static int issinglejump (LexState *ls, TString **label, int *target) { | ||
1635 | if (testnext(ls, TK_BREAK)) { /* a break? */ | ||
1636 | *label = luaS_newliteral(ls->L, "break"); | ||
1637 | return 1; | ||
1638 | } | ||
1639 | else if (ls->t.token != TK_GOTO || luaX_lookahead(ls) != TK_NAME) | ||
1640 | return 0; /* not a valid goto */ | ||
1641 | else { | ||
1642 | TString *lname = ls->lookahead.seminfo.ts; /* label's id */ | ||
1643 | Labeldesc *lb = findlabel(ls, lname); | ||
1644 | if (lb) { /* a backward jump? */ | ||
1645 | /* does it need to close variables? */ | ||
1646 | if (luaY_nvarstack(ls->fs) > stacklevel(ls->fs, lb->nactvar)) | ||
1647 | return 0; /* not a single jump; cannot optimize */ | ||
1648 | *target = lb->pc; | ||
1649 | } | ||
1650 | else /* jump forward */ | ||
1651 | *label = lname; | ||
1652 | luaX_next(ls); /* skip goto */ | ||
1653 | luaX_next(ls); /* skip name */ | ||
1654 | return 1; | ||
1655 | } | ||
1656 | } | ||
1657 | |||
1658 | |||
1659 | static void test_then_block (LexState *ls, int *escapelist) { | 1626 | static void test_then_block (LexState *ls, int *escapelist) { |
1660 | /* test_then_block -> [IF | ELSEIF] cond THEN block */ | 1627 | /* test_then_block -> [IF | ELSEIF] cond THEN block */ |
1661 | BlockCnt bl; | 1628 | BlockCnt bl; |
1662 | int line; | ||
1663 | FuncState *fs = ls->fs; | 1629 | FuncState *fs = ls->fs; |
1664 | TString *jlb = NULL; | ||
1665 | int target = NO_JUMP; | ||
1666 | expdesc v; | 1630 | expdesc v; |
1667 | int jf; /* instruction to skip 'then' code (if condition is false) */ | 1631 | int jf; /* instruction to skip 'then' code (if condition is false) */ |
1668 | luaX_next(ls); /* skip IF or ELSEIF */ | 1632 | luaX_next(ls); /* skip IF or ELSEIF */ |
1669 | expr(ls, &v); /* read condition */ | 1633 | expr(ls, &v); /* read condition */ |
1670 | checknext(ls, TK_THEN); | 1634 | checknext(ls, TK_THEN); |
1671 | line = ls->linenumber; | 1635 | if (ls->t.token == TK_BREAK) { /* 'if x then break' ? */ |
1672 | if (issinglejump(ls, &jlb, &target)) { /* 'if x then goto' ? */ | 1636 | int line = ls->linenumber; |
1673 | luaK_goiffalse(ls->fs, &v); /* will jump to label if condition is true */ | 1637 | luaK_goiffalse(ls->fs, &v); /* will jump if condition is true */ |
1638 | luaX_next(ls); /* skip 'break' */ | ||
1674 | enterblock(fs, &bl, 0); /* must enter block before 'goto' */ | 1639 | enterblock(fs, &bl, 0); /* must enter block before 'goto' */ |
1675 | if (jlb != NULL) /* forward jump? */ | 1640 | newgotoentry(ls, luaS_newliteral(ls->L, "break"), line, v.t); |
1676 | newgotoentry(ls, jlb, line, v.t); /* will be resolved later */ | ||
1677 | else /* backward jump */ | ||
1678 | luaK_patchlist(fs, v.t, target); /* jump directly to 'target' */ | ||
1679 | while (testnext(ls, ';')) {} /* skip semicolons */ | 1641 | while (testnext(ls, ';')) {} /* skip semicolons */ |
1680 | if (block_follow(ls, 0)) { /* jump is the entire block? */ | 1642 | if (block_follow(ls, 0)) { /* jump is the entire block? */ |
1681 | leaveblock(fs); | 1643 | leaveblock(fs); |
@@ -1684,7 +1646,7 @@ static void test_then_block (LexState *ls, int *escapelist) { | |||
1684 | else /* must skip over 'then' part if condition is false */ | 1646 | else /* must skip over 'then' part if condition is false */ |
1685 | jf = luaK_jump(fs); | 1647 | jf = luaK_jump(fs); |
1686 | } | 1648 | } |
1687 | else { /* regular case (not a jump) */ | 1649 | else { /* regular case (not a break) */ |
1688 | luaK_goiftrue(ls->fs, &v); /* skip over block if condition is false */ | 1650 | luaK_goiftrue(ls->fs, &v); /* skip over block if condition is false */ |
1689 | enterblock(fs, &bl, 0); | 1651 | enterblock(fs, &bl, 0); |
1690 | jf = v.f; | 1652 | jf = v.f; |
@@ -1746,13 +1708,13 @@ static void checktoclose (LexState *ls, int level) { | |||
1746 | FuncState *fs = ls->fs; | 1708 | FuncState *fs = ls->fs; |
1747 | markupval(fs, level + 1); | 1709 | markupval(fs, level + 1); |
1748 | fs->bl->insidetbc = 1; /* in the scope of a to-be-closed variable */ | 1710 | fs->bl->insidetbc = 1; /* in the scope of a to-be-closed variable */ |
1749 | luaK_codeABC(fs, OP_TBC, stacklevel(fs, level), 0, 0); | 1711 | luaK_codeABC(fs, OP_TBC, reglevel(fs, level), 0, 0); |
1750 | } | 1712 | } |
1751 | } | 1713 | } |
1752 | 1714 | ||
1753 | 1715 | ||
1754 | static void localstat (LexState *ls) { | 1716 | static void localstat (LexState *ls) { |
1755 | /* stat -> LOCAL ATTRIB NAME {',' ATTRIB NAME} ['=' explist] */ | 1717 | /* stat -> LOCAL NAME ATTRIB { ',' NAME ATTRIB } ['=' explist] */ |
1756 | FuncState *fs = ls->fs; | 1718 | FuncState *fs = ls->fs; |
1757 | int toclose = -1; /* index of to-be-closed variable (if any) */ | 1719 | int toclose = -1; /* index of to-be-closed variable (if any) */ |
1758 | Vardesc *var; /* last variable */ | 1720 | Vardesc *var; /* last variable */ |
diff --git a/src/lua/lparser.h b/src/lua/lparser.h index 618cb01..5e4500f 100644 --- a/src/lua/lparser.h +++ b/src/lua/lparser.h | |||
@@ -23,7 +23,7 @@ | |||
23 | 23 | ||
24 | /* kinds of variables/expressions */ | 24 | /* kinds of variables/expressions */ |
25 | typedef enum { | 25 | typedef enum { |
26 | VVOID, /* when 'expdesc' describes the last expression a list, | 26 | VVOID, /* when 'expdesc' describes the last expression of a list, |
27 | this kind means an empty list (so, no expression) */ | 27 | this kind means an empty list (so, no expression) */ |
28 | VNIL, /* constant nil */ | 28 | VNIL, /* constant nil */ |
29 | VTRUE, /* constant true */ | 29 | VTRUE, /* constant true */ |
@@ -35,10 +35,11 @@ typedef enum { | |||
35 | (string is fixed by the lexer) */ | 35 | (string is fixed by the lexer) */ |
36 | VNONRELOC, /* expression has its value in a fixed register; | 36 | VNONRELOC, /* expression has its value in a fixed register; |
37 | info = result register */ | 37 | info = result register */ |
38 | VLOCAL, /* local variable; var.sidx = stack index (local register); | 38 | VLOCAL, /* local variable; var.ridx = register index; |
39 | var.vidx = relative index in 'actvar.arr' */ | 39 | var.vidx = relative index in 'actvar.arr' */ |
40 | VUPVAL, /* upvalue variable; info = index of upvalue in 'upvalues' */ | 40 | VUPVAL, /* upvalue variable; info = index of upvalue in 'upvalues' */ |
41 | VCONST, /* compile-time constant; info = absolute index in 'actvar.arr' */ | 41 | VCONST, /* compile-time <const> variable; |
42 | info = absolute index in 'actvar.arr' */ | ||
42 | VINDEXED, /* indexed variable; | 43 | VINDEXED, /* indexed variable; |
43 | ind.t = table register; | 44 | ind.t = table register; |
44 | ind.idx = key's R index */ | 45 | ind.idx = key's R index */ |
@@ -76,7 +77,7 @@ typedef struct expdesc { | |||
76 | lu_byte t; /* table (register or upvalue) */ | 77 | lu_byte t; /* table (register or upvalue) */ |
77 | } ind; | 78 | } ind; |
78 | struct { /* for local variables */ | 79 | struct { /* for local variables */ |
79 | lu_byte sidx; /* index in the stack */ | 80 | lu_byte ridx; /* register holding the variable */ |
80 | unsigned short vidx; /* compiler index (in 'actvar.arr') */ | 81 | unsigned short vidx; /* compiler index (in 'actvar.arr') */ |
81 | } var; | 82 | } var; |
82 | } u; | 83 | } u; |
@@ -96,7 +97,7 @@ typedef union Vardesc { | |||
96 | struct { | 97 | struct { |
97 | TValuefields; /* constant value (if it is a compile-time constant) */ | 98 | TValuefields; /* constant value (if it is a compile-time constant) */ |
98 | lu_byte kind; | 99 | lu_byte kind; |
99 | lu_byte sidx; /* index of the variable in the stack */ | 100 | lu_byte ridx; /* register holding the variable */ |
100 | short pidx; /* index of the variable in the Proto's 'locvars' array */ | 101 | short pidx; /* index of the variable in the Proto's 'locvars' array */ |
101 | TString *name; /* variable name */ | 102 | TString *name; /* variable name */ |
102 | } vd; | 103 | } vd; |
diff --git a/src/lua/lstate.c b/src/lua/lstate.c index 4227429..1596b51 100644 --- a/src/lua/lstate.c +++ b/src/lua/lstate.c | |||
@@ -181,7 +181,7 @@ static void stack_init (lua_State *L1, lua_State *L) { | |||
181 | int i; CallInfo *ci; | 181 | int i; CallInfo *ci; |
182 | /* initialize stack array */ | 182 | /* initialize stack array */ |
183 | L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, StackValue); | 183 | L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, StackValue); |
184 | for (i = 0; i < BASIC_STACK_SIZE; i++) | 184 | for (i = 0; i < BASIC_STACK_SIZE + EXTRA_STACK; i++) |
185 | setnilvalue(s2v(L1->stack + i)); /* erase new stack */ | 185 | setnilvalue(s2v(L1->stack + i)); /* erase new stack */ |
186 | L1->top = L1->stack; | 186 | L1->top = L1->stack; |
187 | L1->stack_last = L1->stack + BASIC_STACK_SIZE; | 187 | L1->stack_last = L1->stack + BASIC_STACK_SIZE; |
@@ -213,17 +213,14 @@ static void freestack (lua_State *L) { | |||
213 | ** Create registry table and its predefined values | 213 | ** Create registry table and its predefined values |
214 | */ | 214 | */ |
215 | static void init_registry (lua_State *L, global_State *g) { | 215 | static void init_registry (lua_State *L, global_State *g) { |
216 | TValue temp; | ||
217 | /* create registry */ | 216 | /* create registry */ |
218 | Table *registry = luaH_new(L); | 217 | Table *registry = luaH_new(L); |
219 | sethvalue(L, &g->l_registry, registry); | 218 | sethvalue(L, &g->l_registry, registry); |
220 | luaH_resize(L, registry, LUA_RIDX_LAST, 0); | 219 | luaH_resize(L, registry, LUA_RIDX_LAST, 0); |
221 | /* registry[LUA_RIDX_MAINTHREAD] = L */ | 220 | /* registry[LUA_RIDX_MAINTHREAD] = L */ |
222 | setthvalue(L, &temp, L); /* temp = L */ | 221 | setthvalue(L, ®istry->array[LUA_RIDX_MAINTHREAD - 1], L); |
223 | luaH_setint(L, registry, LUA_RIDX_MAINTHREAD, &temp); | 222 | /* registry[LUA_RIDX_GLOBALS] = new table (table of globals) */ |
224 | /* registry[LUA_RIDX_GLOBALS] = table of globals */ | 223 | sethvalue(L, ®istry->array[LUA_RIDX_GLOBALS - 1], luaH_new(L)); |
225 | sethvalue(L, &temp, luaH_new(L)); /* temp = new table (global table) */ | ||
226 | luaH_setint(L, registry, LUA_RIDX_GLOBALS, &temp); | ||
227 | } | 224 | } |
228 | 225 | ||
229 | 226 | ||
diff --git a/src/lua/ltable.c b/src/lua/ltable.c index 38bee1d..e9410f9 100644 --- a/src/lua/ltable.c +++ b/src/lua/ltable.c | |||
@@ -166,17 +166,24 @@ static Node *mainpositionTV (const Table *t, const TValue *key) { | |||
166 | 166 | ||
167 | 167 | ||
168 | /* | 168 | /* |
169 | ** Check whether key 'k1' is equal to the key in node 'n2'. | 169 | ** Check whether key 'k1' is equal to the key in node 'n2'. This |
170 | ** This equality is raw, so there are no metamethods. Floats | 170 | ** equality is raw, so there are no metamethods. Floats with integer |
171 | ** with integer values have been normalized, so integers cannot | 171 | ** values have been normalized, so integers cannot be equal to |
172 | ** be equal to floats. It is assumed that 'eqshrstr' is simply | 172 | ** floats. It is assumed that 'eqshrstr' is simply pointer equality, so |
173 | ** pointer equality, so that short strings are handled in the | 173 | ** that short strings are handled in the default case. |
174 | ** default case. | ||
175 | ** A true 'deadok' means to accept dead keys as equal to their original | 174 | ** A true 'deadok' means to accept dead keys as equal to their original |
176 | ** values, which can only happen if the original key was collectable. | 175 | ** values. All dead keys are compared in the default case, by pointer |
177 | ** All dead values are compared in the default case, by pointer | 176 | ** identity. (Only collectable objects can produce dead keys.) Note that |
178 | ** identity. (Note that dead long strings are also compared by | 177 | ** dead long strings are also compared by identity. |
179 | ** identity). | 178 | ** Once a key is dead, its corresponding value may be collected, and |
179 | ** then another value can be created with the same address. If this | ||
180 | ** other value is given to 'next', 'equalkey' will signal a false | ||
181 | ** positive. In a regular traversal, this situation should never happen, | ||
182 | ** as all keys given to 'next' came from the table itself, and therefore | ||
183 | ** could not have been collected. Outside a regular traversal, we | ||
184 | ** have garbage in, garbage out. What is relevant is that this false | ||
185 | ** positive does not break anything. (In particular, 'next' will return | ||
186 | ** some other valid item on the table or nil.) | ||
180 | */ | 187 | */ |
181 | static int equalkey (const TValue *k1, const Node *n2, int deadok) { | 188 | static int equalkey (const TValue *k1, const Node *n2, int deadok) { |
182 | if ((rawtt(k1) != keytt(n2)) && /* not the same variants? */ | 189 | if ((rawtt(k1) != keytt(n2)) && /* not the same variants? */ |
@@ -478,7 +485,7 @@ static void reinsert (lua_State *L, Table *ot, Table *t) { | |||
478 | already present in the table */ | 485 | already present in the table */ |
479 | TValue k; | 486 | TValue k; |
480 | getnodekey(L, &k, old); | 487 | getnodekey(L, &k, old); |
481 | setobjt2t(L, luaH_set(L, t, &k), gval(old)); | 488 | luaH_set(L, t, &k, gval(old)); |
482 | } | 489 | } |
483 | } | 490 | } |
484 | } | 491 | } |
@@ -625,7 +632,7 @@ static Node *getfreepos (Table *t) { | |||
625 | ** 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 |
626 | ** position), new key goes to an empty position. | 633 | ** position), new key goes to an empty position. |
627 | */ | 634 | */ |
628 | 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) { |
629 | Node *mp; | 636 | Node *mp; |
630 | TValue aux; | 637 | TValue aux; |
631 | if (unlikely(ttisnil(key))) | 638 | if (unlikely(ttisnil(key))) |
@@ -647,7 +654,8 @@ TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) { | |||
647 | if (f == NULL) { /* cannot find a free place? */ | 654 | if (f == NULL) { /* cannot find a free place? */ |
648 | rehash(L, t, key); /* grow table */ | 655 | rehash(L, t, key); /* grow table */ |
649 | /* whatever called 'newkey' takes care of TM cache */ | 656 | /* whatever called 'newkey' takes care of TM cache */ |
650 | 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; | ||
651 | } | 659 | } |
652 | lua_assert(!isdummy(t)); | 660 | lua_assert(!isdummy(t)); |
653 | othern = mainposition(t, keytt(mp), &keyval(mp)); | 661 | othern = mainposition(t, keytt(mp), &keyval(mp)); |
@@ -675,7 +683,7 @@ TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) { | |||
675 | setnodekey(L, mp, key); | 683 | setnodekey(L, mp, key); |
676 | luaC_barrierback(L, obj2gco(t), key); | 684 | luaC_barrierback(L, obj2gco(t), key); |
677 | lua_assert(isempty(gval(mp))); | 685 | lua_assert(isempty(gval(mp))); |
678 | return gval(mp); | 686 | setobj2t(L, gval(mp), value); |
679 | } | 687 | } |
680 | 688 | ||
681 | 689 | ||
@@ -763,28 +771,39 @@ const TValue *luaH_get (Table *t, const TValue *key) { | |||
763 | 771 | ||
764 | 772 | ||
765 | /* | 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 | /* | ||
766 | ** 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 |
767 | ** barrier and invalidate the TM cache. | 790 | ** barrier and invalidate the TM cache. |
768 | */ | 791 | */ |
769 | 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) { |
770 | const TValue *p = luaH_get(t, key); | 793 | const TValue *slot = luaH_get(t, key); |
771 | if (!isabstkey(p)) | 794 | luaH_finishset(L, t, key, slot, value); |
772 | return cast(TValue *, p); | ||
773 | else return luaH_newkey(L, t, key); | ||
774 | } | 795 | } |
775 | 796 | ||
776 | 797 | ||
777 | 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) { |
778 | const TValue *p = luaH_getint(t, key); | 799 | const TValue *p = luaH_getint(t, key); |
779 | TValue *cell; | 800 | if (isabstkey(p)) { |
780 | if (!isabstkey(p)) | ||
781 | cell = cast(TValue *, p); | ||
782 | else { | ||
783 | TValue k; | 801 | TValue k; |
784 | setivalue(&k, key); | 802 | setivalue(&k, key); |
785 | cell = luaH_newkey(L, t, &k); | 803 | luaH_newkey(L, t, &k, value); |
786 | } | 804 | } |
787 | setobj2t(L, cell, value); | 805 | else |
806 | setobj2t(L, cast(TValue *, p), value); | ||
788 | } | 807 | } |
789 | 808 | ||
790 | 809 | ||
diff --git a/src/lua/ltable.h b/src/lua/ltable.h index c0060f4..7bbbcb2 100644 --- a/src/lua/ltable.h +++ b/src/lua/ltable.h | |||
@@ -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); |
diff --git a/src/lua/lualib.h b/src/lua/lualib.h index eb08b53..2625529 100644 --- a/src/lua/lualib.h +++ b/src/lua/lualib.h | |||
@@ -49,10 +49,4 @@ LUAMOD_API int (luaopen_package) (lua_State *L); | |||
49 | LUALIB_API void (luaL_openlibs) (lua_State *L); | 49 | LUALIB_API void (luaL_openlibs) (lua_State *L); |
50 | 50 | ||
51 | 51 | ||
52 | |||
53 | #if !defined(lua_assert) | ||
54 | #define lua_assert(x) ((void)0) | ||
55 | #endif | ||
56 | |||
57 | |||
58 | #endif | 52 | #endif |
diff --git a/src/lua/lvm.c b/src/lua/lvm.c index aa3b22b..ccebdbe 100644 --- a/src/lua/lvm.c +++ b/src/lua/lvm.c | |||
@@ -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; |