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

ruby-changes:13462

From: matz <ko1@a...>
Date: Mon, 5 Oct 2009 23:37:43 +0900 (JST)
Subject: [ruby-changes:13462] Ruby:r25237 (trunk): * array.c (rb_ary_{times, shuffle_bang, sample}): reducing macro

matz	2009-10-05 23:35:39 +0900 (Mon, 05 Oct 2009)

  New Revision: 25237

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

  Log:
    * array.c (rb_ary_{times, shuffle_bang, sample}): reducing macro
      calls inside of the loop by keeping pointers in local
      variables. a patch from Masahiro Kanai (CanI) in [ruby-dev:39406].
      It was found and fixed at Security and Programming camp 2009.
    
    * string.c (rb_str_{times, split_m}): ditto.
    
    * struct.c (rb_struct_{getmember, set, aref_id, aset_id}, {make,
      inspect}_struct, recursive_{equal, hash, eql}): ditto.

  Modified files:
    trunk/ChangeLog
    trunk/array.c
    trunk/string.c
    trunk/struct.c

Index: array.c
===================================================================
--- array.c	(revision 25236)
+++ array.c	(revision 25237)
@@ -2708,8 +2708,8 @@
 static VALUE
 rb_ary_times(VALUE ary, VALUE times)
 {
-    VALUE ary2, tmp;
-    long i, len;
+    VALUE ary2, tmp, *ptr, *ptr2;
+    long i, t, len;
 
     tmp = rb_check_string_type(times);
     if (!NIL_P(tmp)) {
@@ -2732,8 +2732,11 @@
     ary2 = ary_new(rb_obj_class(ary), len);
     ARY_SET_LEN(ary2, len);
 
-    for (i=0; i<len; i+=RARRAY_LEN(ary)) {
-	MEMCPY(RARRAY_PTR(ary2)+i, RARRAY_PTR(ary), VALUE, RARRAY_LEN(ary));
+    ptr = RARRAY_PTR(ary);
+    ptr2 = RARRAY_PTR(ary2);
+    t = RARRAY_LEN(ary);
+    for (i=0; i<len; i+=t) {
+	MEMCPY(ptr2+i, ptr, VALUE, t);
     }
   out:
     OBJ_INFECT(ary2, ary);
@@ -3491,14 +3494,16 @@
 static VALUE
 rb_ary_shuffle_bang(VALUE ary)
 {
+    VALUE *ptr;
     long i = RARRAY_LEN(ary);
 
     rb_ary_modify(ary);
+    ptr = RARRAY_PTR(ary);
     while (i) {
 	long j = (long)(rb_genrand_real()*i);
-	VALUE tmp = RARRAY_PTR(ary)[--i];
-	RARRAY_PTR(ary)[i] = RARRAY_PTR(ary)[j];
-	RARRAY_PTR(ary)[j] = tmp;
+	VALUE tmp = ptr[--i];
+	ptr[i] = ptr[j];
+	ptr[j] = tmp;
     }
     return ary;
 }
@@ -3576,6 +3581,7 @@
 	return rb_ary_new3(3, ptr[i], ptr[j], ptr[k]);
     }
     if ((size_t)n < sizeof(idx)/sizeof(idx[0])) {
+	VALUE *ptr_result;
 	long sorted[sizeof(idx)/sizeof(idx[0])];
 	sorted[0] = idx[0] = (long)(rb_genrand_real()*len);
 	for (i=1; i<n; i++) {
@@ -3588,18 +3594,21 @@
 	    sorted[j] = idx[i] = k;
 	}
 	result = rb_ary_new2(n);
+	ptr_result = RARRAY_PTR(result);
 	for (i=0; i<n; i++) {
-	    RARRAY_PTR(result)[i] = RARRAY_PTR(ary)[idx[i]];
+	    ptr_result[i] = ptr[idx[i]];
 	}
     }
     else {
+	VALUE *ptr_result;
 	result = rb_ary_new4(len, ptr);
+	ptr_result = RARRAY_PTR(result);
 	RB_GC_GUARD(ary);
 	for (i=0; i<n; i++) {
 	    j = (long)(rb_genrand_real()*(len-i)) + i;
-	    nv = RARRAY_PTR(result)[j];
-	    RARRAY_PTR(result)[j] = RARRAY_PTR(result)[i];
-	    RARRAY_PTR(result)[i] = nv;
+	    nv = ptr_result[j];
+	    ptr_result[j] = ptr_result[i];
+	    ptr_result[i] = nv;
 	}
     }
     ARY_SET_LEN(result, n);
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 25236)
+++ ChangeLog	(revision 25237)
@@ -1,3 +1,15 @@
+Mon Oct  5 12:22:12 2009  Yukihiro Matsumoto  <matz@r...>
+
+	* array.c (rb_ary_{times, shuffle_bang, sample}): reducing macro
+	  calls inside of the loop by keeping pointers in local
+	  variables. a patch from Masahiro Kanai (CanI) in [ruby-dev:39406].
+	  It was found and fixed at Security and Programming camp 2009.
+
+	* string.c (rb_str_{times, split_m}): ditto.
+
+	* struct.c (rb_struct_{getmember, set, aref_id, aset_id}, {make,
+	  inspect}_struct, recursive_{equal, hash, eql}): ditto.
+
 Mon Oct  5 00:09:57 2009  Yukihiro Matsumoto  <matz@r...>
 
 	* vm_method.c (basic_obj_respond_to): should not call
Index: string.c
===================================================================
--- string.c	(revision 25236)
+++ string.c	(revision 25237)
@@ -1173,6 +1173,7 @@
 {
     VALUE str2;
     long n, len;
+    char *ptr2;
 
     len = NUM2LONG(times);
     if (len < 0) {
@@ -1183,16 +1184,17 @@
     }
 
     str2 = rb_str_new5(str, 0, len *= RSTRING_LEN(str));
+    ptr2 = RSTRING_PTR(str2);
     if (len) {
         n = RSTRING_LEN(str);
-        memcpy(RSTRING_PTR(str2), RSTRING_PTR(str), n);
+        memcpy(ptr2, RSTRING_PTR(str), n);
         while (n <= len/2) {
-            memcpy(RSTRING_PTR(str2) + n, RSTRING_PTR(str2), n);
+            memcpy(ptr2 + n, ptr2, n);
             n *= 2;
         }
-        memcpy(RSTRING_PTR(str2) + n, RSTRING_PTR(str2), len-n);
+        memcpy(ptr2 + n, ptr2, len-n);
     }
-    RSTRING_PTR(str2)[RSTRING_LEN(str2)] = '\0';
+    ptr2[RSTRING_LEN(str2)] = '\0';
     OBJ_INFECT(str2, str);
     rb_enc_cr_str_copy_for_substr(str2, str);
 
@@ -5513,6 +5515,7 @@
     }
     else if (split_type == string) {
 	char *ptr = RSTRING_PTR(str);
+	char *temp = ptr;
 	char *eptr = RSTRING_END(str);
 	char *sptr = RSTRING_PTR(spat);
 	long slen = RSTRING_LEN(spat);
@@ -5532,13 +5535,15 @@
 		ptr = t;
 		continue;
 	    }
-	    rb_ary_push(result, rb_str_subseq(str, ptr - RSTRING_PTR(str), end));
+	    rb_ary_push(result, rb_str_subseq(str, ptr - temp, end));
 	    ptr += end + slen;
 	    if (!NIL_P(limit) && lim <= ++i) break;
 	}
