Patch for ruby-core:14813

e$B%o%J%Y$H?=$7$^$9!#e(B

[ruby-core:14813] e$B$KBP$9$k%Q%C%A$r=q$-$^$7$?!#e(B
e$B%V%m%C%/0z?t$,M?$($i$l$?%V%m%C%/!"$*$h$Se(B define_method
e$B$N%V%m%C%/Cf$G$Ne(B
given_block? e$B$He(B yield e$B$N5sF0$,JQ$o$j$^$9!#e(B
e$B%V%m%C%/%U%l!<%`$Ne(B bp
e$B$r2!$7>e$2!"$G$-$?7d4V$K6/0z$K%V%m%C%/0z?t$r;}$?$;$F$$$^$9!#e(B

Index: vm_core.h

— vm_core.h (revision 15984)
+++ vm_core.h (working copy)
@@ -608,6 +608,7 @@
VALUE vm_yield(rb_thread_t *th, int argc, VALUE *argv);
VALUE vm_call0(rb_thread_t *th, VALUE klass, VALUE recv, VALUE id, ID
oid,
int argc, const VALUE *argv, NODE *body, int nosuper);
+rb_block_t *vm_get_block(rb_control_frame_t *cfp);

int vm_get_sourceline(rb_control_frame_t *);

Index: eval.c

— eval.c (revision 15984)
+++ eval.c (working copy)
@@ -837,11 +837,10 @@
JUMP_TAG(tag);
}

-int
-rb_block_given_p(void)
+static inline VALUE
+block_given_p(rb_control_frame_t *cfp)
{

  • rb_thread_t *th = GET_THREAD();
  • if (GC_GUARDED_PTR_REF(th->cfp->lfp[0])) {
  • if (vm_get_block(cfp)) {
    return Qtrue;
    }
    else {
    @@ -850,6 +849,12 @@
    }

int
+rb_block_given_p(void)
+{

  • return block_given_p(GET_THREAD()->cfp);
    +}

+int
rb_iterator_p()
{
return rb_block_given_p();
@@ -882,13 +887,9 @@
{
rb_thread_t *th = GET_THREAD();
rb_control_frame_t *cfp = th->cfp;
+
cfp = vm_get_ruby_level_cfp(th,
RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp));

  • if (GC_GUARDED_PTR_REF(cfp->lfp[0])) {
  • return Qtrue;
  • }
  • else {
  • return Qfalse;
  • }
  • return block_given_p(cfp);
    }

VALUE rb_eThreadError;
Index: vm.c

— vm.c (revision 15984)
+++ vm.c (working copy)
@@ -539,6 +539,30 @@
return vm_call_super(GET_THREAD(), argc, argv);
}

+rb_block_t *
+vm_get_block(rb_control_frame_t *cfp) {

  • rb_block_t *block = 0;
  • if (RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)) {
  • if (cfp->iseq->type == ISEQ_TYPE_BLOCK) {
  •  block = ((rb_block_t *)(GC_GUARDED_PTR_REF(cfp->dfp[1])));
    
  •  if (cfp->iseq->defined_method_id) {
    
  • return block;
  •  }
    
  • }
  • else if (RUBY_VM_NORMAL_ISEQ_P(cfp->iseq->local_iseq)) {
  •  if (cfp->iseq->local_iseq->type != ISEQ_TYPE_METHOD) {
    
  • return 0;
  •  }
    
  • }
  • }
  • if (!block) {
  • block = ((rb_block_t *)(GC_GUARDED_PTR_REF(cfp->lfp[0])));
  • }
  • return block;
    +}

/* C -> Ruby: block */

static VALUE
@@ -568,6 +592,7 @@
self, GC_GUARDED_PTR(block->dfp),
iseq->iseq_encoded + opt_pc, cfp->sp + arg_size, block->lfp,
iseq->local_size - arg_size);

  • vm_add_specval(th, GC_GUARDED_PTR(blockptr));

    val = vm_eval_body(th);
    }
    @@ -1316,6 +1341,7 @@
    vm_push_frame(th, catch_iseq, FRAME_MAGIC_BLOCK,
    cfp->self, (VALUE)cfp->dfp, catch_iseq->iseq_encoded,
    cfp->sp + 1, cfp->lfp, catch_iseq->local_size - 1);

  •  vm_add_specval(th, 0);
    
     state = 0;
     th->errinfo = Qnil;
    

Index: vm_insnhelper.c

— vm_insnhelper.c (revision 15984)
+++ vm_insnhelper.c (working copy)
@@ -68,6 +68,14 @@
}

static inline void
+vm_add_specval(rb_thread_t *th, VALUE specval)
+{

  • *th->cfp->bp = specval;
  • th->cfp->sp++;
  • th->cfp->bp++;
    +}

+static inline void
vm_pop_frame(rb_thread_t *th)
{
#if COLLECT_PROFILE
@@ -792,11 +800,12 @@
vm_invoke_block(rb_thread_t *th, rb_control_frame_t *reg_cfp,
rb_num_t num, rb_num_t flag)
{
VALUE val;

  • rb_block_t *block = GET_BLOCK_PTR();
  • rb_block_t *block = 0;
    rb_iseq_t *iseq;
    int argc = num;
  • if (GET_ISEQ()->local_iseq->type != ISEQ_TYPE_METHOD || block == 0)
    {
  • block = vm_get_block(reg_cfp);

  • if (block == 0) {
    vm_localjump_error(“no block given (yield)”, Qnil, 0);
    }
    iseq = block->iseq;
    @@ -817,6 +826,7 @@
    FRAME_MAGIC_BLOCK, block->self, (VALUE) block->dfp,
    iseq->iseq_encoded + opt_pc, rsp + arg_size, block->lfp,
    iseq->local_size - arg_size);

  • vm_add_specval(th, 0);

    return Qundef;
    }