aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto I <roberto@inf.puc-rio.br>2025-08-09 15:08:53 -0300
committerRoberto I <roberto@inf.puc-rio.br>2025-08-09 15:08:53 -0300
commit5b179eaf6a78af5f000d76147af94669d04487b2 (patch)
treea3466ed22def25294ff1647d1af91cd4ef7fa567
parent8fddca81e7d4137512e92f398ca638d61b935dbd (diff)
downloadlua-5b179eaf6a78af5f000d76147af94669d04487b2.tar.gz
lua-5b179eaf6a78af5f000d76147af94669d04487b2.tar.bz2
lua-5b179eaf6a78af5f000d76147af94669d04487b2.zip
Details
-rw-r--r--lcode.c29
-rw-r--r--lparser.c2
-rw-r--r--ltable.c2
-rw-r--r--manual/manual.of32
-rw-r--r--testes/gengc.lua14
5 files changed, 51 insertions, 28 deletions
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) {
565 TValue val; 565 TValue val;
566 Proto *f = fs->f; 566 Proto *f = fs->f;
567 int tag = luaH_get(fs->kcache, key, &val); /* query scanner table */ 567 int tag = luaH_get(fs->kcache, key, &val); /* query scanner table */
568 int k;
569 if (!tagisempty(tag)) { /* is there an index there? */ 568 if (!tagisempty(tag)) { /* is there an index there? */
570 k = cast_int(ivalue(&val)); 569 int k = cast_int(ivalue(&val));
571 /* collisions can happen only for float keys */ 570 /* collisions can happen only for float keys */
572 lua_assert(ttisfloat(key) || luaV_rawequalobj(&f->k[k], v)); 571 lua_assert(ttisfloat(key) || luaV_rawequalobj(&f->k[k], v));
573 return k; /* reuse index */ 572 return k; /* reuse index */
574 } 573 }
575 /* constant not found; create a new entry */ 574 else { /* constant not found; create a new entry */
576 k = addk(fs, f, v); 575 int k = addk(fs, f, v);
577 /* cache it for reuse; numerical value does not need GC barrier; 576 /* cache it for reuse; numerical value does not need GC barrier;
578 table is not a metatable, so it does not need to invalidate cache */ 577 table is not a metatable, so it does not need to invalidate cache */
579 setivalue(&val, k); 578 setivalue(&val, k);
580 luaH_set(fs->ls->L, fs->kcache, key, &val); 579 luaH_set(fs->ls->L, fs->kcache, key, &val);
581 return k; 580 return k;
581 }
582} 582}
583 583
584 584
@@ -604,13 +604,14 @@ static int luaK_intK (FuncState *fs, lua_Integer n) {
604/* 604/*
605** Add a float to list of constants and return its index. Floats 605** Add a float to list of constants and return its index. Floats
606** with integral values need a different key, to avoid collision 606** with integral values need a different key, to avoid collision
607** with actual integers. To that, we add to the number its smaller 607** with actual integers. To that end, we add to the number its smaller
608** power-of-two fraction that is still significant in its scale. 608** power-of-two fraction that is still significant in its scale.
609** For doubles, that would be 1/2^52. 609** (For doubles, the fraction would be 2^-52).
610** This method is not bulletproof: different numbers may generate the 610** This method is not bulletproof: different numbers may generate the
611** same key (e.g., very large numbers will overflow to 'inf') and for 611** same key (e.g., very large numbers will overflow to 'inf') and for
612** floats larger than 2^53 the result is still an integer. At worst, 612** floats larger than 2^53 the result is still an integer. For those
613** this only wastes an entry with a duplicate. 613** cases, just generate a new entry. At worst, this only wastes an entry
614** with a duplicate.
614*/ 615*/
615static int luaK_numberK (FuncState *fs, lua_Number r) { 616static int luaK_numberK (FuncState *fs, lua_Number r) {
616 TValue o, kv; 617 TValue o, kv;
@@ -625,7 +626,7 @@ static int luaK_numberK (FuncState *fs, lua_Number r) {
625 const lua_Number k = r * (1 + q); /* key */ 626 const lua_Number k = r * (1 + q); /* key */
626 lua_Integer ik; 627 lua_Integer ik;
627 setfltvalue(&kv, k); /* key as a TValue */ 628 setfltvalue(&kv, k); /* key as a TValue */
628 if (!luaV_flttointeger(k, &ik, F2Ieq)) { /* not an integral value? */ 629 if (!luaV_flttointeger(k, &ik, F2Ieq)) { /* not an integer value? */
629 int n = k2proto(fs, &kv, &o); /* use key */ 630 int n = k2proto(fs, &kv, &o); /* use key */
630 if (luaV_rawequalobj(&fs->f->k[n], &o)) /* correct value? */ 631 if (luaV_rawequalobj(&fs->f->k[n], &o)) /* correct value? */
631 return n; 632 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) {
1827 switch (kind) { 1827 switch (kind) {
1828 case RDKTOCLOSE: 1828 case RDKTOCLOSE:
1829 luaK_semerror(ls, "global variables cannot be to-be-closed"); 1829 luaK_semerror(ls, "global variables cannot be to-be-closed");
1830 break; /* to avoid warnings */ 1830 return kind; /* to avoid warnings */
1831 case RDKCONST: 1831 case RDKCONST:
1832 return GDKCONST; /* adjust kind for global variable */ 1832 return GDKCONST; /* adjust kind for global variable */
1833 default: 1833 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) {
156** The main computation should be just 156** The main computation should be just
157** n = frexp(n, &i); return (n * INT_MAX) + i 157** n = frexp(n, &i); return (n * INT_MAX) + i
158** but there are some numerical subtleties. 158** but there are some numerical subtleties.
159** In a two-complement representation, INT_MAX does not has an exact 159** In a two-complement representation, INT_MAX may not have an exact
160** representation as a float, but INT_MIN does; because the absolute 160** representation as a float, but INT_MIN does; because the absolute
161** value of 'frexp' is smaller than 1 (unless 'n' is inf/NaN), the 161** value of 'frexp' is smaller than 1 (unless 'n' is inf/NaN), the
162** absolute value of the product 'frexp * -INT_MIN' is smaller or equal 162** 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,
127including @x{embedded zeros} (@Char{\0}). 127including @x{embedded zeros} (@Char{\0}).
128Lua is also encoding-agnostic; 128Lua is also encoding-agnostic;
129it makes no assumptions about the contents of a string. 129it makes no assumptions about the contents of a string.
130The length of any string in Lua must fit in a Lua integer. 130The length of any string in Lua must fit in a Lua integer,
131and the string plus a small header must fit in @id{size_t}.
131 132
132Lua can call (and manipulate) functions written in Lua and 133Lua can call (and manipulate) functions written in Lua and
133functions written in C @see{functioncall}. 134functions written in C @see{functioncall}.
@@ -1555,7 +1556,8 @@ It has the following syntax:
1555 exp @bnfter{,} exp @bnfopt{@bnfter{,} exp} @Rw{do} block @Rw{end}} 1556 exp @bnfter{,} exp @bnfopt{@bnfter{,} exp} @Rw{do} block @Rw{end}}
1556} 1557}
1557The given identifier (@bnfNter{Name}) defines the control variable, 1558The given identifier (@bnfNter{Name}) defines the control variable,
1558which is a new read-only variable local to the loop body (@emph{block}). 1559which is a new read-only (@id{const}) variable local to the loop body
1560(@emph{block}).
1559 1561
1560The loop starts by evaluating once the three control expressions. 1562The loop starts by evaluating once the three control expressions.
1561Their values are called respectively 1563Their values are called respectively
@@ -1610,7 +1612,7 @@ works as follows.
1610 1612
1611The names @rep{var_i} declare loop variables local to the loop body. 1613The names @rep{var_i} declare loop variables local to the loop body.
1612The first of these variables is the @emph{control variable}, 1614The first of these variables is the @emph{control variable},
1613which is a read-only variable. 1615which is a read-only (@id{const}) variable.
1614 1616
1615The loop starts by evaluating @rep{explist} 1617The loop starts by evaluating @rep{explist}
1616to produce four values: 1618to produce four values:
@@ -4083,7 +4085,7 @@ Lua will call @id{falloc} before raising the error.
4083 4085
4084 4086
4085@APIEntry{const char *lua_pushfstring (lua_State *L, const char *fmt, ...);| 4087@APIEntry{const char *lua_pushfstring (lua_State *L, const char *fmt, ...);|
4086@apii{0,1,m} 4088@apii{0,1,v}
4087 4089
4088Pushes onto the stack a formatted string 4090Pushes onto the stack a formatted string
4089and returns a pointer to this string @see{constchar}. 4091and returns a pointer to this string @see{constchar}.
@@ -4103,6 +4105,9 @@ A conversion specifier (and its corresponding extra argument) can be
4103Every occurrence of @Char{%} in the string @id{fmt} 4105Every occurrence of @Char{%} in the string @id{fmt}
4104must form a valid conversion specifier. 4106must form a valid conversion specifier.
4105 4107
4108Besides memory allocation errors,
4109this function may raise an error if the resulting string is too large.
4110
4106} 4111}
4107 4112
4108@APIEntry{void lua_pushglobaltable (lua_State *L);| 4113@APIEntry{void lua_pushglobaltable (lua_State *L);|
@@ -4135,7 +4140,7 @@ light userdata with the same @N{C address}.
4135} 4140}
4136 4141
4137@APIEntry{const char *lua_pushliteral (lua_State *L, const char *s);| 4142@APIEntry{const char *lua_pushliteral (lua_State *L, const char *s);|
4138@apii{0,1,m} 4143@apii{0,1,v}
4139 4144
4140This macro is equivalent to @Lid{lua_pushstring}, 4145This macro is equivalent to @Lid{lua_pushstring},
4141but should be used only when @id{s} is a literal string. 4146but 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.
4144} 4149}
4145 4150
4146@APIEntry{const char *lua_pushlstring (lua_State *L, const char *s, size_t len);| 4151@APIEntry{const char *lua_pushlstring (lua_State *L, const char *s, size_t len);|
4147@apii{0,1,m} 4152@apii{0,1,v}
4148 4153
4149Pushes the string pointed to by @id{s} with size @id{len} 4154Pushes the string pointed to by @id{s} with size @id{len}
4150onto the stack. 4155onto the stack.
@@ -4156,6 +4161,9 @@ including @x{embedded zeros}.
4156 4161
4157Returns a pointer to the internal copy of the string @see{constchar}. 4162Returns a pointer to the internal copy of the string @see{constchar}.
4158 4163
4164Besides memory allocation errors,
4165this function may raise an error if the string is too large.
4166
4159} 4167}
4160 4168
4161@APIEntry{void lua_pushnil (lua_State *L);| 4169@APIEntry{void lua_pushnil (lua_State *L);|
@@ -5015,8 +5023,8 @@ then @id{name} is set to @id{NULL}.
5015@item{@id{namewhat}| 5023@item{@id{namewhat}|
5016explains the @T{name} field. 5024explains the @T{name} field.
5017The value of @T{namewhat} can be 5025The value of @T{namewhat} can be
5018@T{"global"}, @T{"local"}, @T{"method"}, 5026@T{"global"}, @T{"local"}, @T{"upvalue"},
5019@T{"field"}, @T{"upvalue"}, or @T{""} (the empty string), 5027@T{"field"}, @T{""} (the empty string), plus some other options,
5020according to how the function was called. 5028according to how the function was called.
5021(Lua uses the empty string when no other option seems to apply.) 5029(Lua uses the empty string when no other option seems to apply.)
5022} 5030}
@@ -6571,7 +6579,7 @@ The call always returns the previous value of the parameter.
6571If the call does not give a new value, 6579If the call does not give a new value,
6572the value is left unchanged. 6580the value is left unchanged.
6573 6581
6574Lua rounds these values before storing them; 6582Lua stores these values in a compressed format,
6575so, the value returned as the previous value may not be 6583so, the value returned as the previous value may not be
6576exactly the last value set. 6584exactly the last value set.
6577} 6585}
@@ -6585,10 +6593,10 @@ This function should not be called by a finalizer.
6585} 6593}
6586 6594
6587@LibEntry{dofile ([filename])| 6595@LibEntry{dofile ([filename])|
6588Opens the named file and executes its content as a Lua chunk. 6596Opens the named file and executes its content as a Lua chunk,
6597returning all values returned by the chunk.
6589When called without arguments, 6598When called without arguments,
6590@id{dofile} executes the content of the standard input (@id{stdin}). 6599@id{dofile} executes the content of the standard input (@id{stdin}).
6591Returns all values returned by the chunk.
6592In case of errors, @id{dofile} propagates the error 6600In case of errors, @id{dofile} propagates the error
6593to its caller. 6601to its caller.
6594(That is, @id{dofile} does not run in protected mode.) 6602(That is, @id{dofile} does not run in protected mode.)
@@ -6960,7 +6968,7 @@ in case of error
6960(either the original error that stopped the coroutine or 6968(either the original error that stopped the coroutine or
6961errors in closing methods), 6969errors in closing methods),
6962this function returns @false plus the error object; 6970this function returns @false plus the error object;
6963otherwise ir returns @true. 6971otherwise it returns @true.
6964 6972
6965} 6973}
6966 6974
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"
176 assert(collectgarbage("param", "stepsize") == step) 176 assert(collectgarbage("param", "stepsize") == step)
177end 177end
178 178
179
180if T then -- test GC parameter codification
181 for _, percentage in ipairs{5, 10, 12, 20, 50, 100, 200, 500} do
182 local param = T.codeparam(percentage) -- codify percentage
183 for _, value in ipairs{1, 2, 10, 100, 257, 1023, 6500, 100000} do
184 local exact = value*percentage // 100
185 local aprox = T.applyparam(param, value) -- apply percentage
186 -- difference is at most 10% (+1 compensates difference due to
187 -- rounding to integers)
188 assert(math.abs(aprox - exact) <= exact/10 + 1)
189 end
190 end
191end
192
179collectgarbage(oldmode) 193collectgarbage(oldmode)
180 194
181print('OK') 195print('OK')