diff options
-rw-r--r-- | ChangeLog | 11 | ||||
-rw-r--r-- | cont.c | 10 | ||||
-rw-r--r-- | eval_intern.h | 9 | ||||
-rw-r--r-- | test/ruby/test_continuation.rb | 14 | ||||
-rw-r--r-- | vm.c | 11 |
5 files changed, 45 insertions, 10 deletions
@@ -1,3 +1,14 @@ +Wed May 30 14:43:00 2007 Koichi Sasada <[email protected]> + + * cont.c (cont_capture): store all local variables in heap + ([ruby-dev:30832]). + + * vm.c (th_stack_to_heap): added. + + * test/ruby/test_continuation.rb: add a test for above. + + * eval_intern.h (th_get_ruby_level_cfp): fix to clean code. + Wed May 30 13:32:34 2007 Shugo Maeda <[email protected]> * lib/net/imap.rb (ResponseParser#next_token): fixed @@ -120,11 +120,17 @@ cont_new(VALUE klass) return cont; } +void th_stack_to_heap(rb_thread_t *th); + static VALUE cont_capture(volatile int *stat) { - rb_context_t *cont = cont_new(rb_cCont); - rb_thread_t *th = &cont->saved_thread; + rb_context_t *cont; + rb_thread_t *th; + + th_stack_to_heap(GET_THREAD()); + cont = cont_new(rb_cCont); + th = &cont->saved_thread; cont->vm_stack = ALLOC_N(VALUE, th->stack_size); MEMCPY(cont->vm_stack, th->stack, VALUE, th->stack_size); diff --git a/eval_intern.h b/eval_intern.h index 157e7a58bd..abfb7794a9 100644 --- a/eval_intern.h +++ b/eval_intern.h @@ -207,18 +207,13 @@ NODE *th_set_special_cref(rb_thread_t *th, VALUE *lfp, NODE * cref_stack); static rb_control_frame_t * th_get_ruby_level_cfp(rb_thread_t *th, rb_control_frame_t *cfp) { - rb_iseq_t *iseq = 0; while (!RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(th, cfp)) { if (RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)) { - iseq = cfp->iseq; - break; + return cfp; } cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); } - if (!iseq) { - return 0; - } - return cfp; + return 0; } static inline NODE * diff --git a/test/ruby/test_continuation.rb b/test/ruby/test_continuation.rb index d5c9c32e4b..8af13363dc 100644 --- a/test/ruby/test_continuation.rb +++ b/test/ruby/test_continuation.rb @@ -18,6 +18,20 @@ class TestContinuation < Test::Unit::TestCase assert_equal([:a, :b, :b], ary) end + def test_check_localvars + vv = 0 + @v = 0 + @ary = [] + [1, 2, 3].each{|i| + callcc {|k| @k = k} + @v += 1 + vv += 1 + } + @ary << [vv, @v] + @k.call if @v < 10 + assert_equal((3..10).map{|e| [e, e]}, @ary) + end + def test_error cont = callcc{|c| c} assert_raise(RuntimeError){ @@ -400,7 +400,6 @@ th_collect_local_variables_in_heap(rb_thread_t *th, VALUE *dfp, VALUE ary) } } - VALUE th_make_env_object(rb_thread_t *th, rb_control_frame_t *cfp) { @@ -413,6 +412,16 @@ th_make_env_object(rb_thread_t *th, rb_control_frame_t *cfp) return envval; } +void +th_stack_to_heap(rb_thread_t *th) +{ + rb_control_frame_t *cfp = th->cfp; + while ((cfp = th_get_ruby_level_cfp(th, cfp)) != 0) { + th_make_env_object(th, cfp); + cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); + } +} + static VALUE th_make_proc_from_block(rb_thread_t *th, rb_control_frame_t *cfp, rb_block_t *block) |