Skip to content

Commit

Permalink
Merge branch 'sverker/full_INTEGER_EXT/OTP-8540' into dev
Browse files Browse the repository at this point in the history
* sverker/full_INTEGER_EXT/OTP-8540:
  term_to_binary use all 32 bits of INTEGER_EXT
  • Loading branch information
sverker committed Jul 8, 2010
2 parents d2f1c68 + e5d4187 commit c4b4eda
Show file tree
Hide file tree
Showing 6 changed files with 216 additions and 124 deletions.
53 changes: 35 additions & 18 deletions erts/emulator/beam/external.c
Expand Up @@ -65,11 +65,9 @@
# endif # endif
#endif #endif


/* /* Does Sint fit in Sint32?
* For backward compatibility reasons, only encode integers that
* fit in 28 bits (signed) using INTEGER_EXT.
*/ */
#define IS_SSMALL28(x) (((Uint) (((x) >> (28-1)) + 1)) < 2) #define IS_SSMALL32(x) (((Uint) (((x) >> (32-1)) + 1)) < 2)


/* /*
* Valid creations for nodes are 1, 2, or 3. 0 can also be sent * Valid creations for nodes are 1, 2, or 3. 0 can also be sent
Expand Down Expand Up @@ -1571,13 +1569,15 @@ enc_term(ErtsAtomCacheMap *acmp, Eterm obj, byte* ep, Uint32 dflags)


case SMALL_DEF: case SMALL_DEF:
{ {
/* From R14B we no longer restrict INTEGER_EXT to 28 bits,
* as done earlier for backward compatibility reasons. */
Sint val = signed_val(obj); Sint val = signed_val(obj);


