[前][次][番号順一覧][スレッド一覧][生データ]

yarv-diff:283

From: ko1 atdot.net
Date: 20 Feb 2006 05:15:09 -0000
Subject: [yarv-diff:283] r447 - in trunk: . ext/win32ole test/ruby yarvtest

Author: ko1
Date: 2006-02-20 14:15:09 +0900 (Mon, 20 Feb 2006)
New Revision: 447

Modified:
   trunk/
   trunk/ChangeLog
   trunk/compile.c
   trunk/eval.c
   trunk/ext/win32ole/.document
   trunk/insns.def
   trunk/test.rb
   trunk/test/ruby/test_signal.rb
   trunk/thread.c
   trunk/thread_pthread.h
   trunk/thread_win32.h
   trunk/vm.c
   trunk/vm.h
   trunk/vm_dump.c
   trunk/yarvcore.c
   trunk/yarvcore.h
   trunk/yarvtest/test_bin.rb
   trunk/yarvtest/test_block.rb
   trunk/yarvtest/test_method.rb
   trunk/yarvtest/test_thread.rb
Log:
 r680@lermite:  ko1 | 2006-02-20 14:13:44 +0900
 	* compile.c : support block parameter which is NODE_ATTRASGN
 
 	* yarvtest/test_block.rb : add tests for above
 
 	* compile.c : fix NODE_DASGN_CURR level check
 
 	* compile.c : fix "||=" (at firtst, check "defined? val")
 
 	* compile.c : fix NODE_MATCH3 (permute receiver and argument)
 
 	* yarvtest/test_bin.rb : add tests for above
 
 	* eval.c : add rb_each()
 
 	* test/ruby/test_signal.rb : increment a timeout value
 
 	* thread.c, yarvcore.h : fix "join" flow
 
 	* thread_pthread.h : ditto
 
 	* thread_win32.h : ditto
 
 	* yarvtest/test_thread.rb : add a test for above
 
 	* vm.h, vm.c, vm_dump.c, insns.def : add FRAME_MAGIC_LAMBDA and
 	support return from lambda (especially retrun from method defined
 	by "define_method")
 
 	* yarvtest/test_method.rb : add a test for above
 
 	* yarvcore.c : remove unused functions
 



Property changes on: trunk
___________________________________________________________________
Name: svk:merge
   - 81cd9672-7512-7e48-ae48-6936450e977d:/local/yarv/trunk:670
   + 81cd9672-7512-7e48-ae48-6936450e977d:/local/yarv/trunk:680

Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog	2006-02-20 02:22:42 UTC (rev 446)
+++ trunk/ChangeLog	2006-02-20 05:15:09 UTC (rev 447)
@@ -4,6 +4,41 @@
 #  from Mon, 03 May 2004 01:24:19 +0900
 #
 
+2006-02-20(Mon) 13:58:03 +0900  Koichi Sasada  <ko1 atdot.net>
+
+	* compile.c : support block parameter which is NODE_ATTRASGN
+
+	* yarvtest/test_block.rb : add tests for above
+
+	* compile.c : fix NODE_DASGN_CURR level check
+
+	* compile.c : fix "||=" (at firtst, check "defined? val")
+
+	* compile.c : fix NODE_MATCH3 (permute receiver and argument)
+
+	* yarvtest/test_bin.rb : add tests for above
+
+	* eval.c : add rb_each()
+
+	* test/ruby/test_signal.rb : increment a timeout value
+
+	* thread.c, yarvcore.h : fix "join" flow
+
+	* thread_pthread.h : ditto
+
+	* thread_win32.h : ditto
+
+	* yarvtest/test_thread.rb : add a test for above
+
+	* vm.h, vm.c, vm_dump.c, insns.def : add FRAME_MAGIC_LAMBDA and
+	support return from lambda (especially retrun from method defined
+	by "define_method")
+
+	* yarvtest/test_method.rb : add a test for above
+
+	* yarvcore.c : remove unused functions
+
+
 2006-02-20(Mon) 11:22:31 +0900  Minero Aoki  <aamine loveruby.net>
 
 	* test/ruby/test_eval.rb: now Object#funcall is defined.

Modified: trunk/compile.c
===================================================================
--- trunk/compile.c	2006-02-20 02:22:42 UTC (rev 446)
+++ trunk/compile.c	2006-02-20 05:15:09 UTC (rev 447)
@@ -398,6 +398,7 @@
 	elem2->next->prev = elem2;
     }
 }
+#endif
 
 /*
  * elemX, elem1 => elemX, elem2, elem1
@@ -412,7 +413,6 @@
 	elem2->prev->next = elem2;
     }
 }
-#endif
 /*******************************************/
 
 /*
@@ -570,7 +570,6 @@
 debug_list(LINK_ANCHOR *anchor)
 {
     LINK_ELEMENT *list = FIRST_ELEMENT(anchor);
-    int i = 0;
     printf("----\n");
     printf("anch: %p, frst: %p, last: %p\n", &anchor->anchor,
 	   anchor->anchor.next, anchor->last);
@@ -943,19 +942,32 @@
 }
 
 static int
-set_block_initializer(yarv_iseq_t *iseq, NODE * node, LINK_ANCHOR *anchor)
+set_block_initializer(yarv_iseq_t *iseq, NODE * node, LINK_ANCHOR *anchor, int didx)
 {
     DECL_ANCHOR(anc);
     LINK_ELEMENT *elem;
-
+    
     COMPILE_POPED(anc, "set_block_local_tbl#masgn/other", node);
 
-    elem = FIRST_ELEMENT(anc);
-    if (elem->type == ISEQ_ELEMENT_INSN &&
-	((INSN *)elem)->insn_id == BIN(putnil)) {
-	SHIFT_ELEMENT(anc);
+    if (nd_type(node) == NODE_ATTRASGN) {
+	INSN *iobj = (INSN *)anc->last->prev;
+	iobj->operands[1] = INT2FIX(FIX2INT(iobj->operands[1]) + 1);
+	INSERT_ELEM_PREV((void *)iobj,
+			 (void *)new_insn_body(iseq, nd_line(node),
+					       BIN(getdynamic), 2,
+					       INT2FIX(didx), INT2FIX(0)));
     }
+    else {
+	ADD_INSN2(anchor, nd_line(node), getdynamic,
+		  INT2FIX(didx), INT2FIX(0));
+	elem = FIRST_ELEMENT(anc);
+	if (elem->type == ISEQ_ELEMENT_INSN &&
+	    ((INSN *)elem)->insn_id == BIN(putnil)) {
+	    SHIFT_ELEMENT(anc);
+	}
+    }
     APPEND_LIST(anchor, anc);
+    
     return COMPILE_OK;
 }
 
@@ -986,13 +998,8 @@
 		while (lhsn) {
 		    if (nd_type(lhsn->nd_head) != NODE_DASGN_CURR) {
 			/* idx-th param, current level */
