* 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.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@27714 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
mame 2010-05-09 18:21:39 +00:00
parent b664caeb78
commit 80f7f8d07e
8 changed files with 60 additions and 13 deletions

View File

@ -1,3 +1,19 @@
Mon May 10 02:58:33 2010 Yusuke Endoh <mame@tsg.ne.jp>
* 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 <mame@tsg.ne.jp> Mon May 10 02:29:51 2010 Yusuke Endoh <mame@tsg.ne.jp>
* cont.c (fiber_switch): raise FiberError when returning to dead * cont.c (fiber_switch): raise FiberError when returning to dead

View File

@ -282,3 +282,27 @@ assert_normal_exit %q{
break break
end end
}, '[ruby-core:28172]' }, '[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]'

View File

@ -4225,7 +4225,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
rb_iseq_t *is = iseq; rb_iseq_t *is = iseq;
if (is) { 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")); COMPILE_ERROR((ERROR_ARGS "Invalid return"));
} }
else { else {
@ -4265,7 +4265,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
unsigned long flag = 0; unsigned long flag = 0;
INIT_ANCHOR(args); 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")); COMPILE_ERROR((ERROR_ARGS "Invalid yield"));
} }

View File

@ -953,7 +953,7 @@ defineclass
/* enter scope */ /* enter scope */
vm_push_frame(th, class_iseq, 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->iseq_encoded, GET_SP(), 0,
class_iseq->local_size); class_iseq->local_size);
RESTORE_REGS(); RESTORE_REGS();

6
proc.c
View File

@ -375,16 +375,14 @@ proc_new(VALUE klass, int is_lambda)
rb_control_frame_t *cfp = th->cfp; rb_control_frame_t *cfp = th->cfp;
rb_block_t *block; rb_block_t *block;
if ((GC_GUARDED_PTR_REF(cfp->lfp[0])) != 0 && if ((GC_GUARDED_PTR_REF(cfp->lfp[0])) != 0) {
!RUBY_VM_CLASS_SPECIAL_P(cfp->lfp[0])) {
block = GC_GUARDED_PTR_REF(cfp->lfp[0]); block = GC_GUARDED_PTR_REF(cfp->lfp[0]);
} }
else { else {
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
if ((GC_GUARDED_PTR_REF(cfp->lfp[0])) != 0 && if ((GC_GUARDED_PTR_REF(cfp->lfp[0])) != 0) {
!RUBY_VM_CLASS_SPECIAL_P(cfp->lfp[0])) {
block = GC_GUARDED_PTR_REF(cfp->lfp[0]); block = GC_GUARDED_PTR_REF(cfp->lfp[0]);

2
vm.c
View File

@ -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 (GC_GUARDED_PTR_REF(cfp->lfp[0])) {
if (!RUBY_VM_CLASS_SPECIAL_P(cfp->lfp[0])) {
rb_proc_t *p; rb_proc_t *p;
blockprocval = vm_make_proc_from_block( 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); GetProcPtr(blockprocval, p);
*cfp->lfp = GC_GUARDED_PTR(&p->block); *cfp->lfp = GC_GUARDED_PTR(&p->block);
} }
}
envval = rb_vm_make_env_object(th, cfp); envval = rb_vm_make_env_object(th, cfp);

View File

@ -597,8 +597,6 @@ typedef rb_control_frame_t *
#define RUBY_VM_NORMAL_ISEQ_P(ptr) \ #define RUBY_VM_NORMAL_ISEQ_P(ptr) \
(ptr && !RUBY_VM_IFUNC_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_BLOCK_PTR_IN_CFP(cfp) ((rb_block_t *)(&(cfp)->self))
#define RUBY_VM_GET_CFP_FROM_BLOCK_PTR(b) \ #define RUBY_VM_GET_CFP_FROM_BLOCK_PTR(b) \
((rb_control_frame_t *)((VALUE *)(b) - 5)) ((rb_control_frame_t *)((VALUE *)(b) - 5))

View File

@ -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(); const rb_block_t *block = GET_BLOCK_PTR();
rb_iseq_t *iseq; rb_iseq_t *iseq;
int argc = (int)num; 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); rb_vm_localjump_error("no block given (yield)", Qnil, 0);
} }
iseq = block->iseq; iseq = block->iseq;
@ -1434,6 +1435,11 @@ vm_throw(rb_thread_t *th, rb_control_frame_t *reg_cfp,
search_parent: search_parent:
if (cfp->iseq->type != ISEQ_TYPE_BLOCK) { 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); dfp = GC_GUARDED_PTR_REF((VALUE *) *dfp);
base_iseq = base_iseq->parent_iseq; 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) { else if (state == TAG_RETURN) {
rb_control_frame_t *cfp = GET_CFP(); rb_control_frame_t *cfp = GET_CFP();
VALUE *dfp = GET_DFP(); VALUE *dfp = GET_DFP();
VALUE * const lfp = GET_LFP(); VALUE *lfp = GET_LFP();
/* check orphan and get dfp */ /* check orphan and get dfp */
while ((VALUE *) cfp < th->stack + th->stack_size) { 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 (cfp->lfp == lfp) {
if (VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_LAMBDA) { if (VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_LAMBDA) {
VALUE *tdfp = dfp; VALUE *tdfp = dfp;