diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2024-02-12 15:16:11 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2024-02-12 15:16:11 -0300 |
commit | c8121ce34b39c6fd31899f4da91e26063c8af54f (patch) | |
tree | 5ce96fbe65d5f16f87c816f88bab2df25975ba5d | |
parent | 7360f8d0fd91344deb583ff76b8250a1883dcd4c (diff) | |
download | lua-c8121ce34b39c6fd31899f4da91e26063c8af54f.tar.gz lua-c8121ce34b39c6fd31899f4da91e26063c8af54f.tar.bz2 lua-c8121ce34b39c6fd31899f4da91e26063c8af54f.zip |
Revising code for Varint encoding in dumps
- Usign lua_Unsigned to count strings.
- Varint uses a type large enough both for size_t and lua_Unsigned.
- Most-Significant Bit 0 means last byte, to conform to common usage.
- (unrelated) Change in macro 'getaddr' so that multiplication is
by constants.
Diffstat (limited to '')
-rw-r--r-- | ldump.c | 35 | ||||
-rw-r--r-- | lundump.c | 24 | ||||
-rw-r--r-- | lundump.h | 15 |
3 files changed, 45 insertions, 29 deletions
@@ -30,7 +30,7 @@ typedef struct { | |||
30 | int strip; | 30 | int strip; |
31 | int status; | 31 | int status; |
32 | Table *h; /* table to track saved strings */ | 32 | Table *h; /* table to track saved strings */ |
33 | lua_Integer nstr; /* counter to number saved strings */ | 33 | lua_Unsigned nstr; /* counter to number saved strings */ |
34 | } DumpState; | 34 | } DumpState; |
35 | 35 | ||
36 | 36 | ||
@@ -83,26 +83,27 @@ static void dumpByte (DumpState *D, int y) { | |||
83 | 83 | ||
84 | 84 | ||
85 | /* | 85 | /* |
86 | ** 'dumpSize' buffer size: each byte can store up to 7 bits. (The "+6" | 86 | ** size for 'dumpVarint' buffer: each byte can store up to 7 bits. |
87 | ** rounds up the division.) | 87 | ** (The "+6" rounds up the division.) |
88 | */ | 88 | */ |
89 | #define DIBS ((sizeof(size_t) * CHAR_BIT + 6) / 7) | 89 | #define DIBS ((sizeof(varint_t) * CHAR_BIT + 6) / 7) |
90 | 90 | ||
91 | static void dumpSize (DumpState *D, size_t x) { | 91 | /* |
92 | ** Dumps an unsigned integer using the MSB Varint encoding | ||
93 | */ | ||
94 | static void dumpVarint (DumpState *D, varint_t x) { | ||
92 | lu_byte buff[DIBS]; | 95 | lu_byte buff[DIBS]; |
93 | int n = 0; | 96 | int n = 1; |
94 | do { | 97 | buff[DIBS - 1] = x & 0x7f; /* fill least-significant byte */ |
95 | buff[DIBS - (++n)] = x & 0x7f; /* fill buffer in reverse order */ | 98 | while ((x >>= 7) != 0) /* fill other bytes in reverse order */ |
96 | x >>= 7; | 99 | buff[DIBS - (++n)] = (x & 0x7f) | 0x80; |
97 | } while (x != 0); | ||
98 | buff[DIBS - 1] |= 0x80; /* mark last byte */ | ||
99 | dumpVector(D, buff + DIBS - n, n); | 100 | dumpVector(D, buff + DIBS - n, n); |
100 | } | 101 | } |
101 | 102 | ||
102 | 103 | ||
103 | static void dumpInt (DumpState *D, int x) { | 104 | static void dumpInt (DumpState *D, int x) { |
104 | lua_assert(x >= 0); | 105 | lua_assert(x >= 0); |
105 | dumpSize(D, x); | 106 | dumpVarint(D, x); |
106 | } | 107 | } |
107 | 108 | ||
108 | 109 | ||
@@ -125,22 +126,22 @@ static void dumpInteger (DumpState *D, lua_Integer x) { | |||
125 | */ | 126 | */ |
126 | static void dumpString (DumpState *D, TString *ts) { | 127 | static void dumpString (DumpState *D, TString *ts) { |
127 | if (ts == NULL) | 128 | if (ts == NULL) |
128 | dumpSize(D, 0); | 129 | dumpVarint(D, 0); |
129 | else { | 130 | else { |
130 | TValue idx; | 131 | TValue idx; |
131 | if (luaH_getstr(D->h, ts, &idx) == HOK) { /* string already saved? */ | 132 | if (luaH_getstr(D->h, ts, &idx) == HOK) { /* string already saved? */ |
132 | dumpSize(D, 1); /* reuse a saved string */ | 133 | dumpVarint(D, 1); /* reuse a saved string */ |
133 | dumpInt(D, ivalue(&idx)); /* index of saved string */ | 134 | dumpVarint(D, l_castS2U(ivalue(&idx))); /* index of saved string */ |
134 | } | 135 | } |
135 | else { /* must write and save the string */ | 136 | else { /* must write and save the string */ |
136 | TValue key, value; /* to save the string in the hash */ | 137 | TValue key, value; /* to save the string in the hash */ |
137 | size_t size; | 138 | size_t size; |
138 | const char *s = getlstr(ts, size); | 139 | const char *s = getlstr(ts, size); |
139 | dumpSize(D, size + 2); | 140 | dumpVarint(D, size + 2); |
140 | dumpVector(D, s, size + 1); /* include ending '\0' */ | 141 | dumpVector(D, s, size + 1); /* include ending '\0' */ |
141 | D->nstr++; /* one more saved string */ | 142 | D->nstr++; /* one more saved string */ |
142 | setsvalue(D->L, &key, ts); /* the string is the key */ | 143 | setsvalue(D->L, &key, ts); /* the string is the key */ |
143 | setivalue(&value, D->nstr); /* its index is the value */ | 144 | setivalue(&value, l_castU2S(D->nstr)); /* its index is the value */ |
144 | luaH_set(D->L, D->h, &key, &value); /* h[ts] = nstr */ | 145 | luaH_set(D->L, D->h, &key, &value); /* h[ts] = nstr */ |
145 | /* integer value does not need barrier */ | 146 | /* integer value does not need barrier */ |
146 | } | 147 | } |
@@ -37,7 +37,7 @@ typedef struct { | |||
37 | const char *name; | 37 | const char *name; |
38 | Table *h; /* list for string reuse */ | 38 | Table *h; /* list for string reuse */ |
39 | size_t offset; /* current position relative to beginning of dump */ | 39 | size_t offset; /* current position relative to beginning of dump */ |
40 | lua_Integer nstr; /* number of strings in the list */ | 40 | lua_Unsigned nstr; /* number of strings in the list */ |
41 | lu_byte fixed; /* dump is fixed in memory */ | 41 | lu_byte fixed; /* dump is fixed in memory */ |
42 | } LoadState; | 42 | } LoadState; |
43 | 43 | ||
@@ -71,10 +71,9 @@ static void loadAlign (LoadState *S, int align) { | |||
71 | } | 71 | } |
72 | 72 | ||
73 | 73 | ||
74 | #define getaddr(S,n,t) cast(t *, getaddr_(S,n,sizeof(t))) | 74 | #define getaddr(S,n,t) cast(t *, getaddr_(S,(n) * sizeof(t))) |
75 | 75 | ||
76 | static const void *getaddr_ (LoadState *S, int n, size_t sz) { | 76 | static const void *getaddr_ (LoadState *S, size_t size) { |
77 | size_t size = n * sz; | ||
78 | const void *block = luaZ_getaddr(S->Z, size); | 77 | const void *block = luaZ_getaddr(S->Z, size); |
79 | S->offset += size; | 78 | S->offset += size; |
80 | if (block == NULL) | 79 | if (block == NULL) |
@@ -95,8 +94,8 @@ static lu_byte loadByte (LoadState *S) { | |||
95 | } | 94 | } |
96 | 95 | ||
97 | 96 | ||
98 | static size_t loadUnsigned (LoadState *S, size_t limit) { | 97 | static varint_t loadVarint (LoadState *S, varint_t limit) { |
99 | size_t x = 0; | 98 | varint_t x = 0; |
100 | int b; | 99 | int b; |
101 | limit >>= 7; | 100 | limit >>= 7; |
102 | do { | 101 | do { |
@@ -104,18 +103,18 @@ static size_t loadUnsigned (LoadState *S, size_t limit) { | |||
104 | if (x >= limit) | 103 | if (x >= limit) |
105 | error(S, "integer overflow"); | 104 | error(S, "integer overflow"); |
106 | x = (x << 7) | (b & 0x7f); | 105 | x = (x << 7) | (b & 0x7f); |
107 | } while ((b & 0x80) == 0); | 106 | } while ((b & 0x80) != 0); |
108 | return x; | 107 | return x; |
109 | } | 108 | } |
110 | 109 | ||
111 | 110 | ||
112 | static size_t loadSize (LoadState *S) { | 111 | static size_t loadSize (LoadState *S) { |
113 | return loadUnsigned(S, MAX_SIZET); | 112 | return cast_sizet(loadVarint(S, MAX_SIZET)); |
114 | } | 113 | } |
115 | 114 | ||
116 | 115 | ||
117 | static int loadInt (LoadState *S) { | 116 | static int loadInt (LoadState *S) { |
118 | return cast_int(loadUnsigned(S, INT_MAX)); | 117 | return cast_int(loadVarint(S, INT_MAX)); |
119 | } | 118 | } |
120 | 119 | ||
121 | 120 | ||
@@ -149,9 +148,10 @@ static void loadString (LoadState *S, Proto *p, TString **sl) { | |||
149 | return; | 148 | return; |
150 | } | 149 | } |
151 | else if (size == 1) { /* previously saved string? */ | 150 | else if (size == 1) { /* previously saved string? */ |
152 | int idx = loadInt(S); /* get its index */ | 151 | /* get its index */ |
152 | lua_Unsigned idx = cast(lua_Unsigned, loadVarint(S, LUA_MAXUNSIGNED)); | ||
153 | TValue stv; | 153 | TValue stv; |
154 | luaH_getint(S->h, idx, &stv); | 154 | luaH_getint(S->h, l_castU2S(idx), &stv); /* get its value */ |
155 | *sl = ts = tsvalue(&stv); | 155 | *sl = ts = tsvalue(&stv); |
156 | luaC_objbarrier(L, p, ts); | 156 | luaC_objbarrier(L, p, ts); |
157 | return; /* do not save it again */ | 157 | return; /* do not save it again */ |
@@ -175,7 +175,7 @@ static void loadString (LoadState *S, Proto *p, TString **sl) { | |||
175 | /* add string to list of saved strings */ | 175 | /* add string to list of saved strings */ |
176 | S->nstr++; | 176 | S->nstr++; |
177 | setsvalue(L, &sv, ts); | 177 | setsvalue(L, &sv, ts); |
178 | luaH_setint(L, S->h, S->nstr, &sv); | 178 | luaH_setint(L, S->h, l_castU2S(S->nstr), &sv); |
179 | luaC_objbarrierback(L, obj2gco(S->h), ts); | 179 | luaC_objbarrierback(L, obj2gco(S->h), ts); |
180 | } | 180 | } |
181 | 181 | ||
@@ -7,6 +7,8 @@ | |||
7 | #ifndef lundump_h | 7 | #ifndef lundump_h |
8 | #define lundump_h | 8 | #define lundump_h |
9 | 9 | ||
10 | #include <limits.h> | ||
11 | |||
10 | #include "llimits.h" | 12 | #include "llimits.h" |
11 | #include "lobject.h" | 13 | #include "lobject.h" |
12 | #include "lzio.h" | 14 | #include "lzio.h" |
@@ -25,6 +27,19 @@ | |||
25 | 27 | ||
26 | #define LUAC_FORMAT 0 /* this is the official format */ | 28 | #define LUAC_FORMAT 0 /* this is the official format */ |
27 | 29 | ||
30 | |||
31 | /* | ||
32 | ** Type to handle MSB Varint encoding: Try to get the largest unsigned | ||
33 | ** integer available. (It was enough to be the largest between size_t and | ||
34 | ** lua_Integer, but the C89 preprocessor knows nothing about size_t.) | ||
35 | */ | ||
36 | #if !defined(LUA_USE_C89) && defined(LLONG_MAX) | ||
37 | typedef unsigned long long varint_t; | ||
38 | #else | ||
39 | typedef unsigned long varint_t; | ||
40 | #endif | ||
41 | |||
42 | |||
28 | /* load one chunk; from lundump.c */ | 43 | /* load one chunk; from lundump.c */ |
29 | LUAI_FUNC LClosure* luaU_undump (lua_State* L, ZIO* Z, const char* name, | 44 | LUAI_FUNC LClosure* luaU_undump (lua_State* L, ZIO* Z, const char* name, |
30 | int fixed); | 45 | int fixed); |