-
-			ADD_INSN2(anchor, nd_line(node),
-				  getdynamic,
-				  INT2FIX(iseq->local_size - i),
-				  INT2FIX(0));
 			set_block_initializer(iseq, lhsn->nd_head,
-					      anchor);
+					      anchor, iseq->local_size - i);
 		    }
 		    i++;
 		    lhsn = lhsn->nd_next;
@@ -1005,10 +1012,8 @@
 		iseq->arg_rest = i + 1;
 
 		if (nd_type(massign->nd_args) != NODE_DASGN_CURR) {
-		    ADD_INSN2(anchor, nd_line(node), getdynamic,
-			      INT2FIX(iseq->local_size - i), INT2FIX(0));
 		    set_block_initializer(iseq, massign->nd_args,
-					  anchor);
+					  anchor, iseq->local_size - i);
 		}
 	    }
 	    else if (i == 1) {
@@ -1023,9 +1028,7 @@
 	    /* for 1.x compatibility */
 	default:{
 		/* first param, current level */
-		ADD_INSN2(anchor, nd_line(node), getdynamic,
-			  INT2FIX(iseq->local_size), INT2FIX(0));
-		set_block_initializer(iseq, nargs, anchor);
+		set_block_initializer(iseq, nargs, anchor, iseq->local_size);
 		break;
 	    }
 	}
@@ -1987,23 +1990,24 @@
 
     switch (nd_type(node)) {
     case NODE_ATTRASGN:{
-	    INSN *iobj;
-	    VALUE dupidx;
+	INSN *iobj;
+	VALUE dupidx;
 
-	    COMPILE(ret, "masgn lhs (NODE_ATTRASGN)", node);
-	    iobj = (INSN *)ret->last;
-	    ret->last = ret->last->prev;
+	COMPILE(ret, "masgn lhs (NODE_ATTRASGN)", node);
+	iobj = (INSN *)ret->last;
+	ret->last = ret->last->prev;
 
-	    dupidx = iobj->operands[1];	// RARRAY(iobj->operands)->ptr[1]; /* send sym, num, ... */
-	    dupidx = INT2FIX(FIX2INT(dupidx) + 1);
-	    iobj->operands[1] = dupidx;
+	dupidx = iobj->operands[1];
+	// RARRAY(iobj->operands)->ptr[1]; /* send sym, num, ... */
+	dupidx = INT2FIX(FIX2INT(dupidx) + 1);
+	iobj->operands[1] = dupidx;
 
-	    ADD_INSN1(ret, nd_line(node), topn, dupidx);
-	    ADD_ELEM(ret, (LINK_ELEMENT *)iobj);
-	    ADD_INSN(ret, nd_line(node), pop);	/* result */
-	    ADD_INSN(ret, nd_line(node), pop);	/* rhs    */
-	    break;
-	}
+	ADD_INSN1(ret, nd_line(node), topn, dupidx);
+	ADD_ELEM(ret, (LINK_ELEMENT *)iobj);
+	ADD_INSN(ret, nd_line(node), pop);	/* result */
+	ADD_INSN(ret, nd_line(node), pop);	/* rhs    */
+	break;
+    }
 
     case NODE_MASGN:
 	COMPILE_POPED(ret, "nest masgn lhs", node);
