# Rb\_yield $B$N9bB.HG(B

**URL:** <https://www.ruby-forum.com/t/rb-yield-b-n9bb-hg-b/136377>\
**Category:** Development\
**Created:** [May 1, 2008, 12:27pm UTC](https://www.ruby-forum.com/t/rb-yield-b-n9bb-hg-b/136377 "2008-05-01T12:27:20Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![wanabe](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/51bf81/32.png) [@wanabe](https://www.ruby-forum.com/u/wanabe)\
**Post date:** [May 1, 2008, 12:27pm UTC](https://www.ruby-forum.com/t/rb-yield-b-n9bb-hg-b/136377/1 "2008-05-01T12:27:20Z")

</div>

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

rb\_yield  
e$B$rO"B3$G8F$S=P$9$H$-$K!"@Q$s$@%U%l!\<%`$r;H$$$^$o$94X?t$r=q$-$^$7$?!#e(B  
e$B;n83E\*$Ke(B Fixnum#times e$B$K$@$1AH$\_9~$s$G$$$^$9$,!"$[$+$K$be(B  
Array#each, Range#each e$B$J$I$G;H$($k$H;W$$$^$9!#e(B

ruby -e ‘GC.disable;t=Time.now;(10\*\*7).times {};p Time.now - t’  
e$B$3$s$J46$8$N4JC1$J7WB,$G$Oe(B 4.9e$BIC$+$ie(B 3.5  
e$BIC$[$I$K=L$^$j$^$7$?!#e(B  
e$B0l1~\<j85$G$Oe(B make test e$B$He(B make test-all  
e$B$NF0:n$r3NG’$7$F$"$j$^$9!#e(B

# Index: eval.c

— eval.c (revision 16218)  
+++ eval.c (working copy)  
@@ -960,6 +960,24 @@  
return v;  
}

+rb\_block\_t \*vm\_yield\_fast\_setup(rb\_thread\_t _th, int argc); /_ vm.c \*/  
+void vm\_yield\_fast\_finish(rb\_thread\_t \*th, rb\_block\_t _block); /_ vm.c  
\*/  
+  
+VALUE  
+rb\_yield\_fast(VALUE (\*i\_proc)(ANYARGS), VALUE val)  
+{

- rb\_thread\_t \*th = GET\_THREAD();
- rb\_block\_t \*block = vm\_yield\_fast\_setup(th, 1);
- i\_proc(val, (void\*)block);
- vm\_yield\_fast\_finish(th, block);  
+}
- 

+VALUE  
+rb\_yield\_fast\_call(VALUE val, void \*block)  
+{

- return vm\_yield\_fast(GET\_THREAD(), (rb\_block\_t \*)block, 1, &val);  
+}
- 

# static VALUE loop\_i() { Index: numeric.c

— numeric.c (revision 16218)  
+++ numeric.c (working copy)  
@@ -3016,17 +3016,23 @@  
\*/

static VALUE  
+int\_dotimes\_i(VALUE num, void \*block)  
+{

- long i, end;
- 
- end = FIX2LONG(num);
- for (i=0; i\<end; i++) {
- rb\_yield\_fast\_call(LONG2FIX(i), block);
- }  
+}
- 

+static VALUE  
int\_dotimes(VALUE num)  
{  
RETURN\_ENUMERATOR(num, 0, 0);

```
 if (FIXNUM_P(num)) {

```

- long i, end;
- 
- end = FIX2LONG(num);
- for (i=0; i\<end; i++) {
- 

```
 rb_yield(LONG2FIX(i));

```

- }

- rb\_yield\_fast(int\_dotimes\_i, num);  
}  
else {  
VALUE i = INT2FIX(0);  
Index: vm.c  
===================================================================  
— vm.c (revision 16218)  
+++ vm.c (working copy)  
@@ -541,11 +541,10 @@

/\* C -\> Ruby: block \*/

-static VALUE  
-invoke\_block(rb\_thread\_t \*th, rb\_block\_t \*block, VALUE self,  
+static inline void  
+setup\_block(rb\_thread\_t \*th, rb\_block\_t \*block, VALUE self,  
int argc, VALUE \*argv, rb\_block\_t \*blockptr)  
{

- VALUE val;  
if (BUILTIN\_TYPE(block-\>iseq) != T\_NODE) {  
rb\_iseq\_t \*iseq = block-\>iseq;  
rb\_control\_frame\_t \*cfp = th-\>cfp;  
@@ -557,8 +556,14 @@

CHECK\_STACK\_OVERFLOW(cfp, argc + iseq-\>stack\_max);

- for (i=0; i\<argc; i++) {
- 

```
 cfp->sp[i] = argv[i];

```

- if (argv) {

- 

```
 for (i=0; i<argc; i++) {

```

- cfp-\>sp[i] = argv[i];

- 

```
 }

```

- } else {

- 

```
 for (i=0; i<argc; i++) {

```

- cfp-\>sp[i] = Qnil;

- 

```
 }

```

}

opt\_pc = vm\_yield\_setup\_args(th, iseq, argc, cfp-\>sp, blockptr,  
@@ -568,7 +573,15 @@  
self, GC\_GUARDED\_PTR(block-\>dfp),  
iseq-\>iseq\_encoded + opt\_pc, cfp-\>sp + arg\_size, block-\>lfp,  
iseq-\>local\_size - arg\_size);

- }  
+}

+static inline VALUE  
+invoke\_block\_fast(rb\_thread\_t \*th, rb\_block\_t \*block, VALUE self,

- 

```
  int argc, VALUE *argv, rb_block_t *blockptr)

```

+{

- VALUE val;
- if (BUILTIN\_TYPE(block-\>iseq) != T\_NODE) {  
val = vm\_eval\_body(th);  
}  
else {  
@@ -577,19 +590,85 @@  
return val;  
}

-VALUE  
-vm\_yield(rb\_thread\_t \*th, int argc, VALUE \*argv)  
+static VALUE  
+invoke\_block(rb\_thread\_t \*th, rb\_block\_t \*block, VALUE self,

- 

```
  int argc, VALUE *argv, rb_block_t *blockptr)

```

{

- rb\_block\_t \*block = GC\_GUARDED\_PTR\_REF(th-\>cfp-\>lfp[0]);

- VALUE val;
- setup\_block(th, block, self, argc, argv, blockptr);
- return invoke\_block\_fast(th, block, self, argc, argv, blockptr);  
+}

+static inline rb\_block\_t \*  
+vm\_get\_block(rb\_control\_frame\_t \*cfp)  
+{

- rb\_block\_t \*block = GC\_GUARDED\_PTR\_REF(cfp-\>lfp[0]);
- if (block == 0) {  
vm\_localjump\_error(“no block given”, Qnil, 0);  
}
- return block;  
+}

+VALUE  
+vm\_yield(rb\_thread\_t \*th, int argc, VALUE \*argv)  
+{

- rb\_block\_t \*block = vm\_get\_block(th-\>cfp);  
return invoke\_block(th, block, block-\>self, argc, argv, 0);  
}

+rb\_block\_t \*  
+vm\_yield\_fast\_setup(rb\_thread\_t \*th, int argc)  
+{

- rb\_block\_t \*block = vm\_get\_block(th-\>cfp);
- setup\_block(th, block, block-\>self, argc, 0, 0);
- return block;  
+}
- 

VALUE  
+vm\_yield\_fast(rb\_thread\_t \*th, rb\_block\_t \*block, int argc, VALUE  
\*argv)  
+{

- int i;
- int opt\_pc;
- VALUE retval;
- VALUE pre\_dfp;
- 
- if (BUILTIN\_TYPE(block-\>iseq) != T\_NODE) {
- CHECK\_STACK\_OVERFLOW(th-\>cfp, argc + block-\>iseq-\>stack\_max);
- for (i=0; i\<argc; i++) {
- 

```
 th->cfp->sp[i] = argv[i];

```

- }
- opt\_pc = vm\_yield\_setup\_args(th, block-\>iseq, argc, th-\>cfp-\>sp, 0,
- 

```
     block_proc_is_lambda(block->proc));

