aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornormal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2014-02-24 03:38:14 +0000
committernormal <normal@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2014-02-24 03:38:14 +0000
commitb2f3063cae5cd5997a89717d91fdec06c5041620 (patch)
tree659206e5c7382f73ca808444e4c5d03ef11f6b43
parentba5ed845b30c81fbf92c052b83f54198cd272bbd (diff)
downloadruby-b2f3063cae5cd5997a89717d91fdec06c5041620.tar.gz
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
-rw-r--r--ChangeLog8
-rw-r--r--configure.in10
-rw-r--r--time.c75
-rw-r--r--timev.h18
4 files changed, 74 insertions, 37 deletions
diff --git a/ChangeLog b/ChangeLog
index 21ea9e510b..04b6994aef 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
diff --git a/configure.in b/configure.in
index ae93ea9642..8d7bfba55e 100644
--- a/configure.in
+++ b/configure.in
@@ -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]
diff --git a/time.c b/time.c
index c01ca743d5..208d5c067b 100644
--- a/time.c
+++ b/time.c
@@ -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) {\
diff --git a/timev.h b/timev.h
index 983ef66b80..eda7023eb3 100644
--- a/timev.h
+++ b/timev.h
@@ -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