diff options
Diffstat (limited to 'lparser.c')
-rw-r--r-- | lparser.c | 21 |
1 files changed, 19 insertions, 2 deletions
@@ -843,13 +843,13 @@ static void yindex (LexState *ls, expdesc *v) { | |||
843 | ** ======================================================================= | 843 | ** ======================================================================= |
844 | */ | 844 | */ |
845 | 845 | ||
846 | |||
847 | typedef struct ConsControl { | 846 | typedef struct ConsControl { |
848 | expdesc v; /* last list item read */ | 847 | expdesc v; /* last list item read */ |
849 | expdesc *t; /* table descriptor */ | 848 | expdesc *t; /* table descriptor */ |
850 | int nh; /* total number of 'record' elements */ | 849 | int nh; /* total number of 'record' elements */ |
851 | int na; /* number of array elements already stored */ | 850 | int na; /* number of array elements already stored */ |
852 | int tostore; /* number of array elements pending to be stored */ | 851 | int tostore; /* number of array elements pending to be stored */ |
852 | int maxtostore; /* maximum number of pending elements */ | ||
853 | } ConsControl; | 853 | } ConsControl; |
854 | 854 | ||
855 | 855 | ||
@@ -878,7 +878,7 @@ static void closelistfield (FuncState *fs, ConsControl *cc) { | |||
878 | if (cc->v.k == VVOID) return; /* there is no list item */ | 878 | if (cc->v.k == VVOID) return; /* there is no list item */ |
879 | luaK_exp2nextreg(fs, &cc->v); | 879 | luaK_exp2nextreg(fs, &cc->v); |
880 | cc->v.k = VVOID; | 880 | cc->v.k = VVOID; |
881 | if (cc->tostore == LFIELDS_PER_FLUSH) { | 881 | if (cc->tostore >= cc->maxtostore) { |
882 | luaK_setlist(fs, cc->t->u.info, cc->na, cc->tostore); /* flush */ | 882 | luaK_setlist(fs, cc->t->u.info, cc->na, cc->tostore); /* flush */ |
883 | cc->na += cc->tostore; | 883 | cc->na += cc->tostore; |
884 | cc->tostore = 0; /* no more items pending */ | 884 | cc->tostore = 0; /* no more items pending */ |
@@ -931,6 +931,22 @@ static void field (LexState *ls, ConsControl *cc) { | |||
931 | } | 931 | } |
932 | 932 | ||
933 | 933 | ||
934 | /* | ||
935 | ** Compute a limit for how many registers a constructor can use before | ||
936 | ** emitting a 'SETLIST' instruction, based on how many registers are | ||
937 | ** available. | ||
938 | */ | ||
939 | static int maxtostore (FuncState *fs) { | ||
940 | int numfreeregs = MAX_FSTACK - fs->freereg; | ||
941 | if (numfreeregs >= 160) /* "lots" of registers? */ | ||
942 | return numfreeregs / 5u; /* use up to 1/5 of them */ | ||
943 | else if (numfreeregs >= 80) /* still "enough" registers? */ | ||
944 | return 10; /* one 'SETLIST' instruction for each 10 values */ | ||
945 | else /* save registers for potential more nesting */ | ||
946 | return 1; | ||
947 | } | ||
948 | |||
949 | |||
934 | static void constructor (LexState *ls, expdesc *t) { | 950 | static void constructor (LexState *ls, expdesc *t) { |
935 | /* constructor -> '{' [ field { sep field } [sep] ] '}' | 951 | /* constructor -> '{' [ field { sep field } [sep] ] '}' |
936 | sep -> ',' | ';' */ | 952 | sep -> ',' | ';' */ |
@@ -945,6 +961,7 @@ static void constructor (LexState *ls, expdesc *t) { | |||
945 | luaK_reserveregs(fs, 1); | 961 | luaK_reserveregs(fs, 1); |
946 | init_exp(&cc.v, VVOID, 0); /* no value (yet) */ | 962 | init_exp(&cc.v, VVOID, 0); /* no value (yet) */ |
947 | checknext(ls, '{'); | 963 | checknext(ls, '{'); |
964 | cc.maxtostore = maxtostore(fs); | ||
948 | do { | 965 | do { |
949 | lua_assert(cc.v.k == VVOID || cc.tostore > 0); | 966 | lua_assert(cc.v.k == VVOID || cc.tostore > 0); |
950 | if (ls->t.token == '}') break; | 967 | if (ls->t.token == '}') break; |