diff options
| -rw-r--r-- | ldump.c | 27 | ||||
| -rw-r--r-- | lundump.c | 21 | ||||
| -rw-r--r-- | testes/code.lua | 18 |
3 files changed, 48 insertions, 18 deletions
| @@ -31,7 +31,7 @@ typedef struct { | |||
| 31 | int strip; | 31 | int strip; |
| 32 | int status; | 32 | int status; |
| 33 | Table *h; /* table to track saved strings */ | 33 | Table *h; /* table to track saved strings */ |
| 34 | lua_Integer nstr; /* counter for counting saved strings */ | 34 | lua_Unsigned nstr; /* counter for counting saved strings */ |
| 35 | } DumpState; | 35 | } DumpState; |
| 36 | 36 | ||
| 37 | 37 | ||
| @@ -87,12 +87,12 @@ static void dumpByte (DumpState *D, int y) { | |||
| 87 | ** size for 'dumpVarint' buffer: each byte can store up to 7 bits. | 87 | ** size for 'dumpVarint' buffer: each byte can store up to 7 bits. |
| 88 | ** (The "+6" rounds up the division.) | 88 | ** (The "+6" rounds up the division.) |
| 89 | */ | 89 | */ |
| 90 | #define DIBS ((l_numbits(size_t) + 6) / 7) | 90 | #define DIBS ((l_numbits(lua_Unsigned) + 6) / 7) |
| 91 | 91 | ||
| 92 | /* | 92 | /* |
| 93 | ** Dumps an unsigned integer using the MSB Varint encoding | 93 | ** Dumps an unsigned integer using the MSB Varint encoding |
| 94 | */ | 94 | */ |
| 95 | static void dumpVarint (DumpState *D, size_t x) { | 95 | static void dumpVarint (DumpState *D, lua_Unsigned x) { |
| 96 | lu_byte buff[DIBS]; | 96 | lu_byte buff[DIBS]; |
| 97 | unsigned n = 1; | 97 | unsigned n = 1; |
| 98 | buff[DIBS - 1] = x & 0x7f; /* fill least-significant byte */ | 98 | buff[DIBS - 1] = x & 0x7f; /* fill least-significant byte */ |
| @@ -103,12 +103,13 @@ static void dumpVarint (DumpState *D, size_t x) { | |||
| 103 | 103 | ||
| 104 | 104 | ||
| 105 | static void dumpSize (DumpState *D, size_t sz) { | 105 | static void dumpSize (DumpState *D, size_t sz) { |
| 106 | dumpVarint(D, sz); | 106 | dumpVarint(D, cast(lua_Unsigned, sz)); |
| 107 | } | 107 | } |
| 108 | 108 | ||
| 109 | |||
| 109 | static void dumpInt (DumpState *D, int x) { | 110 | static void dumpInt (DumpState *D, int x) { |
| 110 | lua_assert(x >= 0); | 111 | lua_assert(x >= 0); |
| 111 | dumpVarint(D, cast_sizet(x)); | 112 | dumpVarint(D, cast_uint(x)); |
| 112 | } | 113 | } |
| 113 | 114 | ||
| 114 | 115 | ||
| @@ -117,8 +118,16 @@ static void dumpNumber (DumpState *D, lua_Number x) { | |||
| 117 | } | 118 | } |
| 118 | 119 | ||
| 119 | 120 | ||
| 121 | /* | ||
| 122 | ** Signed integers are coded to keep small values small. (Coding -1 as | ||
| 123 | ** 0xfff...fff would use too many bytes to save a quite common value.) | ||
| 124 | ** A non-negative x is coded as 2x; a negative x is coded as -2x - 1. | ||
| 125 | ** (0 => 0; -1 => 1; 1 => 2; -2 => 3; 2 => 4; ...) | ||
| 126 | */ | ||
| 120 | static void dumpInteger (DumpState *D, lua_Integer x) { | 127 | static void dumpInteger (DumpState *D, lua_Integer x) { |
| 121 | dumpVar(D, x); | 128 | lua_Unsigned cx = (x >= 0) ? 2u * l_castS2U(x) |
| 129 | : (2u * ~l_castS2U(x)) + 1; | ||
| 130 | dumpVarint(D, cx); | ||
| 122 | } | 131 | } |
| 123 | 132 | ||
| 124 | 133 | ||
| @@ -136,8 +145,8 @@ static void dumpString (DumpState *D, TString *ts) { | |||
| 136 | TValue idx; | 145 | TValue idx; |
| 137 | int tag = luaH_getstr(D->h, ts, &idx); | 146 | int tag = luaH_getstr(D->h, ts, &idx); |
| 138 | if (!tagisempty(tag)) { /* string already saved? */ | 147 | if (!tagisempty(tag)) { /* string already saved? */ |
| 139 | dumpSize(D, 1); /* reuse a saved string */ | 148 | dumpVarint(D, 1); /* reuse a saved string */ |
| 140 | dumpSize(D, cast_sizet(ivalue(&idx))); /* index of saved string */ | 149 | dumpVarint(D, l_castS2U(ivalue(&idx))); /* index of saved string */ |
| 141 | } | 150 | } |
| 142 | else { /* must write and save the string */ | 151 | else { /* must write and save the string */ |
| 143 | TValue key, value; /* to save the string in the hash */ | 152 | TValue key, value; /* to save the string in the hash */ |
| @@ -147,7 +156,7 @@ static void dumpString (DumpState *D, TString *ts) { | |||
| 147 | dumpVector(D, s, size + 1); /* include ending '\0' */ | 156 | dumpVector(D, s, size + 1); /* include ending '\0' */ |
| 148 | D->nstr++; /* one more saved string */ | 157 | D->nstr++; /* one more saved string */ |
| 149 | setsvalue(D->L, &key, ts); /* the string is the key */ | 158 | setsvalue(D->L, &key, ts); /* the string is the key */ |
| 150 | setivalue(&value, D->nstr); /* its index is the value */ | 159 | setivalue(&value, l_castU2S(D->nstr)); /* its index is the value */ |
| 151 | luaH_set(D->L, D->h, &key, &value); /* h[ts] = nstr */ | 160 | luaH_set(D->L, D->h, &key, &value); /* h[ts] = nstr */ |
| 152 | /* integer value does not need barrier */ | 161 | /* integer value does not need barrier */ |
| 153 | } | 162 | } |
| @@ -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 | ||
| @@ -94,8 +94,8 @@ static lu_byte loadByte (LoadState *S) { | |||
| 94 | } | 94 | } |
| 95 | 95 | ||
| 96 | 96 | ||
| 97 | static size_t loadVarint (LoadState *S, size_t limit) { | 97 | static lua_Unsigned loadVarint (LoadState *S, lua_Unsigned limit) { |
| 98 | size_t x = 0; | 98 | lua_Unsigned x = 0; |
| 99 | int b; | 99 | int b; |
| 100 | limit >>= 7; | 100 | limit >>= 7; |
| 101 | do { | 101 | do { |
| @@ -127,9 +127,12 @@ static lua_Number loadNumber (LoadState *S) { | |||
| 127 | 127 | ||
| 128 | 128 | ||
| 129 | static lua_Integer loadInteger (LoadState *S) { | 129 | static lua_Integer loadInteger (LoadState *S) { |
| 130 | lua_Integer x; | 130 | lua_Unsigned cx = loadVarint(S, LUA_MAXUNSIGNED); |
| 131 | loadVar(S, x); | 131 | /* decode unsigned to signed */ |
| 132 | return x; | 132 | if ((cx & 1) != 0) |
| 133 | return l_castU2S(~(cx >> 1)); | ||
| 134 | else | ||
| 135 | return l_castU2S(cx >> 1); | ||
| 133 | } | 136 | } |
| 134 | 137 | ||
| 135 | 138 | ||
| @@ -149,9 +152,9 @@ static void loadString (LoadState *S, Proto *p, TString **sl) { | |||
| 149 | return; | 152 | return; |
| 150 | } | 153 | } |
| 151 | else if (size == 1) { /* previously saved string? */ | 154 | else if (size == 1) { /* previously saved string? */ |
| 152 | lua_Integer idx = cast_st2S(loadSize(S)); /* get its index */ | 155 | lua_Unsigned idx = loadVarint(S, LUA_MAXUNSIGNED); /* get its index */ |
| 153 | TValue stv; | 156 | TValue stv; |
| 154 | luaH_getint(S->h, idx, &stv); /* get its value */ | 157 | luaH_getint(S->h, l_castU2S(idx), &stv); /* get its value */ |
| 155 | *sl = ts = tsvalue(&stv); | 158 | *sl = ts = tsvalue(&stv); |
| 156 | luaC_objbarrier(L, p, ts); | 159 | luaC_objbarrier(L, p, ts); |
| 157 | return; /* do not save it again */ | 160 | return; /* do not save it again */ |
| @@ -175,7 +178,7 @@ static void loadString (LoadState *S, Proto *p, TString **sl) { | |||
| 175 | /* add string to list of saved strings */ | 178 | /* add string to list of saved strings */ |
| 176 | S->nstr++; | 179 | S->nstr++; |
| 177 | setsvalue(L, &sv, ts); | 180 | setsvalue(L, &sv, ts); |
| 178 | luaH_setint(L, S->h, S->nstr, &sv); | 181 | luaH_setint(L, S->h, l_castU2S(S->nstr), &sv); |
| 179 | luaC_objbarrierback(L, obj2gco(S->h), ts); | 182 | luaC_objbarrierback(L, obj2gco(S->h), ts); |
| 180 | } | 183 | } |
| 181 | 184 | ||
diff --git a/testes/code.lua b/testes/code.lua index 633f4896..380ff70c 100644 --- a/testes/code.lua +++ b/testes/code.lua | |||
| @@ -482,5 +482,23 @@ do -- basic check for SETLIST | |||
| 482 | assert(count == 1) | 482 | assert(count == 1) |
| 483 | end | 483 | end |
| 484 | 484 | ||
| 485 | |||
| 486 | do print("testing code for integer limits") | ||
| 487 | local function checkints (n) | ||
| 488 | local source = string.format( | ||
| 489 | "local a = {[true] = 0X%x}; return a[true]", n) | ||
| 490 | local f = assert(load(source)) | ||
| 491 | checkKlist(f, {n}) | ||
| 492 | assert(f() == n) | ||
| 493 | f = load(string.dump(f)) | ||
| 494 | assert(f() == n) | ||
| 495 | end | ||
| 496 | |||
| 497 | checkints(math.maxinteger) | ||
| 498 | checkints(math.mininteger) | ||
| 499 | checkints(-1) | ||
| 500 | |||
| 501 | end | ||
| 502 | |||
| 485 | print 'OK' | 503 | print 'OK' |
| 486 | 504 | ||