if ((Uint)val < 256) { if ((Uint)val < 256) {
*ep++ = SMALL_INTEGER_EXT; *ep++ = SMALL_INTEGER_EXT;
put_int8(val, ep); put_int8(val, ep);
ep++; ep++;
} else if (sizeof(Sint) == 4 || IS_SSMALL28(val)) { } else if (sizeof(Sint) == 4 || IS_SSMALL32(val)) {
*ep++ = INTEGER_EXT; *ep++ = INTEGER_EXT;
put_int32(val, ep); put_int32(val, ep);
ep += 4; ep += 4;
Expand All @@ -1599,18 +1599,32 @@ enc_term(ErtsAtomCacheMap *acmp, Eterm obj, byte* ep, Uint32 dflags)
break; break;


case BIG_DEF: case BIG_DEF:
if ((n = big_bytes(obj)) < 256) { {
*ep++ = SMALL_BIG_EXT; int sign = big_sign(obj);
put_int8(n, ep); n = big_bytes(obj);
ep += 1; if (sizeof(Sint)==4 && n<=4) {
} Uint dig = big_digit(obj,0);
else { Sint val = sign ? -dig : dig;
*ep++ = LARGE_BIG_EXT; if ((val<0) == sign) {
put_int32(n, ep); *ep++ = INTEGER_EXT;
ep += 4; put_int32(val, ep);
ep += 4;
break;
}
}
if (n < 256) {
*ep++ = SMALL_BIG_EXT;
put_int8(n, ep);
ep += 1;
}
else {
*ep++ = LARGE_BIG_EXT;
put_int32(n, ep);
ep += 4;
}
*ep++ = sign;
ep = big_to_bytes(obj, ep);
} }
*ep++ = big_sign(obj);
ep = big_to_bytes(obj, ep);
break; break;


case PID_DEF: case PID_DEF:
Expand Down Expand Up @@ -2687,7 +2701,7 @@ encode_size_struct2(ErtsAtomCacheMap *acmp, Eterm obj, unsigned dflags)


if ((Uint)val < 256) if ((Uint)val < 256)
result += 1 + 1; /* SMALL_INTEGER_EXT */ result += 1 + 1; /* SMALL_INTEGER_EXT */
else if (sizeof(Sint) == 4 || IS_SSMALL28(val)) else if (sizeof(Sint) == 4 || IS_SSMALL32(val))
result += 1 + 4; /* INTEGER_EXT */ result += 1 + 4; /* INTEGER_EXT */
else { else {
DeclareTmpHeapNoproc(tmp_big,2); DeclareTmpHeapNoproc(tmp_big,2);
Expand All @@ -2699,7 +2713,10 @@ encode_size_struct2(ErtsAtomCacheMap *acmp, Eterm obj, unsigned dflags)
} }
break; break;
case BIG_DEF: case BIG_DEF:
if ((i = big_bytes(obj)) < 256) i = big_bytes(obj);
if (sizeof(Sint)==4 && i <= 4 && (big_digit(obj,0)-big_sign(obj)) < (1<<31))
result += 1 + 4; /* INTEGER_EXT */
else if (i < 256)
result += 1 + 1 + 1 + i; /* tag,size,sign,digits */ result += 1 + 1 + 1 + i; /* tag,size,sign,digits */
else else
result += 1 + 4 + 1 + i; /* tag,size,sign,digits */ result += 1 + 4 + 1 + i; /* tag,size,sign,digits */
Expand Down
8 changes: 4 additions & 4 deletions erts/emulator/test/hash_SUITE.erl
Expand Up @@ -480,14 +480,14 @@ otp_5292_test() ->
S2 = md5([md5(hash_int(S, E, PH)) || {Start, N, Sz} <- d(), S2 = md5([md5(hash_int(S, E, PH)) || {Start, N, Sz} <- d(),
{S, E} <- int(Start, N, Sz)]), {S, E} <- int(Start, N, Sz)]),
?line Comment = case S1 of ?line Comment = case S1 of
<<43,186,76,102,87,4,110,245,203,177,206,6,130,69,43,99>> -> <<4,248,208,156,200,131,7,1,173,13,239,173,112,81,16,174>> ->
?line big = erlang:system_info(endian), ?line big = erlang:system_info(endian),
"Big endian machine"; "Big endian machine";
<<21,206,139,15,149,28,167,81,98,225,132,254,49,125,174,195>> -> <<180,28,33,231,239,184,71,125,76,47,227,241,78,184,176,233>> ->
?line little = erlang:system_info(endian), ?line little = erlang:system_info(endian),
"Little endian machine" "Little endian machine"
end, end,
?line <<140,37,79,80,26,242,130,22,20,229,123,240,223,244,43,99>> = S2, ?line <<124,81,198,121,174,233,19,137,10,83,33,80,226,111,238,99>> = S2,
?line 2 = erlang:hash(1, (1 bsl 27) -1), ?line 2 = erlang:hash(1, (1 bsl 27) -1),
?line {'EXIT', _} = (catch erlang:hash(1, (1 bsl 27))), ?line {'EXIT', _} = (catch erlang:hash(1, (1 bsl 27))),
{comment, Comment}. {comment, Comment}.
Expand All @@ -507,7 +507,7 @@ hash_int(Start, End, F) ->
{Start, End, md5(HL)}. {Start, End, md5(HL)}.


md5(T) -> md5(T) ->
erlang:md5(term_to_binary(T)). erlang:md5(term_to_binary(T)).


bit_level_binaries() -> bit_level_binaries() ->
?line [3511317,7022633,14044578,28087749,56173436,112344123,90467083|_] = ?line [3511317,7022633,14044578,28087749,56173436,112344123,90467083|_] =
Expand Down
93 changes: 37 additions & 56 deletions lib/erl_interface/src/legacy/erl_marshal.c
Expand Up @@ -26,6 +26,7 @@
#include <ctype.h> #include <ctype.h>
#include <sys/types.h> #include <sys/types.h>
#include <string.h> #include <string.h>
#include <limits.h>


#include "erl_interface.h" #include "erl_interface.h"
#include "erl_marshal.h" #include "erl_marshal.h"
Expand Down Expand Up @@ -178,26 +179,14 @@ int erl_encode_it(ETERM *ep, unsigned char **ext, int dist)
return 0; return 0;


case ERL_INTEGER: case ERL_INTEGER:
i = ep->uval.ival.i; i = ep->uval.ival.i;
/* ERL_SMALL_BIG */
if ((i > ERL_MAX) || (i < ERL_MIN)) {
*(*ext)++ = ERL_SMALL_BIG_EXT;
*(*ext)++ = 4; /* four bytes */
if ((*(*ext)++ = ((i>>31) & 0x01))) /* sign byte */
i = -i;
*(*ext)++ = i & 0xff; /* LSB first */
*(*ext)++ = (i >> 8) & 0xff;
*(*ext)++ = (i >> 16) & 0xff;
*(*ext)++ = (i >> 24) & 0x7f; /* Don't include the sign bit */
return 0;
}
/* SMALL_INTEGER */ /* SMALL_INTEGER */
if ((i < 256) && (i >= 0)) { if ((i < 256) && (i >= 0)) {
*(*ext)++ = ERL_SMALL_INTEGER_EXT; *(*ext)++ = ERL_SMALL_INTEGER_EXT;
*(*ext)++ = i & 0xff; *(*ext)++ = i & 0xff;
return 0; return 0;
} }
/* INTEGER */ /* R14B: Use all 32 bits of INTEGER_EXT */
*(*ext)++ = ERL_INTEGER_EXT; *(*ext)++ = ERL_INTEGER_EXT;
*(*ext)++ = (i >> 24) & 0xff; *(*ext)++ = (i >> 24) & 0xff;
*(*ext)++ = (i >> 16) & 0xff; *(*ext)++ = (i >> 16) & 0xff;
Expand All @@ -208,23 +197,23 @@ int erl_encode_it(ETERM *ep, unsigned char **ext, int dist)
case ERL_U_INTEGER: case ERL_U_INTEGER:
u = ep->uval.uival.u; u = ep->uval.uival.u;
/* ERL_U_SMALL_BIG */ /* ERL_U_SMALL_BIG */
if (u > ERL_MAX) { if ((int)u < 0) {
*(*ext)++ = ERL_SMALL_BIG_EXT; *(*ext)++ = ERL_SMALL_BIG_EXT;
*(*ext)++ = 4; /* four bytes */ *(*ext)++ = 4; /* four bytes */
*(*ext)++ = 0; /* sign byte */ *(*ext)++ = 0; /* sign byte */
*(*ext)++ = u & 0xff; /* LSB first */ *(*ext)++ = u & 0xff; /* LSB first */
*(*ext)++ = (u >> 8) & 0xff; *(*ext)++ = (u >> 8) & 0xff;
*(*ext)++ = (u >> 16) & 0xff; *(*ext)++ = (u >> 16) & 0xff;
*(*ext)++ = (u >> 24) & 0xff; *(*ext)++ = (u >> 24) & 0xff;
return 0; return 0;
} }
/* SMALL_INTEGER */ /* SMALL_INTEGER */
if ((u < 256) && (u >= 0)) { if (u < 256) {
*(*ext)++ = ERL_SMALL_INTEGER_EXT; *(*ext)++ = ERL_SMALL_INTEGER_EXT;
*(*ext)++ = u & 0xff; *(*ext)++ = u & 0xff;
return 0; return 0;
} }
/* INTEGER */ /* R14B: Use all 32 bits of INTEGER_EXT */
*(*ext)++ = ERL_INTEGER_EXT; *(*ext)++ = ERL_INTEGER_EXT;
*(*ext)++ = (u >> 24) & 0xff; *(*ext)++ = (u >> 24) & 0xff;
*(*ext)++ = (u >> 16) & 0xff; *(*ext)++ = (u >> 16) & 0xff;
Expand All @@ -234,29 +223,28 @@ int erl_encode_it(ETERM *ep, unsigned char **ext, int dist)
case ERL_LONGLONG: case ERL_LONGLONG:
l = ep->uval.llval.i; l = ep->uval.llval.i;
/* ERL_SMALL_BIG */ /* ERL_SMALL_BIG */
if ((l > ((long long) ERL_MAX)) || if (l > ((long long) INT_MAX) || l < ((long long) INT_MIN)) {
(l < ((long long) ERL_MIN))) { *(*ext)++ = ERL_SMALL_BIG_EXT;
*(*ext)++ = ERL_SMALL_BIG_EXT; *(*ext)++ = 8;
*(*ext)++ = 8; /* eight bytes */ if ((*(*ext)++ = (l<0))) /* sign byte */
if ((*(*ext)++ = ((l>>63) & 0x01))) /* sign byte */
l = -l; l = -l;
*(*ext)++ = l & 0xff; /* LSB first */ *(*ext)++ = l & 0xff; /* LSB first */
*(*ext)++ = (l >> 8) & 0xff; *(*ext)++ = (l >> 8) & 0xff;
*(*ext)++ = (l >> 16) & 0xff; *(*ext)++ = (l >> 16) & 0xff;
*(*ext)++ = (l >> 24) & 0xff; *(*ext)++ = (l >> 24) & 0xff;
*(*ext)++ = (l >> 32) & 0xff; *(*ext)++ = (l >> 32) & 0xff;
*(*ext)++ = (l >> 40) & 0xff; *(*ext)++ = (l >> 40) & 0xff;
*(*ext)++ = (l >> 48) & 0xff; *(*ext)++ = (l >> 48) & 0xff;
*(*ext)++ = (l >> 56) & 0x7f; /* Don't include the sign bit */ *(*ext)++ = (l >> 56) & 0xff;
return 0; return 0;
} }
/* SMALL_INTEGER */ /* SMALL_INTEGER */
if ((l < 256) && (l >= 0)) { if ((l < 256) && (l >= 0)) {
*(*ext)++ = ERL_SMALL_INTEGER_EXT; *(*ext)++ = ERL_SMALL_INTEGER_EXT;
*(*ext)++ = l & 0xff; *(*ext)++ = l & 0xff;
return 0; return 0;
} }
/* INTEGER */ /* R14B: Use all 32 bits of INTEGER_EXT */
*(*ext)++ = ERL_INTEGER_EXT; *(*ext)++ = ERL_INTEGER_EXT;
*(*ext)++ = (l >> 24) & 0xff; *(*ext)++ = (l >> 24) & 0xff;
*(*ext)++ = (l >> 16) & 0xff; *(*ext)++ = (l >> 16) & 0xff;
Expand All @@ -267,7 +255,7 @@ int erl_encode_it(ETERM *ep, unsigned char **ext, int dist)
case ERL_U_LONGLONG: case ERL_U_LONGLONG:
ul = ep->uval.ullval.u; ul = ep->uval.ullval.u;
/* ERL_U_SMALL_BIG */ /* ERL_U_SMALL_BIG */
if (ul > ((unsigned long long) ERL_MAX)) { if (ul > ((unsigned long long) INT_MAX)) {
*(*ext)++ = ERL_SMALL_BIG_EXT; *(*ext)++ = ERL_SMALL_BIG_EXT;
*(*ext)++ = 8; /* eight bytes */ *(*ext)++ = 8; /* eight bytes */
*(*ext)++ = 0; /* sign byte */ *(*ext)++ = 0; /* sign byte */
Expand All @@ -287,7 +275,7 @@ int erl_encode_it(ETERM *ep, unsigned char **ext, int dist)
*(*ext)++ = ul & 0xff; *(*ext)++ = ul & 0xff;
return 0; return 0;
} }
/* INTEGER */ /* R14B: Use all 32 bits of INTEGER_EXT */
*(*ext)++ = ERL_INTEGER_EXT; *(*ext)++ = ERL_INTEGER_EXT;
*(*ext)++ = (ul >> 24) & 0xff; *(*ext)++ = (ul >> 24) & 0xff;
*(*ext)++ = (ul >> 16) & 0xff; *(*ext)++ = (ul >> 16) & 0xff;
Expand Down Expand Up @@ -732,11 +720,6 @@ static ETERM *erl_decode_it(unsigned char **ext)
if (arity > 8) if (arity > 8)
goto big_truncate; goto big_truncate;


if (arity == 8 && ((*ext)[7] & 0x80) && sign) {
/* MSB already occupied ! */
goto big_truncate;
}

if (arity == 4 && ((*ext)[3] & 0x80) && !sign) { if (arity == 4 && ((*ext)[3] & 0x80) && !sign) {
/* It will fit into an unsigned int !! */ /* It will fit into an unsigned int !! */
u = (((*ext)[3] << 24)|((*ext)[2])<< 16|((*ext)[1]) << 8 |(**ext)); u = (((*ext)[3] << 24)|((*ext)[2])<< 16|((*ext)[1]) << 8 |(**ext));
Expand All @@ -747,14 +730,10 @@ static ETERM *erl_decode_it(unsigned char **ext)
return ep; return ep;
} else if (arity == 4 && !((*ext)[3] & 0x80)) { } else if (arity == 4 && !((*ext)[3] & 0x80)) {
/* It will fit into an int !! /* It will fit into an int !!
* Note: It comes in "one's-complement notation"
*/ */
if (sign) i = (int) (((*ext)[3] << 24) | ((*ext)[2])<< 16 |
i = (int) (~(((*ext)[3] << 24) | ((*ext)[2])<< 16 | ((*ext)[1]) << 8 | (**ext));
((*ext)[1]) << 8 | (**ext)) | (unsigned int) sign); if (sign) i = -i;
else
i = (int) (((*ext)[3] << 24) | ((*ext)[2])<< 16 |
((*ext)[1]) << 8 | (**ext));
ERL_TYPE(ep) = ERL_INTEGER; ERL_TYPE(ep) = ERL_INTEGER;
ep->uval.ival.i = i; ep->uval.ival.i = i;
*ext += arity; *ext += arity;
Expand All @@ -780,8 +759,10 @@ static ETERM *erl_decode_it(unsigned char **ext)
for(x = 0 ; x < arity ; x++) { for(x = 0 ; x < arity ; x++) {
l |= ((long long)(*ext)[x]) << ((long long)(8*x)); l |= ((long long)(*ext)[x]) << ((long long)(8*x));
} }

if (sign) {
if (sign) l = (long long) (~l | (unsigned long long) sign); l = -l;
if (l > 0) goto big_truncate;
}


ERL_TYPE(ep) = ERL_LONGLONG; ERL_TYPE(ep) = ERL_LONGLONG;
ep->uval.llval.i = l; ep->uval.llval.i = l;
Expand Down
34 changes: 19 additions & 15 deletions lib/erl_interface/test/ei_decode_SUITE.erl
Expand Up @@ -222,14 +222,16 @@ send_integers(P) ->
?line send_term_as_binary(P,256), % INTEGER_EXT smallest pos (*) ?line send_term_as_binary(P,256), % INTEGER_EXT smallest pos (*)
?line send_term_as_binary(P,-1), % INTEGER_EXT largest neg ?line send_term_as_binary(P,-1), % INTEGER_EXT largest neg


?line send_term_as_binary(P, 16#07ffffff), % INTEGER_EXT largest (28 bits) ?line send_term_as_binary(P, 16#07ffffff), % INTEGER_EXT old largest (28 bits)
?line send_term_as_binary(P,-16#08000000), % INTEGER_EXT smallest ?line send_term_as_binary(P,-16#08000000), % INTEGER_EXT old smallest
?line send_term_as_binary(P, 16#08000000), % SMALL_BIG_EXT smallest pos(*) ?line send_term_as_binary(P, 16#08000000), % SMALL_BIG_EXT old smallest pos(*)
?line send_term_as_binary(P,-16#08000001), % SMALL_BIG_EXT largest neg (*) ?line send_term_as_binary(P,-16#08000001), % SMALL_BIG_EXT old largest neg (*)


?line send_term_as_binary(P, 16#7fffffff), % SMALL_BIG_EXT largest i32 ?line send_term_as_binary(P, 16#7fffffff), % INTEGER_EXT new largest (32 bits)
?line send_term_as_binary(P,-16#80000000), % SMALL_BIG_EXT smallest i32 ?line send_term_as_binary(P,-16#80000000), % INTEGER_EXT new smallest (32 bis)

?line send_term_as_binary(P, 16#80000000), % SMALL_BIG_EXT new smallest pos(*)
?line send_term_as_binary(P,-16#80000001), % SMALL_BIG_EXT new largest neg (*)

case erlang:system_info(wordsize) of case erlang:system_info(wordsize) of
4 -> 4 ->
?line send_term_as_binary(P, 16#80000000),% SMALL_BIG_EXT u32 ?line send_term_as_binary(P, 16#80000000),% SMALL_BIG_EXT u32
Expand Down Expand Up @@ -266,15 +268,17 @@ send_integers2(P) ->
?line send_term_as_binary(P,255), % SMALL_INTEGER_EXT largest ?line send_term_as_binary(P,255), % SMALL_INTEGER_EXT largest
?line send_term_as_binary(P,256), % INTEGER_EXT smallest pos (*) ?line send_term_as_binary(P,256), % INTEGER_EXT smallest pos (*)
?line send_term_as_binary(P,-1), % INTEGER_EXT largest neg ?line send_term_as_binary(P,-1), % INTEGER_EXT largest neg

?line send_term_as_binary(P, 16#07ffffff), % INTEGER_EXT old largest (28 bits)
?line send_term_as_binary(P,-16#08000000), % INTEGER_EXT old smallest
?line send_term_as_binary(P, 16#08000000), % SMALL_BIG_EXT old smallest pos(*)
?line send_term_as_binary(P,-16#08000001), % SMALL_BIG_EXT old largest neg (*)


?line send_term_as_binary(P, 16#07ffffff), % INTEGER_EXT largest (28 bits) ?line send_term_as_binary(P, 16#7fffffff), % INTEGER_EXT new largest (32 bits)
?line send_term_as_binary(P,-16#08000000), % INTEGER_EXT smallest ?line send_term_as_binary(P,-16#80000000), % INTEGER_EXT new smallest
?line send_term_as_binary(P, 16#08000000), % SMALL_BIG_EXT smallest pos(*) ?line send_term_as_binary(P, 16#80000000), % SMALL_BIG_EXT new smallest pos(*)
?line send_term_as_binary(P,-16#08000001), % SMALL_BIG_EXT largest neg (*) ?line send_term_as_binary(P,-16#80000001), % SMALL_BIG_EXT new largest neg (*)


?line send_term_as_binary(P, 16#7fffffff), % SMALL_BIG_EXT largest i32
?line send_term_as_binary(P,-16#80000000), % SMALL_BIG_EXT smallest i32
?line send_term_as_binary(P, 16#80000000),% SMALL_BIG_EXT u32
?line send_term_as_binary(P, 16#ffffffff),% SMALL_BIG_EXT largest u32 ?line send_term_as_binary(P, 16#ffffffff),% SMALL_BIG_EXT largest u32


?line send_term_as_binary(P, 16#7fffffffffff), % largest i48 ?line send_term_as_binary(P, 16#7fffffffffff), % largest i48
Expand Down

0 comments on commit c4b4eda

Please sign in to comment.