summaryrefslogtreecommitdiffstats
path: root/vm_insnhelper.c
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2009-02-22 01:43:59 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2009-02-22 01:43:59 +0000
commitfb1991448459be553b9140a80eb8c8c149b89464 (patch)
tree45adc1914ed6ec3198dbc48b7a7d91c57f531ac0 /vm_insnhelper.c
parentd9f134e16fe95500ef072985c4e582c3d253122a (diff)
downloadruby-fb1991448459be553b9140a80eb8c8c149b89464.tar.gz
ruby-fb1991448459be553b9140a80eb8c8c149b89464.tar.xz
ruby-fb1991448459be553b9140a80eb8c8c149b89464.zip
* 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: http://svn.ruby-lang.org/repos/ruby/trunk@22494 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'vm_insnhelper.c')
-rw-r--r--vm_insnhelper.c37
1 files changed, 22 insertions, 15 deletions
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index 0e54dddc5..ffb36e9a0 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -403,20 +403,25 @@ vm_call_bmethod(rb_thread_t *th, ID id, VALUE procval, VALUE recv,
return val;
}
-static inline VALUE
-vm_method_missing(rb_thread_t *th, ID id, VALUE recv,
+static inline void
+vm_method_missing_args(rb_thread_t *th, VALUE *argv,
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);
MEMCPY(argv, STACK_ADDR_FROM_TOP(num + 1), VALUE, num + 1);
- argv[0] = ID2SYM(id);
th->method_missing_reason = opt;
th->passed_block = blockptr;
POPN(num + 1);
- val = rb_funcall2(recv, idMethodMissing, num + 1, argv);
- return val;
+}
+
+static inline VALUE
+vm_method_missing(rb_thread_t *th, ID id, VALUE recv,
+ int num, rb_block_t *blockptr, int opt)
+{
+ VALUE *argv = ALLOCA_N(VALUE, num + 1);
+ vm_method_missing_args(th, argv, num, blockptr, opt);
+ argv[0] = ID2SYM(id);
+ return rb_funcall2(recv, idMethodMissing, num + 1, argv);
}
static inline void
@@ -581,17 +586,19 @@ vm_call_method(rb_thread_t * const th, rb_control_frame_t * const cfp,
}
else {
/* 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) {
- 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 {
- 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);
}
}