1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

time: rearrange+pack vtm and time_object structs

struct time_object shrinks from 88 to 46 bytes on my 64-bit system.

* configure.in: use -Wno-packed-bitfield-compat for GCC 4.4+
  use __attribute__((packed)) if available
* timev.h: shrink and pack struct vtm
* time.c: pack struct time_object and adjust/introduce helpers
  [ruby-core:60794]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@45155 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
normal 2014-02-24 03:38:14 +00:00
parent ba5ed845b3
commit b2f3063cae
4 changed files with 74 additions and 37 deletions

View file

@ -1,3 +1,11 @@
Mon Feb 24 12:37:51 2014 Eric Wong <e@80x24.org>
* configure.in: use -Wno-packed-bitfield-compat for GCC 4.4+
use __attribute__((packed)) if available
* timev.h: shrink and pack struct vtm
* time.c: pack struct time_object and adjust/introduce helpers
[ruby-core:60794]
Sun Feb 23 17:55:50 2014 Kouhei Sutou <kou@cozmixng.org>
* lib/rexml/xmltokens.rb: Add missing non ASCII valid characters

View file

@ -746,6 +746,7 @@ if test "$GCC:${warnflags+set}:no" = yes::no; then
-Werror=implicit-function-declaration \
-Werror=division-by-zero \
-Werror=deprecated-declarations \
-Wno-packed-bitfield-compat \
$extra_warning \
; do
if test "$particular_werror_flags" != yes; then
@ -1271,6 +1272,15 @@ RUBY_CHECK_SIZEOF(double)
RUBY_CHECK_SIZEOF(time_t, [long "long long"], [], [@%:@include <time.h>])
RUBY_CHECK_SIZEOF(clock_t, [], [], [@%:@include <time.h>])
AC_CACHE_CHECK(packed struct attribute, rb_cv_packed_struct,
[AC_TRY_COMPILE([struct { int a; } __attribute__((packed));], [],
[rb_cv_packed_struct=yes], [rb_cv_packed_struct=no])])
if test "$rb_cv_packed_struct" = yes; then
AC_DEFINE_UNQUOTED(PACKED_STRUCT, __attribute__((packed)))
else
AC_DEFINE_UNQUOTED(PACKED_STRUCT,)
fi
AC_DEFUN([RUBY_CHECK_PRINTF_PREFIX], [
AC_CACHE_CHECK([for printf prefix for $1], [rb_cv_pri_prefix_]AS_TR_SH($1),[
[rb_cv_pri_prefix_]AS_TR_SH($1)=[NONE]

75
time.c
View file

@ -40,6 +40,9 @@ static ID id_eq, id_ne, id_quo, id_div, id_cmp, id_lshift;
#define NMOD(x,y) ((y)-(-((x)+1)%(y))-1)
#define DIV(n,d) ((n)<0 ? NDIV((n),(d)) : (n)/(d))
#define MOD(n,d) ((n)<0 ? NMOD((n),(d)) : (n)%(d))
#define VTM_WDAY_INITVAL (7)
#define VTM_ISDST_INITVAL (3)
#define TO_GMT_INITVAL (3)
static int
eq(VALUE x, VALUE y)
@ -757,12 +760,13 @@ VALUE rb_cTime;
static VALUE time_utc_offset _((VALUE));
static int obj2int(VALUE obj);
static uint32_t obj2ubits(VALUE obj, size_t bits);
static VALUE obj2vint(VALUE obj);
static int month_arg(VALUE arg);
static uint32_t month_arg(VALUE arg);
static VALUE validate_utc_offset(VALUE utc_offset);
static VALUE validate_zone_name(VALUE zone_name);
static void validate_vtm(struct vtm *vtm);
static int obj2subsecx(VALUE obj, VALUE *subsecx);
static uint32_t obj2subsecx(VALUE obj, VALUE *subsecx);
static VALUE time_gmtime(VALUE);
static VALUE time_localtime(VALUE);
@ -1739,15 +1743,15 @@ localtimew(wideval_t timew, struct vtm *result)
struct time_object {
wideval_t timew; /* time_t value * TIME_SCALE. possibly Rational. */
struct vtm vtm;
int gmt; /* 0:utc 1:localtime 2:fixoff */
int tm_got;
};
uint8_t gmt:3; /* 0:utc 1:localtime 2:fixoff 3:init */
uint8_t tm_got:1;
} PACKED_STRUCT;
#define GetTimeval(obj, tobj) ((tobj) = get_timeval(obj))
#define GetNewTimeval(obj, tobj) ((tobj) = get_new_timeval(obj))
#define IsTimeval(obj) rb_typeddata_is_kind_of((obj), &time_data_type)
#define TIME_INIT_P(tobj) ((tobj)->gmt != -1)
#define TIME_INIT_P(tobj) ((tobj)->gmt != TO_GMT_INITVAL)
#define TIME_UTC_P(tobj) ((tobj)->gmt == 1)
#define TIME_SET_UTC(tobj) ((tobj)->gmt = 1)
@ -1811,7 +1815,7 @@ time_s_alloc(VALUE klass)
struct time_object *tobj;
obj = TypedData_Make_Struct(klass, struct time_object, &time_data_type, tobj);
tobj->gmt = -1;
tobj->gmt = TO_GMT_INITVAL;
tobj->tm_got=0;
tobj->timew = WINT2FIXWV(0);
@ -2114,7 +2118,7 @@ time_init_1(int argc, VALUE *argv, VALUE time)
VALUE v[7];
struct time_object *tobj;
vtm.wday = -1;
vtm.wday = VTM_WDAY_INITVAL;
vtm.yday = 0;
vtm.zone = "";
@ -2125,16 +2129,16 @@ time_init_1(int argc, VALUE *argv, VALUE time)
vtm.mon = NIL_P(v[1]) ? 1 : month_arg(v[1]);
vtm.mday = NIL_P(v[2]) ? 1 : obj2int(v[2]);
vtm.mday = NIL_P(v[2]) ? 1 : obj2ubits(v[2], 5);
vtm.hour = NIL_P(v[3]) ? 0 : obj2int(v[3]);
vtm.hour = NIL_P(v[3]) ? 0 : obj2ubits(v[3], 5);
vtm.min = NIL_P(v[4]) ? 0 : obj2int(v[4]);
vtm.min = NIL_P(v[4]) ? 0 : obj2ubits(v[4], 6);
vtm.subsecx = INT2FIX(0);
vtm.sec = NIL_P(v[5]) ? 0 : obj2subsecx(v[5], &vtm.subsecx);
vtm.isdst = -1;
vtm.isdst = VTM_ISDST_INITVAL;
vtm.utc_offset = Qnil;
if (!NIL_P(v[6])) {
VALUE arg = v[6];
@ -2520,6 +2524,22 @@ obj2int(VALUE obj)
return NUM2INT(obj);
}
static uint32_t
obj2ubits(VALUE obj, size_t bits)
{
static const uint32_t u32max = (uint32_t)-1;
const uint32_t usable_mask = ~(u32max << bits);
uint32_t rv;
int tmp = obj2int(obj);
if (tmp < 0)
rb_raise(rb_eArgError, "argument out of range");
rv = tmp;
if ((rv & usable_mask) != rv)
rb_raise(rb_eArgError, "argument out of range");
return rv;
}
static VALUE
obj2vint(VALUE obj)
{
@ -2533,7 +2553,7 @@ obj2vint(VALUE obj)
return obj;
}
static int
static uint32_t
obj2subsecx(VALUE obj, VALUE *subsecx)
{
VALUE subsec;
@ -2541,12 +2561,11 @@ obj2subsecx(VALUE obj, VALUE *subsecx)
if (RB_TYPE_P(obj, T_STRING)) {
obj = rb_str_to_inum(obj, 10, FALSE);
*subsecx = INT2FIX(0);
return NUM2INT(obj);
} else {
divmodv(num_exact(obj), INT2FIX(1), &obj, &subsec);
*subsecx = w2v(rb_time_magnify(v2w(subsec)));
}
divmodv(num_exact(obj), INT2FIX(1), &obj, &subsec);
*subsecx = w2v(rb_time_magnify(v2w(subsec)));
return NUM2INT(obj);
return obj2ubits(obj, 6); /* vtm->sec */
}
static long
@ -2559,7 +2578,7 @@ usec2subsecx(VALUE obj)
return mulquo(num_exact(obj), INT2FIX(TIME_SCALE), INT2FIX(1000000));
}
static int
static uint32_t
month_arg(VALUE arg)
{
int i, mon;
@ -2578,12 +2597,12 @@ month_arg(VALUE arg)
char c = RSTRING_PTR(s)[0];
if ('0' <= c && c <= '9') {
mon = obj2int(s);
mon = obj2ubits(s, 4);
}
}
}
else {
mon = obj2int(arg);
mon = obj2ubits(arg, 4);
}
return mon;
}
@ -2649,8 +2668,8 @@ time_arg(int argc, VALUE *argv, struct vtm *vtm)
rb_scan_args(argc, argv, "17", &v[0],&v[1],&v[2],&v[3],&v[4],&v[5],&v[6],&v[7]);
/* v[6] may be usec or zone (parsedate) */
/* v[7] is wday (parsedate; ignored) */
vtm->wday = -1;
vtm->isdst = -1;
vtm->wday = VTM_WDAY_INITVAL;
vtm->isdst = VTM_ISDST_INITVAL;
}
vtm->year = obj2vint(v[0]);
@ -2666,15 +2685,15 @@ time_arg(int argc, VALUE *argv, struct vtm *vtm)
vtm->mday = 1;
}
else {
vtm->mday = obj2int(v[2]);
vtm->mday = obj2ubits(v[2], 5);
}
vtm->hour = NIL_P(v[3])?0:obj2int(v[3]);
vtm->hour = NIL_P(v[3])?0:obj2ubits(v[3], 5);
vtm->min = NIL_P(v[4])?0:obj2int(v[4]);
vtm->min = NIL_P(v[4])?0:obj2ubits(v[4], 6);
if (!NIL_P(v[6]) && argc == 7) {
vtm->sec = NIL_P(v[5])?0:obj2int(v[5]);
vtm->sec = NIL_P(v[5])?0:obj2ubits(v[5],6);
vtm->subsecx = usec2subsecx(v[6]);
}
else {
@ -3999,7 +4018,7 @@ time_wday(VALUE time)
GetTimeval(time, tobj);
MAKE_TM(time, tobj);
return INT2FIX(tobj->vtm.wday);
return INT2FIX((int)tobj->vtm.wday);
}
#define wday_p(n) {\

