Roberto I 3 weeks ago
parent
commit
5b179eaf6a
5 changed files with 51 additions and 28 deletions
  1. 15 14
      lcode.c
  2. 1 1
      lparser.c
  3. 1 1
      ltable.c
  4. 20 12
      manual/manual.of
  5. 14 0
      testes/gengc.lua

+ 15 - 14
lcode.c

@@ -565,20 +565,20 @@ static int k2proto (FuncState *fs, TValue *key, TValue *v) {
   TValue val;
   TValue val;
   Proto *f = fs->f;
   Proto *f = fs->f;
   int tag = luaH_get(fs->kcache, key, &val);  /* query scanner table */
   int tag = luaH_get(fs->kcache, key, &val);  /* query scanner table */
-  int k;
   if (!tagisempty(tag)) {  /* is there an index there? */
   if (!tagisempty(tag)) {  /* is there an index there? */
-    k = cast_int(ivalue(&val));
+    int k = cast_int(ivalue(&val));
     /* collisions can happen only for float keys */
     /* collisions can happen only for float keys */
     lua_assert(ttisfloat(key) || luaV_rawequalobj(&f->k[k], v));
     lua_assert(ttisfloat(key) || luaV_rawequalobj(&f->k[k], v));
     return k;  /* reuse index */
     return k;  /* reuse index */
   }
   }
-  /* constant not found; create a new entry */
-  k = addk(fs, f, v);
-  /* cache it for reuse; numerical value does not need GC barrier;
-     table is not a metatable, so it does not need to invalidate cache */
-  setivalue(&val, k);
-  luaH_set(fs->ls->L, fs->kcache, key, &val);
-  return k;
+  else {  /* constant not found; create a new entry */
+    int k = addk(fs, f, v);
+    /* cache it for reuse; numerical value does not need GC barrier;
+       table is not a metatable, so it does not need to invalidate cache */
+    setivalue(&val, k);
+    luaH_set(fs->ls->L, fs->kcache, key, &val);
+    return k;
+  }
 }
 }
 
 
 
 