@@ -3109,7 +3113,7 @@
 	  idx = get_dyna_var_idx(iseq, node->nd_vid, &lv, &ls);
 	  if (nd_type(node) == NODE_DASGN_CURR &&
 	      lv > 0 &&
-	      iseq->type != ISEQ_TYPE_RESCUE &&
+	      iseq->type == ISEQ_TYPE_BLOCK &&
 	      iseq->compile_data->for_iseq != 1) {
 
 	      dpi(node->nd_vid);
@@ -3342,17 +3346,26 @@
       case NODE_OP_ASGN_AND:
       case NODE_OP_ASGN_OR:{
 	  LABEL *lfin = NEW_LABEL(nd_line(node));
-
-	  COMPILE(ret, "NODE_OP_ASGN_AND#nd_head", node->nd_head);
+	  LABEL *lassign = NEW_LABEL(nd_line(node));
+	  
+	  if (nd_type(node) == NODE_OP_ASGN_OR) {
+	      defined_expr(iseq, ret, node->nd_head, lassign, Qfalse);
+	      ADD_INSNL(ret, nd_line(node), unless, lassign);
+	  }
+	  
+	  COMPILE(ret, "NODE_OP_ASGN_AND/OR#nd_head", node->nd_head);
 	  ADD_INSN(ret, nd_line(node), dup);
+	  
 	  if (nd_type(node) == NODE_OP_ASGN_AND) {
 	      ADD_INSNL(ret, nd_line(node), unless, lfin);
 	  }
 	  else {
 	      ADD_INSNL(ret, nd_line(node), if, lfin) ;
 	  }
+
 	  ADD_INSN(ret, nd_line(node), pop);
-	  COMPILE(ret, "NODE_OP_ASGN_AND#nd_value", node->nd_value);
+	  ADD_LABEL(ret, lassign);
+	  COMPILE(ret, "NODE_OP_ASGN_AND/OR#nd_value", node->nd_value);
 	  ADD_LABEL(ret, lfin);
 
 	  if (poped) {
@@ -3825,14 +3838,20 @@
 	  DECL_ANCHOR(recv);
 	  DECL_ANCHOR(val);
 
-	  if (nd_type(node) == NODE_MATCH) {
+	  switch(nd_type(node)) {
+	    case NODE_MATCH:
 	      ADD_INSN1(recv, nd_line(node), putobject, node->nd_lit);
 	      ADD_INSN2(val, nd_line(node), getspecial, INT2FIX(0),
 			INT2FIX(0));
-	  }
-	  else {
+	      break;
+	    case NODE_MATCH2:
 	      COMPILE(recv, "reciever", node->nd_recv);
 	      COMPILE(val, "value", node->nd_value);
+	      break;
+	    case NODE_MATCH3:
+	      COMPILE(recv, "reciever", node->nd_value);
+	      COMPILE(val, "value", node->nd_recv);
+	      break;
 	  }
 
 
@@ -4426,7 +4445,7 @@
 	    char type = types[j];
 
 	    switch (type) {
-	    case TS_OFFSET:	/* label(destination position) */
+	      case TS_OFFSET:	/* label(destination position) */
 		{
 		    char buff[0x100];
 		    LABEL *lobj = (LABEL *)OPERAND_AT(insnobj, j);
@@ -4435,29 +4454,31 @@
 		    break;
 		}
 		break;
-	    case TS_BLOCKISEQ:	/* block */
-	    case TS_NUM:	/* ulong */
-	    case TS_VALUE:	/* VALUE */
+	      case TS_LINDEX:
+	      case TS_DINDEX:
+	      case TS_BLOCKISEQ:	/* block */
+	      case TS_NUM:	/* ulong */
+	      case TS_VALUE:	/* VALUE */
 		rb_str_concat(str, rb_inspect(OPERAND_AT(insnobj, j)));
 		break;
-	    case TS_ID:	/* ID */
+	      case TS_ID:	/* ID */
 		rb_str_concat(str, rb_inspect(OPERAND_AT(insnobj, j)));
 		break;
-	    case TS_GENTRY:
+	      case TS_GENTRY:
 		{
 		    struct global_entry *entry = (struct global_entry *)
-			(OPERAND_AT(insnobj, j) & (~1));
+		      (OPERAND_AT(insnobj, j) & (~1));
 		    rb_str_cat2(str, rb_id2name(entry->id));
 		}
-	    case TS_IC:	/* method cache */
+	      case TS_IC:	/* method cache */
 		rb_str_cat2(str, "<ic>");
 		break;
-	    case TS_CDHASH:	/* case/when condition cache */
+	      case TS_CDHASH:	/* case/when condition cache */
 		rb_str_cat2(str, "<ch>");
 		break;
-	    default:{
-		    rb_bug("unknown operand type: %c", type);
-		}
+	      default:{
+		  rb_bug("unknown operand type: %c", type);
+	      }
 	    }
 	    if (types[j + 1]) {
 		rb_str_cat2(str, ", ");

Modified: trunk/eval.c
===================================================================
--- trunk/eval.c	2006-02-20 02:22:42 UTC (rev 446)
+++ trunk/eval.c	2006-02-20 05:15:09 UTC (rev 447)
@@ -1335,6 +1335,13 @@
 }
 
 VALUE
+rb_each(VALUE obj)
+{
+    return rb_call(CLASS_OF(obj), obj, rb_intern("each"), 0, 0,
+		   NOEX_PRIVATE);
+}
+
+VALUE
 rb_rescue2(VALUE (*b_proc) (ANYARGS), VALUE data1, VALUE (*r_proc) (ANYARGS),
 	   VALUE data2, ...)
 {
@@ -1746,18 +1753,15 @@
 }
 
 VALUE
-rb_call_super(argc, argv)
-    int argc;
-    const VALUE *argv;
+rb_call_super(int argc, const VALUE *argv)
 {
     return th_call_super(GET_THREAD(), argc, argv);
 }
 
 static VALUE
-backtrace(lev)
-    int lev;
+backtrace(int lev)
 {
-    return yarv_backtrace(lev);
+    return th_backtrace(GET_THREAD(), lev);
 }
 
 /*

Modified: trunk/ext/win32ole/.document
===================================================================
--- trunk/ext/win32ole/.document	2006-02-20 02:22:42 UTC (rev 446)
+++ trunk/ext/win32ole/.document	2006-02-20 05:15:09 UTC (rev 447)
@@ -1 +0,0 @@
-win32ole.c

Modified: trunk/insns.def
===================================================================
--- trunk/insns.def	2006-02-20 02:22:42 UTC (rev 446)
+++ trunk/insns.def	2006-02-20 05:15:09 UTC (rev 447)
@@ -1416,14 +1416,23 @@
 	    else if (state == TAG_RETURN) {
 		yarv_control_frame_t *cfp = GET_CFP();
 		int is_orphan = 1;
-
+		VALUE *dfp = GET_DFP();
+		
 		/* check orphan */
 		while ((VALUE *) cfp < th->stack + th->stack_size) {
-		    cfp++;
 		    if (GET_LFP() == cfp->lfp) {
 			is_orphan = 0;
 			break;
 		    }
+		    else if (dfp == cfp->dfp) {
+			/* return from lambda{} */
+			if (cfp->magic == FRAME_MAGIC_LAMBDA) {
+			    is_orphan = 0;
+			    break;
+			}
+			dfp = GC_GUARDED_PTR_REF(*cfp->dfp);
+		    }
+		    cfp++;
 		}
 		if (is_orphan) {
 		    th_localjump_error("unexpected return", throwobj,

Modified: trunk/test/ruby/test_signal.rb
===================================================================
--- trunk/test/ruby/test_signal.rb	2006-02-20 02:22:42 UTC (rev 446)
+++ trunk/test/ruby/test_signal.rb	2006-02-20 05:15:09 UTC (rev 447)
@@ -50,7 +50,7 @@
       assert_nothing_raised("[ruby-dev:26128]") {
         Process.kill(:USR1, pid)
         begin
-          Timeout.timeout(1) {
+          Timeout.timeout(3) {
             Process.waitpid pid
           }
         rescue Timeout::Error

Modified: trunk/test.rb
===================================================================
--- trunk/test.rb	2006-02-20 02:22:42 UTC (rev 446)
+++ trunk/test.rb	2006-02-20 05:15:09 UTC (rev 447)
@@ -1,4 +1,140 @@
+ary = ['123']
 
+if target = ary.shift and /^[a-z-]+$/ =~ target
+  
+end
+
+__END__
+
+100000.times{|i|
+  Thread.new{}.join
+  #p i
+}
+__END__
+
+
+a = Object.new
+def a.b=(x)
+  p x
+end
+
+[1].each{|a.b[0]|
+  
+}
+
+__END__
+
+
+c = {}
+[1].each do |c[:help]|
+  p c
+end
+
+__END__
+
+def tarai( x, y, z )
+  if x <= y
+  then y
+  else tarai(tarai(x-1, y, z),
+             tarai(y-1, z, x),
+             tarai(z-1, x, y))
+  end
+end
+
+pid = fork(){
+  tarai(12, 6, 0)
+}
+tarai(12, 6, 0)
+Process.waitpid(pid)
+p :exit
+
+__END__
+x = :sym;y = /reg/
+/reg/ =~ x
+__END__
+
+eval(':=(')
+
+__END__
+t = Thread.new{
+        sleep
+      }
+      sleep 0.1
+      t.raise
+      while t.alive?
+        Thread.pass
+      end
+
+      p begin
+        t.join
+        :ng
+      rescue
+        :ok
+      end
+__END__
+
+p begin
+        Thread.new{
+          raise "ok"
+        }.join
+      rescue => e
+        e
+      end
+
+__END__
+
+
+1000000.times{|i|
+  p i if i % 10 == 0
+  t = Thread.new{}
+  while t.alive?
+    Thread.pass
+  end
+}
+
+__END__
+
+1.times{
+  begin
+    p
+  ensure
+    foo = nil #noop = nil
+  end
+}
+
+__END__
+
+
+
+p(@@x ||= 1)
+
+
+__END__
+p(@x||=1)
+p @x
+
+__END__
+
+
+unless defined?(@a) && @a
+  @a = 1
+end
+
+__END__
+
+class A
+  @@d = 3
+  unless defined?(@@d) && @@d
+    @@d = 1
+  end
+  #@@d ||= 1
+  p @@d
+end
+
+
+__END__
+
+
 class TrueClass
   @@cvar = :TrueCvar
 end

Modified: trunk/thread.c
===================================================================
--- trunk/thread.c	2006-02-20 02:22:42 UTC (rev 446)
+++ trunk/thread.c	2006-02-20 05:15:09 UTC (rev 447)
@@ -44,7 +44,9 @@
 #define THREAD_DEBUG 0
 
 static void sleep_for_polling();
-static void sleep_timeval(yarv_thread_t *th, struct timeval time);
+static int sleep_timeval(yarv_thread_t *th, struct timeval time);
+static void sleep_wait_for_interrupt(yarv_thread_t *th, double sleepsec);
+static void sleep_forever(yarv_thread_t *th);
 static double timeofday();
 struct timeval rb_time_interval(VALUE);
 static int rb_thread_dead(yarv_thread_t *th);
@@ -173,6 +175,13 @@
 	th->status = THREAD_KILLED;
 	thread_debug("thread end: %p\n", th);
 	st_delete_wrap(GET_VM()->living_threads, th->self);
+
+	/* wake up joinning threads */
+	th = th->join_list_head;
+	while (th) {
+	    native_thread_interrupt(th);
+	    th = th->join_list_next;
+	}
     }
     GVL_LOCK_END();
 
@@ -199,6 +208,62 @@
     return thval;
 }
 
+/* +infty, for this purpose */
+#define DELAY_INFTY 1E30
+
+VALUE th_make_localjump_error(const char *mesg, VALUE value, int reason);
+
+static VALUE
+yarv_thread_join(yarv_thread_t *target_th, double delay)
+{
+    yarv_thread_t *th = GET_THREAD();
+    double now, limit = timeofday() + delay;
+    
+    thread_debug("yarv_thread_join (thid: %p)\n", target_th->thread_id);
+
+    if (target_th->status != THREAD_KILLED) {
+	th->join_list_next = target_th->join_list_head;
+	target_th->join_list_head = th;
+    }
+
+    while (target_th->status != THREAD_KILLED) {
+	if (delay == DELAY_INFTY) {
+	    sleep_forever(th);
+	}
+	else {
+	    now = timeofday();
+	    if (now > limit) {
+		thread_debug("yarv_thread_join: timeout (thid: %p)\n",
+			     target_th->thread_id);
+		return Qnil;
+	    }
+	    sleep_wait_for_interrupt(th, limit - now);
+	}
+	
+	thread_debug("yarv_thread_join: interrupted (thid: %p)\n",
+		     target_th->thread_id);
+    }
+
+    thread_debug("yarv_thread_join: success (thid: %p)\n",
+		 target_th->thread_id);
+
+    if (target_th->errinfo != Qnil) {
+	VALUE err = target_th->errinfo;
+
+	if (FIXNUM_P(err)) {
+	    /* */
+	}
+	else if (TYPE(target_th->errinfo) == T_NODE) {
+	    rb_exc_raise(th_make_jump_tag_but_local_jump(
+		GET_THROWOBJ_STATE(err), GET_THROWOBJ_VAL(err)));
+	}
+	else {
+	    rb_exc_raise(err);
+	}
+    }
+    return target_th->self;
+}
+
 /*
  *  call-seq:
  *     thr.join          => thr
@@ -239,92 +304,20 @@
  *     tick...
  */
 
-VALUE th_make_localjump_error(const char *mesg, VALUE value, int reason);
-
 static VALUE
-yarv_thread_join(int argc, VALUE *argv, VALUE self)
+yarv_thread_join_m(int argc, VALUE *argv, VALUE self)
 {
-    yarv_thread_t *cur_th = GET_THREAD();
-    yarv_thread_t *th;
-    int err, lerrno;
+    yarv_thread_t *target_th;
+    double delay = DELAY_INFTY;
+    VALUE limit;
+    
+    GetThreadVal(self, target_th);
 
-    GetThreadVal(self, th);
-    cur_th->wait_thread_value = self;
-
-  again:
-    if (argc == 0) {
-	thread_debug("yarv_thread_join (thid: %p)\n", th->thread_id);
-
-	GVL_UNLOCK_RANGE(err = native_thread_join(cur_th, th->thread_id, 0);
-			 lerrno = errno;
-	    );
-
-	switch (lerrno) {
-	case EINTR:
-	    thread_debug("yarv_thread_join: interrupted (thid: %p)\n",
-			 th->thread_id);
-	    goto again;
-	case EDEADLK:
-	    cur_th->wait_thread_value = Qnil;
-	    rb_raise(rb_eThreadError,
-		     "can't join current thread (cause dead lock)");
-	    break;
-	case EINVAL:
-	    /* already terminated */
-	    if (th->status == THREAD_KILLED) {
-		thread_debug
-		    ("yarv_thread_join: already terminated (thid: %p)\n",
-		     th->thread_id);
-		break;
-	    }
-	    else {
-		rb_bug("yarv_thread_join: EINVAL");
-	    }
-	}
+    rb_scan_args(argc, argv, "01", &limit);
+    if (!NIL_P(limit)) {
+	delay = rb_num2dbl(limit);
     }
-    else if (argc == 1) {
-	double limit = timeofday();
-	struct timeval interval;
-
-	interval = rb_time_interval(argv[0]);
-	limit += interval.tv_sec;
-	limit += interval.tv_usec * 1e-6;
-
-	while (1) {
-	    GVL_UNLOCK_RANGE(sleep_for_polling());
-
-	    if (th->status == THREAD_KILLED) {
-		break;
-	    }
-	    if (timeofday() > limit) {
-		/* timeout */
-		cur_th->wait_thread_value = Qnil;
-		return self;
-	    }
-	}
-    }
-    else {
-	cur_th->wait_thread_value = Qnil;
-	rb_raise(rb_eArgError, "wrong number of arguments");
-    }
-
-    cur_th->wait_thread_value = Qnil;
-    
-    if (th->errinfo != Qnil) {
-	VALUE err = th->errinfo;
-	
-	if (FIXNUM_P(err)) {
-	    /* */
-	}
-	else if (TYPE(th->errinfo) == T_NODE) {
-	    rb_exc_raise(th_make_jump_tag_but_local_jump(
-		GET_THROWOBJ_STATE(err), GET_THROWOBJ_VAL(err)));
-	}
-	else {
-	    rb_exc_raise(err);
-	}
-    }
-    return self;
+    return yarv_thread_join(target_th, delay);
 }
 
 /*
@@ -342,9 +335,8 @@
 yarv_thread_value(VALUE self)
 {
     yarv_thread_t *th;
-
-    yarv_thread_join(0, 0, self);
     GetThreadVal(self, th);
+    yarv_thread_join(th, DELAY_INFTY);
     return th->value;
 }
 
@@ -362,14 +354,33 @@
 #define pause(th) pause()
 #endif
 
-void
-rb_thread_sleep_forever()
+static struct timeval
+double2timeval(double d)
 {
-    yarv_thread_t *th = GET_THREAD();
+    struct timeval time;
+
+    time.tv_sec = (int)d;
+    time.tv_usec = (int)((d - (int)d) * 1e6);
+    if (time.tv_usec < 0) {
+	time.tv_usec += (long)1e6;
+	time.tv_sec -= 1;
+    }
+    return time;
+}
+
+static void
+sleep_forever(yarv_thread_t *th)
+{
     thread_debug("rb_thread_sleep_forever\n");
     GVL_UNLOCK_RANGE(pause(th));
 }
 
+void
+rb_thread_sleep_forever()
+{
+    sleep_forever(GET_THREAD());
+}
+
 static double
 timeofday(void)
 {
@@ -378,7 +389,7 @@
     return (double)tv.tv_sec + (double)tv.tv_usec * 1e-6;
 }
 
-static void
+static int
 sleep_timeval(yarv_thread_t *th, struct timeval time)
 {
 #if defined(_WIN32) || defined(__CYGWIN__)
@@ -386,45 +397,28 @@
     thread_debug("sleep_timeval - sleep start\n");
     w32_sleep(th, limit);
     thread_debug("sleep_timeval - sleep end\n");
-    return;
+    return 0;
 #else
-#ifndef linux
-    double d, limit;
-    limit = timeofday() + (double)time.tv_sec + (double)time.tv_usec * 1e-6;
-#endif
     thread_debug("sleep_timeval\n");
-    for (;;) {
+    {
 	int n = select(0, 0, 0, 0, &time);
-	if (n == 0)
-	    return;
-	if (n < 0) {
-	    switch (errno) {
-	    case EINTR:
-#ifdef ERESTART
-	    case ERESTART:
-#endif
-		break;
-	    default:
-		rb_sys_fail("sleep");
-	    }
+	if (n == 0) {
+	    return 0;
 	}
-#ifndef linux
-	d = limit - timeofday();
-
-	time.tv_sec = (int)d;
-	time.tv_usec = (int)((d - (int)d) * 1e6);
-	if (time.tv_usec < 0) {
-	    time.tv_usec += (long)1e6;
-	    time.tv_sec -= 1;
+	else {
+	    return errno;
 	}
-	if (time.tv_sec < 0)
-	    return;
-#endif
     }
 #endif
 }
 
 static void
+sleep_wait_for_interrupt(yarv_thread_t *th, double sleepsec)
+{
+    sleep_timeval(th, double2timeval(sleepsec));
+}
+
+static void
 sleep_for_polling(yarv_thread_t *th)
 {
     struct timeval time;
@@ -437,8 +431,33 @@
 rb_thread_wait_for(struct timeval time)
 {
     yarv_thread_t *th = GET_THREAD();
+    double d, limit;
+    limit = timeofday()+(double)time.tv_sec+(double)time.tv_usec*1e-6;
     thread_debug("rb_thread_wait_for\n");
-    GVL_UNLOCK_RANGE(sleep_timeval(th, time));
+
+    while (1) {
+	int ret;
+	GVL_UNLOCK_RANGE(ret = sleep_timeval(th, time));
+
+	switch (ret) {
+	  case 0:
+	    return;
+	  case EINTR:
+#ifdef ERESTART
+	  case ERESTART:
+#endif
+	    break;
+	  default:
+	    rb_sys_fail("rb_thread_wait_for");
+	}
+
+	/* prepare to restart */
+	d = limit - timeofday();
+	time = double2timeval(d);
+	if (time.tv_sec < 0) {
+	    return;
+	}
+    }
 }
 
 void
@@ -462,15 +481,14 @@
 yarv_thraed_schedule()
 {
     thread_debug("yarv_thraed_schedule\n");
-    if (GET_VM()->thread_critical == 0) {
+    if (!rb_thread_alone()) {
 	yarv_thread_t *th = GET_THREAD();
 
 	thread_debug("yarv_thraed_schedule/switch start\n");
 	yarv_save_machine_context(th);
 	native_mutex_unlock(&GET_VM()->global_interpreter_lock);
 	{
-	    /* do nothing. */
-	    /* will be switch to another thread which is trying to acquire GVL */
+	    native_thread_yield();
 	}
 	native_mutex_lock(&GET_VM()->global_interpreter_lock);
 	yarv_set_current_running_thread(th);
@@ -1438,16 +1456,11 @@
 #ifdef ERESTART
 	    case ERESTART:
 #endif
+
 #ifndef linux
 		if (timeout) {
 		    double d = limit - timeofday();
-
-		    tv.tv_sec = (unsigned int)d;
-		    tv.tv_usec = (long)((d - (double)tv.tv_sec) * 1e6);
-		    if (tv.tv_sec < 0)
-			tv.tv_sec = 0;
-		    if (tv.tv_usec < 0)
-			tv.tv_usec = 0;
+		    tv = double2timeval(d);
 		}
 #endif
 		continue;
@@ -1526,6 +1539,7 @@
 	    list->next->prev = list->prev;
 	}
 	th->signal_thread_list = 0;
+	list->th = 0;
 	xfree(list);
     }
     else {
@@ -1906,7 +1920,7 @@
     rb_define_singleton_method(cYarvThread, "abort_on_exception=", rb_thread_s_abort_exc_set, 1);
 
     rb_define_method(cYarvThread, "raise", yarv_thread_raise_m, -1);
-    rb_define_method(cYarvThread, "join", yarv_thread_join, -1);
+    rb_define_method(cYarvThread, "join", yarv_thread_join_m, -1);
     rb_define_method(cYarvThread, "value", yarv_thread_value, 0);
     rb_define_method(cYarvThread, "kill", rb_thread_kill, 0);
     rb_define_method(cYarvThread, "terminate", rb_thread_kill, 0);

Modified: trunk/thread_pthread.h
===================================================================
--- trunk/thread_pthread.h	2006-02-20 02:22:42 UTC (rev 446)
+++ trunk/thread_pthread.h	2006-02-20 05:15:09 UTC (rev 447)
@@ -28,7 +28,7 @@
 
 #define native_cleanup_push pthread_cleanup_push
 #define native_cleanup_pop  pthread_cleanup_pop
-#define native_thread_join(a, b, c)  pthread_join(b, c)
+#define native_thread_yield() sched_yield()
 
 static void
 null_func()
@@ -88,7 +88,10 @@
 
     pthread_attr_init(&attr);
     pthread_attr_setstacksize(&attr, stack_size);
+    pthread_attr_setdetachstate(&attr, 1);
+    
     err = pthread_create(&th->thread_id, &attr, thread_start_func_1, th);
+    
     if (err != 0) {
 	th->status = THREAD_KILLED;
 	rb_raise(rb_eThreadError, "can't create Thread (%d)", err);
@@ -122,7 +125,9 @@
 native_thread_send_interrupt_signal(yarv_thread_t *th)
 {
     thread_debug("native_thread_send_interrupt_signal (%p)\n", th->thread_id);
-    pthread_kill(th->thread_id, SIGVTALRM);
+    if (th) {
+	pthread_kill(th->thread_id, SIGVTALRM);
+    }
 }
 
 void

Modified: trunk/thread_win32.h
===================================================================
--- trunk/thread_win32.h	2006-02-20 02:22:42 UTC (rev 446)
+++ trunk/thread_win32.h	2006-02-20 05:15:09 UTC (rev 447)
@@ -30,6 +30,8 @@
 #define WIN32_WAIT_TIMEOUT 10	/* 10 ms */
 #undef Sleep
 
+#define native_thread_yield() Sleep(0)
+
 static void
 Init_native_thread()
 {
@@ -102,7 +104,7 @@
 
     if (th) {
 	HANDLE intr = th->native_thread_data.interrupt_event;
-	ResetEvent(intr);
+	
 	if (th->interrupt_flag) {
 	    SetEvent(intr);
 	}
@@ -198,35 +200,6 @@
     // thread_debug("initialize mutex: %p\n", *lock);
 }
 
-static int
-native_thread_join(yarv_thread_t *th, yarv_thread_id_t thid, void *ptr)
-{
-    DWORD result;
-
-    while (1) {
-	result = w32_wait_event(thid, INFINITE, th);
-	switch (result) {
-	case WAIT_OBJECT_0:
-	    /* join */
-	    if (ptr) {
-		GetExitCodeThread(thid, ptr);
-	    }
-	    thread_debug("join to %p\n", thid);
-	    return 0;
-	case WAIT_TIMEOUT:
-	    /* TODO: check interrupt */
-	    errno = EINTR;
-	    thread_debug("join timeout (to %p)\n", thid);
-	    break;
-	case -1:
-	    errno = EINVAL;
-	    return 1;
-	}
-    }
-    return 1;
-}
-
-
 NOINLINE(static int
 	 thread_start_func_2(yarv_thread_t *th, VALUE *stack_start));
 void static thread_cleanup_func(void *th_ptr);

Modified: trunk/vm.c
===================================================================
--- trunk/vm.c	2006-02-20 02:22:42 UTC (rev 446)
+++ trunk/vm.c	2006-02-20 05:15:09 UTC (rev 447)
@@ -685,7 +685,8 @@
 	    argc = th_yield_setup_args(iseq, argc, th->cfp->sp);
 	    th->cfp->sp += argc;
 
-	    push_frame(th, iseq, FRAME_MAGIC_PROC,
+	    push_frame(th, iseq,
+		       proc->is_lambda ? FRAME_MAGIC_LAMBDA : FRAME_MAGIC_PROC,
 		       self, (VALUE)proc->block.dfp, iseq->iseq_encoded,
 		       th->cfp->sp, proc->block.lfp,
 		       iseq->local_size - argc);
@@ -693,13 +694,12 @@
 	}
     }
     else {
-
 	if (state == TAG_BREAK ||
 	    (state == TAG_RETURN && proc->is_lambda)) {
 	    VALUE err = th->errinfo;
 	    VALUE *escape_dfp = GET_THROWOBJ_CATCH_POINT(err);
 	    VALUE *cdfp = proc->block.dfp;
-	    
+
 	    if (escape_dfp == cdfp) {
 		state = 0;
 		th->errinfo = Qnil;

Modified: trunk/vm.h
===================================================================
--- trunk/vm.h	2006-02-20 02:22:42 UTC (rev 446)
+++ trunk/vm.h	2006-02-20 05:15:09 UTC (rev 447)
@@ -234,6 +234,7 @@
 #define FRAME_MAGIC_PROC   0xfaffff71
 #define FRAME_MAGIC_IFUNC  0xfaffff81
 #define FRAME_MAGIC_EVAL   0xfaffff91
+#define FRAME_MAGIC_LAMBDA 0xfaffffa1
 
 #define CHECK_FRAME_MAGIC(magic)                   \
 {                                                  \

Modified: trunk/vm_dump.c
===================================================================
--- trunk/vm_dump.c	2006-02-20 02:22:42 UTC (rev 446)
+++ trunk/vm_dump.c	2006-02-20 05:15:09 UTC (rev 447)
@@ -48,6 +48,9 @@
     case FRAME_MAGIC_PROC:
 	magic = "PROC";
 	break;
+      case FRAME_MAGIC_LAMBDA:
+	magic = "LAMBDA";
+	break;
     case FRAME_MAGIC_IFUNC:
 	magic = "IFUNC";
 	break;
@@ -222,8 +225,10 @@
 	cfp->magic == FRAME_MAGIC_BLOCK ||
 	cfp->magic == FRAME_MAGIC_CLASS ||
 	cfp->magic == FRAME_MAGIC_PROC ||
+	cfp->magic == FRAME_MAGIC_LAMBDA ||
 	cfp->magic == FRAME_MAGIC_CFUNC ||
-	cfp->magic == FRAME_MAGIC_IFUNC || cfp->magic == FRAME_MAGIC_EVAL) {
+	cfp->magic == FRAME_MAGIC_IFUNC ||
+	cfp->magic == FRAME_MAGIC_EVAL) {
 
 	VALUE *ptr = dfp - local_size;
 
@@ -540,10 +545,11 @@
 
     if (GET_VM()) {
 	int i;
+	SDR();
+	
 	bt = th_backtrace(th, 0);
 	for (i = 0; i < RARRAY(bt)->len; i++) {
 	    dp(RARRAY(bt)->ptr[i]);
 	}
-	SDR();
     }
 }

Modified: trunk/yarvcore.c
===================================================================
--- trunk/yarvcore.c	2006-02-20 02:22:42 UTC (rev 446)
+++ trunk/yarvcore.c	2006-02-20 05:15:09 UTC (rev 447)
@@ -119,54 +119,10 @@
 /* YARVCore */
 /************/
 
-/* temporalily */
-void yarv_setup(void *p1, void *p2, void *p3, void *p4,
-		void *p5, void *p6, void *p7, void *p8);
-
 yarv_thread_t *yarvCurrentThread = 0;
 yarv_vm_t *theYarvVM = 0;
 static VALUE yarvVMArray = Qnil;
 
-VALUE thread_call0(VALUE self, VALUE klass, VALUE recv, VALUE id, ID oid,
-		   int argc, VALUE *argv, NODE * body, int nosuper);
-
-/* rb_call0 continued for yarv function */
-VALUE
-yarv_call0(VALUE klass, VALUE recv, VALUE id, ID oid,
-	   int argc, VALUE *argv, NODE * body, int nosuper)
-{
-    return th_call0(GET_THREAD(), klass, recv, id, oid, argc, argv, body,
-		    nosuper);
-}
-
-
-VALUE th_call_super(yarv_thread_t *th, int argc, const VALUE *argv);
-
-VALUE
-yarv_call_super(int argc, const VALUE *argv)
-{
-    return th_call_super(GET_THREAD(), argc, argv);
-}
-
-VALUE th_backtrace(yarv_thread_t *th, int level);
-
-VALUE
-yarv_backtrace(int level)
-{
-    return th_backtrace(GET_THREAD(), level);
-}
-
-VALUE
-yarv_caller(VALUE self, VALUE level)
-{
-    if (!IS_YARV_WORKING()) {
-	return rb_funcall(Qnil, rb_intern("caller"), 1, level);
-    }
-    else {
-	return yarv_backtrace(FIX2INT(level));
-    }
-}
-
 RUBY_EXTERN int rb_thread_critical;
 RUBY_EXTERN int ruby_nerrs;
 RUBY_EXTERN NODE *ruby_eval_tree;
@@ -648,7 +604,6 @@
 	MARK_UNLESS_NULL(th->first_args);
 
 	MARK_UNLESS_NULL(th->thgroup);
-	MARK_UNLESS_NULL(th->wait_thread_value);
 	MARK_UNLESS_NULL(th->value);
 	MARK_UNLESS_NULL(th->errinfo);
 
@@ -1167,7 +1122,6 @@
     rb_define_global_function("once", yarv_once, 0);
     rb_define_global_function("segv", yarv_segv, 0);
     rb_define_global_function("cfunc", cfunc, 0);
-    rb_define_global_function("yarv_caller", yarv_caller, 1);
     rb_define_global_function("SDR", sdr, 0);
 
     /* Array#each */

Modified: trunk/yarvcore.h
===================================================================
--- trunk/yarvcore.h	2006-02-20 02:22:42 UTC (rev 446)
+++ trunk/yarvcore.h	2006-02-20 05:15:09 UTC (rev 447)
@@ -381,7 +381,6 @@
 
     VALUE thgroup;
     VALUE value;
-    VALUE wait_thread_value;
 
     VALUE errinfo;
     VALUE throwed_errinfo;
@@ -398,6 +397,9 @@
 	int tail;
     } signal_queue;
 
+    struct yarv_thread_struct *join_list_next;
+    struct yarv_thread_struct *join_list_head;
+    
     void *signal_thread_list;
 
     VALUE first_proc;

Modified: trunk/yarvtest/test_bin.rb
===================================================================
--- trunk/yarvtest/test_bin.rb	2006-02-20 02:22:42 UTC (rev 446)
+++ trunk/yarvtest/test_bin.rb	2006-02-20 05:15:09 UTC (rev 447)
@@ -68,6 +68,17 @@
       i = 10
       /test#{i}/ =~ 'test20'
     }
+    ae %q{
+      :sym =~ /sym/
+    }
+    ae %q{
+      sym = :sym
+      sym =~ /sym/
+    }
+    ae %q{
+      reg = /sym/
+      :sym =~ reg
+    }
   end
 
   def test_array
@@ -339,6 +350,13 @@
     } do
       remove_const :C
     end
+    ae %q{
+      @@x ||= 1
+    }
+    ae %q{
+      @@x = 0
+      @@x ||= 1
+    }
   end
 
   def test_op_assgin_and_or

Modified: trunk/yarvtest/test_block.rb
===================================================================
--- trunk/yarvtest/test_block.rb	2006-02-20 02:22:42 UTC (rev 446)
+++ trunk/yarvtest/test_block.rb	2006-02-20 05:15:09 UTC (rev 447)
@@ -85,7 +85,35 @@
       } + [a, $b, @c]
     }
   end
-  
+
+  def test_param3
+    ae %q{
+      h = {}
+      [1].each{|h[:foo]|}
+      h
+    }
+    ae %q{
+      obj = Object.new
+      def obj.x=(y)
+        $ans = y
+      end
+      [1].each{|obj.x|}
+      $ans
+    }
+  end
+
+  def test_blocklocal
+    ae %q{
+      1.times{
+        begin
+          a = 1
+        ensure
+          foo = nil
+        end
+      }
+    }
+  end
+
   def test_simplenest
     ae %q(
       def m

Modified: trunk/yarvtest/test_method.rb
===================================================================
--- trunk/yarvtest/test_method.rb	2006-02-20 02:22:42 UTC (rev 446)
+++ trunk/yarvtest/test_method.rb	2006-02-20 05:15:09 UTC (rev 447)
@@ -524,5 +524,16 @@
       C.new.foo
     }
   end
+
+  def test_return_from_defined_method
+    ae %q{
+      class C
+        define_method(:m){
+          return :ok
+        }
+      end
+      C.new.m
+    }
+  end
 end
 

Modified: trunk/yarvtest/test_thread.rb
===================================================================
--- trunk/yarvtest/test_thread.rb	2006-02-20 02:22:42 UTC (rev 446)
+++ trunk/yarvtest/test_thread.rb	2006-02-20 05:15:09 UTC (rev 447)
@@ -37,6 +37,14 @@
         }
       }
     }
+    ae %q{
+      5000.times{
+        t = Thread.new{}
+        while t.alive?
+          Thread.pass
+        end
+      }
+    }
   end
 
   def test_raise


-- 
ML: yarv-diff quickml.atdot.net
Info: http://www.atdot.net/~ko1/quickml

[前][次][番号順一覧][スレッド一覧][生データ]