* pack.c (pack_pack): use union instead of bare variable to ease

optimizations and avoid assigning x87 floating point number.
  [ruby-core:74496] [Bug #12209]

* pack.c (pack_unpack): ditto.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55573 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
naruse 2016-07-05 02:08:55 +00:00
parent c73eb62b3f
commit e90e916b44
2 changed files with 62 additions and 149 deletions

View File

@ -1,3 +1,11 @@
Tue Jul 5 11:07:14 2016 NARUSE, Yui <naruse@ruby-lang.org>
* pack.c (pack_pack): use union instead of bare variable to ease
optimizations and avoid assigning x87 floating point number.
[ruby-core:74496] [Bug #12209]
* pack.c (pack_unpack): ditto.
Mon Jul 4 13:56:34 2016 NARUSE, Yui <naruse@ruby-lang.org> Mon Jul 4 13:56:34 2016 NARUSE, Yui <naruse@ruby-lang.org>
* process.c: define sig_t if not exist. * process.c: define sig_t if not exist.

203
pack.c
View File

@ -68,59 +68,18 @@ static const char endstr[] = "sSiIlLqQjJ";
# define NATINT_LEN(type,len) ((int)sizeof(type)) # define NATINT_LEN(type,len) ((int)sizeof(type))
#endif #endif
#define define_swapx(x, xtype) \ typedef union {
static xtype \ float f;
TOKEN_PASTE(swap,x)(xtype z) \ uint32_t u;
{ \ char buf[4];
xtype r; \ } FLOAT_SWAPPER;
xtype *zp; \ typedef union {
unsigned char *s, *t; \ double d;
int i; \ uint64_t u;
\ char buf[8];
zp = xmalloc(sizeof(xtype)); \ } DOUBLE_SWAPPER;
*zp = z; \ #define swapf(x) swap32(x)
s = (unsigned char*)zp; \ #define swapd(x) swap64(x)
t = xmalloc(sizeof(xtype)); \
for (i=0; i<sizeof(xtype); i++) { \
t[sizeof(xtype)-i-1] = s[i]; \
} \
r = *(xtype *)t; \
xfree(t); \
xfree(zp); \
return r; \
}
#if SIZEOF_FLOAT == 4 && defined(HAVE_INT32_T)
# define swapf(x) swap32(x)
# define FLOAT_SWAPPER uint32_t
#else
define_swapx(f,float)
#endif
#if SIZEOF_DOUBLE == 8 && defined(HAVE_INT64_T)
# define swapd(x) swap64(x)
# define DOUBLE_SWAPPER uint64_t
#elif SIZEOF_DOUBLE == 8 && defined(HAVE_INT32_T)
static double
swapd(const double d)
{
double dtmp = d;
uint32_t utmp[2];
uint32_t utmp0;
utmp[0] = 0; utmp[1] = 0;
memcpy(utmp,&dtmp,sizeof(double));
utmp0 = utmp[0];
utmp[0] = swap32(utmp[1]);
utmp[1] = swap32(utmp0);
memcpy(&dtmp,utmp,sizeof(double));
return dtmp;
}
#else
define_swapx(d, double)
#endif
#undef define_swapx
#define rb_ntohf(x) (BIGENDIAN_P()?(x):swapf(x)) #define rb_ntohf(x) (BIGENDIAN_P()?(x):swapf(x))
#define rb_ntohd(x) (BIGENDIAN_P()?(x):swapd(x)) #define rb_ntohd(x) (BIGENDIAN_P()?(x):swapd(x))
@ -131,57 +90,17 @@ TOKEN_PASTE(swap,x)(xtype z) \
#define rb_vtohf(x) (BIGENDIAN_P()?swapf(x):(x)) #define rb_vtohf(x) (BIGENDIAN_P()?swapf(x):(x))
#define rb_vtohd(x) (BIGENDIAN_P()?swapd(x):(x)) #define rb_vtohd(x) (BIGENDIAN_P()?swapd(x):(x))
#ifdef FLOAT_SWAPPER #define FLOAT_CONVWITH(x) FLOAT_SWAPPER x;
# define FLOAT_CONVWITH(y) FLOAT_SWAPPER y; #define HTONF(x) ((x).u = rb_htonf((x).u))
# define HTONF(x,y) (memcpy(&(y),&(x),sizeof(float)), \ #define HTOVF(x) ((x).u = rb_htovf((x).u))
(y) = rb_htonf((FLOAT_SWAPPER)(y)), \ #define NTOHF(x) ((x).u = rb_ntohf((x).u))
memcpy(&(x),&(y),sizeof(float)), \ #define VTOHF(x) ((x).u = rb_vtohf((x).u))
(x))
# define HTOVF(x,y) (memcpy(&(y),&(x),sizeof(float)), \
(y) = rb_htovf((FLOAT_SWAPPER)(y)), \
memcpy(&(x),&(y),sizeof(float)), \
(x))
# define NTOHF(x,y) (memcpy(&(y),&(x),sizeof(float)), \
(y) = rb_ntohf((FLOAT_SWAPPER)(y)), \
memcpy(&(x),&(y),sizeof(float)), \
(x))
# define VTOHF(x,y) (memcpy(&(y),&(x),sizeof(float)), \
(y) = rb_vtohf((FLOAT_SWAPPER)(y)), \
memcpy(&(x),&(y),sizeof(float)), \
(x))
#else
# define FLOAT_CONVWITH(y)
# define HTONF(x,y) rb_htonf(x)
# define HTOVF(x,y) rb_htovf(x)
# define NTOHF(x,y) rb_ntohf(x)
# define VTOHF(x,y) rb_vtohf(x)
#endif
#ifdef DOUBLE_SWAPPER #define DOUBLE_CONVWITH(x) DOUBLE_SWAPPER x;
# define DOUBLE_CONVWITH(y) DOUBLE_SWAPPER y; #define HTOND(x) ((x).u = rb_htond((x).u))
# define HTOND(x,y) (memcpy(&(y),&(x),sizeof(double)), \ #define HTOVD(x) ((x).u = rb_htovd((x).u))
(y) = rb_htond((DOUBLE_SWAPPER)(y)), \ #define NTOHD(x) ((x).u = rb_ntohd((x).u))
memcpy(&(x),&(y),sizeof(double)), \ #define VTOHD(x) ((x).u = rb_vtohd((x).u))
(x))
# define HTOVD(x,y) (memcpy(&(y),&(x),sizeof(double)), \
(y) = rb_htovd((DOUBLE_SWAPPER)(y)), \
memcpy(&(x),&(y),sizeof(double)), \
(x))
# define NTOHD(x,y) (memcpy(&(y),&(x),sizeof(double)), \
(y) = rb_ntohd((DOUBLE_SWAPPER)(y)), \
memcpy(&(x),&(y),sizeof(double)), \
(x))
# define VTOHD(x,y) (memcpy(&(y),&(x),sizeof(double)), \
(y) = rb_vtohd((DOUBLE_SWAPPER)(y)), \
memcpy(&(x),&(y),sizeof(double)), \
(x))
#else
# define DOUBLE_CONVWITH(y)
# define HTOND(x,y) rb_htond(x)
# define HTOVD(x,y) rb_htovd(x)
# define NTOHD(x,y) rb_ntohd(x)
# define VTOHD(x,y) rb_vtohd(x)
#endif
#define MAX_INTEGER_PACK_SIZE 8 #define MAX_INTEGER_PACK_SIZE 8
@ -728,25 +647,22 @@ pack_pack(VALUE ary, VALUE fmt)
case 'e': /* single precision float in VAX byte-order */ case 'e': /* single precision float in VAX byte-order */
while (len-- > 0) { while (len-- > 0) {
float f; FLOAT_CONVWITH(tmp);
FLOAT_CONVWITH(ftmp);
from = NEXTFROM; from = NEXTFROM;
f = (float)RFLOAT_VALUE(rb_to_float(from)); tmp.f = (float)RFLOAT_VALUE(rb_to_float(from));
f = HTOVF(f,ftmp); HTOVF(tmp);
rb_str_buf_cat(res, (char*)&f, sizeof(float)); rb_str_buf_cat(res, tmp.buf, sizeof(float));
} }
break; break;
case 'E': /* double precision float in VAX byte-order */ case 'E': /* double precision float in VAX byte-order */
while (len-- > 0) { while (len-- > 0) {
double d; DOUBLE_CONVWITH(tmp);
DOUBLE_CONVWITH(dtmp);
from = NEXTFROM; from = NEXTFROM;
d = RFLOAT_VALUE(rb_to_float(from)); tmp.d = RFLOAT_VALUE(rb_to_float(from));
d = HTOVD(d,dtmp); HTOVD(tmp);
rb_str_buf_cat(res, (char*)&d, sizeof(double)); rb_str_buf_cat(res, tmp.buf, sizeof(double));
} }
break; break;
@ -763,25 +679,22 @@ pack_pack(VALUE ary, VALUE fmt)
case 'g': /* single precision float in network byte-order */ case 'g': /* single precision float in network byte-order */
while (len-- > 0) { while (len-- > 0) {
float f; FLOAT_CONVWITH(tmp);
FLOAT_CONVWITH(ftmp);
from = NEXTFROM; from = NEXTFROM;
f = (float)RFLOAT_VALUE(rb_to_float(from)); tmp.f = (float)RFLOAT_VALUE(rb_to_float(from));
f = HTONF(f,ftmp); HTONF(tmp);
rb_str_buf_cat(res, (char*)&f, sizeof(float)); rb_str_buf_cat(res, tmp.buf, sizeof(float));
} }
break; break;
case 'G': /* double precision float in network byte-order */ case 'G': /* double precision float in network byte-order */
while (len-- > 0) { while (len-- > 0) {
double d; DOUBLE_CONVWITH(tmp);
DOUBLE_CONVWITH(dtmp);
from = NEXTFROM; from = NEXTFROM;
d = RFLOAT_VALUE(rb_to_float(from)); tmp.d = RFLOAT_VALUE(rb_to_float(from));
d = HTOND(d,dtmp); HTOND(tmp);
rb_str_buf_cat(res, (char*)&d, sizeof(double)); rb_str_buf_cat(res, tmp.buf, sizeof(double));
} }
break; break;
@ -1578,13 +1491,11 @@ pack_unpack(VALUE str, VALUE fmt)
case 'e': case 'e':
PACK_LENGTH_ADJUST_SIZE(sizeof(float)); PACK_LENGTH_ADJUST_SIZE(sizeof(float));
while (len-- > 0) { while (len-- > 0) {
float tmp; FLOAT_CONVWITH(tmp);
FLOAT_CONVWITH(ftmp); memcpy(tmp.buf, s, sizeof(float));
memcpy(&tmp, s, sizeof(float));
s += sizeof(float); s += sizeof(float);
tmp = VTOHF(tmp,ftmp); VTOHF(tmp);
UNPACK_PUSH(DBL2NUM((double)tmp)); UNPACK_PUSH(DBL2NUM(tmp.f));
} }
PACK_ITEM_ADJUST(); PACK_ITEM_ADJUST();
break; break;
@ -1592,13 +1503,11 @@ pack_unpack(VALUE str, VALUE fmt)
case 'E': case 'E':
PACK_LENGTH_ADJUST_SIZE(sizeof(double)); PACK_LENGTH_ADJUST_SIZE(sizeof(double));
while (len-- > 0) { while (len-- > 0) {
double tmp; DOUBLE_CONVWITH(tmp);
DOUBLE_CONVWITH(dtmp); memcpy(tmp.buf, s, sizeof(double));
memcpy(&tmp, s, sizeof(double));
s += sizeof(double); s += sizeof(double);
tmp = VTOHD(tmp,dtmp); VTOHD(tmp);
UNPACK_PUSH(DBL2NUM(tmp)); UNPACK_PUSH(DBL2NUM(tmp.d));
} }
PACK_ITEM_ADJUST(); PACK_ITEM_ADJUST();
break; break;
@ -1618,13 +1527,11 @@ pack_unpack(VALUE str, VALUE fmt)
case 'g': case 'g':
PACK_LENGTH_ADJUST_SIZE(sizeof(float)); PACK_LENGTH_ADJUST_SIZE(sizeof(float));
while (len-- > 0) { while (len-- > 0) {
float tmp; FLOAT_CONVWITH(tmp);
FLOAT_CONVWITH(ftmp); memcpy(tmp.buf, s, sizeof(float));
memcpy(&tmp, s, sizeof(float));
s += sizeof(float); s += sizeof(float);
tmp = NTOHF(tmp,ftmp); NTOHF(tmp);
UNPACK_PUSH(DBL2NUM((double)tmp)); UNPACK_PUSH(DBL2NUM(tmp.f));
} }
PACK_ITEM_ADJUST(); PACK_ITEM_ADJUST();
break; break;
@ -1632,13 +1539,11 @@ pack_unpack(VALUE str, VALUE fmt)
case 'G': case 'G':
PACK_LENGTH_ADJUST_SIZE(sizeof(double)); PACK_LENGTH_ADJUST_SIZE(sizeof(double));
while (len-- > 0) { while (len-- > 0) {
double tmp; DOUBLE_CONVWITH(tmp);
DOUBLE_CONVWITH(dtmp); memcpy(tmp.buf, s, sizeof(double));
memcpy(&tmp, s, sizeof(double));
s += sizeof(double); s += sizeof(double);
tmp = NTOHD(tmp,dtmp); NTOHD(tmp);
UNPACK_PUSH(DBL2NUM(tmp)); UNPACK_PUSH(DBL2NUM(tmp.d));
} }
PACK_ITEM_ADJUST(); PACK_ITEM_ADJUST();
break; break;