summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog16
-rw-r--r--test/ruby/test_settracefunc.rb34
-rw-r--r--version.h2
-rw-r--r--vm.c33
-rw-r--r--vm_core.h10
-rw-r--r--vm_insnhelper.c2
6 files changed, 83 insertions, 14 deletions
diff --git a/ChangeLog b/ChangeLog
index a73f739cd2..0d64bd143e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+Mon May 12 22:22:43 2014 Koichi Sasada <ko1@atdot.net>
+
+ * vm.c (invoke_block_from_c): add VM_FRAME_FLAG_BMETHOD to record
+ it is bmethod frame.
+
+ * vm.c (vm_exec): invoke RUBY_EVENT_RETURN event if rollbacked frame
+ is VM_FRAME_FLAG_BMETHOD.
+ [Bug #9759]
+
+ * test/ruby/test_settracefunc.rb: add a test for TracePoint/set_trace_func.
+
+ * vm_core.h: rename rb_thread_t::passed_me to
+ rb_thread_t::passed_bmethod_me to clarify the usage.
+
+ * vm_insnhelper.c (vm_call_bmethod_body): use renamed member.
+
Mon May 12 22:11:47 2014 Shota Fukumori <her@sorah.jp>
* vm_eval.c (eval_string_with_cref): Unify to use NIL_P.
diff --git a/test/ruby/test_settracefunc.rb b/test/ruby/test_settracefunc.rb
index b106ea5494..1fca312c76 100644
--- a/test/ruby/test_settracefunc.rb
+++ b/test/ruby/test_settracefunc.rb
@@ -1066,4 +1066,38 @@ class TestSetTraceFunc < Test::Unit::TestCase
:b_return
], events)
end
+ class C9759
+ define_method(:foo){
+ raise
+ }
+ end
+
+ def test_define_method_on_exception
+ events = []
+ obj = C9759.new
+ TracePoint.new(:call, :return){|tp|
+ next unless target_thread?
+ events << [tp.event, tp.method_id]
+ }.enable{
+ obj.foo rescue nil
+ }
+ assert_equal([[:call, :foo], [:return, :foo]], events, 'Bug #9759')
+
+ events = []
+ begin
+ set_trace_func(lambda{|event, file, lineno, mid, binding, klass|
+ next unless target_thread?
+ case event
+ when 'call', 'return'
+ events << [event, mid]
+ end
+ })
+ obj.foo rescue nil
+ set_trace_func(nil)
+
+ assert_equal([['call', :foo], ['return', :foo]], events, 'Bug #9759')
+ ensure
+ end
+
+ end
end
diff --git a/version.h b/version.h
index 576a550a88..1b6ce0375f 100644
--- a/version.h
+++ b/version.h
@@ -1,6 +1,6 @@
#define RUBY_VERSION "2.1.2"
#define RUBY_RELEASE_DATE "2014-05-12"
-#define RUBY_PATCHLEVEL 98
+#define RUBY_PATCHLEVEL 99
#define RUBY_RELEASE_YEAR 2014
#define RUBY_RELEASE_MONTH 5
diff --git a/vm.c b/vm.c
index 947b1811e5..8e40b9f4a6 100644
--- a/vm.c
+++ b/vm.c
@@ -717,13 +717,24 @@ invoke_block_from_c(rb_thread_t *th, const rb_block_t *block,
opt_pc = vm_yield_setup_args(th, iseq, argc, cfp->sp, blockptr,
type == VM_FRAME_MAGIC_LAMBDA);
- vm_push_frame(th, iseq, type | VM_FRAME_FLAG_FINISH,
- self, defined_class,
- VM_ENVVAL_PREV_EP_PTR(block->ep),
- iseq->iseq_encoded + opt_pc,
- cfp->sp + arg_size, iseq->local_size - arg_size,
- th->passed_me, iseq->stack_max);
- th->passed_me = 0;
+ if (th->passed_bmethod_me != 0) {
+ /* bmethod */
+ vm_push_frame(th, iseq, type | VM_FRAME_FLAG_FINISH | VM_FRAME_FLAG_BMETHOD,
+ self, defined_class,
+ VM_ENVVAL_PREV_EP_PTR(block->ep),
+ iseq->iseq_encoded + opt_pc,
+ cfp->sp + arg_size, iseq->local_size - arg_size,
+ th->passed_bmethod_me, iseq->stack_max);
+ th->passed_bmethod_me = 0;
+ }
+ else {
+ vm_push_frame(th, iseq, type | VM_FRAME_FLAG_FINISH,
+ self, defined_class,
+ VM_ENVVAL_PREV_EP_PTR(block->ep),
+ iseq->iseq_encoded + opt_pc,
+ cfp->sp + arg_size, iseq->local_size - arg_size,
+ 0, iseq->stack_max);
+ }
if (cref) {
th->cfp->ep[-1] = (VALUE)cref;
@@ -1512,7 +1523,13 @@ vm_exec(rb_thread_t *th)
break;
case VM_FRAME_MAGIC_BLOCK:
case VM_FRAME_MAGIC_LAMBDA:
- EXEC_EVENT_HOOK_AND_POP_FRAME(th, RUBY_EVENT_B_RETURN, th->cfp->self, 0, 0, Qnil);
+ if (VM_FRAME_TYPE_BMETHOD_P(th->cfp)) {
+ EXEC_EVENT_HOOK(th, RUBY_EVENT_B_RETURN, th->cfp->self, 0, 0, Qnil);
+ EXEC_EVENT_HOOK_AND_POP_FRAME(th, RUBY_EVENT_RETURN, th->cfp->self, th->cfp->me->called_id, th->cfp->me->klass, Qnil);
+ }
+ else {
+ EXEC_EVENT_HOOK_AND_POP_FRAME(th, RUBY_EVENT_B_RETURN, th->cfp->self, 0, 0, Qnil);
+ }
break;
case VM_FRAME_MAGIC_CLASS:
EXEC_EVENT_HOOK_AND_POP_FRAME(th, RUBY_EVENT_END, th->cfp->self, 0, 0, Qnil);
diff --git a/vm_core.h b/vm_core.h
index 08a09da610..befdbfdc26 100644
--- a/vm_core.h
+++ b/vm_core.h
@@ -542,7 +542,7 @@ typedef struct rb_thread_struct {
const rb_block_t *passed_block;
/* for bmethod */
- const rb_method_entry_t *passed_me;
+ const rb_method_entry_t *passed_bmethod_me;
/* for cfunc */
rb_call_info_t *passed_ci;
@@ -768,9 +768,11 @@ enum vm_special_object_type {
#define VM_FRAME_TYPE(cfp) ((cfp)->flag & VM_FRAME_MAGIC_MASK)
/* other frame flag */
-#define VM_FRAME_FLAG_PASSED 0x0100
-#define VM_FRAME_FLAG_FINISH 0x0200
-#define VM_FRAME_TYPE_FINISH_P(cfp) (((cfp)->flag & VM_FRAME_FLAG_FINISH) != 0)
+#define VM_FRAME_FLAG_PASSED 0x0100
+#define VM_FRAME_FLAG_FINISH 0x0200
+#define VM_FRAME_FLAG_BMETHOD 0x0400
+#define VM_FRAME_TYPE_FINISH_P(cfp) (((cfp)->flag & VM_FRAME_FLAG_FINISH) != 0)
+#define VM_FRAME_TYPE_BMETHOD_P(cfp) (((cfp)->flag & VM_FRAME_FLAG_BMETHOD) != 0)
#define RUBYVM_CFUNC_FRAME_P(cfp) \
(VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_CFUNC)
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index 1228b3f4df..55c0515425 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -1587,7 +1587,7 @@ vm_call_bmethod_body(rb_thread_t *th, rb_call_info_t *ci, const VALUE *argv)
EXEC_EVENT_HOOK(th, RUBY_EVENT_CALL, ci->recv, ci->me->called_id, ci->me->klass, Qnil);
/* control block frame */
- th->passed_me = ci->me;
+ th->passed_bmethod_me = ci->me;
GetProcPtr(ci->me->def->body.proc, proc);
val = vm_invoke_proc(th, proc, ci->recv, ci->defined_class, ci->argc, argv, ci->blockptr);