summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog22
-rw-r--r--eval.c7
-rw-r--r--include/ruby/intern.h5
-rw-r--r--internal.h1
-rw-r--r--test/ruby/test_settracefunc.rb84
-rw-r--r--variable.c2
-rw-r--r--version.h6
-rw-r--r--vm.c18
-rw-r--r--vm_eval.c13
9 files changed, 139 insertions, 19 deletions
diff --git a/ChangeLog b/ChangeLog
index b3fc15e683..54f5a0eb93 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,25 @@
+Mon Jun 30 00:57:05 2014 Koichi Sasada <ko1@atdot.net>
+
+ * 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.
+
Sun Jun 29 01:34:06 2014 Tanaka Akira <akr@fsij.org>
* lib/webrick/utils.rb (create_listeners): Close socket objects.
diff --git a/eval.c b/eval.c
index c077f79ecd..e58496ecce 100644
--- a/eval.c
+++ b/eval.c
@@ -978,13 +978,6 @@ prev_frame_func(void)
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
diff --git a/include/ruby/intern.h b/include/ruby/intern.h
index 6200e77a63..46af270bb3 100644
--- a/include/ruby/intern.h
+++ b/include/ruby/intern.h
@@ -939,11 +939,14 @@ VALUE rb_mod_remove_cvar(VALUE, VALUE);
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)
diff --git a/internal.h b/internal.h
index 9e48c13906..af8e69517c 100644
--- a/internal.h
+++ b/internal.h
@@ -766,6 +766,7 @@ void rb_vm_inc_const_missing_count(void);
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);
diff --git a/test/ruby/test_settracefunc.rb b/test/ruby/test_settracefunc.rb
index 1fca312c76..79f315edd5 100644
--- a/test/ruby/test_settracefunc.rb
+++ b/test/ruby/test_settracefunc.rb
@@ -1066,6 +1066,90 @@ class TestSetTraceFunc < Test::Unit::TestCase
: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
+
class C9759
define_method(:foo){
raise
diff --git a/variable.c b/variable.c
index e53dc8207f..e0d0eded82 100644
--- a/variable.c
+++ b/variable.c
@@ -1518,7 +1518,7 @@ const_missing(VALUE klass, ID id)
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;
diff --git a/version.h b/version.h
index 22d26c2689..95226f7b26 100644
--- a/version.h
+++ b/version.h
@@ -1,10 +1,10 @@
#define RUBY_VERSION "2.1.2"
-#define RUBY_RELEASE_DATE "2014-06-29"
-#define RUBY_PATCHLEVEL 145
+#define RUBY_RELEASE_DATE "2014-06-30"
+#define RUBY_PATCHLEVEL 146
#define RUBY_RELEASE_YEAR 2014
#define RUBY_RELEASE_MONTH 6
-#define RUBY_RELEASE_DAY 29
+#define RUBY_RELEASE_DAY 30
#include "ruby/version.h"
diff --git a/vm.c b/vm.c
index 99acce2fad..2109e8f197 100644
--- a/vm.c
+++ b/vm.c
@@ -277,6 +277,24 @@ vm_get_ruby_level_caller_cfp(rb_thread_t *th, rb_control_frame_t *cfp)
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
diff --git a/vm_eval.c b/vm_eval.c
index 7382b198a7..87d99d096c 100644
--- a/vm_eval.c
+++ b/vm_eval.c
@@ -686,7 +686,7 @@ raise_method_missing(rb_thread_t *th, int argc, const VALUE *argv, VALUE obj,
{
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);
}
@@ -1094,13 +1094,12 @@ rb_iterate(VALUE (* it_proc) (VALUE), VALUE data1,
#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{