Bug #3141: yield in an eigenclass definition
http://redmine.ruby-lang.org/issues/show/3141
e$B5/I<<Te(B: Yusuke E.
e$B%9%F!<%?%9e(B: Open, e$BM%@hEYe(B: Normal
e$BC4Ev<Te(B: Yusuke E., e$B%+%F%4%je(B: core, Target version: 1.9.2
ruby -v: ruby 1.9.2dev (2010-04-13 trunk 27329) [i686-linux]
e$B$5$5$@$5$se(B
e$B1sF#$G$9!#e(B
#1018 e$B$K4XO"$7$^$9$,!"FC0[%/%i%9Dj5A$NCf$Ge(B yield
e$B$,$G$-$^$;$s!#e(B
class Object
def yield_eigenclass
class << self
yield self
end
end
end
Object.yield_eigenclass {|c| p c }
$ ruby19 t.rb
t.rb:4: Invalid yield
t.rb: compile error (SyntaxError)
e$BD4$Y$F$$$FCN$C$?$N$G$9$,!"e(Bdfp[0] e$B$K$Oe(B
- ISEQ_TYPE_METHOD, _CFUNC, _FINISH, _TOP e$B$N>l9g$Oe(B rb_block_t*
- e$B$=$l0J30$N>l9g$OA0$N%U%l!<%`$Ne(B dfp (vm_throw e$B$G;H$&e(B)
e$B$,F~$C$F$$$k$s$G$9$Me(B (e$B$J$s$H$$$&e(B dirty hack e$B!D!De(B)
e$B!#e(B
vm_push_frame e$B$Ne(B 5 e$BHVL$N0z?te(B (specval)
e$B$KEO$5$l$kCM$O$:$C$HFfe(B
e$B$G$7$?!#e(B
ISEQ_TYPE_CLASS e$B$Ne(B dfp[0] e$B$K$OA0$N%U%l!<%`$Ne(B dfp
e$B$,F~$C$F$$$^$9!#e(B
(e$B%V%m%C%/$X$N%]%$%s%?$H6hJL$G$-$k$h$&!“2<$+$ie(B 2
e$B%S%C%HL$rN)$F$Fe(B
e$B$*$/$H$$$&!”$5$i$J$ke(B dirty hack (RUBY_VM_CLASS_SPECIAL_P)
e$B$r8+$Fe(B
e$BL$,$D$V$l$^$7$?e(B)
e$B0lJ}$G!“e(BISEQ_TYPE_CLASS
e$B0J2<$NJ8L.$+$i$O%V%m%C%/$X$N;2>H$,$J$$e(B
e$B>uBV$K$J$C$F$$$k$H;W$$$^$7$?!#$3$3$^$G!”>-Mh$N<+J,$N$?$a$N%a%b!#e(B
e$B$=$3$G!"e(BISEQ_TYPE_CLASS e$B$Ne(B dfp[0] e$B$K$be(B rb_block_t*
e$B$rF~$l$k$3$H$Ke(B
e$B$7$^$;$s$+!#e(B
e$B%a%j%C%He(B:
- e$B>e5-$N%3!<%I$,F0$/e(B
- RUBY_VM_CLASS_SPECIAL_P e$B$Ne(B dirty hack e$B$,ITMW$K$J$ke(B
e$B%G%a%j%C%He(B:
- vm_throw e$B$GJ,4t$,A}$($k>l9g$,$"$ke(B
e$B%G%a%j%C%H$K$D$$$F$O!"e(Bbreak e$B$G0J2<$rH4$1$k$4$H$Ke(B 1
e$B2sJ,4t$,A}$(e(B
e$B$^$9!#e(B
- e$B%/%i%9Dj5Ae(B 1.times { class C; break; end }
- rescue e$B@ae(B 1.times { begin; …; rescue; break; end }
- ensure e$B@ae(B 1.times { begin; …; ensure; break; end }
e$B$3$3$K%/%i%9Dj5A$,Mh$k$3$H$OHs>o$K%l%"$G$9$7!“e(Brescue e$B@a$de(B
ensure
e$B@a$r%M%9%H$9$k$3$H$b%l%”$@$H;W$&$N$G!“LdBj$K$J$i$J$$$s$8$c$J$$e(B
e$B$+$J!”$H;W$$$^$9!#e(B
e$B$H$$$&$o$1$G%Q%C%A$G$9!#e(B#1018 e$B$Ne(B wanabe
e$B$5$s$N%Q%C%A$b4^$$^$9!#e(B
make test-rubyspec e$B$He(B make check
e$B$GFC$K%(%i!<$,A}$($J$$46$8$Je(B
e$B$3$H$O3NG’$7$F$$$^$9!#%3%%C%H$7$F$b$$$$$G$7$g$&$+!#e(B
diff --git a/compile.c b/compile.c
index 64411f9…7748fca 100644
— a/compile.c
+++ b/compile.c
@@ -4229,7 +4229,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 {
@@ -4269,7 +4269,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”));
}
diff --git a/insns.def b/insns.def
index 9541465…14485f2 100644
— a/insns.def
+++ b/insns.def
@@ -953,7 +953,7 @@ defineclass
/* enter scope */
vm_push_frame(th, class_iseq,
-
VM_FRAME_MAGIC_CLASS, klass, (VALUE) GET_DFP() | 0x02,
-
RESTORE_REGS();VM_FRAME_MAGIC_CLASS, klass, (VALUE) GET_BLOCK_PTR(), class_iseq->iseq_encoded, GET_SP(), 0, class_iseq->local_size);
diff --git a/proc.c b/proc.c
index eff7a0b…5fa46f1 100644
— a/proc.c
+++ b/proc.c
@@ -374,16 +374,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]);
diff --git a/vm.c b/vm.c
index 678fcb8…e5de8ac 100644
— a/vm.c
+++ b/vm.c
@@ -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);
diff --git a/vm_core.h b/vm_core.h
index b5c1bf0…7ee1c1c 100644
— a/vm_core.h
+++ b/vm_core.h
@@ -592,8 +592,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 cd74c8e…ae28ef3 100644
— a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -890,8 +890,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;
@@ -1411,6 +1412,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;
@@ -1476,10 +1482,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;
–
Yusuke E. [email protected]