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

ruby-changes:27015

From: ko1 <ko1@a...>
Date: Tue, 5 Feb 2013 15:07:40 +0900 (JST)
Subject: [ruby-changes:27015] ko1:r39067 (trunk): * proc.c (rb_binding_new_with_cfp): permit to create binding object

ko1	2013-02-05 15:04:59 +0900 (Tue, 05 Feb 2013)

  New Revision: 39067

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

  Log:
    * proc.c (rb_binding_new_with_cfp): permit to create binding object
      of IFUNC frame.
      When `rb_binding_new_with_cfp()' is called, VM finds out the first
      normal (has iseq) frame and create a binding object of this frame
      and create Env objects. `ep's of related frames are updated
      (`ep's point Env object managed spaces).
      However, `ep' of skipped IFUNC frame was not updated and
      old invalid `ep' was remained. It causes serious problems.
      To solve this issue, permit IFUNC to create binding.
      (Maybe there is no problem on it)
      [ruby-dev:46908] [ruby-trunk - Bug #7774]
    * test/ruby/test_settracefunc.rb: add a test.
    * vm.c (rb_vm_get_binding_creatable_next_cfp), vm_core.h: added.
    * vm_trace.c: fix to use `rb_vm_get_binding_creatable_next_cfp()'.

  Modified files:
    trunk/ChangeLog
    trunk/proc.c
    trunk/test/ruby/test_settracefunc.rb
    trunk/vm.c
    trunk/vm_core.h
    trunk/vm_trace.c

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 39066)
+++ ChangeLog	(revision 39067)
@@ -1,3 +1,23 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Tue Feb 05 15:04:34 2013  Koichi Sasada  <ko1@a...>
+
+	* proc.c (rb_binding_new_with_cfp): permit to create binding object
+	  of IFUNC frame.
+	  When `rb_binding_new_with_cfp()' is called, VM finds out the first
+	  normal (has iseq) frame and create a binding object of this frame
+	  and create Env objects. `ep's of related frames are updated
+	  (`ep's point Env object managed spaces).
+	  However, `ep' of skipped IFUNC frame was not updated and
+	  old invalid `ep' was remained. It causes serious problems.
+	  To solve this issue, permit IFUNC to create binding.
+	  (Maybe there is no problem on it)
+	  [ruby-dev:46908] [ruby-trunk - Bug #7774]
+
+	* test/ruby/test_settracefunc.rb: add a test.
+
+	* vm.c (rb_vm_get_binding_creatable_next_cfp), vm_core.h: added.
+
+	* vm_trace.c: fix to use `rb_vm_get_binding_creatable_next_cfp()'.
+
 Tue Feb  5 14:43:15 2013  Marc-Andre Lafortune  <ruby-core@m...>
 
 	* lib/matrix.rb: Fix error message, patch by pypypy [Bug #7777]
Index: vm_core.h
===================================================================
--- vm_core.h	(revision 39066)
+++ vm_core.h	(revision 39067)
@@ -843,6 +843,7 @@ void rb_thread_wakeup_timer_thread(void) https://github.com/ruby/ruby/blob/trunk/vm_core.h#L843
 int ruby_thread_has_gvl_p(void);
 typedef int rb_backtrace_iter_func(void *, VALUE, int, VALUE);
 rb_control_frame_t *rb_vm_get_ruby_level_next_cfp(rb_thread_t *th, const rb_control_frame_t *cfp);
+rb_control_frame_t *rb_vm_get_binding_creatable_next_cfp(rb_thread_t *th, const rb_control_frame_t *cfp); 
 int rb_vm_get_sourceline(const rb_control_frame_t *);
 VALUE rb_name_err_mesg_new(VALUE obj, VALUE mesg, VALUE recv, VALUE method);
 void rb_vm_stack_to_heap(rb_thread_t *th);
Index: proc.c
===================================================================
--- proc.c	(revision 39066)
+++ proc.c	(revision 39067)
@@ -313,19 +313,21 @@ binding_clone(VALUE self) https://github.com/ruby/ruby/blob/trunk/proc.c#L313
 VALUE
 rb_binding_new_with_cfp(rb_thread_t *th, const rb_control_frame_t *src_cfp)
 {
-    rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, src_cfp);
+    rb_control_frame_t *cfp = rb_vm_get_binding_creatable_next_cfp(th, src_cfp);
+    rb_control_frame_t *ruby_level_cfp = rb_vm_get_ruby_level_next_cfp(th, src_cfp);
     VALUE bindval;
     rb_binding_t *bind;
 
-    if (cfp == 0) {
+    if (cfp == 0 || ruby_level_cfp == 0) {
 	rb_raise(rb_eRuntimeError, "Can't create Binding Object on top of Fiber.");
     }
 
     bindval = binding_alloc(rb_cBinding);
     GetBindingPtr(bindval, bind);
     bind->env = rb_vm_make_env_object(th, cfp);
-    bind->path = cfp->iseq->location.path;
-    bind->first_lineno = rb_vm_get_sourceline(cfp);
+    bind->path = ruby_level_cfp->iseq->location.path;
+    bind->first_lineno = rb_vm_get_sourceline(ruby_level_cfp);
+
     return bindval;
 }
 
Index: vm_trace.c
===================================================================
--- vm_trace.c	(revision 39066)
+++ vm_trace.c	(revision 39067)
@@ -763,7 +763,8 @@ VALUE https://github.com/ruby/ruby/blob/trunk/vm_trace.c#L763
 rb_tracearg_binding(rb_trace_arg_t *trace_arg)
 {
     rb_control_frame_t *cfp;
-    cfp = rb_vm_get_ruby_level_next_cfp(trace_arg->th, trace_arg->cfp);
+    cfp = rb_vm_get_binding_creatable_next_cfp(trace_arg->th, trace_arg->cfp);
+
     if (cfp) {
 	return rb_binding_new_with_cfp(trace_arg->th, cfp);
     }
Index: vm.c
===================================================================
--- vm.c	(revision 39066)
+++ vm.c	(revision 39067)
@@ -186,6 +186,18 @@ vm_set_main_stack(rb_thread_t *th, VALUE https://github.com/ruby/ruby/blob/trunk/vm.c#L186
 }
 
 rb_control_frame_t *
+rb_vm_get_binding_creatable_next_cfp(rb_thread_t *th, const rb_control_frame_t *cfp)
+{
+    while (!RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(th, cfp)) {
+	if (cfp->iseq) {
+	    return (rb_control_frame_t *)cfp;
+	}
+	cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
+    }
+    return 0;
+}
+
+rb_control_frame_t *
 rb_vm_get_ruby_level_next_cfp(rb_thread_t *th, const rb_control_frame_t *cfp)
 {
     while (!RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(th, cfp)) {
Index: test/ruby/test_settracefunc.rb
===================================================================
--- test/ruby/test_settracefunc.rb	(revision 39066)
+++ test/ruby/test_settracefunc.rb	(revision 39067)
@@ -941,4 +941,22 @@ class TestSetTraceFunc < Test::Unit::Tes https://github.com/ruby/ruby/blob/trunk/test/ruby/test_settracefunc.rb#L941
     end
     assert_security_error_safe4(func)
   end
+
+  def test_trace_point_binding_in_ifunc
+    assert_normal_exit %q{
+      tp = TracePoint.new(:raise) do |tp|
+        tp.binding
+      end
+      tp.enable do
+        obj = Object.new
+        class << obj
+          include Enumerable
+          def each
+            yield 1
+          end
+        end
+        obj.zip({}) {}
+      end
+    }, '[ruby-dev:46908] [ruby-trunk - Bug #7774]'
+  end
 end

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

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