18
timev.h
View file

@ -3,18 +3,18 @@
struct vtm {
VALUE year; /* 2000 for example. Integer. */
int mon; /* 1..12 */
int mday; /* 1..31 */
int hour; /* 0..23 */
int min; /* 0..59 */
int sec; /* 0..60 */
VALUE subsecx; /* 0 <= subsecx < TIME_SCALE. possibly Rational. */
VALUE utc_offset; /* -3600 as -01:00 for example. possibly Rational. */
int wday; /* 0:Sunday, 1:Monday, ..., 6:Saturday */
int yday; /* 1..366 */
int isdst; /* 0:StandardTime 1:DayLightSavingTime */
const char *zone; /* "JST", "EST", "EDT", etc. */
};
uint16_t yday:9; /* 1..366 */
uint8_t mon:4; /* 1..12 */
uint8_t mday:5; /* 1..31 */
uint8_t hour:5; /* 0..23 */
uint8_t min:6; /* 0..59 */
uint8_t sec:6; /* 0..60 */
uint8_t wday:3; /* 0:Sunday, 1:Monday, ..., 6:Saturday 7:init */
uint8_t isdst:2; /* 0:StandardTime 1:DayLightSavingTime 3:init */
} PACKED_STRUCT;
#define TIME_SCALE 1000000000