aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ldump.c2
-rw-r--r--lundump.c23
-rw-r--r--manual/manual.of6
-rw-r--r--testes/api.lua14
4 files changed, 29 insertions, 16 deletions
diff --git a/ldump.c b/ldump.c
index c6f2c4e1..090d6aab 100644
--- a/ldump.c
+++ b/ldump.c
@@ -126,7 +126,7 @@ static void dumpString (DumpState *D, TString *ts) {
126 size_t size; 126 size_t size;
127 const char *s = getlstr(ts, size); 127 const char *s = getlstr(ts, size);
128 dumpSize(D, size + 2); 128 dumpSize(D, size + 2);
129 dumpVector(D, s, size); 129 dumpVector(D, s, size + 1); /* include ending '\0' */
130 D->nstr++; /* one more saved string */ 130 D->nstr++; /* one more saved string */
131 setsvalue(D->L, &key, ts); /* the string is the key */ 131 setsvalue(D->L, &key, ts); /* the string is the key */
132 setivalue(&value, D->nstr); /* its index is the value */ 132 setivalue(&value, D->nstr); /* its index is the value */
diff --git a/lundump.c b/lundump.c
index 5b4cd2ea..09752d99 100644
--- a/lundump.c
+++ b/lundump.c
@@ -147,17 +147,24 @@ static TString *loadStringN (LoadState *S, Proto *p) {
147 luaH_getint(S->h, idx, &stv); 147 luaH_getint(S->h, idx, &stv);
148 return tsvalue(&stv); 148 return tsvalue(&stv);
149 } 149 }
150 else if (size -= 2, size <= LUAI_MAXSHORTLEN) { /* short string? */ 150 else if ((size -= 2) <= LUAI_MAXSHORTLEN) { /* short string? */
151 char buff[LUAI_MAXSHORTLEN]; 151 char buff[LUAI_MAXSHORTLEN + 1]; /* extra space for '\0' */
152 loadVector(S, buff, size); /* load string into buffer */ 152 loadVector(S, buff, size + 1); /* load string into buffer */
153 ts = luaS_newlstr(L, buff, size); /* create string */ 153 ts = luaS_newlstr(L, buff, size); /* create string */
154 } 154 }
155 else { /* long string */ 155 else { /* long string */
156 ts = luaS_createlngstrobj(L, size); /* create string */ 156 if (S->fixed) { /* for a fixed buffer, use a fixed string */
157 setsvalue2s(L, L->top.p, ts); /* anchor it ('loadVector' can GC) */ 157 const char *s = getaddr(S, size + 1, char); /* get content address */
158 luaD_inctop(L); 158 ts = luaS_newextlstr(L, s, size, NULL, NULL);
159 loadVector(S, getlngstr(ts), size); /* load directly in final place */ 159 }
160 L->top.p--; /* pop string */ 160 else { /* create internal copy */
161 ts = luaS_createlngstrobj(L, size); /* create string */
162 setsvalue2s(L, L->top.p, ts); /* anchor it ('loadVector' can GC) */
163 luaD_inctop(L);
164 loadVector(S, getlngstr(ts), size); /* load directly in final place */
165 loadByte(S); /* skip ending '\0' */
166 L->top.p--; /* pop string */
167 }
161 } 168 }
162 luaC_objbarrier(L, p, ts); 169 luaC_objbarrier(L, p, ts);
163 S->nstr++; /* add string to list of saved strings */ 170 S->nstr++; /* add string to list of saved strings */
diff --git a/manual/manual.of b/manual/manual.of
index 9d6a7fd9..9ca28aee 100644
--- a/manual/manual.of
+++ b/manual/manual.of
@@ -3651,8 +3651,10 @@ Moreover, it may have a @Char{B} instead of a @Char{b},
3651meaning a @emphx{fixed buffer} with the binary dump. 3651meaning a @emphx{fixed buffer} with the binary dump.
3652 3652
3653A fixed buffer means that the address returned by the reader function 3653A fixed buffer means that the address returned by the reader function
3654should contain the chunk until everything created by the chunk has 3654will contain the chunk until everything created by the chunk has
3655been collected. 3655been collected;
3656therefore, Lua can avoid copying to internal structures
3657some parts of the chunk.
3656(In general, a fixed buffer would keep the chunk 3658(In general, a fixed buffer would keep the chunk
3657as its contents until the end of the program, 3659as its contents until the end of the program,
3658for instance with the chunk in ROM.) 3660for instance with the chunk in ROM.)
diff --git a/testes/api.lua b/testes/api.lua
index 181c1d53..7d64cb22 100644
--- a/testes/api.lua
+++ b/testes/api.lua
@@ -528,13 +528,15 @@ do
528 local N = 1000 528 local N = 1000
529 -- create a somewhat "large" source 529 -- create a somewhat "large" source
530 for i = 1, N do source[i] = "X = X + 1; " end 530 for i = 1, N do source[i] = "X = X + 1; " end
531 -- add a long string to the source
532 source[#source + 1] = string.format("Y = '%s'", string.rep("a", N));
531 source = table.concat(source) 533 source = table.concat(source)
532 -- give chunk an explicit name to avoid using source as name 534 -- give chunk an explicit name to avoid using source as name
533 source = load(source, "name1") 535 source = load(source, "name1")
534 -- dump without debug information 536 -- dump without debug information
535 source = string.dump(source, true) 537 source = string.dump(source, true)
536 -- each "X=X+1" generates 4 opcodes with 4 bytes each 538 -- each "X=X+1" generates 4 opcodes with 4 bytes each, plus the string
537 assert(#source > N * 4 * 4) 539 assert(#source > N * 4 * 4 + N)
538 collectgarbage(); collectgarbage() 540 collectgarbage(); collectgarbage()
539 local m1 = collectgarbage"count" * 1024 541 local m1 = collectgarbage"count" * 1024
540 -- load dump using fixed buffer 542 -- load dump using fixed buffer
@@ -544,9 +546,11 @@ do
544 ]], source) 546 ]], source)
545 collectgarbage() 547 collectgarbage()
546 local m2 = collectgarbage"count" * 1024 548 local m2 = collectgarbage"count" * 1024
547 -- load used fewer than 300 bytes 549 -- load used fewer than 350 bytes. Code alone has more than 3*N bytes,
548 assert(m2 > m1 and m2 - m1 < 300) 550 -- and string literal has N bytes. Both were not loaded.
549 X = 0; code(); assert(X == N); X = nil 551 assert(m2 > m1 and m2 - m1 < 350)
552 X = 0; code(); assert(X == N and Y == string.rep("a", N))
553 X = nil; Y = nil
550end 554end
551 555
552 556