summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog9
-rw-r--r--ext/-test-/proc/call_super.c23
-rw-r--r--ext/-test-/proc/extconf.rb7
-rw-r--r--ext/-test-/proc/init.c11
-rw-r--r--vm.c3
-rw-r--r--vm_eval.c2
-rw-r--r--vm_insnhelper.c13
7 files changed, 61 insertions, 7 deletions
diff --git a/ChangeLog b/ChangeLog
index 1d5e195651..115da412b0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+Sun Nov 9 23:25:49 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * vm_eval.c (vm_call_super): allow bound proc method to call super
+ method.
+
+ * vm_insnhelper.c (vm_yield_with_cfunc): push defined class and
+ bound proc method entry to the control frame.
+
+
Sun Nov 9 22:46:13 2014 Tanaka Akira <akr@fsij.org>
* test/open-uri: Test server log in server thread.
diff --git a/ext/-test-/proc/call_super.c b/ext/-test-/proc/call_super.c
new file mode 100644
index 0000000000..c5cb3eb46a
--- /dev/null
+++ b/ext/-test-/proc/call_super.c
@@ -0,0 +1,23 @@
+#include "ruby.h"
+
+static VALUE
+bug_proc_call_super(VALUE yieldarg, VALUE procarg)
+{
+ VALUE args[2];
+ args[0] = yieldarg;
+ args[1] = procarg;
+ return rb_call_super(2, args);
+}
+
+static VALUE
+bug_proc_make_caller(VALUE self, VALUE procarg)
+{
+ return rb_proc_new(bug_proc_call_super, procarg);
+}
+
+void
+Init_call_super(VALUE klass)
+{
+ rb_define_method(klass, "call_super", bug_proc_call_super, 1);
+ rb_define_singleton_method(klass, "make_caller", bug_proc_make_caller, 1);
+}
diff --git a/ext/-test-/proc/extconf.rb b/ext/-test-/proc/extconf.rb
new file mode 100644
index 0000000000..40741d07cc
--- /dev/null
+++ b/ext/-test-/proc/extconf.rb
@@ -0,0 +1,7 @@
+$INCFLAGS << " -I$(topdir) -I$(top_srcdir)"
+$srcs = Dir[File.join($srcdir, "*.{#{SRC_EXT.join(%q{,})}}")]
+inits = $srcs.map {|s| File.basename(s, ".*")}
+inits.delete("init")
+inits.map! {|s|"X(#{s})"}
+$defs << "-DTEST_INIT_FUNCS(X)=\"#{inits.join(' ')}\""
+create_makefile("-test-/proc")
diff --git a/ext/-test-/proc/init.c b/ext/-test-/proc/init.c
new file mode 100644
index 0000000000..814c55d98b
--- /dev/null
+++ b/ext/-test-/proc/init.c
@@ -0,0 +1,11 @@
+#include "ruby.h"
+
+#define init(n) {void Init_##n(VALUE klass); Init_##n(klass);}
+
+void
+Init_proc(void)
+{
+ VALUE mBug = rb_define_module("Bug");
+ VALUE klass = rb_define_module_under(mBug, "Proc");
+ TEST_INIT_FUNCS(init);
+}
diff --git a/vm.c b/vm.c
index cb343236a4..017437b619 100644
--- a/vm.c
+++ b/vm.c
@@ -825,7 +825,8 @@ invoke_block_from_c(rb_thread_t *th, const rb_block_t *block,
return ret;
}
else {
- return vm_yield_with_cfunc(th, block, self, argc, argv, blockptr);
+ return vm_yield_with_cfunc(th, block, self, defined_class,
+ argc, argv, blockptr);
}
}
diff --git a/vm_eval.c b/vm_eval.c
index 14e5414f6d..a057ece390 100644
--- a/vm_eval.c
+++ b/vm_eval.c
@@ -265,7 +265,7 @@ vm_call_super(rb_thread_t *th, int argc, const VALUE *argv)
rb_method_entry_t *me;
rb_control_frame_t *cfp = th->cfp;
- if (cfp->iseq || NIL_P(cfp->klass)) {
+ if (RUBY_VM_NORMAL_ISEQ_P(cfp->iseq) || NIL_P(cfp->klass)) {
rb_bug("vm_call_super: should not be reached");
}
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index d67fd50db5..e442383a04 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -1969,7 +1969,8 @@ block_proc_is_lambda(const VALUE procval)
static inline VALUE
vm_yield_with_cfunc(rb_thread_t *th, const rb_block_t *block,
- VALUE self, int argc, const VALUE *argv,
+ VALUE self, VALUE defined_class,
+ int argc, const VALUE *argv,
const rb_block_t *blockargptr)
{
NODE *ifunc = (NODE *) block->iseq;
@@ -1998,9 +1999,10 @@ vm_yield_with_cfunc(rb_thread_t *th, const rb_block_t *block,
blockarg = Qnil;
}
- vm_push_frame(th, (rb_iseq_t *)ifunc, VM_FRAME_MAGIC_IFUNC, self,
- 0, VM_ENVVAL_PREV_EP_PTR(block->ep), 0,
- th->cfp->sp, 1, 0, 0);
+ vm_push_frame(th, (rb_iseq_t *)ifunc, VM_FRAME_MAGIC_IFUNC,
+ self, defined_class,
+ VM_ENVVAL_PREV_EP_PTR(block->ep), 0,
+ th->cfp->sp, 1, th->passed_bmethod_me, 0);
val = (*ifunc->nd_cfnc) (arg, ifunc->nd_tval, argc, argv, blockarg);
@@ -2065,7 +2067,8 @@ vm_invoke_block(rb_thread_t *th, rb_control_frame_t *reg_cfp, rb_call_info_t *ci
else {
VALUE val;
CALLER_SETUP_ARG(th->cfp, ci);
- val = vm_yield_with_cfunc(th, block, block->self, ci->argc, STACK_ADDR_FROM_TOP(ci->argc), 0);
+ val = vm_yield_with_cfunc(th, block, block->self, block->klass,
+ ci->argc, STACK_ADDR_FROM_TOP(ci->argc), 0);
POPN(ci->argc); /* TODO: should put before C/yield? */
return val;
}