summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorusa <usa@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2014-08-31 08:14:15 +0000
committerusa <usa@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2014-08-31 08:14:15 +0000
commitb10c3b6d51d7fb0597670d88a537d713b445098e (patch)
treeeac8836aaeea3d68ea97e76d1ec8b8db87423dd6
parent3ed06c80eb01000bc293c5cd88a09e92a3c15904 (diff)
merge revision(s) 46465,46469,46484: [Backport #9961]
* vm.c (rb_vm_rewind_cfp): add new function to rewind specified cfp with invoking RUBY_EVENT_C_RETURN. [Bug #9961] * vm_core.h: ditto. * eval.c (rb_protect): use it. * eval.c (rb_rescue2): ditto. * vm_eval.c (rb_iterate): ditto. * test/ruby/test_settracefunc.rb: add a test. * vm_core.h (rb_name_err_mesg_new): * vm_eval.c (rb_catch_protect): fix same problem of [Bug #9961]. * vm_eval.c (rb_iterate): ditto. * vm_core.h (rb_vm_rewind_cfp): add the prototype declaration. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_2_0_0@47342 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog24
-rw-r--r--eval.c4
-rw-r--r--test/ruby/test_settracefunc.rb51
-rw-r--r--version.h2
-rw-r--r--vm.c17
-rw-r--r--vm_core.h1
-rw-r--r--vm_eval.c18
7 files changed, 100 insertions, 17 deletions
diff --git a/ChangeLog b/ChangeLog
index e30e63491a..0d5b79f0fc 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,27 @@
+Sun Aug 31 16:59:45 2014 Koichi Sasada <ko1@atdot.net>
+
+ * vm_eval.c (rb_catch_protect): fix same problem of [Bug #9961].
+
+ * vm_eval.c (rb_iterate): ditto.
+
+Sun Aug 31 16:59:45 2014 Koichi Sasada <ko1@atdot.net>
+
+ * vm.c (rb_vm_rewind_cfp): add new function to rewind specified cfp
+ with invoking RUBY_EVENT_C_RETURN.
+ [Bug #9961]
+
+ * vm_core.h: ditto.
+
+ * eval.c (rb_protect): use it.
+
+ * eval.c (rb_rescue2): ditto.
+
+ * vm_eval.c (rb_iterate): ditto.
+
+ * test/ruby/test_settracefunc.rb: add a test.
+
+ * vm_core.h (rb_name_err_mesg_new):
+
Sun Aug 31 16:50:06 2014 Koichi Sasada <ko1@atdot.net>
* compile.c (rb_iseq_compile_node): put start label of block after
diff --git a/eval.c b/eval.c
index c682a8358d..ec563bc4f7 100644
--- a/eval.c
+++ b/eval.c
@@ -714,7 +714,7 @@ rb_rescue2(VALUE (* b_proc) (ANYARGS), VALUE data1,
result = (*b_proc) (data1);
}
else {
- th->cfp = cfp; /* restore */
+ rb_vm_rewind_cfp(th, cfp);
if (state == TAG_RAISE) {
int handle = FALSE;
@@ -793,7 +793,7 @@ rb_protect(VALUE (* proc) (VALUE), VALUE data, int * state)
*state = status;
}
if (status != 0) {
- th->cfp = cfp;
+ rb_vm_rewind_cfp(th, cfp);
return Qnil;
}
diff --git a/test/ruby/test_settracefunc.rb b/test/ruby/test_settracefunc.rb
index 831923c358..5e9cafcfba 100644
--- a/test/ruby/test_settracefunc.rb
+++ b/test/ruby/test_settracefunc.rb
@@ -1184,6 +1184,57 @@ class TestSetTraceFunc < Test::Unit::TestCase
assert_equal call_events, return_events.reverse, message
end
+ def test_rb_rescue
+ events = []
+ curr_thread = Thread.current
+ TracePoint.new(:b_call, :b_return, :c_call, :c_return){|tp|
+ next if curr_thread != Thread.current
+ events << [tp.event, tp.method_id]
+ }.enable do
+ begin
+ -Numeric.new
+ rescue => e
+ # ignore
+ end
+ end
+
+ assert_equal [
+ [:b_call, :test_rb_rescue],
+ [:c_call, :new],
+ [:c_call, :initialize],
+ [:c_return, :initialize],
+ [:c_return, :new],
+ [:c_call, :-@],
+ [:c_call, :coerce],
+ [:c_call, :to_s],
+ [:c_return, :to_s],
+ [:c_call, :new],
+ [:c_call, :initialize],
+ [:c_return, :initialize],
+ [:c_return, :new],
+ [:c_call, :exception],
+ [:c_return, :exception],
+ [:c_call, :backtrace],
+ [:c_return, :backtrace],
+ [:c_return, :coerce], # don't miss it!
+ [:c_call, :to_s],
+ [:c_return, :to_s],
+ [:c_call, :to_s],
+ [:c_return, :to_s],
+ [:c_call, :new],
+ [:c_call, :initialize],
+ [:c_return, :initialize],
+ [:c_return, :new],
+ [:c_call, :exception],
+ [:c_return, :exception],
+ [:c_call, :backtrace],
+ [:c_return, :backtrace],
+ [:c_return, :-@],
+ [:c_call, :===],
+ [:c_return, :===],
+ [:b_return, :test_rb_rescue]], events
+ end
+
def test_b_call_with_redo
assert_consistent_call_return do
i = 0
diff --git a/version.h b/version.h
index 5afa5db401..1700289be7 100644
--- a/version.h
+++ b/version.h
@@ -1,6 +1,6 @@
#define RUBY_VERSION "2.0.0"
#define RUBY_RELEASE_DATE "2014-08-31"
-#define RUBY_PATCHLEVEL 541
+#define RUBY_PATCHLEVEL 542
#define RUBY_RELEASE_YEAR 2014
#define RUBY_RELEASE_MONTH 8
diff --git a/vm.c b/vm.c
index d960520d5d..34e8daa3f7 100644
--- a/vm.c
+++ b/vm.c
@@ -241,6 +241,23 @@ rb_vm_pop_cfunc_frame(void)
vm_pop_frame(th);
}
+void
+rb_vm_rewind_cfp(rb_thread_t *th, rb_control_frame_t *cfp)
+{
+ /* check skipped frame */
+ while (th->cfp != cfp) {
+#if VMDEBUG
+ printf("skipped frame: %s\n", vm_frametype_name(th->cfp));
+#endif
+ if (VM_FRAME_TYPE(th->cfp) != VM_FRAME_MAGIC_CFUNC) {
+ vm_pop_frame(th);
+ }
+ else { /* unlikely path */
+ rb_vm_pop_cfunc_frame();
+ }
+ }
+}
+
/* obsolete */
void
rb_frame_pop(void)
diff --git a/vm_core.h b/vm_core.h
index 3457773494..2bb69b668f 100644
--- a/vm_core.h
+++ b/vm_core.h
@@ -854,6 +854,7 @@ VALUE rb_name_err_mesg_new(VALUE obj, VALUE mesg, VALUE recv, VALUE method);
void rb_vm_stack_to_heap(rb_thread_t *th);
void ruby_thread_init_stack(rb_thread_t *th);
int rb_vm_control_frame_id_and_class(const rb_control_frame_t *cfp, ID *idp, VALUE *klassp);
+void rb_vm_rewind_cfp(rb_thread_t *th, rb_control_frame_t *cfp);
void rb_gc_mark_machine_stack(rb_thread_t *th);
diff --git a/vm_eval.c b/vm_eval.c
index da2b094bf0..dff323f105 100644
--- a/vm_eval.c
+++ b/vm_eval.c
@@ -1068,18 +1068,7 @@ rb_iterate(VALUE (* it_proc) (VALUE), VALUE data1,
th->errinfo = Qnil;
retval = GET_THROWOBJ_VAL(err);
- /* check skipped frame */
- while (th->cfp != cfp) {
-#if VMDEBUG
- printf("skipped frame: %s\n", vm_frametype_name(th->cfp));
-#endif
- if (VM_FRAME_TYPE(th->cfp) != VM_FRAME_MAGIC_CFUNC) {
- vm_pop_frame(th);
- }
- else { /* unlikely path */
- rb_vm_pop_cfunc_frame();
- }
- }
+ rb_vm_rewind_cfp(th, cfp);
}
else{
/* SDR(); printf("%p, %p\n", cdfp, escape_dfp); */
@@ -1090,10 +1079,11 @@ rb_iterate(VALUE (* it_proc) (VALUE), VALUE data1,
VALUE *cep = cfp->ep;
if (cep == escape_ep) {
+ rb_vm_rewind_cfp(th, cfp);
+
state = 0;
th->state = 0;
th->errinfo = Qnil;
- th->cfp = cfp;
goto iter_retry;
}
}
@@ -1835,7 +1825,7 @@ rb_catch_obj(VALUE tag, VALUE (*func)(), VALUE data)
val = (*func)(tag, data, 1, &tag, Qnil);
}
else if (state == TAG_THROW && RNODE(th->errinfo)->u1.value == tag) {
- th->cfp = saved_cfp;
+ rb_vm_rewind_cfp(th, saved_cfp);
val = th->tag->retval;
th->errinfo = Qnil;
state = 0;