aboutsummaryrefslogtreecommitdiff
path: root/lparser.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2019-07-12 16:13:50 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2019-07-12 16:13:50 -0300
commit1fb4d539254b67e7e35ed698250c66d1edff0e08 (patch)
tree8f48b7ca736a7fb02834bcfac1415cd43307f529 /lparser.c
parentf6aab3ec1f111cd8d968bdcb7ca800e93b819d24 (diff)
downloadlua-1fb4d539254b67e7e35ed698250c66d1edff0e08.tar.gz
lua-1fb4d539254b67e7e35ed698250c66d1edff0e08.tar.bz2
lua-1fb4d539254b67e7e35ed698250c66d1edff0e08.zip
OP_NEWTABLE keeps exact size of arrays
OP_NEWTABLE is followed by an OP_EXTRAARG, so that it can keep the exact size of the array part of the table to be created. (Functions 'luaO_int2fb'/'luaO_fb2int' were removed.)
Diffstat (limited to 'lparser.c')
-rw-r--r--lparser.c37
1 files changed, 26 insertions, 11 deletions
diff --git a/lparser.c b/lparser.c
index 79df0217..193e50f1 100644
--- a/lparser.c
+++ b/lparser.c
@@ -811,16 +811,16 @@ static void yindex (LexState *ls, expdesc *v) {
811*/ 811*/
812 812
813 813
814struct ConsControl { 814typedef struct ConsControl {
815 expdesc v; /* last list item read */ 815 expdesc v; /* last list item read */
816 expdesc *t; /* table descriptor */ 816 expdesc *t; /* table descriptor */
817 int nh; /* total number of 'record' elements */ 817 int nh; /* total number of 'record' elements */
818 int na; /* total number of array elements */ 818 int na; /* total number of array elements */
819 int tostore; /* number of array elements pending to be stored */ 819 int tostore; /* number of array elements pending to be stored */
820}; 820} ConsControl;
821 821
822 822
823static void recfield (LexState *ls, struct ConsControl *cc) { 823static void recfield (LexState *ls, ConsControl *cc) {
824 /* recfield -> (NAME | '['exp']') = exp */ 824 /* recfield -> (NAME | '['exp']') = exp */
825 FuncState *fs = ls->fs; 825 FuncState *fs = ls->fs;
826 int reg = ls->fs->freereg; 826 int reg = ls->fs->freereg;
@@ -841,7 +841,7 @@ static void recfield (LexState *ls, struct ConsControl *cc) {
841} 841}
842 842
843 843
844static void closelistfield (FuncState *fs, struct ConsControl *cc) { 844static void closelistfield (FuncState *fs, ConsControl *cc) {
845 if (cc->v.k == VVOID) return; /* there is no list item */ 845 if (cc->v.k == VVOID) return; /* there is no list item */
846 luaK_exp2nextreg(fs, &cc->v); 846 luaK_exp2nextreg(fs, &cc->v);
847 cc->v.k = VVOID; 847 cc->v.k = VVOID;
@@ -852,7 +852,7 @@ static void closelistfield (FuncState *fs, struct ConsControl *cc) {
852} 852}
853 853
854 854
855static void lastlistfield (FuncState *fs, struct ConsControl *cc) { 855static void lastlistfield (FuncState *fs, ConsControl *cc) {
856 if (cc->tostore == 0) return; 856 if (cc->tostore == 0) return;
857 if (hasmultret(cc->v.k)) { 857 if (hasmultret(cc->v.k)) {
858 luaK_setmultret(fs, &cc->v); 858 luaK_setmultret(fs, &cc->v);
@@ -867,16 +867,15 @@ static void lastlistfield (FuncState *fs, struct ConsControl *cc) {
867} 867}
868 868
869 869
870static void listfield (LexState *ls, struct ConsControl *cc) { 870static void listfield (LexState *ls, ConsControl *cc) {
871 /* listfield -> exp */ 871 /* listfield -> exp */
872 expr(ls, &cc->v); 872 expr(ls, &cc->v);
873 checklimit(ls->fs, cc->na, MAX_INT, "items in a constructor");
874 cc->na++; 873 cc->na++;
875 cc->tostore++; 874 cc->tostore++;
876} 875}
877 876
878 877
879static void field (LexState *ls, struct ConsControl *cc) { 878static void field (LexState *ls, ConsControl *cc) {
880 /* field -> listfield | recfield */ 879 /* field -> listfield | recfield */
881 switch(ls->t.token) { 880 switch(ls->t.token) {
882 case TK_NAME: { /* may be 'listfield' or 'recfield' */ 881 case TK_NAME: { /* may be 'listfield' or 'recfield' */
@@ -898,13 +897,30 @@ static void field (LexState *ls, struct ConsControl *cc) {
898} 897}
899 898
900 899
900static void settablesize (FuncState *fs, ConsControl *cc, int pc) {
901 Instruction *inst = &fs->f->code[pc];
902 int rc = (cc->nh == 0) ? 0 : luaO_ceillog2(cc->nh) + 1;
903 int rb = cc->na;
904 int extra = 0;
905 if (rb >= LIMTABSZ) {
906 extra = rb / LFIELDS_PER_FLUSH;
907 rb = rb % LFIELDS_PER_FLUSH + LIMTABSZ;
908 checklimit(fs, extra, MAXARG_Ax, "items in a constructor");
909 }
910 SETARG_C(*inst, rc); /* set initial table size */
911 SETARG_B(*inst, rb); /* set initial array size */
912 SETARG_Ax(*(inst + 1), extra);
913}
914
915
901static void constructor (LexState *ls, expdesc *t) { 916static void constructor (LexState *ls, expdesc *t) {
902 /* constructor -> '{' [ field { sep field } [sep] ] '}' 917 /* constructor -> '{' [ field { sep field } [sep] ] '}'
903 sep -> ',' | ';' */ 918 sep -> ',' | ';' */
904 FuncState *fs = ls->fs; 919 FuncState *fs = ls->fs;
905 int line = ls->linenumber; 920 int line = ls->linenumber;
906 int pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0); 921 int pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0);
907 struct ConsControl cc; 922 ConsControl cc;
923 luaK_codeextraarg(fs, 0);
908 cc.na = cc.nh = cc.tostore = 0; 924 cc.na = cc.nh = cc.tostore = 0;
909 cc.t = t; 925 cc.t = t;
910 init_exp(t, VRELOC, pc); 926 init_exp(t, VRELOC, pc);
@@ -919,8 +935,7 @@ static void constructor (LexState *ls, expdesc *t) {
919 } while (testnext(ls, ',') || testnext(ls, ';')); 935 } while (testnext(ls, ',') || testnext(ls, ';'));
920 check_match(ls, '}', '{', line); 936 check_match(ls, '}', '{', line);
921 lastlistfield(fs, &cc); 937 lastlistfield(fs, &cc);
922 SETARG_B(fs->f->code[pc], luaO_int2fb(cc.na)); /* set initial array size */ 938 settablesize(fs, &cc, pc);
923 SETARG_C(fs->f->code[pc], luaO_int2fb(cc.nh)); /* set initial table size */
924} 939}
925 940
926/* }====================================================================== */ 941/* }====================================================================== */