diff --git a/lcode.c b/lcode.c index 7ca895f1..cafe265e 100644 --- a/lcode.c +++ b/lcode.c @@ -565,20 +565,20 @@ static int k2proto (FuncState *fs, TValue *key, TValue *v) { TValue val; Proto *f = fs->f; int tag = luaH_get(fs->kcache, key, &val); /* query scanner table */ - int k; 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 */ lua_assert(ttisfloat(key) || luaV_rawequalobj(&f->k[k], v)); 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 ** 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. -** 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 ** 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) { TValue o, kv; @@ -625,7 +626,7 @@ static int luaK_numberK (FuncState *fs, lua_Number r) { const lua_Number k = r * (1 + q); /* key */ lua_Integer ik; 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 */ if (luaV_rawequalobj(&fs->f->k[n], &o)) /* correct value? */ return n; diff --git a/lparser.c b/lparser.c index dde0b6d5..73dad6d7 100644 --- a/lparser.c +++ b/lparser.c @@ -1827,7 +1827,7 @@ static lu_byte getglobalattribute (LexState *ls, lu_byte df) { switch (kind) { case RDKTOCLOSE: luaK_semerror(ls, "global variables cannot be to-be-closed"); - break; /* to avoid warnings */ + return kind; /* to avoid warnings */ case RDKCONST: return GDKCONST; /* adjust kind for global variable */ default: diff --git a/ltable.c b/ltable.c index 4017d8c7..b7f88f6f 100644 --- a/ltable.c +++ b/ltable.c @@ -156,7 +156,7 @@ static Node *hashint (const Table *t, lua_Integer i) { ** The main computation should be just ** n = frexp(n, &i); return (n * INT_MAX) + i ** 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 ** 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 diff --git a/manual/manual.of b/manual/manual.of index b2765774..61dd42f2 100644 --- a/manual/manual.of +++ b/manual/manual.of @@ -127,7 +127,8 @@ strings can contain any 8-bit value, including @x{embedded zeros} (@Char{\0}). Lua is also encoding-agnostic; 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 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}} } 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. 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 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} 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, ...);| -@apii{0,1,m} +@apii{0,1,v} Pushes onto the stack a formatted string 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} 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);| @@ -4135,7 +4140,7 @@ light userdata with the same @N{C address}. } @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}, 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);| -@apii{0,1,m} +@apii{0,1,v} Pushes the string pointed to by @id{s} with size @id{len} onto the stack. @@ -4156,6 +4161,9 @@ including @x{embedded zeros}. 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);| @@ -5015,8 +5023,8 @@ then @id{name} is set to @id{NULL}. @item{@id{namewhat}| explains the @T{name} field. 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. (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, 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 exactly the last value set. } @@ -6585,10 +6593,10 @@ This function should not be called by a finalizer. } @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, @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 to its caller. (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 errors in closing methods), this function returns @false plus the error object; -otherwise ir returns @true. +otherwise it returns @true. } diff --git a/testes/gengc.lua b/testes/gengc.lua index ea99bdc4..6509e39d 100644 --- a/testes/gengc.lua +++ b/testes/gengc.lua @@ -176,6 +176,20 @@ do print"testing stop-the-world collection" assert(collectgarbage("param", "stepsize") == step) 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) print('OK')