From: SASADA Koichi Date: 2004-12-02T02:43:46+09:00 Subject: [ruby-dev:25021] Re: object.c convert_type says error with -d option SASADA Koichi wrote : [ [ruby-dev:25011] Re: object.c convert_type says error with -d option ] at Wed, 1 Dec 2004 13:39:08 +0900  ささだです。 >>ruby -de "puts 'abc'" > Exception `NoMethodError' at -e:1 - undefined method `to_ary' for "abc":String > abc  先のメールの方式 2.1 を行う自分なりのパッチを書いてみたの でご検討頂ければ幸いです。  それなりに速くなっているような気がします。 ---- require 'benchmark' class C def respond_to? *args true @ary = [:C] end def to_ary [:C]# @ary end end obj = Object.new c = C.new max = 1000000 Benchmark.bm{|x| x.report("miss"){ max.times{ Array(1) } } x.report("hit "){ max.times{ Array(c) } } } パッチを当てる前 (ruby 1.9.0 (2004-11-30) [i386-mswin32]) user system total real miss127.547000 0.063000 127.610000 (129.860000) hit 73.468000 0.062000 73.530000 ( 74.797000) パッチを当てた後 user system total real miss 3.234000 0.000000 3.234000 ( 3.281000) hit 8.204000 0.000000 8.204000 ( 8.391000)  まぁ、極端な例ですが。 -- // SASADA Koichi at atdot dot net // ・グローバル変数名はとても嫌な名前にしてます ・node は gc 避けしないとまずい気がします Index: eval.c =================================================================== RCS file: /src/ruby/eval.c,v retrieving revision 1.738 diff -u -r1.738 eval.c --- eval.c 30 Nov 2004 17:28:16 -0000 1.738 +++ eval.c 1 Dec 2004 17:41:24 -0000 @@ -3937,17 +3963,27 @@ return result; } +NODE *node_Object_respond_to = 0; +ID id_Object_respond_to = 0; + int rb_respond_to(obj, id) VALUE obj; ID id; { - if (rb_method_boundp(CLASS_OF(obj), id, 0)) { - return Qtrue; + VALUE klass = CLASS_OF(obj); + if (rb_method_node(klass, id_Object_respond_to) == node_Object_respond_to){ + if (rb_method_boundp(klass, id, 0)) { + return Qtrue; + } + } + else{ + return rb_funcall(obj, id_Object_respond_to, 1, ID2SYM(id)); } return Qfalse; } + /* * call-seq: * obj.respond_to?(symbol, include_private=false) => true or false @@ -7596,7 +7646,9 @@ rb_define_global_function("loop", rb_f_loop, 0); rb_define_method(rb_mKernel, "respond_to?", rb_obj_respond_to, -1); - + id_Object_respond_to = rb_intern("respond_to?"); + node_Object_respond_to = rb_method_node(rb_cObject, id_Object_respond_to); + rb_define_global_function("raise", rb_f_raise, -1); rb_define_global_function("fail", rb_f_raise, -1); Index: object.c =================================================================== RCS file: /src/ruby/object.c,v retrieving revision 1.162 diff -u -r1.162 object.c --- object.c 29 Nov 2004 06:09:40 -0000 1.162 +++ object.c 1 Dec 2004 13:18:20 -0000 @@ -2056,9 +2056,10 @@ const char *tname, *method; int raise; { - VALUE result = rb_funcall_rescue(val, rb_intern(method), 0); + ID m; - if (result == Qundef) { + m = rb_intern(method); + if (!rb_respond_to(val, m)) { if (raise) { rb_raise(rb_eTypeError, "cannot convert %s into %s", NIL_P(val) ? "nil" : @@ -2068,11 +2069,10 @@ tname); } else { - ruby_errinfo = Qnil; return Qnil; } } - return result; + return rb_funcall(val, m, 0); } VALUE