Browse Source

No need to limit variable declarations to 250

Only local variables, which use registers, need this low limit.
Roberto Ierusalimschy 1 month ago
parent
commit
07b009c371
4 changed files with 38 additions and 11 deletions
  1. 2 3
      lparser.c
  2. 2 2
      lparser.h
  3. 1 1
      testes/errors.lua
  4. 33 5
      testes/goto.lua

+ 2 - 3
lparser.c

@@ -50,7 +50,7 @@ typedef struct BlockCnt {
   struct BlockCnt *previous;  /* chain */
   int firstlabel;  /* index of first label in this block */
   int firstgoto;  /* index of first pending goto in this block */
-  lu_byte nactvar;  /* # active locals outside the block */
+  short nactvar;  /* number of active declarations at block entry */
   lu_byte upval;  /* true if some variable in the block is an upvalue */
   lu_byte isloop;  /* 1 if 'block' is a loop; 2 if it has pending breaks */
   lu_byte insidetbc;  /* true if inside the scope of a to-be-closed var. */
@@ -196,8 +196,6 @@ static int new_varkind (LexState *ls, TString *name, lu_byte kind) {
   FuncState *fs = ls->fs;
   Dyndata *dyd = ls->dyd;
   Vardesc *var;
-  luaY_checklimit(fs, dyd->actvar.n + 1 - fs->firstlocal,
-                 MAXVARS, "local variables");
   luaM_growvector(L, dyd->actvar.arr, dyd->actvar.n + 1,
              dyd->actvar.size, Vardesc, SHRT_MAX, "variable declarationss");
   var = &dyd->actvar.arr[dyd->actvar.n++];
@@ -330,6 +328,7 @@ static void adjustlocalvars (LexState *ls, int nvars) {
     Vardesc *var = getlocalvardesc(fs, vidx);
     var->vd.ridx = cast_byte(reglevel++);
     var->vd.pidx = registerlocalvar(ls, fs, var->vd.name);
+    luaY_checklimit(fs, reglevel, MAXVARS, "local variables");
   }
 }
 

+ 2 - 2
lparser.h

@@ -128,7 +128,7 @@ typedef struct Labeldesc {
   TString *name;  /* label identifier */
   int pc;  /* position in code */
   int line;  /* line where it appeared */
-  lu_byte nactvar;  /* number of active variables in that position */
+  short nactvar;  /* number of active variables in that position */
   lu_byte close;  /* true for goto that escapes upvalues */
 } Labeldesc;
 
@@ -173,7 +173,7 @@ typedef struct FuncState {
   int firstlocal;  /* index of first local var (in Dyndata array) */
   int firstlabel;  /* index of first label (in 'dyd->label->arr') */
   short ndebugvars;  /* number of elements in 'f->locvars' */
-  lu_byte nactvar;  /* number of active local variables */
+  short nactvar;  /* number of active variable declarations */
   lu_byte nups;  /* number of upvalues */
   lu_byte freereg;  /* first free register */
   lu_byte iwthabs;  /* instructions issued since last absolute line info */

+ 1 - 1
testes/errors.lua

@@ -742,7 +742,7 @@ assert(c > 255 and string.find(b, "too many upvalues") and
 
 -- local variables
 s = "\nfunction foo ()\n  local "
-for j = 1,300 do
+for j = 1,200 do
   s = s.."a"..j..", "
 end
 s = s.."b\n"

+ 33 - 5
testes/goto.lua

@@ -293,14 +293,14 @@ end
 foo()
 --------------------------------------------------------------------------
 
+local function checkerr (code, err)
+  local st, msg = load(code)
+  assert(not st and string.find(msg, err))
+end
+
 do
   global T<const>
 
-  local function checkerr (code, err)
-    local st, msg = load(code)
-    assert(not st and string.find(msg, err))
-  end
-
   -- globals must be declared, after a global declaration
   checkerr("global none; X = 1", "variable 'X'")
   checkerr("global none; function XX() end", "variable 'XX'")
@@ -383,5 +383,33 @@ do
 
 end
 
+
+do   -- Ok to declare hundreds of globals
+  global table
+  local code = {}
+  for i = 1, 1000 do
+    code[#code + 1] = ";global x" .. i
+  end
+  code[#code + 1] = "; return x990"
+  code = table.concat(code)
+  _ENV.x990 = 11
+  assert(load(code)() == 11)
+  _ENV.x990 = nil
+end
+
+do   -- mixing lots of global/local declarations
+  global table
+  local code = {}
+  for i = 1, 200 do
+    code[#code + 1] = ";global x" .. i
+    code[#code + 1] = ";local y" .. i .. "=" .. (2*i)
+  end
+  code[#code + 1] = "; return x200 + y200"
+  code = table.concat(code)
+  _ENV.x200 = 11
+  assert(assert(load(code))() == 2*200 + 11)
+  _ENV.x200 = nil
+end
+
 print'OK'