diff options
-rw-r--r-- | ChangeLog | 16 | ||||
-rw-r--r-- | bootstraptest/test_jump.rb | 24 | ||||
-rw-r--r-- | compile.c | 4 | ||||
-rw-r--r-- | insns.def | 2 | ||||
-rw-r--r-- | proc.c | 6 | ||||
-rw-r--r-- | vm.c | 2 | ||||
-rw-r--r-- | vm_core.h | 2 | ||||
-rw-r--r-- | vm_insnhelper.c | 17 |
8 files changed, 60 insertions, 13 deletions
@@ -1,3 +1,19 @@ +Mon May 10 02:58:33 2010 Yusuke Endoh <[email protected]> + + * compile.c (iseq_compile_each), vm_insnhelper.c (vm_invoke_block, + vm_throw): allow "return" and "yield" even in singleton class + definition. based on a patch from wanabe <s.wanabe AT gmail.com> + for "return". [ruby-core:21379] [ruby-dev:40975] + + * insns.def (defineclass): ditto (straightforwardly push block ptr, + instead of dfp ptr with special flag). + + * vm_core.h (RUBY_VM_CLASS_SPECIAL_P): ditto (no longer needed). + + * proc.c (proc_new): ditto (remove handling for special flag). + + * bootstraptest/test_jump.rb: add tests for above. + Mon May 10 02:29:51 2010 Yusuke Endoh <[email protected]> * cont.c (fiber_switch): raise FiberError when returning to dead diff --git a/bootstraptest/test_jump.rb b/bootstraptest/test_jump.rb index 9484df8852..c53d83591e 100644 --- a/bootstraptest/test_jump.rb +++ b/bootstraptest/test_jump.rb @@ -282,3 +282,27 @@ assert_normal_exit %q{ break end }, '[ruby-core:28172]' + +assert_equal "true", %q{ + class Object + def return_eigenclass + class << self + return self + end + end + end + s = "foo" + s.return_eigenclass == class << s; self; end +}, '[ruby-core:21379]' + +assert_equal "true", %q{ + class Object + def yield_eigenclass + class << self + yield self + end + end + end + s = "foo" + s.yield_eigenclass {|c| c == class << s; self; end } +}, '[ruby-dev:40975]' @@ -4225,7 +4225,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) rb_iseq_t *is = iseq; if (is) { - if (is->type == ISEQ_TYPE_TOP || is->type == ISEQ_TYPE_CLASS) { + if (is->type == ISEQ_TYPE_TOP) { COMPILE_ERROR((ERROR_ARGS "Invalid return")); } else { @@ -4265,7 +4265,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) unsigned long flag = 0; INIT_ANCHOR(args); - if (iseq->type == ISEQ_TYPE_TOP || iseq->type == ISEQ_TYPE_CLASS) { + if (iseq->type == ISEQ_TYPE_TOP) { COMPILE_ERROR((ERROR_ARGS "Invalid yield")); } @@ -953,7 +953,7 @@ defineclass /* enter scope */ vm_push_frame(th, class_iseq, - VM_FRAME_MAGIC_CLASS, klass, (VALUE) GET_DFP() | 0x02, + VM_FRAME_MAGIC_CLASS, klass, (VALUE) GET_BLOCK_PTR(), class_iseq->iseq_encoded, GET_SP(), 0, class_iseq->local_size); RESTORE_REGS(); @@ -375,16 +375,14 @@ proc_new(VALUE klass, int is_lambda) rb_control_frame_t *cfp = th->cfp; rb_block_t *block; - if ((GC_GUARDED_PTR_REF(cfp->lfp[0])) != 0 && - !RUBY_VM_CLASS_SPECIAL_P(cfp->lfp[0])) { + if ((GC_GUARDED_PTR_REF(cfp->lfp[0])) != 0) { block = GC_GUARDED_PTR_REF(cfp->lfp[0]); } else { cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); - if ((GC_GUARDED_PTR_REF(cfp->lfp[0])) != 0 && - !RUBY_VM_CLASS_SPECIAL_P(cfp->lfp[0])) { + if ((GC_GUARDED_PTR_REF(cfp->lfp[0])) != 0) { block = GC_GUARDED_PTR_REF(cfp->lfp[0]); @@ -477,7 +477,6 @@ rb_vm_make_proc(rb_thread_t *th, const rb_block_t *block, VALUE klass) } if (GC_GUARDED_PTR_REF(cfp->lfp[0])) { - if (!RUBY_VM_CLASS_SPECIAL_P(cfp->lfp[0])) { rb_proc_t *p; blockprocval = vm_make_proc_from_block( @@ -486,7 +485,6 @@ rb_vm_make_proc(rb_thread_t *th, const rb_block_t *block, VALUE klass) GetProcPtr(blockprocval, p); *cfp->lfp = GC_GUARDED_PTR(&p->block); } - } envval = rb_vm_make_env_object(th, cfp); @@ -597,8 +597,6 @@ typedef rb_control_frame_t * #define RUBY_VM_NORMAL_ISEQ_P(ptr) \ (ptr && !RUBY_VM_IFUNC_P(ptr)) -#define RUBY_VM_CLASS_SPECIAL_P(ptr) (((VALUE)(ptr)) & 0x02) - #define RUBY_VM_GET_BLOCK_PTR_IN_CFP(cfp) ((rb_block_t *)(&(cfp)->self)) #define RUBY_VM_GET_CFP_FROM_BLOCK_PTR(b) \ ((rb_control_frame_t *)((VALUE *)(b) - 5)) diff --git a/vm_insnhelper.c b/vm_insnhelper.c index 4f041a9465..f1ef50981f 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -913,8 +913,9 @@ vm_invoke_block(rb_thread_t *th, rb_control_frame_t *reg_cfp, rb_num_t num, rb_n const rb_block_t *block = GET_BLOCK_PTR(); rb_iseq_t *iseq; int argc = (int)num; + int type = GET_ISEQ()->local_iseq->type; - if (GET_ISEQ()->local_iseq->type != ISEQ_TYPE_METHOD || block == 0) { + if ((type != ISEQ_TYPE_METHOD && type != ISEQ_TYPE_CLASS) || block == 0) { rb_vm_localjump_error("no block given (yield)", Qnil, 0); } iseq = block->iseq; @@ -1434,6 +1435,11 @@ vm_throw(rb_thread_t *th, rb_control_frame_t *reg_cfp, search_parent: if (cfp->iseq->type != ISEQ_TYPE_BLOCK) { + if (cfp->iseq->type == ISEQ_TYPE_CLASS) { + cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); + dfp = cfp->dfp; + goto search_parent; + } dfp = GC_GUARDED_PTR_REF((VALUE *) *dfp); base_iseq = base_iseq->parent_iseq; @@ -1499,10 +1505,17 @@ vm_throw(rb_thread_t *th, rb_control_frame_t *reg_cfp, else if (state == TAG_RETURN) { rb_control_frame_t *cfp = GET_CFP(); VALUE *dfp = GET_DFP(); - VALUE * const lfp = GET_LFP(); + VALUE *lfp = GET_LFP(); /* check orphan and get dfp */ while ((VALUE *) cfp < th->stack + th->stack_size) { + if (!lfp) { + lfp = cfp->lfp; + } + if (cfp->dfp == lfp && cfp->iseq->type == ISEQ_TYPE_CLASS) { + lfp = 0; + } + if (cfp->lfp == lfp) { if (VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_LAMBDA) { VALUE *tdfp = dfp; |