diff options
Diffstat (limited to '')
-rw-r--r-- | lcode.c | 2 | ||||
-rw-r--r-- | lopcodes.h | 3 | ||||
-rw-r--r-- | lparser.c | 21 | ||||
-rw-r--r-- | ltests.c | 1 | ||||
-rw-r--r-- | testes/code.lua | 11 |
5 files changed, 31 insertions, 7 deletions
@@ -1804,7 +1804,7 @@ void luaK_settablesize (FuncState *fs, int pc, int ra, int asize, int hsize) { | |||
1804 | ** table (or LUA_MULTRET to add up to stack top). | 1804 | ** table (or LUA_MULTRET to add up to stack top). |
1805 | */ | 1805 | */ |
1806 | void luaK_setlist (FuncState *fs, int base, int nelems, int tostore) { | 1806 | void luaK_setlist (FuncState *fs, int base, int nelems, int tostore) { |
1807 | lua_assert(tostore != 0 && tostore <= LFIELDS_PER_FLUSH); | 1807 | lua_assert(tostore != 0); |
1808 | if (tostore == LUA_MULTRET) | 1808 | if (tostore == LUA_MULTRET) |
1809 | tostore = 0; | 1809 | tostore = 0; |
1810 | if (nelems <= MAXARG_C) | 1810 | if (nelems <= MAXARG_C) |
@@ -406,7 +406,4 @@ LUAI_DDEC(const lu_byte luaP_opmodes[NUM_OPCODES];) | |||
406 | (((mm) << 7) | ((ot) << 6) | ((it) << 5) | ((t) << 4) | ((a) << 3) | (m)) | 406 | (((mm) << 7) | ((ot) << 6) | ((it) << 5) | ((t) << 4) | ((a) << 3) | (m)) |
407 | 407 | ||
408 | 408 | ||
409 | /* number of list items to accumulate before a SETLIST instruction */ | ||
410 | #define LFIELDS_PER_FLUSH 50 | ||
411 | |||
412 | #endif | 409 | #endif |
@@ -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; |
@@ -835,7 +835,6 @@ static int get_limits (lua_State *L) { | |||
835 | setnameval(L, "MAXARG_Ax", MAXARG_Ax); | 835 | setnameval(L, "MAXARG_Ax", MAXARG_Ax); |
836 | setnameval(L, "MAXARG_Bx", MAXARG_Bx); | 836 | setnameval(L, "MAXARG_Bx", MAXARG_Bx); |
837 | setnameval(L, "OFFSET_sBx", OFFSET_sBx); | 837 | setnameval(L, "OFFSET_sBx", OFFSET_sBx); |
838 | setnameval(L, "LFPF", LFIELDS_PER_FLUSH); | ||
839 | setnameval(L, "NUM_OPCODES", NUM_OPCODES); | 838 | setnameval(L, "NUM_OPCODES", NUM_OPCODES); |
840 | return 1; | 839 | return 1; |
841 | } | 840 | } |
diff --git a/testes/code.lua b/testes/code.lua index 329619f1..08b3e23f 100644 --- a/testes/code.lua +++ b/testes/code.lua | |||
@@ -460,5 +460,16 @@ do -- check number of available registers | |||
460 | assert(string.find(msg, "too many registers")) | 460 | assert(string.find(msg, "too many registers")) |
461 | end | 461 | end |
462 | 462 | ||
463 | |||
464 | do -- basic check for SETLIST | ||
465 | -- create a list constructor with 50 elements | ||
466 | local source = "local a; return {" .. string.rep("a, ", 50) .. "}" | ||
467 | local func = assert(load(source)) | ||
468 | local code = table.concat(T.listcode(func), "\n") | ||
469 | local _, count = string.gsub(code, "SETLIST", "") | ||
470 | -- code uses only 1 SETLIST for the constructor | ||
471 | assert(count == 1) | ||
472 | end | ||
473 | |||
463 | print 'OK' | 474 | print 'OK' |
464 | 475 | ||