[前][次][番号順一覧][スレッド一覧]

ruby-changes:33076

From: normal <ko1@a...>
Date: Mon, 24 Feb 2014 12:38:27 +0900 (JST)
Subject: [ruby-changes:33076] normal:r45155 (trunk): time: rearrange+pack vtm and time_object structs

normal	2014-02-24 12:38:14 +0900 (Mon, 24 Feb 2014)

  New Revision: 45155

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=45155

  Log:
    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]

  Modified files:
    trunk/ChangeLog
    trunk/configure.in
    trunk/time.c
    trunk/timev.h
Index: time.c
===================================================================
--- time.c	(revision 45154)
+++ time.c	(revision 45155)
@@ -40,6 +40,9 @@ static ID id_eq, id_ne, id_quo, id_div, https://github.com/ruby/ruby/blob/trunk/time.c#L40
 #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; https://github.com/ruby/ruby/blob/trunk/time.c#L760
 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 * https://github.com/ruby/ruby/blob/trunk/time.c#L1743
 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) https://github.com/ruby/ruby/blob/trunk/time.c#L1815
     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 https://github.com/ruby/ruby/blob/trunk/time.c#L2118
     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 https://github.com/ruby/ruby/blob/trunk/time.c#L2129
 
     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) https://github.com/ruby/ruby/blob/trunk/time.c#L2524
     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) https://github.com/ruby/ruby/blob/trunk/time.c#L2553
     return obj;
 }
 
-static int
+static uint32_t
 obj2subsecx(VALUE obj, VALUE *subsecx)
 {
     VALUE subsec;
@@ -2541,12 +2561,11 @@ obj2subsecx(VALUE obj, VALUE *subsecx) https://github.com/ruby/ruby/blob/trunk/time.c#L2561
     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) https://github.com/ruby/ruby/blob/trunk/time.c#L2578
     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) https://github.com/ruby/ruby/blob/trunk/time.c#L2597
             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 v https://github.com/ruby/ruby/blob/trunk/time.c#L2668
 	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 v https://github.com/ruby/ruby/blob/trunk/time.c#L2685
 	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) https://github.com/ruby/ruby/blob/trunk/time.c#L4018
 
     GetTimeval(time, tobj);
     MAKE_TM(time, tobj);
-    return INT2FIX(tobj->vtm.wday);
+    return INT2FIX((int)tobj->vtm.wday);
 }
 
 #define wday_p(n) {\
Index: configure.in
===================================================================
--- configure.in	(revision 45154)
+++ configure.in	(revision 45155)
@@ -746,6 +746,7 @@ if test "$GCC:${warnflags+set}:no" = yes https://github.com/ruby/ruby/blob/trunk/configure.in#L746
 		 -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) https://github.com/ruby/ruby/blob/trunk/configure.in#L1272
 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]
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 45154)
+++ ChangeLog	(revision 45155)
@@ -1,3 +1,11 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Mon Feb 24 12:37:51 2014  Eric Wong  <e@8...>
+
+	* 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@c...>
 
 	* lib/rexml/xmltokens.rb: Add missing non ASCII valid characters
Index: timev.h
===================================================================
--- timev.h	(revision 45154)
+++ timev.h	(revision 45155)
@@ -3,18 +3,18 @@ https://github.com/ruby/ruby/blob/trunk/timev.h#L3
 
 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
 

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]