ruby-changes:32456
From: ko1 <ko1@a...>
Date: Thu, 9 Jan 2014 19:13:10 +0900 (JST)
Subject: [ruby-changes:32456] ko1:r44535 (trunk): * vm.c (rb_vm_pop_cfunc_frame): added. It cares c_return event.
ko1 2014-01-09 19:12:59 +0900 (Thu, 09 Jan 2014) New Revision: 44535 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=44535 Log: * vm.c (rb_vm_pop_cfunc_frame): added. It cares c_return event. The patch base by drkaes (Stefan Kaes). [Bug #9321] * variable.c (rb_mod_const_missing): use rb_vm_pop_cfunc_frame() instead of rb_frame_pop(). * vm_eval.c (raise_method_missing): ditto. * vm_eval.c (rb_iterate): ditto. * internal.h (rb_vm_pop_cfunc_frame): add decl. * test/ruby/test_settracefunc.rb: add tests. provided by drkaes (Stefan Kaes). * vm.c, eval.c, include/ruby/intern.h (rb_frame_pop): move definition of rb_frame_pop() and deprecate it. It doesn't care about `return' events. Modified files: trunk/ChangeLog trunk/eval.c trunk/include/ruby/intern.h trunk/internal.h trunk/test/ruby/test_settracefunc.rb trunk/variable.c trunk/vm.c trunk/vm_eval.c Index: include/ruby/intern.h =================================================================== --- include/ruby/intern.h (revision 44534) +++ include/ruby/intern.h (revision 44535) @@ -939,11 +939,14 @@ VALUE rb_mod_remove_cvar(VALUE, VALUE); https://github.com/ruby/ruby/blob/trunk/include/ruby/intern.h#L939 ID rb_frame_callee(void); VALUE rb_str_succ(VALUE); VALUE rb_time_succ(VALUE); -void rb_frame_pop(void); int rb_frame_method_id_and_class(ID *idp, VALUE *klassp); VALUE rb_make_backtrace(void); VALUE rb_make_exception(int, VALUE*); +/* deprecated */ +DEPRECATED(void rb_frame_pop(void)); + + RUBY_SYMBOL_EXPORT_END #if defined(__cplusplus) Index: ChangeLog =================================================================== --- ChangeLog (revision 44534) +++ ChangeLog (revision 44535) @@ -1,3 +1,25 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Thu Jan 9 19:12:37 2014 Koichi Sasada <ko1@a...> + + * vm.c (rb_vm_pop_cfunc_frame): added. It cares c_return event. + The patch base by drkaes (Stefan Kaes). + [Bug #9321] + + * variable.c (rb_mod_const_missing): use rb_vm_pop_cfunc_frame() + instead of rb_frame_pop(). + + * vm_eval.c (raise_method_missing): ditto. + + * vm_eval.c (rb_iterate): ditto. + + * internal.h (rb_vm_pop_cfunc_frame): add decl. + + * test/ruby/test_settracefunc.rb: add tests. + provided by drkaes (Stefan Kaes). + + * vm.c, eval.c, include/ruby/intern.h (rb_frame_pop): + move definition of rb_frame_pop() and deprecate it. + It doesn't care about `return' events. + Thu Jan 9 17:40:28 2014 NAKAMURA Usaku <usa@r...> * hash.c (rb_any_hash): should treat the return value of rb_objid_hash() Index: variable.c =================================================================== --- variable.c (revision 44534) +++ variable.c (revision 44535) @@ -1518,7 +1518,7 @@ const_missing(VALUE klass, ID id) https://github.com/ruby/ruby/blob/trunk/variable.c#L1518 VALUE rb_mod_const_missing(VALUE klass, VALUE name) { - rb_frame_pop(); /* pop frame for "const_missing" */ + rb_vm_pop_cfunc_frame(); uninitialized_constant(klass, rb_to_id(name)); UNREACHABLE; Index: vm_eval.c =================================================================== --- vm_eval.c (revision 44534) +++ vm_eval.c (revision 44535) @@ -686,7 +686,7 @@ raise_method_missing(rb_thread_t *th, in https://github.com/ruby/ruby/blob/trunk/vm_eval.c#L686 { exc = make_no_method_exception(exc, format, obj, argc, argv); if (!(last_call_status & NOEX_MISSING)) { - th->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp); + rb_vm_pop_cfunc_frame(); } rb_exc_raise(exc); } @@ -1087,13 +1087,12 @@ rb_iterate(VALUE (* it_proc) (VALUE), VA https://github.com/ruby/ruby/blob/trunk/vm_eval.c#L1087 #if VMDEBUG printf("skipped frame: %s\n", vm_frametype_name(th->cfp)); #endif - if (UNLIKELY(VM_FRAME_TYPE(th->cfp) == VM_FRAME_MAGIC_CFUNC)) { - const rb_method_entry_t *me = th->cfp->me; - EXEC_EVENT_HOOK(th, RUBY_EVENT_C_RETURN, th->cfp->self, me->called_id, me->klass, Qnil); - RUBY_DTRACE_CMETHOD_RETURN_HOOK(th, me->klass, me->called_id); + if (VM_FRAME_TYPE(th->cfp) != VM_FRAME_MAGIC_CFUNC) { + vm_pop_frame(th); + } + else { /* unlikely path */ + rb_vm_pop_cfunc_frame(); } - - th->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp); } } else{ Index: eval.c =================================================================== --- eval.c (revision 44534) +++ eval.c (revision 44535) @@ -1010,13 +1010,6 @@ prev_frame_func(void) https://github.com/ruby/ruby/blob/trunk/eval.c#L1010 return frame_func_id(prev_cfp); } -void -rb_frame_pop(void) -{ - rb_thread_t *th = GET_THREAD(); - th->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp); -} - /* * call-seq: * append_features(mod) -> mod Index: internal.h =================================================================== --- internal.h (revision 44534) +++ internal.h (revision 44535) @@ -764,6 +764,7 @@ void rb_vm_inc_const_missing_count(void) https://github.com/ruby/ruby/blob/trunk/internal.h#L764 void rb_thread_mark(void *th); const void **rb_vm_get_insns_address_table(void); VALUE rb_sourcefilename(void); +void rb_vm_pop_cfunc_frame(void); /* vm_dump.c */ void rb_vm_bugreport(void); Index: vm.c =================================================================== --- vm.c (revision 44534) +++ vm.c (revision 44535) @@ -277,6 +277,24 @@ vm_get_ruby_level_caller_cfp(rb_thread_t https://github.com/ruby/ruby/blob/trunk/vm.c#L277 return 0; } +void +rb_vm_pop_cfunc_frame(void) +{ + rb_thread_t *th = GET_THREAD(); + const rb_method_entry_t *me = th->cfp->me; + EXEC_EVENT_HOOK(th, RUBY_EVENT_C_RETURN, th->cfp->self, me->called_id, me->klass, Qnil); + RUBY_DTRACE_CMETHOD_RETURN_HOOK(th, me->klass, me->called_id); + vm_pop_frame(th); +} + +/* obsolete */ +void +rb_frame_pop(void) +{ + rb_thread_t *th = GET_THREAD(); + vm_pop_frame(th); +} + /* at exit */ void Index: test/ruby/test_settracefunc.rb =================================================================== --- test/ruby/test_settracefunc.rb (revision 44534) +++ test/ruby/test_settracefunc.rb (revision 44535) @@ -1066,4 +1066,88 @@ class TestSetTraceFunc < Test::Unit::Tes https://github.com/ruby/ruby/blob/trunk/test/ruby/test_settracefunc.rb#L1066 :b_return ], events) end + + def test_const_missing + bug59398 = '[ruby-core:59398]' + events = [] + assert !defined?(MISSING_CONSTANT_59398) + TracePoint.new(:c_call, :c_return, :call, :return){|tp| + next unless tp.defined_class == Module + # rake/ext/module.rb aliases :const_missing and Ruby uses the aliased name + # but this only happens when running the full test suite + events << [tp.event,tp.method_id] if tp.method_id == :const_missing || tp.method_id == :rake_original_const_missing + }.enable{ + MISSING_CONSTANT_59398 rescue nil + } + if events.map{|e|e[1]}.include?(:rake_original_const_missing) + assert_equal([ + [:call, :const_missing], + [:c_call, :rake_original_const_missing], + [:c_return, :rake_original_const_missing], + [:return, :const_missing], + ], events, bug59398) + else + assert_equal([ + [:c_call, :const_missing], + [:c_return, :const_missing] + ], events, bug59398) + end + end + + class AliasedRubyMethod + def foo; 1; end; + alias bar foo + end + def test_aliased_ruby_method + events = [] + aliased = AliasedRubyMethod.new + TracePoint.new(:call, :return){|tp| + events << [tp.event, tp.method_id] + }.enable{ + aliased.bar + } + assert_equal([ + [:call, :foo], + [:return, :foo] + ], events, "should use original method name for tracing ruby methods") + end + class AliasedCMethod < Hash + alias original_size size + def size; original_size; end + end + + def test_aliased_c_method + events = [] + aliased = AliasedCMethod.new + TracePoint.new(:call, :return, :c_call, :c_return){|tp| + events << [tp.event, tp.method_id] + }.enable{ + aliased.size + } + assert_equal([ + [:call, :size], + [:c_call, :original_size], + [:c_return, :original_size], + [:return, :size] + ], events, "should use alias method name for tracing c methods") + end + + def test_method_missing + bug59398 = '[ruby-core:59398]' + events = [] + assert !respond_to?(:missing_method_59398) + TracePoint.new(:c_call, :c_return, :call, :return){|tp| + next unless tp.defined_class == BasicObject + # rake/ext/module.rb aliases :const_missing and Ruby uses the aliased name + # but this only happens when running the full test suite + events << [tp.event,tp.method_id] if tp.method_id == :method_missing + }.enable{ + missing_method_59398 rescue nil + } + assert_equal([ + [:c_call, :method_missing], + [:c_return, :method_missing] + ], events, bug59398) + end + end -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/