-	beg = ptr - RSTRING_PTR(str);
+	beg = ptr - temp;
     }
     else {
+	char *ptr = RSTRING_PTR(str);
+	long len = RSTRING_LEN(str);
 	long start = beg;
 	long idx;
 	int last_null = 0;
@@ -5547,22 +5552,22 @@
 	while ((end = rb_reg_search(spat, str, start, 0)) >= 0) {
 	    regs = RMATCH_REGS(rb_backref_get());
 	    if (start == end && BEG(0) == END(0)) {
-		if (!RSTRING_PTR(str)) {
+		if (!ptr) {
 		    rb_ary_push(result, rb_str_new("", 0));
 		    break;
 		}
 		else if (last_null == 1) {
 		    rb_ary_push(result, rb_str_subseq(str, beg,
-						      rb_enc_fast_mbclen(RSTRING_PTR(str)+beg,
-									 RSTRING_END(str),
+						      rb_enc_fast_mbclen(ptr+beg,
+									 ptr+len,
 									 enc)));
 		    beg = start;
 		}
 		else {
-                    if (RSTRING_PTR(str)+start == RSTRING_END(str))
+                    if (ptr+start == ptr+len)
                         start++;
                     else
-                        start += rb_enc_fast_mbclen(RSTRING_PTR(str)+start,RSTRING_END(str),enc);
+                        start += rb_enc_fast_mbclen(ptr+start,ptr+len,enc);
 		    last_null = 1;
 		    continue;
 		}
Index: struct.c
===================================================================
--- struct.c	(revision 25236)
+++ struct.c	(revision 25237)
@@ -98,14 +98,17 @@
 VALUE
 rb_struct_getmember(VALUE obj, ID id)
 {
-    VALUE members, slot;
-    long i;
+    VALUE members, slot, *ptr, *ptr_members;
+    long i, len;
 
+    ptr = RSTRUCT_PTR(obj);
     members = rb_struct_members(obj);
+    ptr_members = RARRAY_PTR(members);
     slot = ID2SYM(id);
-    for (i=0; i<RARRAY_LEN(members); i++) {
-	if (RARRAY_PTR(members)[i] == slot) {
-	    return RSTRUCT_PTR(obj)[i];
+    len = RARRAY_LEN(members);
+    for (i=0; i<len; i++) {
+	if (ptr_members[i] == slot) {
+	    return ptr[i];
 	}
     }
     rb_name_error(id, "%s is not struct member", rb_id2name(id));
@@ -156,15 +159,18 @@
 static VALUE
 rb_struct_set(VALUE obj, VALUE val)
 {
-    VALUE members, slot;
-    long i;
+    VALUE members, slot, *ptr, *ptr_members;
+    long i, len;
 
     members = rb_struct_members(obj);
+    ptr_members = RARRAY_PTR(members);
+    len = RARRAY_LEN(members);
     rb_struct_modify(obj);
-    for (i=0; i<RARRAY_LEN(members); i++) {
-	slot = RARRAY_PTR(members)[i];
+    ptr = RSTRUCT_PTR(obj);
+    for (i=0; i<len; i++) {
+	slot = ptr_members[i];
 	if (rb_id_attrset(SYM2ID(slot)) == rb_frame_this_func()) {
-	    return RSTRUCT_PTR(obj)[i] = val;
+	    return ptr[i] = val;
 	}
     }
     rb_name_error(rb_frame_this_func(), "`%s' is not a struct member",
@@ -175,9 +181,9 @@
 static VALUE
 make_struct(VALUE name, VALUE members, VALUE klass)
 {
-    VALUE nstr;
+    VALUE nstr, *ptr_members;
     ID id;
-    long i;
+    long i, len;
 
     OBJ_FREEZE(members);
     if (NIL_P(name)) {
@@ -204,8 +210,10 @@
     rb_define_singleton_method(nstr, "new", rb_class_new_instance, -1);
     rb_define_singleton_method(nstr, "[]", rb_class_new_instance, -1);
     rb_define_singleton_method(nstr, "members", rb_struct_s_members_m, 0);
-    for (i=0; i< RARRAY_LEN(members); i++) {
-	ID id = SYM2ID(RARRAY_PTR(members)[i]);
+    ptr_members = RARRAY_PTR(members);
+    len = RARRAY_LEN(members);
+    for (i=0; i< len; i++) {
+	ID id = SYM2ID(ptr_members[i]);
 	if (rb_is_local_id(id) || rb_is_const_id(id)) {
 	    if (i < N_REF_FUNC) {
 		rb_define_method_id(nstr, id, ref_func[i], 0);
@@ -498,7 +506,8 @@
 {
     VALUE cname = rb_class_name(rb_obj_class(s));
     VALUE members, str = rb_str_new2("#<struct ");
-    long i;
+    VALUE *ptr, *ptr_members;
+    long i, len;
     char first = RSTRING_PTR(cname)[0];
 
     if (recur || first != '#') {
@@ -509,7 +518,10 @@
     }
 
     members = rb_struct_members(s);
-    for (i=0; i<RSTRUCT_LEN(s); i++) {
+    ptr_members = RARRAY_PTR(members);
+    ptr = RSTRUCT_PTR(s);
+    len = RSTRUCT_LEN(s);
+    for (i=0; i<len; i++) {
 	VALUE slot;
 	ID id;
 
@@ -519,7 +531,7 @@
 	else if (first != '#') {
 	    rb_str_cat2(str, " ");
 	}
-	slot = RARRAY_PTR(members)[i];
+	slot = ptr_members[i];
 	id = SYM2ID(slot);
 	if (rb_is_local_id(id) || rb_is_const_id(id)) {
 	    rb_str_append(str, rb_id2str(id));
@@ -528,7 +540,7 @@
 	    rb_str_append(str, rb_inspect(slot));
 	}
 	rb_str_cat2(str, "=");
-	rb_str_append(str, rb_inspect(RSTRUCT_PTR(s)[i]));
+	rb_str_append(str, rb_inspect(ptr[i]));
     }
     rb_str_cat2(str, ">");
     OBJ_INFECT(str, s);
@@ -588,14 +600,16 @@
 static VALUE
 rb_struct_aref_id(VALUE s, ID id)
 {
-    VALUE members;
+    VALUE *ptr, members, *ptr_members;
     long i, len;
 
+    ptr = RSTRUCT_PTR(s);
     members = rb_struct_members(s);
+    ptr_members = RARRAY_PTR(members);
     len = RARRAY_LEN(members);
     for (i=0; i<len; i++) {
-	if (SYM2ID(RARRAY_PTR(members)[i]) == id) {
-	    return RSTRUCT_PTR(s)[i];
+	if (SYM2ID(ptr_members[i]) == id) {
+	    return ptr[i];
 	}
     }
     rb_name_error(id, "no member '%s' in struct", rb_id2name(id));
@@ -644,19 +658,21 @@
 static VALUE
 rb_struct_aset_id(VALUE s, ID id, VALUE val)
 {
-    VALUE members;
+    VALUE members, *ptr, *ptr_members;
     long i, len;
 
     members = rb_struct_members(s);
+    len = RARRAY_LEN(members);
     rb_struct_modify(s);
-    len = RARRAY_LEN(members);
-    if (RSTRUCT_LEN(s) != RARRAY_LEN(members)) {
+    if (RSTRUCT_LEN(s) != len) {
 	rb_raise(rb_eTypeError, "struct size differs (%ld required %ld given)",
-		 RARRAY_LEN(members), RSTRUCT_LEN(s));
+		 len, RSTRUCT_LEN(s));
     }
+    ptr = RSTRUCT_PTR(s);
+    ptr_members = RARRAY_PTR(members);
     for (i=0; i<len; i++) {
-	if (SYM2ID(RARRAY_PTR(members)[i]) == id) {
-	    RSTRUCT_PTR(s)[i] = val;
+	if (SYM2ID(ptr_members[i]) == id) {
+	    ptr[i] = val;
 	    return val;
 	}
     }
@@ -771,11 +787,15 @@
 static VALUE
 recursive_equal(VALUE s, VALUE s2, int recur)
 {
-    long i;
+    VALUE *ptr, *ptr2;
+    long i, len;
 
     if (recur) return Qtrue; /* Subtle! */
-    for (i=0; i<RSTRUCT_LEN(s); i++) {
-	if (!rb_equal(RSTRUCT_PTR(s)[i], RSTRUCT_PTR(s2)[i])) return Qfalse;
+    ptr = RSTRUCT_PTR(s);
+    ptr2 = RSTRUCT_PTR(s2);
+    len = RSTRUCT_LEN(s);
+    for (i=0; i<len; i++) {
+	if (!rb_equal(ptr[i], ptr2[i])) return Qfalse;
     }
     return Qtrue;
 }
@@ -813,14 +833,16 @@
 static VALUE
 recursive_hash(VALUE s, VALUE dummy, int recur)
 {
-    long i;
+    long i, len;
     st_index_t h;
-    VALUE n;
+    VALUE n, *ptr;
 
     h = rb_hash_start(rb_hash(rb_obj_class(s)));
     if (!recur) {
-	for (i = 0; i < RSTRUCT_LEN(s); i++) {
-	    n = rb_hash(RSTRUCT_PTR(s)[i]);
+	ptr = RSTRUCT_PTR(s);
+	len = RSTRUCT_LEN(s);
+	for (i = 0; i < len; i++) {
+	    n = rb_hash(ptr[i]);
 	    h = rb_hash_uint(h, NUM2LONG(n));
 	}
     }
@@ -844,11 +866,15 @@
 static VALUE
 recursive_eql(VALUE s, VALUE s2, int recur)
 {
-    long i;
+    VALUE *ptr, *ptr2;
+    long i, len;
 
     if (recur) return Qtrue; /* Subtle! */
-    for (i=0; i<RSTRUCT_LEN(s); i++) {
-	if (!rb_eql(RSTRUCT_PTR(s)[i], RSTRUCT_PTR(s2)[i])) return Qfalse;
+    ptr = RSTRUCT_PTR(s);
+    ptr2 = RSTRUCT_PTR(s2);
+    len = RSTRUCT_LEN(s);
+    for (i=0; i<len; i++) {
+	if (!rb_eql(ptr[i], ptr2[i])) return Qfalse;
     }
     return Qtrue;
 }

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

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