summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog16
-rw-r--r--test/ruby/test_settracefunc.rb34
-rw-r--r--vm.c33
-rw-r--r--vm_core.h10
-rw-r--r--vm_insnhelper.c2
5 files changed, 82 insertions, 13 deletions
diff --git a/ChangeLog b/ChangeLog
index 48ac50f271..7c315cc403 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+Wed Apr 30 17:58:40 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: renmae 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.
+
Wed Apr 30 17:06:49 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
* parse.y (rb_id_attrset): pin down dynamic symbol only. it is
diff --git a/test/ruby/test_settracefunc.rb b/test/ruby/test_settracefunc.rb
index 70a2be6a50..8164d60ce1 100644
--- a/test/ruby/test_settracefunc.rb
+++ b/test/ruby/test_settracefunc.rb
@@ -1156,4 +1156,38 @@ class TestSetTraceFunc < Test::Unit::TestCase
], events, bug59398)
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/vm.c b/vm.c
index 1742cc5008..82bf75bc44 100644
--- a/vm.c
+++ b/vm.c
@@ -737,13 +737,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) ? splattable+1 : 0);
- 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;
@@ -1536,7 +1547,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 b1b9cadf98..c436b55b4d 100644
--- a/vm_core.h
+++ b/vm_core.h
@@ -521,7 +521,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;
@@ -749,9 +749,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 dc752e7963..a9cb971fe6 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -1619,7 +1619,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);