mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* vm_eval.c (method_missing): should not pop cfp if missing method
is method_missing. [ruby-core:22298] * vm_eval.c (rb_raise_method_missing): new function to directly raise NoMethodError. * vm_insnhelper.c (vm_call_method): fixed the case method_missing is missing. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@22494 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
3b39217fb4
commit
19bbab6140
4 changed files with 63 additions and 22 deletions
11
ChangeLog
11
ChangeLog
|
@ -1,3 +1,14 @@
|
||||||
|
Sun Feb 22 10:43:57 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||||
|
|
||||||
|
* vm_eval.c (method_missing): should not pop cfp if missing method
|
||||||
|
is method_missing. [ruby-core:22298]
|
||||||
|
|
||||||
|
* vm_eval.c (rb_raise_method_missing): new function to directly
|
||||||
|
raise NoMethodError.
|
||||||
|
|
||||||
|
* vm_insnhelper.c (vm_call_method): fixed the case method_missing
|
||||||
|
is missing.
|
||||||
|
|
||||||
Sun Feb 22 02:15:40 2009 Tanaka Akira <akr@fsij.org>
|
Sun Feb 22 02:15:40 2009 Tanaka Akira <akr@fsij.org>
|
||||||
|
|
||||||
* ext/socket/ancdata.c (bsock_recvmsg_internal): handle EMSGSIZE as
|
* ext/socket/ancdata.c (bsock_recvmsg_internal): handle EMSGSIZE as
|
||||||
|
|
|
@ -195,6 +195,8 @@ NORETURN(void rb_fiber_start(void));
|
||||||
NORETURN(void rb_print_undef(VALUE, ID, int));
|
NORETURN(void rb_print_undef(VALUE, ID, int));
|
||||||
NORETURN(void rb_vm_localjump_error(const char *,VALUE, int));
|
NORETURN(void rb_vm_localjump_error(const char *,VALUE, int));
|
||||||
NORETURN(void rb_vm_jump_tag_but_local_jump(int, VALUE));
|
NORETURN(void rb_vm_jump_tag_but_local_jump(int, VALUE));
|
||||||
|
NORETURN(void rb_raise_method_missing(rb_thread_t *th, int argc, VALUE *argv,
|
||||||
|
VALUE obj, int call_status));
|
||||||
|
|
||||||
VALUE rb_vm_make_jump_tag_but_local_jump(int state, VALUE val);
|
VALUE rb_vm_make_jump_tag_but_local_jump(int state, VALUE val);
|
||||||
NODE *rb_vm_cref(void);
|
NODE *rb_vm_cref(void);
|
||||||
|
|
33
vm_eval.c
33
vm_eval.c
|
@ -256,6 +256,9 @@ rb_call(VALUE klass, VALUE recv, ID mid, int argc, const VALUE *argv, int scope)
|
||||||
return rb_call0(klass, recv, mid, argc, argv, scope, Qundef);
|
return rb_call0(klass, recv, mid, argc, argv, scope, Qundef);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NORETURN(static void raise_method_missing(rb_thread_t *th, int argc, const VALUE *argv,
|
||||||
|
VALUE obj, int call_status));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* call-seq:
|
* call-seq:
|
||||||
* obj.method_missing(symbol [, *args] ) => result
|
* obj.method_missing(symbol [, *args] ) => result
|
||||||
|
@ -291,12 +294,22 @@ rb_call(VALUE klass, VALUE recv, ID mid, int argc, const VALUE *argv, int scope)
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
rb_method_missing(int argc, const VALUE *argv, VALUE obj)
|
rb_method_missing(int argc, const VALUE *argv, VALUE obj)
|
||||||
|
{
|
||||||
|
rb_thread_t *th = GET_THREAD();
|
||||||
|
raise_method_missing(th, argc, argv, obj, th->method_missing_reason);
|
||||||
|
return Qnil; /* not reached */
|
||||||
|
}
|
||||||
|
|
||||||
|
#define NOEX_MISSING 0x80
|
||||||
|
|
||||||
|
static void
|
||||||
|
raise_method_missing(rb_thread_t *th, int argc, const VALUE *argv, VALUE obj,
|
||||||
|
int last_call_status)
|
||||||
{
|
{
|
||||||
ID id;
|
ID id;
|
||||||
VALUE exc = rb_eNoMethodError;
|
VALUE exc = rb_eNoMethodError;
|
||||||
const char *format = 0;
|
const char *format = 0;
|
||||||
rb_thread_t *th = GET_THREAD();
|
|
||||||
int last_call_status = th->method_missing_reason;
|
|
||||||
if (argc == 0 || !SYMBOL_P(argv[0])) {
|
if (argc == 0 || !SYMBOL_P(argv[0])) {
|
||||||
rb_raise(rb_eArgError, "no id given");
|
rb_raise(rb_eArgError, "no id given");
|
||||||
}
|
}
|
||||||
|
@ -333,11 +346,11 @@ rb_method_missing(int argc, const VALUE *argv, VALUE obj)
|
||||||
}
|
}
|
||||||
exc = rb_class_new_instance(n, args, exc);
|
exc = rb_class_new_instance(n, args, exc);
|
||||||
|
|
||||||
th->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp);
|
if (!(last_call_status & NOEX_MISSING)) {
|
||||||
|
th->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp);
|
||||||
|
}
|
||||||
rb_exc_raise(exc);
|
rb_exc_raise(exc);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Qnil; /* not reached */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline VALUE
|
static inline VALUE
|
||||||
|
@ -350,7 +363,7 @@ method_missing(VALUE obj, ID id, int argc, const VALUE *argv, int call_status)
|
||||||
th->passed_block = 0;
|
th->passed_block = 0;
|
||||||
|
|
||||||
if (id == idMethodMissing) {
|
if (id == idMethodMissing) {
|
||||||
rb_method_missing(argc, argv, obj);
|
raise_method_missing(th, argc, argv, obj, call_status | NOEX_MISSING);
|
||||||
}
|
}
|
||||||
else if (id == ID_ALLOCATOR) {
|
else if (id == ID_ALLOCATOR) {
|
||||||
rb_raise(rb_eTypeError, "allocator undefined for %s",
|
rb_raise(rb_eTypeError, "allocator undefined for %s",
|
||||||
|
@ -372,6 +385,14 @@ method_missing(VALUE obj, ID id, int argc, const VALUE *argv, int call_status)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rb_raise_method_missing(rb_thread_t *th, int argc, VALUE *argv,
|
||||||
|
VALUE obj, int call_status)
|
||||||
|
{
|
||||||
|
th->passed_block = 0;
|
||||||
|
raise_method_missing(th, argc, argv, obj, call_status | NOEX_MISSING);
|
||||||
|
}
|
||||||
|
|
||||||
VALUE
|
VALUE
|
||||||
rb_apply(VALUE recv, ID mid, VALUE args)
|
rb_apply(VALUE recv, ID mid, VALUE args)
|
||||||
{
|
{
|
||||||
|
|
|
@ -403,20 +403,25 @@ vm_call_bmethod(rb_thread_t *th, ID id, VALUE procval, VALUE recv,
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
vm_method_missing_args(rb_thread_t *th, VALUE *argv,
|
||||||
|
int num, rb_block_t *blockptr, int opt)
|
||||||
|
{
|
||||||
|
rb_control_frame_t * const reg_cfp = th->cfp;
|
||||||
|
MEMCPY(argv, STACK_ADDR_FROM_TOP(num + 1), VALUE, num + 1);
|
||||||
|
th->method_missing_reason = opt;
|
||||||
|
th->passed_block = blockptr;
|
||||||
|
POPN(num + 1);
|
||||||
|
}
|
||||||
|
|
||||||
static inline VALUE
|
static inline VALUE
|
||||||
vm_method_missing(rb_thread_t *th, ID id, VALUE recv,
|
vm_method_missing(rb_thread_t *th, ID id, VALUE recv,
|
||||||
int num, rb_block_t *blockptr, int opt)
|
int num, rb_block_t *blockptr, int opt)
|
||||||
{
|
{
|
||||||
VALUE val;
|
|
||||||
rb_control_frame_t * const reg_cfp = th->cfp;
|
|
||||||
VALUE *argv = ALLOCA_N(VALUE, num + 1);
|
VALUE *argv = ALLOCA_N(VALUE, num + 1);
|
||||||
MEMCPY(argv, STACK_ADDR_FROM_TOP(num + 1), VALUE, num + 1);
|
vm_method_missing_args(th, argv, num, blockptr, opt);
|
||||||
argv[0] = ID2SYM(id);
|
argv[0] = ID2SYM(id);
|
||||||
th->method_missing_reason = opt;
|
return rb_funcall2(recv, idMethodMissing, num + 1, argv);
|
||||||
th->passed_block = blockptr;
|
|
||||||
POPN(num + 1);
|
|
||||||
val = rb_funcall2(recv, idMethodMissing, num + 1, argv);
|
|
||||||
return val;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
|
@ -581,17 +586,19 @@ vm_call_method(rb_thread_t * const th, rb_control_frame_t * const cfp,
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* method missing */
|
/* method missing */
|
||||||
|
int stat = 0;
|
||||||
|
if (flag & VM_CALL_VCALL_BIT) {
|
||||||
|
stat |= NOEX_VCALL;
|
||||||
|
}
|
||||||
|
if (flag & VM_CALL_SUPER_BIT) {
|
||||||
|
stat |= NOEX_SUPER;
|
||||||
|
}
|
||||||
if (id == idMethodMissing) {
|
if (id == idMethodMissing) {
|
||||||
rb_bug("method missing");
|
VALUE *argv = ALLOCA_N(VALUE, num);
|
||||||
|
vm_method_missing_args(th, argv, num - 1, 0, stat);
|
||||||
|
rb_raise_method_missing(th, num, argv, recv, stat);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
int stat = 0;
|
|
||||||
if (flag & VM_CALL_VCALL_BIT) {
|
|
||||||
stat |= NOEX_VCALL;
|
|
||||||
}
|
|
||||||
if (flag & VM_CALL_SUPER_BIT) {
|
|
||||||
stat |= NOEX_SUPER;
|
|
||||||
}
|
|
||||||
val = vm_method_missing(th, id, recv, num, blockptr, stat);
|
val = vm_method_missing(th, id, recv, num, blockptr, stat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue