aboutsummaryrefslogtreecommitdiff
path: root/lparser.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2024-06-27 11:24:27 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2024-06-27 11:24:27 -0300
commit9904c253da9690728710082cfb94654709ab89e7 (patch)
treef556ebbf8d99baa37ea8e39608a3d6bea77f8267 /lparser.c
parentfb7e5b76c9d41108c399cf4d16470018b717007b (diff)
downloadlua-9904c253da9690728710082cfb94654709ab89e7.tar.gz
lua-9904c253da9690728710082cfb94654709ab89e7.tar.bz2
lua-9904c253da9690728710082cfb94654709ab89e7.zip
Flexible limit for use of registers by constructors
Instead of a fixed limit of 50 registers (which, in a bad worst case, can limit the nesting of constructors to 5 levels), the compiler computes an individual limit for each constructor based on how many registers are available when it runs. This limit then controls the frequency of SETLIST instructions.
Diffstat (limited to 'lparser.c')
-rw-r--r--lparser.c21
1 files changed, 19 insertions, 2 deletions
diff --git a/lparser.c b/lparser.c
index cdc8cf42..f3779864 100644
--- a/lparser.c
+++ b/lparser.c
@@ -843,13 +843,13 @@ static void yindex (LexState *ls, expdesc *v) {
843** ======================================================================= 843** =======================================================================
844*/ 844*/
845 845
846
847typedef struct ConsControl { 846typedef 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*/
939static 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
934static void constructor (LexState *ls, expdesc *t) { 950static 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;