@@ -604,13 +604,14 @@ static int luaK_intK (FuncState *fs, lua_Integer n) {
 /*
 /*
 ** Add a float to list of constants and return its index. Floats
 ** Add a float to list of constants and return its index. Floats
 ** with integral values need a different key, to avoid collision
 ** with integral values need a different key, to avoid collision
-** with actual integers. To that, we add to the number its smaller
+** with actual integers. To that end, we add to the number its smaller
 ** power-of-two fraction that is still significant in its scale.
 ** power-of-two fraction that is still significant in its scale.
-** For doubles, that would be 1/2^52.
+** (For doubles, the fraction would be 2^-52).
 ** This method is not bulletproof: different numbers may generate the
 ** This method is not bulletproof: different numbers may generate the
 ** same key (e.g., very large numbers will overflow to 'inf') and for
 ** same key (e.g., very large numbers will overflow to 'inf') and for
-** floats larger than 2^53 the result is still an integer. At worst,
-** this only wastes an entry with a duplicate.
+** floats larger than 2^53 the result is still an integer. For those
+** cases, just generate a new entry. At worst, this only wastes an entry
+** with a duplicate.
 */
 */
 static int luaK_numberK (FuncState *fs, lua_Number r) {
 static int luaK_numberK (FuncState *fs, lua_Number r) {
   TValue o, kv;
   TValue o, kv;
@@ -625,7 +626,7 @@ static int luaK_numberK (FuncState *fs, lua_Number r) {
     const lua_Number k =  r * (1 + q);  /* key */
     const lua_Number k =  r * (1 + q);  /* key */
     lua_Integer ik;
     lua_Integer ik;
     setfltvalue(&kv, k);  /* key as a TValue */
     setfltvalue(&kv, k);  /* key as a TValue */
-    if (!luaV_flttointeger(k, &ik, F2Ieq)) {  /* not an integral value? */
+    if (!luaV_flttointeger(k, &ik, F2Ieq)) {  /* not an integer value? */
       int n = k2proto(fs, &kv, &o);  /* use key */
       int n = k2proto(fs, &kv, &o);  /* use key */
       if (luaV_rawequalobj(&fs->f->k[n], &o))  /* correct value? */
       if (luaV_rawequalobj(&fs->f->k[n], &o))  /* correct value? */
         return n;
         return n;

+ 1 - 1
lparser.c

@@ -1827,7 +1827,7 @@ static lu_byte getglobalattribute (LexState *ls, lu_byte df) {
   switch (kind) {
   switch (kind) {
     case RDKTOCLOSE:
     case RDKTOCLOSE:
       luaK_semerror(ls, "global variables cannot be to-be-closed");
       luaK_semerror(ls, "global variables cannot be to-be-closed");
-      break;  /* to avoid warnings */
+      return kind;  /* to avoid warnings */
     case RDKCONST:
     case RDKCONST:
       return GDKCONST;  /* adjust kind for global variable */
       return GDKCONST;  /* adjust kind for global variable */
     default:
     default:

+ 1 - 1
ltable.c

@@ -156,7 +156,7 @@ static Node *hashint (const Table *t, lua_Integer i) {
 ** The main computation should be just
 ** The main computation should be just
 **     n = frexp(n, &i); return (n * INT_MAX) + i
 **     n = frexp(n, &i); return (n * INT_MAX) + i
 ** but there are some numerical subtleties.
 ** but there are some numerical subtleties.
-** In a two-complement representation, INT_MAX does not has an exact
+** In a two-complement representation, INT_MAX may not have an exact
 ** representation as a float, but INT_MIN does; because the absolute
 ** representation as a float, but INT_MIN does; because the absolute
 ** value of 'frexp' is smaller than 1 (unless 'n' is inf/NaN), the
 ** value of 'frexp' is smaller than 1 (unless 'n' is inf/NaN), the
 ** absolute value of the product 'frexp * -INT_MIN' is smaller or equal
 ** absolute value of the product 'frexp * -INT_MIN' is smaller or equal

+ 20 - 12
manual/manual.of

@@ -127,7 +127,8 @@ strings can contain any 8-bit value,
 including @x{embedded zeros} (@Char{\0}).
 including @x{embedded zeros} (@Char{\0}).
 Lua is also encoding-agnostic;
 Lua is also encoding-agnostic;
 it makes no assumptions about the contents of a string.
 it makes no assumptions about the contents of a string.
-The length of any string in Lua must fit in a Lua integer.
+The length of any string in Lua must fit in a Lua integer,
+and the string plus a small header must fit in @id{size_t}.
 
 
 Lua can call (and manipulate) functions written in Lua and
 Lua can call (and manipulate) functions written in Lua and
 functions written in C @see{functioncall}.
 functions written in C @see{functioncall}.
@@ -1555,7 +1556,8 @@ It has the following syntax:
   exp @bnfter{,} exp @bnfopt{@bnfter{,} exp} @Rw{do} block @Rw{end}}
   exp @bnfter{,} exp @bnfopt{@bnfter{,} exp} @Rw{do} block @Rw{end}}
 }
 }
 The given identifier (@bnfNter{Name}) defines the control variable,
 The given identifier (@bnfNter{Name}) defines the control variable,
-which is a new read-only variable local to the loop body (@emph{block}).
+which is a new read-only (@id{const}) variable local to the loop body
+(@emph{block}).
 
 
 The loop starts by evaluating once the three control expressions.
 The loop starts by evaluating once the three control expressions.
 Their values are called respectively
 Their values are called respectively
@@ -1610,7 +1612,7 @@ works as follows.
 
 
 The names @rep{var_i} declare loop variables local to the loop body.
 The names @rep{var_i} declare loop variables local to the loop body.
 The first of these variables is the @emph{control variable},
 The first of these variables is the @emph{control variable},
-which is a read-only variable.
+which is a read-only (@id{const}) variable.
 
 
 The loop starts by evaluating @rep{explist}
 The loop starts by evaluating @rep{explist}
 to produce four values:
 to produce four values:
@@ -4083,7 +4085,7 @@ Lua will call @id{falloc} before raising the error.
 
 
 
 
 @APIEntry{const char *lua_pushfstring (lua_State *L, const char *fmt, ...);|
 @APIEntry{const char *lua_pushfstring (lua_State *L, const char *fmt, ...);|
-@apii{0,1,m}
+@apii{0,1,v}
 
 
 Pushes onto the stack a formatted string
 Pushes onto the stack a formatted string
 and returns a pointer to this string @see{constchar}.
 and returns a pointer to this string @see{constchar}.
@@ -4103,6 +4105,9 @@ A conversion specifier (and its corresponding extra argument) can be
 Every occurrence of @Char{%} in the string @id{fmt}
 Every occurrence of @Char{%} in the string @id{fmt}
 must form a valid conversion specifier.
 must form a valid conversion specifier.
 
 
+Besides memory allocation errors,
+this function may raise an error if the resulting string is too large.
+
 }
 }
 
 
 @APIEntry{void lua_pushglobaltable (lua_State *L);|
 @APIEntry{void lua_pushglobaltable (lua_State *L);|
@@ -4135,7 +4140,7 @@ light userdata with the same @N{C address}.
 }
 }
 
 
 @APIEntry{const char *lua_pushliteral (lua_State *L, const char *s);|
 @APIEntry{const char *lua_pushliteral (lua_State *L, const char *s);|
-@apii{0,1,m}
+@apii{0,1,v}
 
 
 This macro is equivalent to @Lid{lua_pushstring},
 This macro is equivalent to @Lid{lua_pushstring},
 but should be used only when @id{s} is a literal string.
 but should be used only when @id{s} is a literal string.
@@ -4144,7 +4149,7 @@ but should be used only when @id{s} is a literal string.
 }
 }
 
 
 @APIEntry{const char *lua_pushlstring (lua_State *L, const char *s, size_t len);|
 @APIEntry{const char *lua_pushlstring (lua_State *L, const char *s, size_t len);|
-@apii{0,1,m}
+@apii{0,1,v}
 
 
 Pushes the string pointed to by @id{s} with size @id{len}
 Pushes the string pointed to by @id{s} with size @id{len}
 onto the stack.
 onto the stack.
@@ -4156,6 +4161,9 @@ including @x{embedded zeros}.
 
 
 Returns a pointer to the internal copy of the string @see{constchar}.
 Returns a pointer to the internal copy of the string @see{constchar}.
 
 
+Besides memory allocation errors,
+this function may raise an error if the string is too large.
+
 }
 }
 
 
 @APIEntry{void lua_pushnil (lua_State *L);|
 @APIEntry{void lua_pushnil (lua_State *L);|
@@ -5015,8 +5023,8 @@ then @id{name} is set to @id{NULL}.
 @item{@id{namewhat}|
 @item{@id{namewhat}|
 explains the @T{name} field.
 explains the @T{name} field.
 The value of @T{namewhat} can be
 The value of @T{namewhat} can be
-@T{"global"}, @T{"local"}, @T{"method"},
-@T{"field"}, @T{"upvalue"}, or @T{""} (the empty string),
+@T{"global"}, @T{"local"}, @T{"upvalue"},
+@T{"field"}, @T{""} (the empty string), plus some other options,
 according to how the function was called.
 according to how the function was called.
 (Lua uses the empty string when no other option seems to apply.)
 (Lua uses the empty string when no other option seems to apply.)
 }
 }
@@ -6571,7 +6579,7 @@ The call always returns the previous value of the parameter.
 If the call does not give a new value,
 If the call does not give a new value,
 the value is left unchanged.
 the value is left unchanged.
 
 
-Lua rounds these values before storing them;
+Lua stores these values in a compressed format,
 so, the value returned as the previous value may not be
 so, the value returned as the previous value may not be
 exactly the last value set.
 exactly the last value set.
 }
 }
@@ -6585,10 +6593,10 @@ This function should not be called by a finalizer.
 }
 }
 
 
 @LibEntry{dofile ([filename])|
 @LibEntry{dofile ([filename])|
-Opens the named file and executes its content as a Lua chunk.
+Opens the named file and executes its content as a Lua chunk,
+returning all values returned by the chunk.
 When called without arguments,
 When called without arguments,
 @id{dofile} executes the content of the standard input (@id{stdin}).
 @id{dofile} executes the content of the standard input (@id{stdin}).
-Returns all values returned by the chunk.
 In case of errors, @id{dofile} propagates the error
 In case of errors, @id{dofile} propagates the error
 to its caller.
 to its caller.
 (That is, @id{dofile} does not run in protected mode.)
 (That is, @id{dofile} does not run in protected mode.)
@@ -6960,7 +6968,7 @@ in case of error
 (either the original error that stopped the coroutine or
 (either the original error that stopped the coroutine or
 errors in closing methods),
 errors in closing methods),
 this function returns @false plus the error object;
 this function returns @false plus the error object;
-otherwise ir returns @true.
+otherwise it returns @true.
 
 
 }
 }
 
 

+ 14 - 0
testes/gengc.lua

@@ -176,6 +176,20 @@ do  print"testing stop-the-world collection"
   assert(collectgarbage("param", "stepsize") == step)
   assert(collectgarbage("param", "stepsize") == step)
 end
 end
 
 
+
+if T then   -- test GC parameter codification
+  for _, percentage in ipairs{5, 10, 12, 20, 50, 100, 200, 500} do
+    local param = T.codeparam(percentage)   -- codify percentage
+    for _, value in ipairs{1, 2, 10, 100, 257, 1023, 6500, 100000} do
+      local exact = value*percentage // 100
+      local aprox = T.applyparam(param, value)   -- apply percentage
+      -- difference is at most 10% (+1 compensates difference due to
+      -- rounding to integers)
+      assert(math.abs(aprox - exact) <= exact/10 + 1)
+    end
+  end
+end
+
 collectgarbage(oldmode)
 collectgarbage(oldmode)
 
 
 print('OK')
 print('OK')