```

- for (i=0; iiseq-\>arg\_size; i++) {
- 

```
 th->cfp[2].sp[i] = th->cfp->sp[i];

```

- }
- th-\>cfp-\>pc = block-\>iseq-\>iseq\_encoded + opt\_pc;
- th-\>cfp-\>dfp[0] = GC\_GUARDED\_PTR(block-\>dfp);
- }
- retval = invoke\_block\_fast(th, block, block-\>self, argc, argv, 0);
- if (BUILTIN\_TYPE(block-\>iseq) != T\_NODE) {
- for (i=0; iiseq-\>local\_size; i++) {
- 

```
 th->cfp->sp[i] = Qnil;

```

- }
- th-\>cfp–;
- th-\>cfp-\>pc–;
- th-\>cfp–;
- }
- return retval;  
+}
- 

+void  
+vm\_yield\_fast\_finish(rb\_thread\_t \*th, rb\_block\_t \*block)  
+{

- if (BUILTIN\_TYPE(block-\>iseq) != T\_NODE) {
- th-\>cfp++;
- th-\>cfp-\>pc++;
- th-\>cfp++;
- }  
+}
- 

+VALUE  
vm\_invoke\_proc(rb\_thread\_t \*th, rb\_proc\_t \*proc,  
VALUE self, int argc, VALUE \*argv, rb\_block\_t \*blockptr)  
{

---

<div class="post-metadata">

**Author:** ![wanabe](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/51bf81/32.png) [@wanabe](https://www.ruby-forum.com/u/wanabe)\
**Post date:** [May 1, 2008, 4:07pm UTC](https://www.ruby-forum.com/t/rb-yield-b-n9bb-hg-b/136377/2 "2008-05-01T16:07:59Z")

</div>

e$B$^$D$b$He(B e$B$f$-$R$m$G$9e(B

In message “Re: [ruby-dev:34560] rb\_yield e$B$N9bB.HGe(B”  
on Thu, 1 May 2008 19:27:02 +0900, wanabe [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
writes:

|rb\_yield e$B$rO"B3$G8F$S=P$9$H$-$K!“@Q$s$@%U%l!\<%`$r;H$$$^$o$94X?t$r=q$-$^$7$?!#e(B  
|e$B;n83E\*$Ke(B Fixnum#times e$B$K$@$1AH$\_9~$s$G$$$^$9$,!”$[$+$K$be(B  
|Array#each, Range#each e$B$J$I$G;H$($k$H;W$$$^$9!#e(B  
|  
|ruby -e ‘GC.disable;t=Time.now;(10\*\*7).times {};p Time.now - t’  
|e$B$3$s$J46$8$N4JC1$J7WB,$G$Oe(B 4.9e$BIC$+$ie(B 3.5 e$BIC$[$I$K=L$^$j$^$7$?!#e(B  
|e$B0l1~\<j85$G$Oe(B make test e$B$He(B make test-all e$B$NF0:n$r3NG’$7$F$"$j$^$9!#e(B

e$BHs\>o$K6=L#?\<$$$N$G$9$,!“$5$5$@$/$s$O%V%m%C%/$K4X$7$FJL$N9M$(e(B  
e$B$,$”$k$+$b$7$l$^$;$s!#H`$,;?@.$7$?$i\<h$j9~$\_$^$7$g$&!#e(B

---

<div class="post-metadata">

**Author:** ![wanabe](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/51bf81/32.png) [@wanabe](https://www.ruby-forum.com/u/wanabe)\
**Post date:** [May 1, 2008, 4:30pm UTC](https://www.ruby-forum.com/t/rb-yield-b-n9bb-hg-b/136377/3 "2008-05-01T16:30:18Z")

</div>

e$B!!$5$5$@$G$9!#e(B

Yukihiro M. wrote:

> |rb\_yield e$B$rO"B3$G8F$S=P$9$H$-$K!"@Q$s$@%U%l!\<%`$r;H$$$^$o$94X?t$r=q$-$^$7$?!#e(B  
> |e$B;n83E\*$Ke(B Fixnum#times e$B$K$@$1AH$\_9~$s$G$$$^$9$,!"$[$+$K$be(B  
> |Array#each, Range#each e$B$J$I$G;H$($k$H;W$$$^$9!#e(B  
> |  
> |ruby -e ‘GC.disable;t=Time.now;(10\*\*7).times {};p Time.now - t’  
> |e$B$3$s$J46$8$N4JC1$J7WB,$G$Oe(B 4.9e$BIC$+$ie(B 3.5 e$BIC$[$I$K=L$^$j$^$7$?!#e(B  
> |e$B0l1~\<j85$G$Oe(B make test e$B$He(B make test-all e$B$NF0:n$r3NG’$7$F$"$j$^$9!#e(B
> 
> e$BHs\>o$K6=L#?\<$$$N$G$9$,!"$5$5$@$/$s$O%V%m%C%/$K4X$7$FJL$N9M$(e(B  
> e$B$,$"$k$+$b$7$l$^$;$s!#H`$,;?@.$7$?$i\<h$j9~$\_$^$7$g$&!#e(B

e$B!!@N!"$3$&$$$&5!G=$rF~$l$F$$$^$7$?!#$,!“e(Bblock inlining (BI)  
e$B$N$[$&$,e(B  
e$B$$$$$@$m$&!”$H;W$C$F;W$$@Z$C$F:o$C$?$s$G$9$,!“e(BBI  
e$B$r\<BAu$9$k$N$O?’!9e(B  
e$B$HFq$7$$$N$G$A$g$C$H8=\<BE\*$8$c$J$$$J$!!”$H;W$$D\>$7$F$-$^$7$?!Je(BBIe$B$N;De(B  
e$B3\<$O;D$C$F$$$^$9$,!"B?J,$^$H$b$KF0$-$^$;$s!K!#e(B

e$B!!$H$$$&$o$1$G!"$d$C$Q$j$3$&$$$&;EAH$_$,NI$$$N$G$O$J$$$+!"$H$$$&0U8+e(B  
e$B$G$9!#J#;(EY$O\>e$,$k$N$G$9$,!"$=$l$G$H$/$K$^$D$b$H$5$s$,LdBj$J$$$N$Ge(B  
e$B$7$?$i!"%=!\<%9$r8+$F$+$i!"%3%_%C%H$5$;$F$$$?$@$-$^$9!#e(B

e$B!!5$$K$J$C$?E@$H$7$F$O!“e(Bcfp e$B$rD\>@\e(B ++  
e$B$J$I$GA`:n$9$k$N$O$^$:$$$+$Je(B  
e$B!J%^%/%m$r;H$C$F$/$@$5$$!K$H$+!”$=$N$"$?$j$G$9!#$"$H!“e(BRuby  
e$B$K$O7y$Je(B  
e$BNc30$,Bt;3$”$k$N$G!"$=$N$"$?$j$r3NG’$5$;$F$/$@$5$$!#e(B

e$B!!$A$J$\_$K!"%Y%s%A%^!\<%/$Oe(B make benchmark  
e$B$G3NG’$G$-$^$9!#$4MxMQ$/$@e(B  
e$B$5$$!#e(B

---

<div class="post-metadata">

**Author:** ![wanabe](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/51bf81/32.png) [@wanabe](https://www.ruby-forum.com/u/wanabe)\
**Post date:** [August 14, 2008, 7:16am UTC](https://www.ruby-forum.com/t/rb-yield-b-n9bb-hg-b/136377/4 "2008-08-14T07:16:40Z")

</div>

e$B$^$D$b$He(B e$B$f$-$R$m$G$9e(B

In message “Re: [ruby-dev:34560] rb\_yield e$B$N9bB.HGe(B”  
on Thu, 1 May 2008 19:27:02 +0900, wanabe [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
writes:  
|  
|e$B%o%J%Y$H?=$7$^$9!#e(B  
|  
|rb\_yield e$B$rO"B3$G8F$S=P$9$H$-$K!“@Q$s$@%U%l!\<%`$r;H$$$^$o$94X?t$r=q$-$^$7$?!#e(B  
|e$B;n83E\*$Ke(B Fixnum#times e$B$K$@$1AH$\_9~$s$G$$$^$9$,!”$[$+$K$be(B  
|Array#each, Range#each e$B$J$I$G;H$($k$H;W$$$^$9!#e(B  
|  
|ruby -e ‘GC.disable;t=Time.now;(10\*\*7).times {};p Time.now - t’  
|e$B$3$s$J46$8$N4JC1$J7WB,$G$Oe(B 4.9e$BIC$+$ie(B 3.5 e$BIC$[$I$K=L$^$j$^$7$?!#e(B  
|e$B0l1~\<j85$G$Oe(B make test e$B$He(B make test-all e$B$NF0:n$r3NG’$7$F$"$j$^$9!#e(B

e$B$3$l$r\<h$j9~$s$G$_$h$&$H:n6H$7$F$_$^$7$?!#7kO@$+$i$$$&$He(B

- e$BA4A3B.$/$J$i$J$+$C$?e(B
- e$B$7$+$be(Btest-alle$B$GMn$A$ke(B

e$B$H$$$&$3$H$G!“A4A3%@%a$G$9!#$3$l$,!“e(B5e$B7n$+$i:#$^$G$Ke(Bcoree$B$KF~$Ce(B  
e$B$?2~A1$N$?$aM-8z$J:GE,2=$G$J$/$J$C$?$N$+!”$=$l$H$b;d$N:n$C$?e(B  
e$B%Q%C%A$KITHw$,$”$k$N$+$O$^$@J,$+$j$^$;$s!#$^$?!“e(Btest-alle$B$GMne(B  
e$B$A$k860x$b$^$@J,$+$j$^$;$s!#\<+J,$N%@%a$52C8:$,\<B46$G$-$FHa$7e(B  
e$B$$$N$G$9$,!”$;$C$+$/:n6H$7$?$N$G!"8=\>u$N%Q%C%A$rEj9F$7$F$\*$-e(B  
e$B$^$9!#e(B

diff --git a/array.c b/array.c  
index e7eb280…a91fcb1 100644  
— a/array.c  
+++ b/array.c  
@@ -19,6 +19,9 @@ VALUE rb\_cArray;

static ID id\_cmp;

+VALUE rb\_fast\_yield\_loop(VALUE (\*i\_proc)(ANYARGS), VALUE val);  
+VALUE rb\_fast\_yield(VALUE val, void \*block);  
+  
#define ARY\_DEFAULT\_SIZE 16  
#define ARY\_MAX\_SIZE (LONG\_MAX / sizeof(VALUE))

@@ -1116,6 +1119,17 @@ rb\_ary\_insert(int argc, VALUE \*argv, VALUE ary)  
return ary;  
}

+static VALUE  
+each\_i(VALUE ary, void \*block)  
+{

- long i;
- 
- for (i=0; i\<RARRAY\_LEN(ary); i++) {
- rb\_fast\_yield(RARRAY\_PTR(ary)[i], block);
- }
- return Qnil;  
+}
- 

/\*

- call-seq:
- 

```
array.each {|item| block } -> array

```

@@ -1134,12 +1148,8 @@ rb\_ary\_insert(int argc, VALUE \*argv, VALUE ary)  
VALUE  
rb\_ary\_each(VALUE ary)  
{

- long i;
- RETURN\_ENUMERATOR(ary, 0, 0);
- for (i=0; i\<RARRAY\_LEN(ary); i++) {
- rb\_yield(RARRAY\_PTR(ary)[i]);
- }

- rb\_fast\_yield\_loop(each\_i, ary);  
return ary;  
}

diff --git a/eval.c b/eval.c  
index b39da54…fd08d0a 100644  
— a/eval.c  
+++ b/eval.c  
@@ -950,6 +950,32 @@ rb\_obj\_extend(int argc, VALUE \*argv, VALUE obj)

- in each module to the receiver.  
\*/

+const rb\_block\_t \*vm\_yield\_fast\_setup(rb\_thread\_t _th, int argc); /_  
vm.c \*/  
+void vm\_yield\_fast\_finish(rb\_thread\_t \*th, const rb\_block\_t _block); /_  
vm.c \*/  
+VALUE vm\_yield\_fast(rb\_thread\_t \*th, rb\_block\_t \*block, int argc, VALUE  
_argv); /_ vm.c \*/  
+  
+VALUE  
+rb\_fast\_yield\_loop(VALUE (\*i\_proc)(ANYARGS), VALUE val)  
+{

- rb\_thread\_t \*th = GET\_THREAD();
- const rb\_block\_t \*block = vm\_yield\_fast\_setup(th, 1);
- val = i\_proc(val, (void\*)block);
- vm\_yield\_fast\_finish(th, block);
- return val;  
+}
- 

+VALUE  
+rb\_fast\_yield(VALUE val, void \*block)  
+{

- return vm\_yield\_fast(GET\_THREAD(), (rb\_block\_t \*)block, 1, &val);  
+}
- 

+VALUE  
+rb\_fast\_yield\_argv(int argc, VALUE \*argv, void \*block)  
+{

- return vm\_yield\_fast(GET\_THREAD(), (rb\_block\_t \*)block, argc,  
argv);  
+}
- 

static VALUE  
top\_include(int argc, VALUE \*argv, VALUE self)  
{  
diff --git a/numeric.c b/numeric.c  
index 745a217…fbd6498 100644  
— a/numeric.c  
+++ b/numeric.c  
@@ -80,6 +80,9 @@ round(double x)  
}  
#endif

+VALUE rb\_fast\_yield\_loop(VALUE (\*i\_proc)(ANYARGS), VALUE val);  
+VALUE rb\_fast\_yield(VALUE val, void \*block);  
+  
static ID id\_coerce, id\_to\_i, id\_eq;

VALUE rb\_cNumeric;  
@@ -2992,17 +2995,24 @@ int\_downto(VALUE from, VALUE to)  
\*/

static VALUE  
+int\_dotimes\_i(VALUE num, void \*block)  
+{

- long i, end;
- 
- end = FIX2LONG(num);
- for (i=0; i\<end; i++) {
- rb\_fast\_yield(LONG2FIX(i), block);
- }
- return Qnil;  
+}
- 

+static VALUE  
int\_dotimes(VALUE num)  
{  
RETURN\_ENUMERATOR(num, 0, 0);

```
 if (FIXNUM_P(num)) {

```

- long i, end;
- 
- end = FIX2LONG(num);
- for (i=0; i\<end; i++) {
- 

```
 rb_yield(LONG2FIX(i));

```

- }

- rb\_fast\_yield\_loop(int\_dotimes\_i, num);  
}  
else {  
VALUE i = INT2FIX(0);  
diff --git a/vm.c b/vm.c  
index f06ba0e…6942462 100644  
— a/vm.c  
+++ b/vm.c  
@@ -437,10 +437,10 @@ vm\_make\_proc(rb\_thread\_t \*th,

/\* C → Ruby: block \*/

-static inline VALUE  
-invoke\_block\_from\_c(rb\_thread\_t \*th, const rb\_block\_t \*block,  
+static inline void  
+setup\_block(rb\_thread\_t \*th, const rb\_block\_t \*block,  
VALUE self, int argc, const VALUE \*argv,

- 

```
   const rb_block_t *blockptr, const NODE *cref)

```

- 

```
   const rb_block_t *blockptr)

```

{  
if (BUILTIN\_TYPE(block-\>iseq) != T\_NODE) {  
const rb\_iseq\_t \*iseq = block-\>iseq;  
@@ -453,8 +453,14 @@ invoke\_block\_from\_c(rb\_thread\_t \*th, const  
rb\_block\_t \*block,

CHECK\_STACK\_OVERFLOW(cfp, argc + iseq-\>stack\_max);

- for (i=0; i\<argc; i++) {
- 

```
 cfp->sp[i] = argv[i];

```

- if (argv) {

- 

```
 for (i=0; i<argc; i++) {

```

- cfp-\>sp[i] = argv[i];

- 

```
 }

```

- } else {

- 

```
 for (i=0; i<argc; i++) {

```

- cfp-\>sp[i] = Qnil;

- 

```
 }

```

}

opt\_pc = vm\_yield\_setup\_args(th, iseq, argc, cfp-\>sp, blockptr,  
@@ -464,11 +470,18 @@ invoke\_block\_from\_c(rb\_thread\_t \*th, const  
rb\_block\_t \*block,  
self, GC\_GUARDED\_PTR(block-\>dfp),  
iseq-\>iseq\_encoded + opt\_pc, cfp-\>sp + arg\_size, block-\>lfp,  
iseq-\>local\_size - arg\_size);

- }  
+}

+static inline VALUE  
+invoke\_block\_fast(rb\_thread\_t \*th, const rb\_block\_t \*block,

- 

```
 VALUE self, int argc, const VALUE *argv,

```

- 

```
 const rb_block_t *blockptr, const NODE *cref)

```

+{

- if (BUILTIN\_TYPE(block-\>iseq) != T\_NODE) {  
if (cref) {  
th-\>cfp-\>dfp[-1] = (VALUE)cref;  
}

- return vm\_eval\_body(th);  
}  
else {  
@@ -476,6 +489,16 @@ invoke\_block\_from\_c(rb\_thread\_t \*th, const  
rb\_block\_t \*block,  
}  
}

+static inline VALUE  
+invoke\_block\_from\_c(rb\_thread\_t \*th, const rb\_block\_t \*block,

- 

```
   VALUE self, int argc, const VALUE *argv,

```

- 

```
   const rb_block_t *blockptr, const NODE *cref)

```

+{

- setup\_block(th, block, self, argc, argv, blockptr);
- return invoke\_block\_fast(th, block, self, argc, argv, blockptr,  
cref);  
+}
- 
- 

static inline const rb\_block\_t \*  
check\_block(rb\_thread\_t \*th)  
{  
@@ -502,6 +525,56 @@ vm\_yield(rb\_thread\_t \*th, int argc, const VALUE  
\*argv)  
return invoke\_block\_from\_c(th, blockptr, blockptr-\>self, argc,  
argv, 0, 0);  
}

+const rb\_block\_t \*  
+vm\_yield\_fast\_setup(rb\_thread\_t \*th, int argc)  
+{

- const rb\_block\_t \*block = check\_block(th);
- setup\_block(th, block, block-\>self, argc, 0, 0);
- return block;  
+}
- 

+VALUE  
+vm\_yield\_fast(rb\_thread\_t \*th, rb\_block\_t \*block, int argc, VALUE  
\*argv)  
+{

- int i;
- int opt\_pc;
- VALUE retval;
- 
- if (BUILTIN\_TYPE(block-\>iseq) != T\_NODE) {
- CHECK\_STACK\_OVERFLOW(th-\>cfp, argc + block-\>iseq-\>stack\_max);
- for (i=0; i\<argc; i++) {
- 

```
 th->cfp->sp[i] = argv[i];

```

- }
- opt\_pc = vm\_yield\_setup\_args(th, block-\>iseq, argc, th-\>cfp-\>sp, 0,
- 

```
        block_proc_is_lambda(block->proc));

```

- for (i=0; iiseq-\>arg\_size; i++) {
- 

```
 th->cfp[2].sp[i] = th->cfp->sp[i];

```

- }
- th-\>cfp-\>pc = block-\>iseq-\>iseq\_encoded + opt\_pc;
- th-\>cfp-\>dfp[0] = GC\_GUARDED\_PTR(block-\>dfp);
- }
- retval = invoke\_block\_fast(th, block, block-\>self, argc, argv, 0,  
0);
- if (BUILTIN\_TYPE(block-\>iseq) != T\_NODE) {
- for (i=0; iiseq-\>local\_size; i++) {
- 

```
 th->cfp->sp[i] = Qnil;

```

- }
- th-\>cfp–;
- th-\>cfp-\>pc–;
- th-\>cfp–;
- }
- return retval;  
+}
- 

+void  
+vm\_yield\_fast\_finish(rb\_thread\_t \*th, const rb\_block\_t \*block)  
+{

- if (BUILTIN\_TYPE(block-\>iseq) != T\_NODE) {
- th-\>cfp++;
- th-\>cfp-\>pc++;
- th-\>cfp++;
- }  
+}
- 

VALUE  
vm\_invoke\_proc(rb\_thread\_t \*th, rb\_proc\_t \*proc, VALUE self,  
int argc, const VALUE \*argv, rb\_block\_t \* blockptr)  
diff --git a/vm\_eval.c b/vm\_eval.c  
index 1de5371…1c318e6 100644  
— a/vm\_eval.c  
+++ b/vm\_eval.c  
@@ -535,15 +535,25 @@ rb\_yield\_splat(VALUE values)  
return v;  
}

+VALUE rb\_fast\_yield\_loop(VALUE (\*i\_proc)(ANYARGS), VALUE val);  
+VALUE rb\_fast\_yield\_argv(int argc, VALUE \*argv, void \*block);  
+  
static VALUE  
-loop\_i(void)  
+loop\_ii(VALUE dummy, void \*block)  
{  
for (;😉 {

- rb\_yield\_0(0, 0);

- rb\_fast\_yield\_argv(0, 0, block);  
}  
return Qnil;  
}

+static VALUE  
+loop\_i(void)  
+{

- rb\_fast\_yield\_loop(loop\_ii, Qnil);
- return Qnil;  
+}
- 

/\*

- call-seq:
- 

```
loop {|| block }

```
