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