Ruby Forum Ruby-dev > rb_yield $B$N9bB.HG(B

Posted by wanabe (Guest)
on 01.05.2008 12:27
(Received via mailing list)
$B%o%J%Y$H?=$7$^$9!#(B

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

ruby -e 'GC.disable;t=Time.now;(10**7).times {};p Time.now - t'
$B$3$s$J46$8$N4JC1$J7WB,$G$O(B 4.9$BIC$+$i(B 3.5 
$BIC$[$I$K=L$^$j$^$7$?!#(B
$B0l1~<j85$G$O(B make test $B$H(B make test-all 
$B$NF0:n$r3NG'$7$F$"$j$^$9!#(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; i<block->iseq->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; i<block->iseq->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)
 {
Posted by Yukihiro Matsumoto (Guest)
on 01.05.2008 16:07
(Received via mailing list)
$B$^$D$b$H(B $B$f$-$R$m$G$9(B

In message "Re: [ruby-dev:34560] rb_yield $B$N9bB.HG(B"
    on Thu, 1 May 2008 19:27:02 +0900, wanabe <s.wanabe@gmail.com> 
writes:

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

$BHs>o$K6=L#?<$$$N$G$9$,!"$5$5$@$/$s$O%V%m%C%/$K4X$7$FJL$N9M$((B
$B$,$"$k$+$b$7$l$^$;$s!#H`$,;?@.$7$?$i<h$j9~$_$^$7$g$&!#(B
Posted by SASADA Koichi (Guest)
on 01.05.2008 16:30
(Received via mailing list)
$B!!$5$5$@$G$9!#(B

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

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

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

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

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