lua

A copy of the Lua development repository
Log | Files | Refs | README

commit 3b57e37e4821ddce4756428956b7e9f4969efa4c
parent 024f9064f1b43758eb36aba52547edc0312bf4ba
Author: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
Date:   Fri, 10 Nov 2023 12:35:21 -0300

Fixed buffers save long strings as external.

Diffstat:
Mldump.c | 2+-
Mlundump.c | 23+++++++++++++++--------
Mmanual/manual.of | 6++++--
Mtestes/api.lua | 14+++++++++-----
4 files changed, 29 insertions(+), 16 deletions(-)

diff --git a/ldump.c b/ldump.c @@ -126,7 +126,7 @@ static void dumpString (DumpState *D, TString *ts) { size_t size; const char *s = getlstr(ts, size); dumpSize(D, size + 2); - dumpVector(D, s, size); + dumpVector(D, s, size + 1); /* include ending '\0' */ D->nstr++; /* one more saved string */ setsvalue(D->L, &key, ts); /* the string is the key */ setivalue(&value, D->nstr); /* its index is the value */ diff --git a/lundump.c b/lundump.c @@ -147,17 +147,24 @@ static TString *loadStringN (LoadState *S, Proto *p) { luaH_getint(S->h, idx, &stv); return tsvalue(&stv); } - else if (size -= 2, size <= LUAI_MAXSHORTLEN) { /* short string? */ - char buff[LUAI_MAXSHORTLEN]; - loadVector(S, buff, size); /* load string into buffer */ + else if ((size -= 2) <= LUAI_MAXSHORTLEN) { /* short string? */ + char buff[LUAI_MAXSHORTLEN + 1]; /* extra space for '\0' */ + loadVector(S, buff, size + 1); /* load string into buffer */ ts = luaS_newlstr(L, buff, size); /* create string */ } else { /* long string */ - ts = luaS_createlngstrobj(L, size); /* create string */ - setsvalue2s(L, L->top.p, ts); /* anchor it ('loadVector' can GC) */ - luaD_inctop(L); - loadVector(S, getlngstr(ts), size); /* load directly in final place */ - L->top.p--; /* pop string */ + if (S->fixed) { /* for a fixed buffer, use a fixed string */ + const char *s = getaddr(S, size + 1, char); /* get content address */ + ts = luaS_newextlstr(L, s, size, NULL, NULL); + } + else { /* create internal copy */ + ts = luaS_createlngstrobj(L, size); /* create string */ + setsvalue2s(L, L->top.p, ts); /* anchor it ('loadVector' can GC) */ + luaD_inctop(L); + loadVector(S, getlngstr(ts), size); /* load directly in final place */ + loadByte(S); /* skip ending '\0' */ + L->top.p--; /* pop string */ + } } luaC_objbarrier(L, p, ts); S->nstr++; /* add string to list of saved strings */ diff --git a/manual/manual.of b/manual/manual.of @@ -3651,8 +3651,10 @@ Moreover, it may have a @Char{B} instead of a @Char{b}, meaning a @emphx{fixed buffer} with the binary dump. A fixed buffer means that the address returned by the reader function -should contain the chunk until everything created by the chunk has -been collected. +will contain the chunk until everything created by the chunk has +been collected; +therefore, Lua can avoid copying to internal structures +some parts of the chunk. (In general, a fixed buffer would keep the chunk as its contents until the end of the program, for instance with the chunk in ROM.) diff --git a/testes/api.lua b/testes/api.lua @@ -528,13 +528,15 @@ do local N = 1000 -- create a somewhat "large" source for i = 1, N do source[i] = "X = X + 1; " end + -- add a long string to the source + source[#source + 1] = string.format("Y = '%s'", string.rep("a", N)); source = table.concat(source) -- give chunk an explicit name to avoid using source as name source = load(source, "name1") -- dump without debug information source = string.dump(source, true) - -- each "X=X+1" generates 4 opcodes with 4 bytes each - assert(#source > N * 4 * 4) + -- each "X=X+1" generates 4 opcodes with 4 bytes each, plus the string + assert(#source > N * 4 * 4 + N) collectgarbage(); collectgarbage() local m1 = collectgarbage"count" * 1024 -- load dump using fixed buffer @@ -544,9 +546,11 @@ do ]], source) collectgarbage() local m2 = collectgarbage"count" * 1024 - -- load used fewer than 300 bytes - assert(m2 > m1 and m2 - m1 < 300) - X = 0; code(); assert(X == N); X = nil + -- load used fewer than 350 bytes. Code alone has more than 3*N bytes, + -- and string literal has N bytes. Both were not loaded. + assert(m2 > m1 and m2 - m1 < 350) + X = 0; code(); assert(X == N and Y == string.rep("a", N)) + X = nil; Y = nil end