From 0580ba06110f7998fdaead724907a4c8d6540107 Mon Sep 17 00:00:00 2001 From: matz Date: Thu, 29 Oct 2009 04:55:10 +0000 Subject: * array.c (rb_ary_to_ary): do not use #respond_to? to detect to_ary. Just call. [ruby-core:23738] * eval.c (rb_check_funcall): new function with method existence check. returns Qundef when the method does not exist. * enumerator.c (enumerator_rewind): just call method, using rb_check_funcall(). [ruby-core:23738] * error.c (exc_equal): ditto. * object.c (convert_type): ditto. * error.c (rb_name_err_mesg_new): export function. * eval.c (make_exception): ditto. * io.c (pop_last_hash): return early when the last argument is nil. * io.c (rb_io_puts): treat T_STRING specially for small optimization. * vm_eval.c (raise_method_missing): skip method call if possible using rb_method_basic_definition_p(). * vm_eval.c (method_missing): ditto. * test/ruby/test_rubyoptions.rb (TestRubyOptions#test_debug): test suites changed to ignore exceptions caused by just-call policy. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@25556 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- eval.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 51 insertions(+), 9 deletions(-) (limited to 'eval.c') diff --git a/eval.c b/eval.c index 5133181c4b..dec628204a 100644 --- a/eval.c +++ b/eval.c @@ -425,11 +425,13 @@ rb_longjmp(int tag, volatile VALUE mesg) JUMP_TAG(tag); } +static VALUE make_exception(int argc, VALUE *argv, int isstr); + void rb_exc_raise(VALUE mesg) { if (!NIL_P(mesg)) { - mesg = rb_make_exception(1, &mesg); + mesg = make_exception(1, &mesg, Qfalse); } rb_longjmp(TAG_RAISE, mesg); } @@ -438,7 +440,7 @@ void rb_exc_fatal(VALUE mesg) { if (!NIL_P(mesg)) { - mesg = rb_make_exception(1, &mesg); + mesg = make_exception(1, &mesg, Qfalse); } rb_longjmp(TAG_FATAL, mesg); } @@ -490,8 +492,40 @@ rb_f_raise(int argc, VALUE *argv) return Qnil; /* not reached */ } +struct rescue_funcall_args { + VALUE obj; + ID id; + int argc; + VALUE *argv; +}; + +static VALUE +check_funcall(struct rescue_funcall_args *args) +{ + return rb_funcall2(args->obj, args->id, args->argc, args->argv); +} + +static VALUE +check_failed(VALUE data) +{ + return data; +} + VALUE -rb_make_exception(int argc, VALUE *argv) +rb_check_funcall(VALUE obj, ID id, int argc, VALUE *argv) +{ + struct rescue_funcall_args args; + + args.obj = obj; + args.id = id; + args.argc = argc; + args.argv = argv; + return rb_rescue2(check_funcall, (VALUE)&args, check_failed, Qundef, + rb_eNoMethodError, (VALUE)0); +} + +static VALUE +make_exception(int argc, VALUE *argv, int isstr) { VALUE mesg; ID exception; @@ -504,10 +538,12 @@ rb_make_exception(int argc, VALUE *argv) case 1: if (NIL_P(argv[0])) break; - mesg = rb_check_string_type(argv[0]); - if (!NIL_P(mesg)) { - mesg = rb_exc_new3(rb_eRuntimeError, mesg); - break; + if (isstr) { + mesg = rb_check_string_type(argv[0]); + if (!NIL_P(mesg)) { + mesg = rb_exc_new3(rb_eRuntimeError, mesg); + break; + } } n = 0; goto exception_call; @@ -517,10 +553,10 @@ rb_make_exception(int argc, VALUE *argv) n = 1; exception_call: CONST_ID(exception, "exception"); - if (!rb_respond_to(argv[0], exception)) { + mesg = rb_check_funcall(argv[0], exception, n, argv+1); + if (mesg == Qundef) { rb_raise(rb_eTypeError, "exception class/object expected"); } - mesg = rb_funcall(argv[0], exception, n, argv[1]); break; default: rb_raise(rb_eArgError, "wrong number of arguments"); @@ -536,6 +572,12 @@ rb_make_exception(int argc, VALUE *argv) return mesg; } +VALUE +rb_make_exception(int argc, VALUE *argv) +{ + return make_exception(argc, argv, Qtrue); +} + void rb_raise_jump(VALUE mesg) { -- cgit v1.2.3