* 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.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@25237 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
matz 2009-10-05 14:35:39 +00:00
parent c984f77122
commit 40229f892c
4 changed files with 111 additions and 59 deletions

View File

@ -1,3 +1,15 @@
Mon Oct 5 12:22:12 2009 Yukihiro Matsumoto <matz@ruby-lang.org>
* 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@ruby-lang.org> Mon Oct 5 00:09:57 2009 Yukihiro Matsumoto <matz@ruby-lang.org>
* vm_method.c (basic_obj_respond_to): should not call * vm_method.c (basic_obj_respond_to): should not call

31
array.c
View File

@ -2708,8 +2708,8 @@ rb_ary_concat(VALUE x, VALUE y)
static VALUE static VALUE
rb_ary_times(VALUE ary, VALUE times) rb_ary_times(VALUE ary, VALUE times)
{ {
VALUE ary2, tmp; VALUE ary2, tmp, *ptr, *ptr2;
long i, len; long i, t, len;
tmp = rb_check_string_type(times); tmp = rb_check_string_type(times);
if (!NIL_P(tmp)) { if (!NIL_P(tmp)) {
@ -2732,8 +2732,11 @@ rb_ary_times(VALUE ary, VALUE times)
ary2 = ary_new(rb_obj_class(ary), len); ary2 = ary_new(rb_obj_class(ary), len);
ARY_SET_LEN(ary2, len); ARY_SET_LEN(ary2, len);
for (i=0; i<len; i+=RARRAY_LEN(ary)) { ptr = RARRAY_PTR(ary);
MEMCPY(RARRAY_PTR(ary2)+i, RARRAY_PTR(ary), VALUE, RARRAY_LEN(ary)); ptr2 = RARRAY_PTR(ary2);
t = RARRAY_LEN(ary);
for (i=0; i<len; i+=t) {
MEMCPY(ptr2+i, ptr, VALUE, t);
} }
out: out:
OBJ_INFECT(ary2, ary); OBJ_INFECT(ary2, ary);
@ -3491,14 +3494,16 @@ rb_ary_flatten(int argc, VALUE *argv, VALUE ary)
static VALUE static VALUE
rb_ary_shuffle_bang(VALUE ary) rb_ary_shuffle_bang(VALUE ary)
{ {
VALUE *ptr;
long i = RARRAY_LEN(ary); long i = RARRAY_LEN(ary);
rb_ary_modify(ary); rb_ary_modify(ary);
ptr = RARRAY_PTR(ary);
while (i) { while (i) {
long j = (long)(rb_genrand_real()*i); long j = (long)(rb_genrand_real()*i);
VALUE tmp = RARRAY_PTR(ary)[--i]; VALUE tmp = ptr[--i];
RARRAY_PTR(ary)[i] = RARRAY_PTR(ary)[j]; ptr[i] = ptr[j];
RARRAY_PTR(ary)[j] = tmp; ptr[j] = tmp;
} }
return ary; return ary;
} }
@ -3576,6 +3581,7 @@ rb_ary_sample(int argc, VALUE *argv, VALUE ary)
return rb_ary_new3(3, ptr[i], ptr[j], ptr[k]); return rb_ary_new3(3, ptr[i], ptr[j], ptr[k]);
} }
if ((size_t)n < sizeof(idx)/sizeof(idx[0])) { if ((size_t)n < sizeof(idx)/sizeof(idx[0])) {
VALUE *ptr_result;
long sorted[sizeof(idx)/sizeof(idx[0])]; long sorted[sizeof(idx)/sizeof(idx[0])];
sorted[0] = idx[0] = (long)(rb_genrand_real()*len); sorted[0] = idx[0] = (long)(rb_genrand_real()*len);
for (i=1; i<n; i++) { for (i=1; i<n; i++) {
@ -3588,18 +3594,21 @@ rb_ary_sample(int argc, VALUE *argv, VALUE ary)
sorted[j] = idx[i] = k; sorted[j] = idx[i] = k;
} }
result = rb_ary_new2(n); result = rb_ary_new2(n);
ptr_result = RARRAY_PTR(result);
for (i=0; i<n; i++) { for (i=0; i<n; i++) {
RARRAY_PTR(result)[i] = RARRAY_PTR(ary)[idx[i]]; ptr_result[i] = ptr[idx[i]];
} }
} }
else { else {
VALUE *ptr_result;
result = rb_ary_new4(len, ptr); result = rb_ary_new4(len, ptr);
ptr_result = RARRAY_PTR(result);
RB_GC_GUARD(ary); RB_GC_GUARD(ary);
for (i=0; i<n; i++) { for (i=0; i<n; i++) {
j = (long)(rb_genrand_real()*(len-i)) + i; j = (long)(rb_genrand_real()*(len-i)) + i;
nv = RARRAY_PTR(result)[j]; nv = ptr_result[j];
RARRAY_PTR(result)[j] = RARRAY_PTR(result)[i]; ptr_result[j] = ptr_result[i];
RARRAY_PTR(result)[i] = nv; ptr_result[i] = nv;
} }
} }
ARY_SET_LEN(result, n); ARY_SET_LEN(result, n);

View File

@ -1173,6 +1173,7 @@ rb_str_times(VALUE str, VALUE times)
{ {
VALUE str2; VALUE str2;
long n, len; long n, len;
char *ptr2;
len = NUM2LONG(times); len = NUM2LONG(times);
if (len < 0) { if (len < 0) {
@ -1183,16 +1184,17 @@ rb_str_times(VALUE str, VALUE times)
} }
str2 = rb_str_new5(str, 0, len *= RSTRING_LEN(str)); str2 = rb_str_new5(str, 0, len *= RSTRING_LEN(str));
ptr2 = RSTRING_PTR(str2);
if (len) { if (len) {
n = RSTRING_LEN(str); n = RSTRING_LEN(str);
memcpy(RSTRING_PTR(str2), RSTRING_PTR(str), n); memcpy(ptr2, RSTRING_PTR(str), n);
while (n <= len/2) { while (n <= len/2) {
memcpy(RSTRING_PTR(str2) + n, RSTRING_PTR(str2), n); memcpy(ptr2 + n, ptr2, n);
n *= 2; 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); OBJ_INFECT(str2, str);
rb_enc_cr_str_copy_for_substr(str2, str); rb_enc_cr_str_copy_for_substr(str2, str);
@ -5513,6 +5515,7 @@ rb_str_split_m(int argc, VALUE *argv, VALUE str)
} }
else if (split_type == string) { else if (split_type == string) {
char *ptr = RSTRING_PTR(str); char *ptr = RSTRING_PTR(str);
char *temp = ptr;
char *eptr = RSTRING_END(str); char *eptr = RSTRING_END(str);
char *sptr = RSTRING_PTR(spat); char *sptr = RSTRING_PTR(spat);
long slen = RSTRING_LEN(spat); long slen = RSTRING_LEN(spat);
@ -5532,13 +5535,15 @@ rb_str_split_m(int argc, VALUE *argv, VALUE str)
ptr = t; ptr = t;
continue; 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; ptr += end + slen;
if (!NIL_P(limit) && lim <= ++i) break; if (!NIL_P(limit) && lim <= ++i) break;
} }
beg = ptr - RSTRING_PTR(str); beg = ptr - temp;
} }
else { else {
char *ptr = RSTRING_PTR(str);
long len = RSTRING_LEN(str);
long start = beg; long start = beg;
long idx; long idx;
int last_null = 0; int last_null = 0;
@ -5547,22 +5552,22 @@ rb_str_split_m(int argc, VALUE *argv, VALUE str)
while ((end = rb_reg_search(spat, str, start, 0)) >= 0) { while ((end = rb_reg_search(spat, str, start, 0)) >= 0) {
regs = RMATCH_REGS(rb_backref_get()); regs = RMATCH_REGS(rb_backref_get());
if (start == end && BEG(0) == END(0)) { if (start == end && BEG(0) == END(0)) {
if (!RSTRING_PTR(str)) { if (!ptr) {
rb_ary_push(result, rb_str_new("", 0)); rb_ary_push(result, rb_str_new("", 0));
break; break;
} }
else if (last_null == 1) { else if (last_null == 1) {
rb_ary_push(result, rb_str_subseq(str, beg, rb_ary_push(result, rb_str_subseq(str, beg,
rb_enc_fast_mbclen(RSTRING_PTR(str)+beg, rb_enc_fast_mbclen(ptr+beg,
RSTRING_END(str), ptr+len,
enc))); enc)));
beg = start; beg = start;
} }
else { else {
if (RSTRING_PTR(str)+start == RSTRING_END(str)) if (ptr+start == ptr+len)
start++; start++;
else 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; last_null = 1;
continue; continue;
} }

100
struct.c
View File

@ -98,14 +98,17 @@ rb_struct_members_m(VALUE obj)
VALUE VALUE
rb_struct_getmember(VALUE obj, ID id) rb_struct_getmember(VALUE obj, ID id)
{ {
VALUE members, slot; VALUE members, slot, *ptr, *ptr_members;
long i; long i, len;
ptr = RSTRUCT_PTR(obj);
members = rb_struct_members(obj); members = rb_struct_members(obj);
ptr_members = RARRAY_PTR(members);
slot = ID2SYM(id); slot = ID2SYM(id);
for (i=0; i<RARRAY_LEN(members); i++) { len = RARRAY_LEN(members);
if (RARRAY_PTR(members)[i] == slot) { for (i=0; i<len; i++) {
return RSTRUCT_PTR(obj)[i]; if (ptr_members[i] == slot) {
return ptr[i];
} }
} }
rb_name_error(id, "%s is not struct member", rb_id2name(id)); rb_name_error(id, "%s is not struct member", rb_id2name(id));
@ -156,15 +159,18 @@ rb_struct_modify(VALUE s)
static VALUE static VALUE
rb_struct_set(VALUE obj, VALUE val) rb_struct_set(VALUE obj, VALUE val)
{ {
VALUE members, slot; VALUE members, slot, *ptr, *ptr_members;
long i; long i, len;
members = rb_struct_members(obj); members = rb_struct_members(obj);
ptr_members = RARRAY_PTR(members);
len = RARRAY_LEN(members);
rb_struct_modify(obj); rb_struct_modify(obj);
for (i=0; i<RARRAY_LEN(members); i++) { ptr = RSTRUCT_PTR(obj);
slot = RARRAY_PTR(members)[i]; for (i=0; i<len; i++) {
slot = ptr_members[i];
if (rb_id_attrset(SYM2ID(slot)) == rb_frame_this_func()) { 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", rb_name_error(rb_frame_this_func(), "`%s' is not a struct member",
@ -175,9 +181,9 @@ rb_struct_set(VALUE obj, VALUE val)
static VALUE static VALUE
make_struct(VALUE name, VALUE members, VALUE klass) make_struct(VALUE name, VALUE members, VALUE klass)
{ {
VALUE nstr; VALUE nstr, *ptr_members;
ID id; ID id;
long i; long i, len;
OBJ_FREEZE(members); OBJ_FREEZE(members);
if (NIL_P(name)) { if (NIL_P(name)) {
@ -204,8 +210,10 @@ make_struct(VALUE name, VALUE members, VALUE klass)
rb_define_singleton_method(nstr, "new", rb_class_new_instance, -1); 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, "[]", rb_class_new_instance, -1);
rb_define_singleton_method(nstr, "members", rb_struct_s_members_m, 0); rb_define_singleton_method(nstr, "members", rb_struct_s_members_m, 0);
for (i=0; i< RARRAY_LEN(members); i++) { ptr_members = RARRAY_PTR(members);
ID id = SYM2ID(RARRAY_PTR(members)[i]); 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 (rb_is_local_id(id) || rb_is_const_id(id)) {
if (i < N_REF_FUNC) { if (i < N_REF_FUNC) {
rb_define_method_id(nstr, id, ref_func[i], 0); rb_define_method_id(nstr, id, ref_func[i], 0);
@ -498,7 +506,8 @@ inspect_struct(VALUE s, VALUE dummy, int recur)
{ {
VALUE cname = rb_class_name(rb_obj_class(s)); VALUE cname = rb_class_name(rb_obj_class(s));
VALUE members, str = rb_str_new2("#<struct "); VALUE members, str = rb_str_new2("#<struct ");
long i; VALUE *ptr, *ptr_members;
long i, len;
char first = RSTRING_PTR(cname)[0]; char first = RSTRING_PTR(cname)[0];
if (recur || first != '#') { if (recur || first != '#') {
@ -509,7 +518,10 @@ inspect_struct(VALUE s, VALUE dummy, int recur)
} }
members = rb_struct_members(s); 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; VALUE slot;
ID id; ID id;
@ -519,7 +531,7 @@ inspect_struct(VALUE s, VALUE dummy, int recur)
else if (first != '#') { else if (first != '#') {
rb_str_cat2(str, " "); rb_str_cat2(str, " ");
} }
slot = RARRAY_PTR(members)[i]; slot = ptr_members[i];
id = SYM2ID(slot); id = SYM2ID(slot);
if (rb_is_local_id(id) || rb_is_const_id(id)) { if (rb_is_local_id(id) || rb_is_const_id(id)) {
rb_str_append(str, rb_id2str(id)); rb_str_append(str, rb_id2str(id));
@ -528,7 +540,7 @@ inspect_struct(VALUE s, VALUE dummy, int recur)
rb_str_append(str, rb_inspect(slot)); rb_str_append(str, rb_inspect(slot));
} }
rb_str_cat2(str, "="); 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, ">"); rb_str_cat2(str, ">");
OBJ_INFECT(str, s); OBJ_INFECT(str, s);
@ -588,14 +600,16 @@ rb_struct_init_copy(VALUE copy, VALUE s)
static VALUE static VALUE
rb_struct_aref_id(VALUE s, ID id) rb_struct_aref_id(VALUE s, ID id)
{ {
VALUE members; VALUE *ptr, members, *ptr_members;
long i, len; long i, len;
ptr = RSTRUCT_PTR(s);
members = rb_struct_members(s); members = rb_struct_members(s);
ptr_members = RARRAY_PTR(members);
len = RARRAY_LEN(members); len = RARRAY_LEN(members);
for (i=0; i<len; i++) { for (i=0; i<len; i++) {
if (SYM2ID(RARRAY_PTR(members)[i]) == id) { if (SYM2ID(ptr_members[i]) == id) {
return RSTRUCT_PTR(s)[i]; return ptr[i];
} }
} }
rb_name_error(id, "no member '%s' in struct", rb_id2name(id)); rb_name_error(id, "no member '%s' in struct", rb_id2name(id));
@ -644,19 +658,21 @@ rb_struct_aref(VALUE s, VALUE idx)
static VALUE static VALUE
rb_struct_aset_id(VALUE s, ID id, VALUE val) rb_struct_aset_id(VALUE s, ID id, VALUE val)
{ {
VALUE members; VALUE members, *ptr, *ptr_members;
long i, len; long i, len;
members = rb_struct_members(s); members = rb_struct_members(s);
rb_struct_modify(s);
len = RARRAY_LEN(members); len = RARRAY_LEN(members);
if (RSTRUCT_LEN(s) != RARRAY_LEN(members)) { rb_struct_modify(s);
if (RSTRUCT_LEN(s) != len) {
rb_raise(rb_eTypeError, "struct size differs (%ld required %ld given)", 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++) { for (i=0; i<len; i++) {
if (SYM2ID(RARRAY_PTR(members)[i]) == id) { if (SYM2ID(ptr_members[i]) == id) {
RSTRUCT_PTR(s)[i] = val; ptr[i] = val;
return val; return val;
} }
} }
@ -771,11 +787,15 @@ rb_struct_select(int argc, VALUE *argv, VALUE s)
static VALUE static VALUE
recursive_equal(VALUE s, VALUE s2, int recur) recursive_equal(VALUE s, VALUE s2, int recur)
{ {
long i; VALUE *ptr, *ptr2;
long i, len;
if (recur) return Qtrue; /* Subtle! */ if (recur) return Qtrue; /* Subtle! */
for (i=0; i<RSTRUCT_LEN(s); i++) { ptr = RSTRUCT_PTR(s);
if (!rb_equal(RSTRUCT_PTR(s)[i], RSTRUCT_PTR(s2)[i])) return Qfalse; 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; return Qtrue;
} }
@ -813,14 +833,16 @@ rb_struct_equal(VALUE s, VALUE s2)
static VALUE static VALUE
recursive_hash(VALUE s, VALUE dummy, int recur) recursive_hash(VALUE s, VALUE dummy, int recur)
{ {
long i; long i, len;
st_index_t h; st_index_t h;
VALUE n; VALUE n, *ptr;
h = rb_hash_start(rb_hash(rb_obj_class(s))); h = rb_hash_start(rb_hash(rb_obj_class(s)));
if (!recur) { if (!recur) {
for (i = 0; i < RSTRUCT_LEN(s); i++) { ptr = RSTRUCT_PTR(s);
n = rb_hash(RSTRUCT_PTR(s)[i]); len = RSTRUCT_LEN(s);
for (i = 0; i < len; i++) {
n = rb_hash(ptr[i]);
h = rb_hash_uint(h, NUM2LONG(n)); h = rb_hash_uint(h, NUM2LONG(n));
} }
} }
@ -844,11 +866,15 @@ rb_struct_hash(VALUE s)
static VALUE static VALUE
recursive_eql(VALUE s, VALUE s2, int recur) recursive_eql(VALUE s, VALUE s2, int recur)
{ {
long i; VALUE *ptr, *ptr2;
long i, len;
if (recur) return Qtrue; /* Subtle! */ if (recur) return Qtrue; /* Subtle! */
for (i=0; i<RSTRUCT_LEN(s); i++) { ptr = RSTRUCT_PTR(s);
if (!rb_eql(RSTRUCT_PTR(s)[i], RSTRUCT_PTR(s2)[i])) return Qfalse; 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; return Qtrue;
} }