Removing constant-able macros inside of the loop

e$B6b0fe(B e$B?N90$H?=$7$^$9!#e(B

e$B%k!<%WFb$GDj?t2=$5$l$&$k%^%/%m$r!"%k!<%W$N30$K=P$9$3$H$K$h$C$F!"e(B
e$B0lIt%a%=%C%I$N9bB.2=$r?^$j$^$7$?!#e(B
revision 24444e$B$G$N=$@5$HF1MM$NH/A[$G$9!#e(B
http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=24444

e$B:#2s$N=$@5$O!"e(BArray, String, Structe$B$KBP$7$F9T$$$^$7$?!#e(B
e$B$$$:$l$b!“e(BR{Array, String, Struct}_{LEN, PTR}e$B$r;}$C$F$$j!"e(B
e$BFCDj$N>l9g$K$
$$$F!”%k!<%WFb$GDj?t2=2DG=$G$9!#e(B
e$B$?$@!"e(B[ruby-dev:24254]e$BEy$G5s$2$i$l$F$$$k$h$&$K!"e(B
e$B%k!<%WCf$K!"85$Ne(B{Array, String,
Struct}e$B$KGK2uE*JQ99$,2C$o$C$?>l9g$O!“e(B
SEGVe$B$7$F$7$^$&$N$G!”$=$NE@$O9MN8$7$^$7$?!#e(B

e$B%Y%s%A%^!<%/7k2L$O!"0J2<$NDL$j$G$9!#e(B
$ ./ruby -v
ruby 1.9.2dev (2009-09-23 trunk 25052) [i686-linux]

a : revision 25052
b : working copy

                      a  b  %

String#* 2.06 1.85 111.35
String#split 2.25 2.13 105.63
String#start_with? 1.93 1.79 107.82
String#end_with? 2.9 2.86 101.4
Array#* e$B!!e(B 2.17 2.1 103.33
Array#shuffle! 7.76 7.62 101.84
Array#sample 1.52 1.49 102.01
Struct#[] 2.61 2.59 100.77
Struct#[]= 1.37 1.36 100.74
Struct#inspect 3.61 3.57 101.12
Struct#== 3.46 2.11 163.98
Struct#eql? 1.65 1.62 101.85
Struct#hash 1.32 1.31 100.76

e$BA4BN$GLse(B8%e$B!":G9b$O!“e(BStruct#==e$B$G!“Lse(B63%e$B$N9bB.2=$H$J$j$^$9!#e(B
e$B>:Y$O!”<+J,$,=q$$$?e(Bbloge$B%(%s%H%j$K$b$”$j$^$9!#e(B
http://d.hatena.ne.jp/CanI/20090921/1253549503

e$B<+J,$N8!>Z$G$O!"e(BStruct#{==, eql?, inspect,
hash}e$B$N%k!<%WCf$K!"e(B
rubye$B>e$G$N%a%=%C%I$N:FDj5A$K$h$C$F!"85$Ne(BStructe$B$KGK2uEJQ99$re(B
e$B2C$($kJ}K!$O8+$D$+$j$^$;$s$G$7$?!#e(B
e$B$7$+$7!"2>$K85$Ne(BStructe$B$KGK2uE
JQ99$,2C$($i$l$k>l9g$O!"e(B
SEGVe$B$N860x$H$J$j$($^$9!#e(B

e$B!&e(Brubye$B>e$G!"85$Ne(BStructe$B$KGK2uE*JQ99$r2C$($k$3$H$O2DG=$G$7$g$&$+!)e(B

e$B>e5-e(B1e$BE@$b4^$a!"$h$m$7$/$*4j$$$$$?$7$^$9!#e(B

e$B$J$!"$3$N%Q%C%A$O!"e(Brevision 24547e$B$G$N%Q%C%A$HF1MM$K!"e(B
e$B%;%-%e%j%F%#!u%W%m%0%i%_%s%0%-%c%s%We([email protected]
$G$9!#e(B
http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=24547

— array.c (revision 25052)
+++ array.c (working copy)
@@ -2708,8 +2708,8 @@ rb_ary_concat(VALUE x, VALUE y)
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 @@ rb_ary_times(VALUE ary, VALUE times)
    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 @@ rb_ary_flatten(int argc, VALUE *argv, VALUE ary)
    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 @@ rb_ary_sample(int argc, VALUE *argv, VALUE ary)
    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 @@ rb_ary_sample(int argc, VALUE *argv, VALUE ary)
    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);
    diff --git a/string.c b/string.c
    index daf6ed1…487c6de 100644
    — a/string.c
    +++ b/string.c
    @@ -1159,6 +1159,7 @@ rb_str_times(VALUE str, VALUE times)
    {
    VALUE str2;
    long n, len;

  • char *ptr2;

    len = NUM2LONG(times);
    if (len < 0) {
    @@ -1169,16 +1170,17 @@ rb_str_times(VALUE str, VALUE times)
    }

    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);

@@ -5697,6 +5699,7 @@ rb_str_split_m(int argc, VALUE *argv, VALUE str)
}
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);
    @@ -5716,13 +5719,15 @@ rb_str_split_m(int argc, VALUE *argv, VALUE str)
    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;
    @@ -5731,22 +5736,22 @@ rb_str_split_m(int argc, VALUE *argv, VALUE str)
    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;
}
@@ -7048,13 +7053,15 @@ static VALUE
rb_str_start_with(int argc, VALUE *argv, VALUE str)
{
int i;

  • char *ptr = RSTRING_PTR(str);

  • long len = RSTRING_LEN(str);

    for (i=0; i<argc; i++) {
    VALUE tmp = rb_check_string_type(argv[i]);
    if (NIL_P(tmp)) continue;
    rb_enc_check(str, tmp);

  • if (RSTRING_LEN(str) < RSTRING_LEN(tmp)) continue;
  • if (memcmp(RSTRING_PTR(str), RSTRING_PTR(tmp), RSTRING_LEN(tmp)) ==
  • if (len < RSTRING_LEN(tmp)) continue;

  • if (memcmp(ptr, RSTRING_PTR(tmp), RSTRING_LEN(tmp)) == 0)
    return Qtrue;
    }
    return Qfalse;
    @@ -7072,15 +7079,17 @@ rb_str_end_with(int argc, VALUE *argv, VALUE
    str)
    {
    int i;
    char *p, *s, *e;

  • long len;
    rb_encoding *enc;

  • p = RSTRING_PTR(str);

  • len = RSTRING_LEN(str);
    for (i=0; i<argc; i++) {
    VALUE tmp = rb_check_string_type(argv[i]);
    if (NIL_P(tmp)) continue;
    enc = rb_enc_check(str, tmp);

  • if (RSTRING_LEN(str) < RSTRING_LEN(tmp)) continue;
  • p = RSTRING_PTR(str);
  •    e = p + RSTRING_LEN(str);
    
  • if (len < RSTRING_LEN(tmp)) continue;
  •    e = p + len;
    
    s = e - RSTRING_LEN(tmp);
    if (rb_enc_left_char_head(p, s, e, enc) != s)
    continue;
    diff --git a/struct.c b/struct.c
    index 4f3e508…68cad6b 100644
    — a/struct.c
    +++ b/struct.c
    @@ -98,14 +98,17 @@ rb_struct_members_m(VALUE obj)
    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 @@ rb_struct_modify(VALUE s)
    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 @@ rb_struct_set(VALUE obj, VALUE val)
    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 @@ make_struct(VALUE name, VALUE members, VALUE klass)
    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);
    @@ -461,6 +469,7 @@ rb_struct_each(VALUE s)
    return s;
    }

/*

  • call-seq:
  • struct.each_pair {|sym, obj| block }     => struct
    

@@ -498,7 +507,8 @@ inspect_struct(VALUE s, VALUE dummy, int recur)
{
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 +519,10 @@ inspect_struct(VALUE s, VALUE dummy, int recur)
    }

    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 +532,7 @@ inspect_struct(VALUE s, VALUE dummy, int recur)
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 +541,7 @@ inspect_struct(VALUE s, VALUE dummy, int recur)
    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 +601,16 @@ rb_struct_init_copy(VALUE copy, VALUE s)
    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 +659,21 @@ rb_struct_aref(VALUE s, VALUE idx)
    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);

  • rb_struct_modify(s);
    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)”,
  • 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 +788,15 @@ rb_struct_select(int argc, VALUE *argv, VALUE s)
    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 +834,16 @@ rb_struct_equal(VALUE s, VALUE s2)
    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 +867,15 @@ rb_struct_hash(VALUE s)
    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;
    }

In article
[email protected],
“Masahiro Kanai (CanI)” [email protected] writes:

e$B!&e(Brubye$B>e$G!"85$Ne(BStructe$B$KGK2uE*JQ99$r2C$($k$3$H$O2DG=$G$7$g$&$+!)e(B

e$B$H$j$"$($:!“e(Brb_check_string_type
e$B$”$?$j$,A@$$L$8$c$J$$$G$7$ge(B
e$B$&$+!#e(B

rb_enc_check(str, tmp);

  • if (RSTRING_LEN(str) < RSTRING_LEN(tmp)) continue;
  • if (memcmp(RSTRING_PTR(str), RSTRING_PTR(tmp), RSTRING_LEN(tmp)) == 0)
  • if (len < RSTRING_LEN(tmp)) continue;
  • if (memcmp(ptr, RSTRING_PTR(tmp), RSTRING_LEN(tmp)) == 0)
    return Qtrue;
    }
    return Qfalse;

% cat z.rb
$a = “a”*1000
b = Object.new
def b.to_str
$a.replace “b”*1000
“a”
end
p $a.start_with?(b)

% valgrind ./miniruby z.rb
==26867== Memcheck, a memory error detector.
==26867== Copyright (C) 2002-2007, and GNU GPL’d, by Julian Seward et
al.
==26867== Using LibVEX rev 1854, a library for dynamic binary
translation.
==26867== Copyright (C) 2004-2007, and GNU GPL’d, by OpenWorks LLP.
==26867== Using valgrind-3.3.1-Debian, a dynamic binary instrumentation
framework.
==26867== Copyright (C) 2000-2007, and GNU GPL’d, by Julian Seward et
al.
==26867== For more details, rerun with: -v
==26867==
==26867== Invalid read of size 1
==26867== at 0x4025087: bcmp (mc_replace_strmem.c:442)
==26867== by 0x814286D: rb_str_start_with (string.c:6847)
==26867== by 0x817FB06: call_cfunc (vm_insnhelper.c:286)
==26867== by 0x817F9B5: vm_call_cfunc (vm_insnhelper.c:386)
==26867== by 0x817EFD9: vm_call_method (vm_insnhelper.c:511)
==26867== by 0x817ACAD: vm_exec_core (insns.def:994)
==26867== by 0x818735C: vm_exec (vm.c:1117)
==26867== by 0x81879CF: rb_iseq_eval_main (vm.c:1341)
==26867== by 0x808B920: ruby_exec_node (eval.c:212)
==26867== by 0x808B9C1: ruby_run_node (eval.c:240)
==26867== by 0x805D1F7: main (main.c:35)
==26867== Address 0x439e278 is 0 bytes inside a block of size 1,001
free’d
==26867== at 0x4022B8A: free (vg_replace_malloc.c:323)
==26867== by 0x8099CBC: vm_xfree (gc.c:730)
==26867== by 0x8099E13: ruby_xfree (gc.c:778)
==26867== by 0x8131510: str_discard (string.c:1279)
==26867== by 0x8139F71: rb_str_replace (string.c:3733)
==26867== by 0x817FB3B: call_cfunc (vm_insnhelper.c:292)
==26867== by 0x817F9B5: vm_call_cfunc (vm_insnhelper.c:386)
==26867== by 0x817EFD9: vm_call_method (vm_insnhelper.c:511)
==26867== by 0x817ACAD: vm_exec_core (insns.def:994)
==26867== by 0x818735C: vm_exec (vm.c:1117)
==26867== by 0x8182633: vm_call0 (vm_eval.c:64)
==26867== by 0x8183312: rb_call0 (vm_eval.c:283)
true
==26867==
==26867== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 25 from
1)
==26867== malloc/free: in use at exit: 377,787 bytes in 12,896 blocks.
==26867== malloc/free: 13,198 allocs, 302 frees, 1,171,105 bytes
allocated.
==26867== For counts of detected errors, rerun with: -v
==26867== searching for pointers to 12,896 not-freed blocks.
==26867== checked 420,024 bytes.
==26867==
==26867== LEAK SUMMARY:
==26867== definitely lost: 253,258 bytes in 8,953 blocks.
==26867== possibly lost: 0 bytes in 0 blocks.
==26867== still reachable: 124,529 bytes in 3,943 blocks.
==26867== suppressed: 0 bytes in 0 blocks.
==26867== Rerun with --leak-check=full to see details of leaked memory.

e$B$^$D$b$He(B e$B$f$-$R$m$G$9e(B

In message “Re: [ruby-dev:39392] Re: Removing constant-able macros
inside of the loop.”
on Mon, 28 Sep 2009 23:31:45 +0900, “Masahiro Kanai (CanI)”
[email protected] writes:

|e$B:F%A%'%C%/$7$?7k2L!“e(Brb_str_{start, end}_with, rb_ary_timese$B$,e(B
|rb_check_string_typee$B$r<B9T$9$k2DG=@-$,$”$j$^$7$?$,!"e(B
|rb_ary_timese$B$K$*$$$F$O!"e(BRSTRING_PTR()e$B$N0LCV$r9)IW$9$k$3$H$Ge(B
|e$BBP1~$,2DG=$G$7$?!#e(B(e$B4{$KBP1~$5$l$F$^$7$?!#e(B)
|
|
|e$B=$@58e$N%Q%C%A$O!"0J2<$NDL$j$G$9!#e(B

e$B;n$7$F$_$h$&$H;W$$$^$9$,!“;DG0$J$,$ie(Bfolde$B$5$l$F$$$F%Q%C%A$,2ue(B
e$B$l$F$^$9!#;d$,<j$G=$@5$9$k$3$H$O$b$A$m$s2DG=$G$9$,!”:#8e$N$?e(B
e$B$a$K$b!“$<$Re(Bfolde$B$7$J$$$h$&$K$7$F:FEj9F$7$F$$$?$@$1$k$H$”$j$,e(B
e$B$?$$$G$9!#e(B

e$B$“$H!“e(BChangeLoge$B%(%s%H%j$b$$$?$@$1$k$H$9$4$/$h$$$G$9$,!”$3$Ae(B
e$B$i$OI,?$G$O$”$j$^$;$s!#e(B

e$B6b0f$G$9!#e(B

2009e$BG/e(B9e$B7ne(B28e$BF|e(B0:47 Tanaka A. [email protected]:

e$B!&e(Brubye$B>e$G!"85$Ne(BStructe$B$KGK2uE*JQ99$r2C$($k$3$H$O2DG=$G$7$g$&$+!)e(B

e$B$H$j$"$($:!“e(Brb_check_string_type e$B$”$?$j$,A@$$L$8$c$J$$$G$7$ge(B
e$B$&$+!#e(B

rb_check_string_typee$B$O!"e(Bto_stre$B$r<B9T$9$k$N$G$9$M!D!#e(B
e$B9MN8$7$F$$$^$;$s$G$7$?!#e(B

e$B:F%A%'%C%/$7$?7k2L!“e(Brb_str_{start, end}_with, rb_ary_timese$B$,e(B
rb_check_string_typee$B$r<B9T$9$k2DG=@-$,$”$j$^$7$?$,!"e(B
rb_ary_timese$B$K$*$$$F$O!"e(BRSTRING_PTR()e$B$N0LCV$r9)IW$9$k$3$H$Ge(B
e$BBP1~$,2DG=$G$7$?!#e(B(e$B4{$KBP1~$5$l$F$^$7$?!#e(B)

e$B=$@58e$N%Q%C%A$O!"0J2<$NDL$j$G$9!#e(B

— array.c (revision 25052)
+++ array.c (working copy)
@@ -2708,8 +2708,8 @@ rb_ary_concat(VALUE x, VALUE y)
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 @@ rb_ary_times(VALUE ary, VALUE times)
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 @@ rb_ary_flatten(int argc, VALUE *argv, VALUE ary)
    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 @@ rb_ary_sample(int argc, VALUE *argv, VALUE ary)
    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 @@ rb_ary_sample(int argc, VALUE *argv, VALUE ary)
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);
    — string.c (revision 25052)
    +++ string.c (working copy)
    @@ -1159,6 +1159,7 @@ rb_str_times(VALUE str, VALUE times)
    {
    VALUE str2;
    long n, len;
  • char *ptr2;
len = NUM2LONG(times);
if (len < 0) {

@@ -1169,16 +1170,17 @@ rb_str_times(VALUE str, VALUE times)
}

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);

@@ -5697,6 +5699,7 @@ rb_str_split_m(int argc, VALUE *argv, VALUE str)
}
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);
    

@@ -5716,13 +5719,15 @@ rb_str_split_m(int argc, VALUE *argv, VALUE str)
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;
    

@@ -5731,22 +5736,22 @@ rb_str_split_m(int argc, VALUE *argv, VALUE str)
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;
}
— struct.c (revision 25052)
+++ struct.c (working copy)
@@ -98,14 +98,17 @@ rb_struct_members_m(VALUE obj)
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 @@ rb_struct_modify(VALUE s)
    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 @@ rb_struct_set(VALUE obj, VALUE val)
    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 @@ make_struct(VALUE name, VALUE members, VALUE klass)
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 +507,8 @@ inspect_struct(VALUE s, VALUE dummy, int recur)
{
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 +519,10 @@ inspect_struct(VALUE s, VALUE dummy, int recur)
}

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 +532,7 @@ inspect_struct(VALUE s, VALUE dummy, int recur)
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 +541,7 @@ inspect_struct(VALUE s, VALUE dummy, int recur)
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 +601,16 @@ rb_struct_init_copy(VALUE copy, VALUE s)
    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 +659,21 @@ rb_struct_aref(VALUE s, VALUE idx)
    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);
  • rb_struct_modify(s);
    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)”,
  •            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 +788,15 @@ rb_struct_select(int argc, VALUE *argv, VALUE s)
    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 +834,16 @@ rb_struct_equal(VALUE s, VALUE s2)
    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 +867,15 @@ rb_struct_hash(VALUE s)
    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;
    }