mirror of
https://github.com/lua/lua.git
synced 2025-07-03 14:43:26 +00:00
Dump uses varints also for integer constants
Unlike sizes, these constants can be negative, so it encodes those integers into unsigned integers in a way that keeps small numbers small.
This commit is contained in:
parent
e657a48ea5
commit
0cecf1ab6d
3 changed files with 48 additions and 18 deletions
27
ldump.c
27
ldump.c
|
@ -31,7 +31,7 @@ typedef struct {
|
|||
int strip;
|
||||
int status;
|
||||
Table *h; /* table to track saved strings */
|
||||
lua_Integer nstr; /* counter for counting saved strings */
|
||||
lua_Unsigned nstr; /* counter for counting saved strings */
|
||||
} DumpState;
|
||||
|
||||
|
||||
|
@ -87,12 +87,12 @@ static void dumpByte (DumpState *D, int y) {
|
|||
** size for 'dumpVarint' buffer: each byte can store up to 7 bits.
|
||||
** (The "+6" rounds up the division.)
|
||||
*/
|
||||
#define DIBS ((l_numbits(size_t) + 6) / 7)
|
||||
#define DIBS ((l_numbits(lua_Unsigned) + 6) / 7)
|
||||
|
||||
/*
|
||||
** Dumps an unsigned integer using the MSB Varint encoding
|
||||
*/
|
||||
static void dumpVarint (DumpState *D, size_t x) {
|
||||
static void dumpVarint (DumpState *D, lua_Unsigned x) {
|
||||
lu_byte buff[DIBS];
|
||||
unsigned n = 1;
|
||||
buff[DIBS - 1] = x & 0x7f; /* fill least-significant byte */
|
||||
|
@ -103,12 +103,13 @@ static void dumpVarint (DumpState *D, size_t x) {
|
|||
|
||||
|
||||
static void dumpSize (DumpState *D, size_t sz) {
|
||||
dumpVarint(D, sz);
|
||||
dumpVarint(D, cast(lua_Unsigned, sz));
|
||||
}
|
||||
|
||||
|
||||
static void dumpInt (DumpState *D, int x) {
|
||||
lua_assert(x >= 0);
|
||||
dumpVarint(D, cast_sizet(x));
|
||||
dumpVarint(D, cast_uint(x));
|
||||
}
|
||||
|
||||
|
||||
|
@ -117,8 +118,16 @@ static void dumpNumber (DumpState *D, lua_Number x) {
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
** Signed integers are coded to keep small values small. (Coding -1 as
|
||||
** 0xfff...fff would use too many bytes to save a quite common value.)
|
||||
** A non-negative x is coded as 2x; a negative x is coded as -2x - 1.
|
||||
** (0 => 0; -1 => 1; 1 => 2; -2 => 3; 2 => 4; ...)
|
||||
*/
|
||||
static void dumpInteger (DumpState *D, lua_Integer x) {
|
||||
dumpVar(D, x);
|
||||
lua_Unsigned cx = (x >= 0) ? 2u * l_castS2U(x)
|
||||
: (2u * ~l_castS2U(x)) + 1;
|
||||
dumpVarint(D, cx);
|
||||
}
|
||||
|
||||
|
||||
|
@ -136,8 +145,8 @@ static void dumpString (DumpState *D, TString *ts) {
|
|||
TValue idx;
|
||||
int tag = luaH_getstr(D->h, ts, &idx);
|
||||
if (!tagisempty(tag)) { /* string already saved? */
|
||||
dumpSize(D, 1); /* reuse a saved string */
|
||||
dumpSize(D, cast_sizet(ivalue(&idx))); /* index of saved string */
|
||||
dumpVarint(D, 1); /* reuse a saved string */
|
||||
dumpVarint(D, l_castS2U(ivalue(&idx))); /* index of saved string */
|
||||
}
|
||||
else { /* must write and save the string */
|
||||
TValue key, value; /* to save the string in the hash */
|
||||
|
@ -147,7 +156,7 @@ static void dumpString (DumpState *D, TString *ts) {
|
|||
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 */
|
||||
setivalue(&value, l_castU2S(D->nstr)); /* its index is the value */
|
||||
luaH_set(D->L, D->h, &key, &value); /* h[ts] = nstr */
|
||||
/* integer value does not need barrier */
|
||||
}
|
||||
|
|
21
lundump.c
21
lundump.c
|
@ -37,7 +37,7 @@ typedef struct {
|
|||
const char *name;
|
||||
Table *h; /* list for string reuse */
|
||||
size_t offset; /* current position relative to beginning of dump */
|
||||
lua_Integer nstr; /* number of strings in the list */
|
||||
lua_Unsigned nstr; /* number of strings in the list */
|
||||
lu_byte fixed; /* dump is fixed in memory */
|
||||
} LoadState;
|
||||
|
||||
|
@ -94,8 +94,8 @@ static lu_byte loadByte (LoadState *S) {
|
|||
}
|
||||
|
||||
|
||||
static size_t loadVarint (LoadState *S, size_t limit) {
|
||||
size_t x = 0;
|
||||
static lua_Unsigned loadVarint (LoadState *S, lua_Unsigned limit) {
|
||||
lua_Unsigned x = 0;
|
||||
int b;
|
||||
limit >>= 7;
|
||||
do {
|
||||
|
@ -127,9 +127,12 @@ static lua_Number loadNumber (LoadState *S) {
|
|||
|
||||
|
||||
static lua_Integer loadInteger (LoadState *S) {
|
||||
lua_Integer x;
|
||||
loadVar(S, x);
|
||||
return x;
|
||||
lua_Unsigned cx = loadVarint(S, LUA_MAXUNSIGNED);
|
||||
/* decode unsigned to signed */
|
||||
if ((cx & 1) != 0)
|
||||
return l_castU2S(~(cx >> 1));
|
||||
else
|
||||
return l_castU2S(cx >> 1);
|
||||
}
|
||||
|
||||
|
||||
|
@ -149,9 +152,9 @@ static void loadString (LoadState *S, Proto *p, TString **sl) {
|
|||
return;
|
||||
}
|
||||
else if (size == 1) { /* previously saved string? */
|
||||
lua_Integer idx = cast_st2S(loadSize(S)); /* get its index */
|
||||
lua_Unsigned idx = loadVarint(S, LUA_MAXUNSIGNED); /* get its index */
|
||||
TValue stv;
|
||||
luaH_getint(S->h, idx, &stv); /* get its value */
|
||||
luaH_getint(S->h, l_castU2S(idx), &stv); /* get its value */
|
||||
*sl = ts = tsvalue(&stv);
|
||||
luaC_objbarrier(L, p, ts);
|
||||
return; /* do not save it again */
|
||||
|
@ -175,7 +178,7 @@ static void loadString (LoadState *S, Proto *p, TString **sl) {
|
|||
/* add string to list of saved strings */
|
||||
S->nstr++;
|
||||
setsvalue(L, &sv, ts);
|
||||
luaH_setint(L, S->h, S->nstr, &sv);
|
||||
luaH_setint(L, S->h, l_castU2S(S->nstr), &sv);
|
||||
luaC_objbarrierback(L, obj2gco(S->h), ts);
|
||||
}
|
||||
|
||||
|
|
|
@ -482,5 +482,23 @@ do -- basic check for SETLIST
|
|||
assert(count == 1)
|
||||
end
|
||||
|
||||
|
||||
do print("testing code for integer limits")
|
||||
local function checkints (n)
|
||||
local source = string.format(
|
||||
"local a = {[true] = 0X%x}; return a[true]", n)
|
||||
local f = assert(load(source))
|
||||
checkKlist(f, {n})
|
||||
assert(f() == n)
|
||||
f = load(string.dump(f))
|
||||
assert(f() == n)
|
||||
end
|
||||
|
||||
checkints(math.maxinteger)
|
||||
checkints(math.mininteger)
|
||||
checkints(-1)
|
||||
|
||||
end
|
||||
|
||||
print 'OK'
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue