[前][次][番号順一覧][スレッド一覧]

ruby-changes:5579

From: ko1 <ko1@a...>
Date: Wed, 11 Jun 2008 06:47:07 +0900 (JST)
Subject: [ruby-changes:5579] Ruby:r17084 (trunk): * vm.c, eval_intern.h (PASS_PASSED_BLOCK):

ko1	2008-06-11 06:46:43 +0900 (Wed, 11 Jun 2008)

  New Revision: 17084

  Modified files:
    trunk/ChangeLog
    trunk/KNOWNBUGS.rb
    trunk/bootstraptest/test_eval.rb
    trunk/bootstraptest/test_proc.rb
    trunk/bootstraptest/test_syntax.rb
    trunk/bootstraptest/test_thread.rb
    trunk/eval.c
    trunk/eval_intern.h
    trunk/insns.def
    trunk/proc.c
    trunk/vm.c
    trunk/vm.h
    trunk/vm_core.h
    trunk/vm_dump.c
    trunk/vm_eval.c
    trunk/vm_evalbody.c
    trunk/vm_insnhelper.c

  Log:
    * vm.c, eval_intern.h (PASS_PASSED_BLOCK):
      set a VM_FRAME_FLAG_PASSED flag to skip this frame when
      searching ruby-level-cfp.
    * eval.c, eval_intern.h, proc.c: fix to check cfp.  if there is
      no valid ruby-level-cfp, cause RuntimeError exception.
      [ruby-dev:34128]
    * vm_core.h, vm_evalbody.c, vm.c, vm_dump.c, vm_insnhelper.c,
      insns.def: rename FRAME_MAGIC_* to VM_FRAME_MAGIC_*.
    * KNOWNBUGS.rb, bootstraptest/test*.rb: move solved bugs.
    


  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/vm_dump.c?r1=17084&r2=17083&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/vm.h?r1=17084&r2=17083&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/ChangeLog?r1=17084&r2=17083&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/vm_evalbody.c?r1=17084&r2=17083&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/eval.c?r1=17084&r2=17083&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/bootstraptest/test_proc.rb?r1=17084&r2=17083&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/KNOWNBUGS.rb?r1=17084&r2=17083&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/vm_core.h?r1=17084&r2=17083&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/proc.c?r1=17084&r2=17083&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/bootstraptest/test_thread.rb?r1=17084&r2=17083&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/bootstraptest/test_syntax.rb?r1=17084&r2=17083&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/vm.c?r1=17084&r2=17083&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/vm_eval.c?r1=17084&r2=17083&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/insns.def?r1=17084&r2=17083&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/vm_insnhelper.c?r1=17084&r2=17083&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/eval_intern.h?r1=17084&r2=17083&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/bootstraptest/test_eval.rb?r1=17084&r2=17083&diff_format=u

Index: eval_intern.h
===================================================================
--- eval_intern.h	(revision 17083)
+++ eval_intern.h	(revision 17084)
@@ -2,10 +2,16 @@
 #ifndef RUBY_EVAL_INTERN_H
 #define RUBY_EVAL_INTERN_H
 
-#define PASS_PASSED_BLOCK() \
-  (GET_THREAD()->passed_block = \
-   GC_GUARDED_PTR_REF((rb_block_t *)GET_THREAD()->cfp->lfp[0]))
+#define PASS_PASSED_BLOCK_TH(th) do { \
+    (th)->passed_block = GC_GUARDED_PTR_REF((rb_block_t *)(th)->cfp->lfp[0]); \
+    (th)->cfp->flag |= VM_FRAME_FLAG_PASSED; \
+} while (0)
 
+#define PASS_PASSED_BLOCK() do { \
+    rb_thread_t * const __th__ = GET_THREAD(); \
+    PASS_PASSED_BLOCK_TH(__th__); \
+} while (0)
+
 #include "ruby/ruby.h"
 #include "ruby/node.h"
 #include "ruby/util.h"
@@ -219,7 +225,7 @@
 
 VALUE vm_make_jump_tag_but_local_jump(int state, VALUE val);
 NODE *vm_cref(void);
-rb_control_frame_t *vm_get_ruby_level_cfp(rb_thread_t *th, rb_control_frame_t *cfp);
+rb_control_frame_t *vm_get_ruby_level_caller_cfp(rb_thread_t *th, rb_control_frame_t *cfp);
 VALUE rb_obj_is_proc(VALUE);
 VALUE rb_vm_call_cfunc(VALUE recv, VALUE (*func)(VALUE), VALUE arg, const rb_block_t *blockptr, VALUE filename);
 void rb_thread_terminate_all(void);
Index: insns.def
===================================================================
--- insns.def	(revision 17083)
+++ insns.def	(revision 17084)
@@ -996,7 +996,7 @@
 
     /* enter scope */
     vm_push_frame(th, class_iseq,
-		  FRAME_MAGIC_CLASS, klass, (VALUE) GET_DFP() | 0x02,
+		  VM_FRAME_MAGIC_CLASS, klass, (VALUE) GET_DFP() | 0x02,
 		  class_iseq->iseq_encoded, GET_SP(), 0,
 		  class_iseq->local_size);
     RESTORE_REGS();
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 17083)
+++ ChangeLog	(revision 17084)
@@ -1,3 +1,18 @@
+Wed Jun 11 05:53:20 2008  Koichi Sasada  <ko1@a...>
+
+	* vm.c, eval_intern.h (PASS_PASSED_BLOCK):
+	  set a VM_FRAME_FLAG_PASSED flag to skip this frame when
+	  searching ruby-level-cfp.
+
+	* eval.c, eval_intern.h, proc.c: fix to check cfp.  if there is
+	  no valid ruby-level-cfp, cause RuntimeError exception.
+	  [ruby-dev:34128]
+
+	* vm_core.h, vm_evalbody.c, vm.c, vm_dump.c, vm_insnhelper.c,
+	  insns.def: rename FRAME_MAGIC_* to VM_FRAME_MAGIC_*.
+
+	* KNOWNBUGS.rb, bootstraptest/test*.rb: move solved bugs.
+
 Wed Jun 11 05:55:31 2008  Hidetoshi NAGAI  <nagai@a...>
 
 	* ext/tk/tcltklib.c: SEGV when tcltk-stubs is enabled.
Index: bootstraptest/test_syntax.rb
===================================================================
--- bootstraptest/test_syntax.rb	(revision 17083)
+++ bootstraptest/test_syntax.rb	(revision 17084)
@@ -817,3 +817,14 @@
   end
 }, '[ruby-core:14537]'
 
+assert_equal 'ok', %q{
+  a = [false]
+  (a[0] &&= true) == false ? :ok : :ng
+}, '[ruby-dev:34679]'
+
+assert_normal_exit %q{
+  a = []
+  100.times {|i| a << i << nil << nil }
+  p a.compact!
+}
+
Index: bootstraptest/test_eval.rb
===================================================================
--- bootstraptest/test_eval.rb	(revision 17083)
+++ bootstraptest/test_eval.rb	(revision 17084)
@@ -282,3 +282,7 @@
     :ok
   end
 }, '[ruby-core:16796]'
+
+assert_normal_exit %q{
+  eval("", method(:proc).call {}.binding)
+}
Index: bootstraptest/test_proc.rb
===================================================================
--- bootstraptest/test_proc.rb	(revision 17083)
+++ bootstraptest/test_proc.rb	(revision 17084)
@@ -259,3 +259,20 @@
   GC.start
   block.call
 }, '[ruby-core:14885]'
+
+assert_equal 'ok', %q{
+  a = lambda {|x, y, &b| b }
+  b = a.curry[1]
+  if b.call(2){} == nil
+    :ng
+  else
+    :ok
+  end
+}, '[ruby-core:15551]'
+
+assert_equal 'ok', %q{
+  lambda {
+    break :ok
+    :ng
+  }.call
+}, '[ruby-dev:34646]'
Index: bootstraptest/test_thread.rb
===================================================================
--- bootstraptest/test_thread.rb	(revision 17083)
+++ bootstraptest/test_thread.rb	(revision 17084)
@@ -1,3 +1,5 @@
+# Thread and Fiber
+
 assert_equal %q{ok}, %q{
   Thread.new{
   }.join
@@ -268,3 +270,35 @@
   at_exit { Fiber.new{}.resume }
 }
 
+assert_normal_exit %q{
+  g = enum_for(:local_variables)
+  loop { g.next }
+}, '[ruby-dev:34128]'
+
+assert_normal_exit %q{
+  g = enum_for(:block_given?)
+  loop { g.next }
+}, '[ruby-dev:34128]'
+
+assert_normal_exit %q{
+  g = enum_for(:binding)
+  loop { g.next }
+}, '[ruby-dev:34128]'
+
+assert_normal_exit %q{
+  g = "abc".enum_for(:scan, /./)
+  loop { g.next }
+}, '[ruby-dev:34128]'
+
+assert_normal_exit %q{
+  g = Module.enum_for(:new)
+  loop { g.next }
+}, '[ruby-dev:34128]'
+
+assert_normal_exit %q{
+  Fiber.new(&Object.method(:class_eval)).resume("foo")
+}, '[ruby-dev:34128]'
+
+assert_normal_exit %q{
+  Thread.new("foo", &Object.method(:class_eval)).join
+}, '[ruby-dev:34128]'
Index: vm_core.h
===================================================================
--- vm_core.h	(revision 17083)
+++ vm_core.h	(revision 17084)
@@ -539,6 +539,29 @@
 #define VM_CALL_SUPER_BIT          (0x01 << 7)
 #define VM_CALL_SEND_BIT           (0x01 << 8)
 
+#define VM_FRAME_MAGIC_METHOD 0x11
+#define VM_FRAME_MAGIC_BLOCK  0x21
+#define VM_FRAME_MAGIC_CLASS  0x31
+#define VM_FRAME_MAGIC_TOP    0x41
+#define VM_FRAME_MAGIC_FINISH 0x51
+#define VM_FRAME_MAGIC_CFUNC  0x61
+#define VM_FRAME_MAGIC_PROC   0x71
+#define VM_FRAME_MAGIC_IFUNC  0x81
+#define VM_FRAME_MAGIC_EVAL   0x91
+#define VM_FRAME_MAGIC_LAMBDA 0xa1
+#define VM_FRAME_MAGIC_MASK_BITS   8
+#define VM_FRAME_MAGIC_MASK   (~(~0<<VM_FRAME_MAGIC_MASK_BITS))
+
+#define VM_FRAME_TYPE(cfp) ((cfp)->flag & VM_FRAME_MAGIC_MASK)
+
+/* other frame flag */
+#define VM_FRAME_FLAG_PASSED 0x0100
+
+
+#define RUBYVM_CFUNC_FRAME_P(cfp) \
+  (VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_CFUNC)
+
+
 /* inline (method|const) cache */
 #define NEW_INLINE_CACHE_ENTRY() NEW_WHILE(Qundef, 0, 0)
 #define ic_class  u1.value
Index: vm_eval.c
===================================================================
--- vm_eval.c	(revision 17083)
+++ vm_eval.c	(revision 17084)
@@ -66,7 +66,7 @@
 	{
 	    rb_control_frame_t *reg_cfp = th->cfp;
 	    rb_control_frame_t *cfp =
-		vm_push_frame(th, 0, FRAME_MAGIC_CFUNC,
+		vm_push_frame(th, 0, VM_FRAME_MAGIC_CFUNC,
 			      recv, (VALUE)blockptr, 0, reg_cfp->sp, 0, 1);
 
 	    cfp->method_id = id;
@@ -412,13 +412,15 @@
 {
     VALUE vid;
     VALUE self = RUBY_VM_PREVIOUS_CONTROL_FRAME(GET_THREAD()->cfp)->self;
+    rb_thread_t *th = GET_THREAD();
 
     if (argc == 0) {
 	rb_raise(rb_eArgError, "no method name given");
     }
 
     vid = *argv++; argc--;
-    PASS_PASSED_BLOCK();
+    PASS_PASSED_BLOCK_TH(th);
+
     return rb_call0(CLASS_OF(recv), recv, rb_to_id(vid), argc, argv, scope, self);
 }
 
@@ -687,11 +689,17 @@
 	    th->base_block = &env->block;
 	}
 	else {
-	    rb_control_frame_t *cfp = vm_get_ruby_level_cfp(th, th->cfp);
-	    block = *RUBY_VM_GET_BLOCK_PTR_IN_CFP(cfp);
-	    th->base_block = &block;
-	    th->base_block->self = self;
-	    th->base_block->iseq = cfp->iseq;	/* TODO */
+	    rb_control_frame_t *cfp = vm_get_ruby_level_caller_cfp(th, th->cfp);
+
+	    if (cfp != 0) {
+		block = *RUBY_VM_GET_BLOCK_PTR_IN_CFP(cfp);
+		th->base_block = &block;
+		th->base_block->self = self;
+		th->base_block->iseq = cfp->iseq;	/* TODO */
+	    }
+	    else {
+		rb_raise(rb_eRuntimeError, "Can't eval on top of Fiber or Thread");
+	    }
 	}
 
 	/* make eval iseq */
Index: proc.c
===================================================================
--- proc.c	(revision 17083)
+++ proc.c	(revision 17084)
@@ -275,10 +275,14 @@
 rb_binding_new(void)
 {
     rb_thread_t *th = GET_THREAD();
-    rb_control_frame_t *cfp = vm_get_ruby_level_cfp(th, th->cfp);
+    rb_control_frame_t *cfp = vm_get_ruby_level_caller_cfp(th, th->cfp);
     VALUE bindval = binding_alloc(rb_cBinding);
     rb_binding_t *bind;
 
+    if (cfp == 0) {
+	rb_raise(rb_eRuntimeError, "Can't create Binding Object on top of Fiber.");
+    }
+
     GetBindingPtr(bindval, bind);
     bind->env = vm_make_env_object(th, cfp);
     return bindval;
@@ -1187,11 +1191,12 @@
 	}
     }
     if ((state = EXEC_TAG()) == 0) {
+	rb_thread_t *th = GET_THREAD();
 	VALUE rb_vm_call(rb_thread_t * th, VALUE klass, VALUE recv, VALUE id, ID oid,
 			 int argc, const VALUE *argv, const NODE *body, int nosuper);
 
-	PASS_PASSED_BLOCK();
-	result = rb_vm_call(GET_THREAD(), data->oclass, data->recv, data->id, data->oid,
+	PASS_PASSED_BLOCK_TH(th);
+	result = rb_vm_call(th, data->oclass, data->recv, data->id, data->oid,
 			    argc, argv, data->body, 0);
     }
     POP_TAG();
Index: eval.c
===================================================================
--- eval.c	(revision 17083)
+++ eval.c	(revision 17084)
@@ -17,8 +17,6 @@
 VALUE rb_binding_new(void);
 NORETURN(void rb_raise_jump(VALUE));
 
-VALUE rb_f_block_given_p(void);
-
 ID rb_frame_callee(void);
 VALUE rb_eLocalJumpError;
 VALUE rb_eSysStackError;
@@ -586,9 +584,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));
+    cfp = vm_get_ruby_level_caller_cfp(th, RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp));
 
-    if (GC_GUARDED_PTR_REF(cfp->lfp[0])) {
+    if (cfp != 0 && GC_GUARDED_PTR_REF(cfp->lfp[0])) {
 	return Qtrue;
     }
     else {
@@ -1089,10 +1087,10 @@
     VALUE ary = rb_ary_new();
     rb_thread_t *th = GET_THREAD();
     rb_control_frame_t *cfp =
-	vm_get_ruby_level_cfp(th, RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp));
+	vm_get_ruby_level_caller_cfp(th, RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp));
     int i;
 
-    while (1) {
+    while (cfp) {
 	if (cfp->iseq) {
 	    for (i = 0; i < cfp->iseq->local_table_size; i++) {
 		ID lid = cfp->iseq->local_table[i];
Index: KNOWNBUGS.rb
===================================================================
--- KNOWNBUGS.rb	(revision 17083)
+++ KNOWNBUGS.rb	(revision 17084)
@@ -29,49 +29,6 @@
   C.new.foo
 }, '[ruby-core:14813]'
 
-assert_equal 'ok', %q{
-  a = lambda {|x, y, &b| b }
-  b = a.curry[1]
-  if b.call(2){} == nil
-    :ng
-  else
-    :ok
-  end
-}, '[ruby-core:15551]'
-
-assert_normal_exit %q{
-  g = Module.enum_for(:new)
-  loop { g.next }
-}, '[ruby-dev:34128]'
-
-assert_normal_exit %q{
-  Fiber.new(&Object.method(:class_eval)).resume("foo")
-}, '[ruby-dev:34128]'
-
-assert_normal_exit %q{
-  Thread.new("foo", &Object.method(:class_eval)).join
-}, '[ruby-dev:34128]'
-
-assert_normal_exit %q{
-  g = enum_for(:local_variables)
-  loop { g.next }
-}, '[ruby-dev:34128]'
-
-assert_normal_exit %q{
-  g = enum_for(:block_given?)
-  loop { g.next }
-}, '[ruby-dev:34128]'
-
-assert_normal_exit %q{
-  g = enum_for(:binding)
-  loop { g.next }
-}, '[ruby-dev:34128]'
-
-assert_normal_exit %q{
-  g = "abc".enum_for(:scan, /./)
-  loop { g.next }
-}, '[ruby-dev:34128]'
-
 assert_equal %q{[:bar, :foo]}, %q{
   def foo
     klass = Class.new do
@@ -84,24 +41,3 @@
   foo
 }, "[ ruby-Bugs-19304 ]"
 
-assert_equal 'ok', %q{
-  lambda {
-    break :ok
-    :ng
-  }.call
-}, '[ruby-dev:34646]'
-
-assert_normal_exit %q{
-  eval("", method(:proc).call {}.binding)
-}
-
-assert_normal_exit %q{
-  a = []
-  100.times {|i| a << i << nil << nil }
-  p a.compact!
-}
-
-assert_equal 'ok', %q{
-  a = [false]
-  (a[0] &&= true) == false ? :ok : :ng
-}, '[ruby-dev:34679]'
Index: vm_evalbody.c
===================================================================
--- vm_evalbody.c	(revision 17083)
+++ vm_evalbody.c	(revision 17084)
@@ -131,7 +131,7 @@
 	}
     }
 
-    if (VM_FRAME_TYPE(th->cfp) != FRAME_MAGIC_FINISH) {
+    if (VM_FRAME_TYPE(th->cfp) != VM_FRAME_MAGIC_FINISH) {
 	rb_bug("cfp consistency error");
     }
 
Index: vm.c
===================================================================
--- vm.c	(revision 17083)
+++ vm.c	(revision 17084)
@@ -52,7 +52,7 @@
 static inline VALUE
 rb_vm_set_finish_env(rb_thread_t * th)
 {
-    vm_push_frame(th, 0, FRAME_MAGIC_FINISH,
+    vm_push_frame(th, 0, VM_FRAME_MAGIC_FINISH,
 		  Qnil, th->cfp->lfp[0], 0,
 		  th->cfp->sp, 0, 1);
     th->cfp->pc = (VALUE *)&finish_insn_seq[0];
@@ -72,7 +72,7 @@
     /* for return */
     rb_vm_set_finish_env(th);
 
-    vm_push_frame(th, iseq, FRAME_MAGIC_TOP,
+    vm_push_frame(th, iseq, VM_FRAME_MAGIC_TOP,
 		  th->top_self, 0, iseq->iseq_encoded,
 		  th->cfp->sp, 0, iseq->local_size);
 }
@@ -86,7 +86,7 @@
 
     /* for return */
     rb_vm_set_finish_env(th);
-    vm_push_frame(th, iseq, FRAME_MAGIC_EVAL, block->self,
+    vm_push_frame(th, iseq, VM_FRAME_MAGIC_EVAL, block->self,
 		  GC_GUARDED_PTR(block->dfp), iseq->iseq_encoded,
 		  th->cfp->sp, block->lfp, iseq->local_size);
 
@@ -95,13 +95,35 @@
     }
 }
 
+static rb_control_frame_t *
+vm_get_ruby_level_next_cfp(rb_thread_t *th, rb_control_frame_t *cfp)
+{
+    while (!RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(th, cfp)) {
+	if (RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)) {
+	    return cfp;
+	}
+	cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
+    }
+    return 0;
+}
+
 rb_control_frame_t *
-vm_get_ruby_level_cfp(rb_thread_t *th, rb_control_frame_t *cfp)
+vm_get_ruby_level_caller_cfp(rb_thread_t *th, rb_control_frame_t *cfp)
 {
+    if (RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)) {
+	return cfp;
+    }
+
+    cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
+
     while (!RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(th, cfp)) {
 	if (RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)) {
 	    return cfp;
 	}
+
+	if ((cfp->flag & VM_FRAME_FLAG_PASSED) == 0) {
+	    break;
+	}
 	cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
     }
     return 0;
@@ -322,7 +344,7 @@
 {
     VALUE envval;
 
-    if (VM_FRAME_FLAG(cfp->flag) == FRAME_MAGIC_FINISH) {
+    if (VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_FINISH) {
 	/* for method_missing */
 	cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
     }
@@ -340,7 +362,7 @@
 vm_stack_to_heap(rb_thread_t * const th)
 {
     rb_control_frame_t *cfp = th->cfp;
-    while ((cfp = vm_get_ruby_level_cfp(th, cfp)) != 0) {
+    while ((cfp = vm_get_ruby_level_next_cfp(th, cfp)) != 0) {
 	vm_make_env_object(th, cfp);
 	cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
     }
@@ -423,7 +445,8 @@
 	const rb_iseq_t *iseq = block->iseq;
 	const rb_control_frame_t *cfp = th->cfp;
 	int i, opt_pc, arg_size = iseq->arg_size;
-	int type = block_proc_is_lambda(block->proc) ? FRAME_MAGIC_LAMBDA : FRAME_MAGIC_BLOCK;
+	int type = block_proc_is_lambda(block->proc) ?
+	  VM_FRAME_MAGIC_LAMBDA : VM_FRAME_MAGIC_BLOCK;
 
 	rb_vm_set_finish_env(th);
 
@@ -434,7 +457,7 @@
 	}
 
 	opt_pc = vm_yield_setup_args(th, iseq, argc, cfp->sp, blockptr,
-				     type == FRAME_MAGIC_LAMBDA);
+				     type == VM_FRAME_MAGIC_LAMBDA);
 
 	vm_push_frame(th, iseq, type,
 		      self, GC_GUARDED_PTR(block->dfp),
@@ -521,22 +544,30 @@
 
 /* special variable */
 
-static VALUE
-vm_cfp_svar_get(rb_thread_t *th, rb_control_frame_t *cfp, VALUE key)
+static rb_control_frame_t *
+vm_normal_frame(rb_thread_t *th, rb_control_frame_t *cfp)
 {
     while (cfp->pc == 0) {
-	cfp++;
+	cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
+	if (RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(th, cfp)) {
+	    return 0;
+	}
     }
-    return lfp_svar_get(th, cfp->lfp, key);
+    return cfp;
 }
 
+static VALUE
+vm_cfp_svar_get(rb_thread_t *th, rb_control_frame_t *cfp, VALUE key)
+{
+    cfp = vm_normal_frame(th, cfp);
+    return lfp_svar_get(th, cfp ? cfp->lfp : 0, key);
+}
+
 static void
 vm_cfp_svar_set(rb_thread_t *th, rb_control_frame_t *cfp, VALUE key, const VALUE val)
 {
-    while (cfp->pc == 0) {
-	cfp++;
-    }
-    lfp_svar_set(th, cfp->lfp, key, val);
+    cfp = vm_normal_frame(th, cfp);
+    lfp_svar_set(th, cfp ? cfp->lfp : 0, key, val);
 }
 
 static VALUE
@@ -663,7 +694,7 @@
 rb_sourcefile(void)
 {
     rb_thread_t *th = GET_THREAD();
-    rb_control_frame_t *cfp = vm_get_ruby_level_cfp(th, th->cfp);
+    rb_control_frame_t *cfp = vm_get_ruby_level_next_cfp(th, th->cfp);
 
     if (cfp) {
 	return RSTRING_PTR(cfp->iseq->filename);
@@ -677,7 +708,7 @@
 rb_sourceline(void)
 {
     rb_thread_t *th = GET_THREAD();
-    rb_control_frame_t *cfp = vm_get_ruby_level_cfp(th, th->cfp);
+    rb_control_frame_t *cfp = vm_get_ruby_level_next_cfp(th, th->cfp);
 
     if (cfp) {
 	return vm_get_sourceline(cfp);
@@ -691,7 +722,7 @@
 vm_cref(void)
 {
     rb_thread_t *th = GET_THREAD();
-    rb_control_frame_t *cfp = vm_get_ruby_level_cfp(th, th->cfp);
+    rb_control_frame_t *cfp = vm_get_ruby_level_next_cfp(th, th->cfp);
     return vm_get_cref(cfp->iseq, cfp->lfp, cfp->dfp);
 }
 
@@ -710,12 +741,15 @@
 static NODE *
 vm_cref_push(rb_thread_t *th, VALUE klass, int noex)
 {
+    rb_control_frame_t *cfp = vm_get_ruby_level_caller_cfp(th, th->cfp);
     NODE *cref = NEW_BLOCK(klass);
-    rb_control_frame_t *cfp = vm_get_ruby_level_cfp(th, th->cfp);
-
     cref->nd_file = 0;
-    cref->nd_next = vm_get_cref(cfp->iseq, cfp->lfp, cfp->dfp);
     cref->nd_visi = noex;
+
+    if (cfp) {
+	cref->nd_next = vm_get_cref(cfp->iseq, cfp->lfp, cfp->dfp);
+    }
+
     return cref;
 }
 
@@ -739,7 +773,8 @@
 rb_vm_cbase(void)
 {
     rb_thread_t *th = GET_THREAD();
-    rb_control_frame_t *cfp = vm_get_ruby_level_cfp(th, th->cfp);
+    rb_control_frame_t *cfp = vm_get_ruby_level_next_cfp(th, th->cfp);
+
     return vm_get_cbase(cfp->iseq, cfp->lfp, cfp->dfp);
 }
 
@@ -1183,7 +1218,7 @@
 
 	    /* push block frame */
 	    cfp->sp[0] = err;
-	    vm_push_frame(th, catch_iseq, FRAME_MAGIC_BLOCK,
+	    vm_push_frame(th, catch_iseq, VM_FRAME_MAGIC_BLOCK,
 			  cfp->self, (VALUE)cfp->dfp, catch_iseq->iseq_encoded,
 			  cfp->sp + 1 /* push value */, cfp->lfp, catch_iseq->local_size - 1);
 
@@ -1297,7 +1332,7 @@
     volatile VALUE iseqval = rb_iseq_new(0, filename, filename, 0, ISEQ_TYPE_TOP);
     VALUE val;
 
-    vm_push_frame(th, DATA_PTR(iseqval), FRAME_MAGIC_TOP,
+    vm_push_frame(th, DATA_PTR(iseqval), VM_FRAME_MAGIC_TOP,
 		  recv, (VALUE)blockptr, 0, reg_cfp->sp, 0, 1);
 
     val = (*func)(arg);
@@ -1306,14 +1341,6 @@
     return val;
 }
 
-int
-rb_vm_cfunc_funcall_p(const rb_control_frame_t *cfp)
-{
-    if (vm_cfunc_flags(cfp) & (VM_CALL_FCALL_BIT | VM_CALL_VCALL_BIT))
-	return Qtrue;
-    return Qfalse;
-}
-
 /* vm */
 
 static void
@@ -1548,7 +1575,7 @@
 
     th->cfp = (void *)(th->stack + th->stack_size);
 
-    vm_push_frame(th, 0, FRAME_MAGIC_TOP, Qnil, 0, 0,
+    vm_push_frame(th, 0, VM_FRAME_MAGIC_TOP, Qnil, 0, 0,
 		  th->stack, 0, 1);
 
     th->status = THREAD_RUNNABLE;
Index: vm.h
===================================================================
--- vm.h	(revision 17083)
+++ vm.h	(revision 17084)
@@ -219,27 +219,6 @@
   (!((th)->stack < (env) && (env) < ((th)->stack + (th)->stack_size)))
 #define ENV_VAL(env)        ((env)[1])
 
-#define FRAME_MAGIC_METHOD 0x11
-#define FRAME_MAGIC_BLOCK  0x21
-#define FRAME_MAGIC_CLASS  0x31
-#define FRAME_MAGIC_TOP    0x41
-#define FRAME_MAGIC_FINISH 0x51
-#define FRAME_MAGIC_CFUNC  0x61
-#define FRAME_MAGIC_PROC   0x71
-#define FRAME_MAGIC_IFUNC  0x81
-#define FRAME_MAGIC_EVAL   0x91
-#define FRAME_MAGIC_LAMBDA 0xa1
-#define FRAME_MAGIC_MASK_BITS   8
-#define FRAME_MAGIC_MASK   (~(~0<<FRAME_MAGIC_MASK_BITS))
-
-#define VM_FRAME_FLAG(type) ((VALUE)((type) & FRAME_MAGIC_MASK))
-
-#define VM_FRAME_TYPE(cfp) \
-  ((cfp)->flag & FRAME_MAGIC_MASK)
-
-#define RUBYVM_CFUNC_FRAME_P(cfp) \
-  (VM_FRAME_TYPE(cfp) == FRAME_MAGIC_CFUNC)
-
 #if OPT_CALL_THREADED_CODE
 #define THROW_EXCEPTION(exc) do { \
     th->errinfo = (VALUE)(exc); \
Index: vm_dump.c
===================================================================
--- vm_dump.c	(revision 17083)
+++ vm_dump.c	(revision 17084)
@@ -46,34 +46,34 @@
     }
 
     switch (VM_FRAME_TYPE(cfp)) {
-      case FRAME_MAGIC_TOP:
+      case VM_FRAME_MAGIC_TOP:
 	magic = "TOP";
 	break;
-      case FRAME_MAGIC_METHOD:
+      case VM_FRAME_MAGIC_METHOD:
 	magic = "METHOD";
 	break;
-      case FRAME_MAGIC_CLASS:
+      case VM_FRAME_MAGIC_CLASS:
 	magic = "CLASS";
 	break;
-      case FRAME_MAGIC_BLOCK:
+      case VM_FRAME_MAGIC_BLOCK:
 	magic = "BLOCK";
 	break;
-      case FRAME_MAGIC_FINISH:
+      case VM_FRAME_MAGIC_FINISH:
 	magic = "FINISH";
 	break;
-      case FRAME_MAGIC_CFUNC:
+      case VM_FRAME_MAGIC_CFUNC:
 	magic = "CFUNC";
 	break;
-      case FRAME_MAGIC_PROC:
+      case VM_FRAME_MAGIC_PROC:
 	magic = "PROC";
 	break;
-      case FRAME_MAGIC_LAMBDA:
+      case VM_FRAME_MAGIC_LAMBDA:
 	magic = "LAMBDA";
 	break;
-      case FRAME_MAGIC_IFUNC:
+      case VM_FRAME_MAGIC_IFUNC:
 	magic = "IFUNC";
 	break;
-      case FRAME_MAGIC_EVAL:
+      case VM_FRAME_MAGIC_EVAL:
 	magic = "EVAL";
 	break;
       case 0:
@@ -271,15 +271,15 @@
 
     /* stack trace header */
 
-    if (VM_FRAME_TYPE(cfp) == FRAME_MAGIC_METHOD ||
-	VM_FRAME_TYPE(cfp) == FRAME_MAGIC_TOP ||
-	VM_FRAME_TYPE(cfp) == FRAME_MAGIC_BLOCK ||
-	VM_FRAME_TYPE(cfp) == FRAME_MAGIC_CLASS ||
-	VM_FRAME_TYPE(cfp) == FRAME_MAGIC_PROC ||
-	VM_FRAME_TYPE(cfp) == FRAME_MAGIC_LAMBDA ||
-	VM_FRAME_TYPE(cfp) == FRAME_MAGIC_CFUNC ||
-	VM_FRAME_TYPE(cfp) == FRAME_MAGIC_IFUNC ||
-	VM_FRAME_TYPE(cfp) == FRAME_MAGIC_EVAL) {
+    if (VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_METHOD ||
+	VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_TOP ||
+	VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_BLOCK ||
+	VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_CLASS ||
+	VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_PROC ||
+	VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_LAMBDA ||
+	VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_CFUNC ||
+	VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_IFUNC ||
+	VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_EVAL) {
 
 	VALUE *ptr = dfp - local_size;
 
@@ -312,7 +312,7 @@
 		   ptr - th->stack);
 	}
     }
-    else if (VM_FRAME_TYPE(cfp) == FRAME_MAGIC_FINISH) {
+    else if (VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_FINISH) {
 	if ((th)->stack + (th)->stack_size > (VALUE *)(cfp + 2)) {
 	    stack_dump_each(th, cfp + 1);
 	}
@@ -362,7 +362,7 @@
 {
     rb_iseq_t *iseq = cfp->iseq;
 
-    if (iseq != 0 && VM_FRAME_TYPE(cfp) != FRAME_MAGIC_FINISH) {
+    if (iseq != 0 && VM_FRAME_TYPE(cfp) != VM_FRAME_MAGIC_FINISH) {
 	VALUE *seq = iseq->iseq;
 	int pc = cfp->pc - iseq->iseq_encoded;
 
Index: vm_insnhelper.c
===================================================================
--- vm_insnhelper.c	(revision 17083)
+++ vm_insnhelper.c	(revision 17084)
@@ -367,7 +367,7 @@
     EXEC_EVENT_HOOK(th, RUBY_EVENT_C_CALL, recv, id, klass);
     {
 	rb_control_frame_t *cfp =
-	    vm_push_frame(th, 0, FRAME_MAGIC_CFUNC | (flag << FRAME_MAGIC_MASK_BITS),
+	    vm_push_frame(th, 0, VM_FRAME_MAGIC_CFUNC,
 			  recv, (VALUE) blockptr, 0, reg_cfp->sp, 0, 1);
 
 	cfp->method_id = id;
@@ -380,6 +380,7 @@
 	if (reg_cfp != th->cfp + 1) {
 	    rb_bug("cfp consistency error - send");
 	}
+
 	vm_pop_frame(th);
     }
     EXEC_EVENT_HOOK(th, RUBY_EVENT_C_RETURN, recv, id, klass);
@@ -387,14 +388,6 @@
     return val;
 }
 
-static inline int
-vm_cfunc_flags(const rb_control_frame_t *cfp)
-{
-    if (RUBYVM_CFUNC_FRAME_P(cfp))
-	return cfp->flag >> FRAME_MAGIC_MASK_BITS;
-    return 0;
-}
-
 static inline VALUE
 vm_call_bmethod(rb_thread_t *th, ID id, VALUE procval, VALUE recv,
 		VALUE klass, int argc, VALUE *argv, rb_block_t *blockptr)
@@ -455,7 +448,7 @@
 	}
 
 	vm_push_frame(th, iseq,
-		      FRAME_MAGIC_METHOD, recv, (VALUE) blockptr,
+		      VM_FRAME_MAGIC_METHOD, recv, (VALUE) blockptr,
 		      iseq->iseq_encoded + opt_pc, sp, 0, 0);
 
 	cfp->sp = rsp - 1 /* recv */;
@@ -478,7 +471,7 @@
 	}
 
 	vm_push_frame(th, iseq,
-		      FRAME_MAGIC_METHOD, recv, (VALUE) blockptr,
+		      VM_FRAME_MAGIC_METHOD, recv, (VALUE) blockptr,
 		      iseq->iseq_encoded + opt_pc, sp, 0, 0);
     }
 }
@@ -675,7 +668,7 @@
 	blockarg = Qnil;
     }
 
-    vm_push_frame(th, 0, FRAME_MAGIC_IFUNC,
+    vm_push_frame(th, 0, VM_FRAME_MAGIC_IFUNC,
 		  self, (VALUE)block->dfp,
 		  0, th->cfp->sp, block->lfp, 1);
 
@@ -831,7 +824,7 @@
 				     block_proc_is_lambda(block->proc));
 
 	vm_push_frame(th, iseq,
-		      FRAME_MAGIC_BLOCK, block->self, (VALUE) block->dfp,
+		      VM_FRAME_MAGIC_BLOCK, block->self, (VALUE) block->dfp,
 		      iseq->iseq_encoded + opt_pc, rsp + arg_size, block->lfp,
 		      iseq->local_size - arg_size);
 
@@ -849,23 +842,18 @@
 static inline NODE *
 lfp_svar_place(rb_thread_t *th, VALUE *lfp)
 {
-    NODE *svar;
+    VALUE *svar;
 
-    if (th->local_lfp != lfp) {
-	svar = (NODE *)lfp[-1];
-	if ((VALUE)svar == Qnil) {
-	    svar = NEW_IF(Qnil, Qnil, Qnil);
-	    lfp[-1] = (VALUE)svar;
-	}
+    if (lfp && th->local_lfp != lfp) {
+	svar = &lfp[-1];
     }
     else {
-	svar = (NODE *)th->local_svar;
-	if ((VALUE)svar == Qnil) {
-	    svar = NEW_IF(Qnil, Qnil, Qnil);
-	    th->local_svar = (VALUE)svar;
-	}
+	svar = &th->local_svar;
     }
-    return svar;
+    if (NIL_P(*svar)) {
+	*svar = (VALUE)NEW_IF(Qnil, Qnil, Qnil);
+    }
+    return (NODE *)*svar;
 }
 
 static VALUE
@@ -1238,7 +1226,7 @@
 		    rb_bug("VM (throw): can't find break base.");
 		}
 
-		if (VM_FRAME_TYPE(cfp) == FRAME_MAGIC_LAMBDA) {
+		if (VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_LAMBDA) {
 		    /* lambda{... break ...} */
 		    is_orphan = 0;
 		    pt = GET_LFP();
@@ -1297,7 +1285,7 @@
 		 */
 		while ((VALUE *) cfp < th->stack + th->stack_size) {
 		    if (GET_DFP() == dfp) {
-			if (VM_FRAME_TYPE(cfp) == FRAME_MAGIC_LAMBDA) {
+			if (VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_LAMBDA) {
 			    /* in lambda */
 			    is_orphan = 0;
 			    break;

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]