Fixed buffers save long strings as external.

This commit is contained in:
Roberto Ierusalimschy
2023-11-10 12:35:48 -03:00
parent 024f9064f1
commit 3b57e37e48
4 changed files with 29 additions and 16 deletions

View File

@@ -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 */

View File

@@ -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 */

View File

@@ -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.)

View File

@@ -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