diff options
-rw-r--r-- | ChangeLog | 20 | ||||
-rw-r--r-- | proc.c | 10 | ||||
-rw-r--r-- | test/ruby/test_settracefunc.rb | 18 | ||||
-rw-r--r-- | vm.c | 12 | ||||
-rw-r--r-- | vm_core.h | 1 | ||||
-rw-r--r-- | vm_trace.c | 3 |
6 files changed, 59 insertions, 5 deletions
@@ -1,3 +1,23 @@ +Tue Feb 05 15:04:34 2013 Koichi Sasada <ko1@atdot.net> + + * 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@marc-andre.ca> * lib/matrix.rb: Fix error message, patch by pypypy [Bug #7777] @@ -313,19 +313,21 @@ binding_clone(VALUE self) 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; } diff --git a/test/ruby/test_settracefunc.rb b/test/ruby/test_settracefunc.rb index b0c6f2bcca..cfb06010ef 100644 --- a/test/ruby/test_settracefunc.rb +++ b/test/ruby/test_settracefunc.rb @@ -941,4 +941,22 @@ class TestSetTraceFunc < Test::Unit::TestCase 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 @@ -186,6 +186,18 @@ vm_set_main_stack(rb_thread_t *th, VALUE iseqval) } 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)) { @@ -843,6 +843,7 @@ void rb_thread_wakeup_timer_thread(void); 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); diff --git a/vm_trace.c b/vm_trace.c index 93e6212909..79d3731dc1 100644 --- a/vm_trace.c +++ b/vm_trace.c @@ -763,7 +763,8 @@ VALUE 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); } |