[前][次][番号順一覧][スレッド一覧]

ruby-changes:33677

From: ko1 <ko1@a...>
Date: Wed, 30 Apr 2014 18:08:18 +0900 (JST)
Subject: [ruby-changes:33677] ko1:r45758 (trunk): * vm.c (invoke_block_from_c): add VM_FRAME_FLAG_BMETHOD to record

ko1	2014-04-30 18:08:10 +0900 (Wed, 30 Apr 2014)

  New Revision: 45758

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=45758

  Log:
    * 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.

  Modified files:
    trunk/ChangeLog
    trunk/test/ruby/test_settracefunc.rb
    trunk/vm.c
    trunk/vm_core.h
    trunk/vm_insnhelper.c
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 45757)
+++ ChangeLog	(revision 45758)
@@ -1,3 +1,19 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Wed Apr 30 17:58:40 2014  Koichi Sasada  <ko1@a...>
+
+	* 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@r...>
 
 	* parse.y (rb_id_attrset): pin down dynamic symbol only. it is
Index: vm_core.h
===================================================================
--- vm_core.h	(revision 45757)
+++ vm_core.h	(revision 45758)
@@ -521,7 +521,7 @@ typedef struct rb_thread_struct { https://github.com/ruby/ruby/blob/trunk/vm_core.h#L521
     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 { https://github.com/ruby/ruby/blob/trunk/vm_core.h#L749
 #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)
Index: vm.c
===================================================================
--- vm.c	(revision 45757)
+++ vm.c	(revision 45758)
@@ -737,13 +737,24 @@ invoke_block_from_c(rb_thread_t *th, con https://github.com/ruby/ruby/blob/trunk/vm.c#L737
 	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) https://github.com/ruby/ruby/blob/trunk/vm.c#L1547
 		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);
Index: vm_insnhelper.c
===================================================================
--- vm_insnhelper.c	(revision 45757)
+++ vm_insnhelper.c	(revision 45758)
@@ -1619,7 +1619,7 @@ vm_call_bmethod_body(rb_thread_t *th, rb https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L1619
     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);
 
Index: test/ruby/test_settracefunc.rb
===================================================================
--- test/ruby/test_settracefunc.rb	(revision 45757)
+++ test/ruby/test_settracefunc.rb	(revision 45758)
@@ -1156,4 +1156,38 @@ class TestSetTraceFunc < Test::Unit::Tes https://github.com/ruby/ruby/blob/trunk/test/ruby/test_settracefunc.rb#L1156
     ], 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

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]