[macruby-changes] [3056] MacRuby/trunk

source_changes at macosforge.org source_changes at macosforge.org
Fri Nov 27 16:57:41 PST 2009


Revision: 3056
          http://trac.macosforge.org/projects/ruby/changeset/3056
Author:   lsansonetti at apple.com
Date:     2009-11-27 16:57:38 -0800 (Fri, 27 Nov 2009)
Log Message:
-----------
fixing a bunch of GCD bugs

Modified Paths:
--------------
    MacRuby/trunk/dispatcher.cpp
    MacRuby/trunk/gcd.c
    MacRuby/trunk/test_vm/gcd.rb
    MacRuby/trunk/vm.cpp
    MacRuby/trunk/vm.h

Modified: MacRuby/trunk/dispatcher.cpp
===================================================================
--- MacRuby/trunk/dispatcher.cpp	2009-11-26 00:52:54 UTC (rev 3055)
+++ MacRuby/trunk/dispatcher.cpp	2009-11-28 00:57:38 UTC (rev 3056)
@@ -71,8 +71,7 @@
 
 static force_inline VALUE
 __rb_vm_bcall(VALUE self, SEL sel, VALUE dvars, rb_vm_block_t *b,
-	      IMP pimp, const rb_vm_arity_t &arity, int argc,
-	      const VALUE *argv)
+	IMP pimp, const rb_vm_arity_t &arity, int argc, const VALUE *argv)
 {
     if ((arity.real != argc) || (arity.max == -1)) {
 	VALUE *new_argv = (VALUE *)alloca(sizeof(VALUE) * arity.real);
@@ -113,7 +112,7 @@
 
 static force_inline VALUE
 __rb_vm_rcall(VALUE self, SEL sel, IMP pimp, const rb_vm_arity_t &arity,
-              int argc, const VALUE *argv)
+	int argc, const VALUE *argv)
 {
     if ((arity.real != argc) || (arity.max == -1)) {
 	VALUE *new_argv = (VALUE *)alloca(sizeof(VALUE) * arity.real);
@@ -1373,10 +1372,8 @@
 }
 
 static rb_vm_block_t *
-rb_vm_dup_active_block(rb_vm_block_t *src_b)
+dup_block(rb_vm_block_t *src_b)
 {
-    assert(src_b->flags & VM_BLOCK_ACTIVE);
-
     const size_t block_size = sizeof(rb_vm_block_t)
 	    + (sizeof(VALUE *) * src_b->dvars_size);
 
@@ -1403,6 +1400,36 @@
     return new_b;
 }
 
+extern "C"
+rb_vm_block_t *
+rb_vm_uncache_or_dup_block(rb_vm_block_t *b)
+{
+    return GET_VM()->uncache_or_dup_block(b);
+}
+
+extern "C"
+rb_vm_block_t *
+rb_vm_dup_block(rb_vm_block_t *b)
+{
+    return dup_block(b);
+}
+
+rb_vm_block_t *
+RoxorVM::uncache_or_dup_block(rb_vm_block_t *b)
+{
+    void *key = (void *)b->imp;
+    std::map<void *, rb_vm_block_t *>::iterator iter = blocks.find(key);
+    if (iter == blocks.end()) {
+	b = dup_block(b);
+	GC_RETAIN(b);
+	blocks[key] = b;
+    }
+    else {
+	b = iter->second;
+    }
+    return b;
+}
+
 static force_inline VALUE
 rb_vm_block_eval0(rb_vm_block_t *b, SEL sel, VALUE self, int argc,
 	const VALUE *argv)
@@ -1467,7 +1494,7 @@
 block_call:
 
     if (b->flags & VM_BLOCK_ACTIVE) {
-	b = rb_vm_dup_active_block(b);
+	b = dup_block(b);
     }
     b->flags |= VM_BLOCK_ACTIVE;
 
@@ -1611,16 +1638,15 @@
 	const bool is_ifunc = (iter != blocks.end())
 	    && ((iter->second->flags & VM_BLOCK_IFUNC) == VM_BLOCK_IFUNC);
 
-	if (!is_ifunc && iter != blocks.end()) {
-	    rb_objc_release(iter->second);
-	}
 	b = (rb_vm_block_t *)xmalloc(sizeof(rb_vm_block_t)
 		+ (sizeof(VALUE *) * dvars_size));
 	if (!is_ifunc) {
-	    rb_objc_retain(b);
+	    if (iter != blocks.end()) {
+		GC_RELEASE(iter->second);
+	    }
+	    GC_RETAIN(b);
 	    blocks[key] = b;
 	}
-
 	*cached = false;
     }
     else {

Modified: MacRuby/trunk/gcd.c
===================================================================
--- MacRuby/trunk/gcd.c	2009-11-26 00:52:54 UTC (rev 3055)
+++ MacRuby/trunk/gcd.c	2009-11-28 00:57:38 UTC (rev 3056)
@@ -129,7 +129,7 @@
 {
     VALUE q = rb_queue_alloc(cQueue, 0);
     if (should_retain) { 
-        rb_objc_retain((void*)q);
+        GC_RETAIN(q);
     }
     RQueue(q)->queue = dq;
     return q;
@@ -284,20 +284,31 @@
 }
 
 static VALUE
-rb_queue_dispatch_body(VALUE val)
+rb_queue_dispatch_body(VALUE data)
 {
-    rb_vm_block_t *the_block = (rb_vm_block_t *)val;
-    return rb_vm_block_eval(the_block, 0, NULL);
+    GC_RELEASE(data);
+    //rb_vm_block_t *b = rb_vm_uncache_or_dup_block((rb_vm_block_t *)data);
+    rb_vm_block_t *b = (rb_vm_block_t *)data;
+    return rb_vm_block_eval(b, 0, NULL);
 }
 
 static void
-rb_queue_dispatcher(void* block)
+rb_queue_dispatcher(void *data)
 {
-    assert(block != NULL);
-    rb_rescue2(rb_queue_dispatch_body, (VALUE)block, NULL, 0,
+    assert(data != NULL);
+    rb_rescue2(rb_queue_dispatch_body, (VALUE)data, NULL, 0,
 	    rb_eStandardError);
 }
 
+static rb_vm_block_t *
+rb_queue_dispatcher_prepare_block(rb_vm_block_t *block)
+{
+    rb_vm_set_multithreaded(true);
+    rb_vm_block_make_detachable_proc(block);
+    GC_RETAIN(block);
+    return block;
+}
+
 /* 
  *  call-seq:
  *    gcdq.dispatch(synchronicity) { i = 42 }
@@ -332,8 +343,7 @@
     VALUE synchronous;
     rb_scan_args(argc, argv, "01", &synchronous);
 
-    rb_vm_block_make_detachable_proc(block);
-    rb_vm_set_multithreaded(true);
+    block = rb_queue_dispatcher_prepare_block(block);
 
     if (RTEST(synchronous)){
         dispatch_sync_f(RQueue(self)->queue, (void *)block,
@@ -369,8 +379,7 @@
         rb_raise(rb_eArgError, "dispatch_after() requires a block argument");
     }
 
-    rb_vm_block_make_detachable_proc(block);
-    rb_vm_set_multithreaded(true);
+    block = rb_queue_dispatcher_prepare_block(block);
 
     dispatch_after_f(offset, RQueue(self)->queue, (void *)block,
 	    rb_queue_dispatcher);
@@ -378,15 +387,6 @@
     return Qnil;
 }
 
-static void
-rb_queue_applier(void* block, size_t ii)
-{
-    assert(block != NULL);
-    rb_vm_block_t *the_block = (rb_vm_block_t*)block;
-    VALUE num = SIZET2NUM(ii);
-    rb_vm_block_eval(the_block, 1, &num);
-}
-
 /* 
  *  call-seq:
  *    gcdq.apply(amount_size) { block }
@@ -400,6 +400,16 @@
  *
  */
  
+static void
+rb_queue_applier(void *data, size_t ii)
+{
+    assert(data != NULL);
+    rb_vm_block_t *block = rb_vm_uncache_or_dup_block((rb_vm_block_t *)data);
+    rb_vm_block_make_detachable_proc(block);
+    VALUE num = SIZET2NUM(ii);
+    rb_vm_block_eval(block, 1, &num);
+}
+
 static VALUE
 rb_queue_apply(VALUE self, SEL sel, VALUE n)
 {
@@ -408,7 +418,6 @@
         rb_raise(rb_eArgError, "apply() requires a block argument");
     }
 
-    rb_vm_block_make_detachable_proc(block);
     rb_vm_set_multithreaded(true);
 
     dispatch_apply_f(NUM2SIZET(n), RQueue(self)->queue, (void *)block,
@@ -565,9 +574,13 @@
         rb_raise(rb_eArgError, "dispatch() requires a block argument");
     }
 
-    rb_vm_block_make_detachable_proc(block);
-    rb_vm_set_multithreaded(true);
+    if (CLASS_OF(target) != cQueue) {
+	rb_raise(rb_eArgError, "expected Queue object, but got %s",
+		rb_class2name(CLASS_OF(target)));
+    }
 
+    block = rb_queue_dispatcher_prepare_block(block);
+
     dispatch_group_async_f(RGroup(self)->group, RQueue(target)->queue,
 	    (void *)block, rb_queue_dispatcher);
 
@@ -597,8 +610,7 @@
         rb_raise(rb_eArgError, "notify() requires a block argument");
     }
 
-    rb_vm_block_make_detachable_proc(block);
-    rb_vm_set_multithreaded(true);
+    block = rb_queue_dispatcher_prepare_block(block);
 
     dispatch_group_notify_f(RGroup(self)->group, RQueue(target)->queue,
 	    (void *)block, rb_queue_dispatcher);

Modified: MacRuby/trunk/test_vm/gcd.rb
===================================================================
--- MacRuby/trunk/test_vm/gcd.rb	2009-11-26 00:52:54 UTC (rev 3055)
+++ MacRuby/trunk/test_vm/gcd.rb	2009-11-28 00:57:38 UTC (rev 3056)
@@ -1,34 +1,44 @@
-n = (0..999).to_a.inject(0) { |b, i| b + i }.to_s
+n = (0..9999).to_a.inject(0) { |b, i| b + i }.to_s
 
+# sequential + synchronous
 assert n, %{
   n = 0
   q = Dispatch::Queue.new('foo')
-  g = Dispatch::Group.new
-  1000.times do |i|
-    g.dispatch(q) { n += i }
+  10000.times do |i|
+    q.dispatch(true) { n += i }
   end
-  g.wait
   p n
 }
 
+# sequential + asynchronous
 assert n, %{
   n = 0
   q = Dispatch::Queue.new('foo')
+  10000.times do |i|
+    q.dispatch { n += i }
+  end
+  q.dispatch(true) {}
+  p n
+}
+
+# group + sequential
+assert n, %{
+  n = 0
+  q = Dispatch::Queue.new('foo')
   g = Dispatch::Group.new
-  1000.times do |i|
-    g.dispatch(Dispatch::Queue.concurrent) do
-      g.dispatch(q) { n += i }
-    end
+  10000.times do |i|
+    g.dispatch(q) { n += i }
   end
   g.wait
   p n
 }
 
+# group + concurrent
 assert n, %{
   n = 0
   q = Dispatch::Queue.new('foo')
   g = Dispatch::Group.new
-  1000.times do |i|
+  10000.times do |i|
     g.dispatch(Dispatch::Queue.concurrent) do
       q.dispatch(true) { n += i }
     end
@@ -37,25 +47,28 @@
   p n
 }
 
+# apply + sequential
 assert n, %{
   n = 0
   q = Dispatch::Queue.new('foo')
-  q.apply(1000) do |i|
+  q.apply(10000) do |i|
     n += i
   end
   p n
 }
 
+# apply + concurrent
 assert n, %{
   n = 0
   q = Dispatch::Queue.new('foo')
-  Dispatch::Queue.concurrent.apply(1000) do |i|
+  Dispatch::Queue.concurrent.apply(10000) do |i|
     q.dispatch { n += i }
   end
   q.dispatch(true) {}
   p n
 }
 
+# exceptions should be ignored
 assert ':ok', %{
   g = Dispatch::Group.new
   g.dispatch(Dispatch::Queue.concurrent) { raise('hey') }
@@ -66,15 +79,15 @@
 # Stress tests
 
 assert ':ok', %{
-  Dispatch::Queue.concurrent.apply(10000000) {}
+  Dispatch::Queue.concurrent.apply(10000000) { |i| i+2*3/4-5}
   p :ok
 }
 
 assert ':ok', %{
   i = 0
   g = Dispatch::Group.new
-  while i < 10000000
-    g.dispatch(Dispatch::Queue.concurrent) { 1+2*3/4-5 }
+  while i < 100000
+    g.dispatch(Dispatch::Queue.concurrent) { i+2*3/4-5 }
     i += 1
   end
   g.wait

Modified: MacRuby/trunk/vm.cpp
===================================================================
--- MacRuby/trunk/vm.cpp	2009-11-26 00:52:54 UTC (rev 3055)
+++ MacRuby/trunk/vm.cpp	2009-11-28 00:57:38 UTC (rev 3056)
@@ -2686,7 +2686,8 @@
 };
 
 static void
-rb_vm_add_lvar_use(rb_vm_var_uses **var_uses, void *use, unsigned char use_type)
+rb_vm_add_lvar_use(rb_vm_var_uses **var_uses, void *use,
+	unsigned char use_type)
 {
     if (var_uses == NULL) {
 	return;
@@ -2701,7 +2702,8 @@
 	new_uses->uses_count = 0;
 	*var_uses = new_uses;
     }
-    int current_index = (*var_uses)->uses_count;
+
+    const int current_index = (*var_uses)->uses_count;
     rb_gc_assign_weak_ref(use, &(*var_uses)->uses[current_index]);
     (*var_uses)->use_types[current_index] = use_type;
     ++(*var_uses)->uses_count;

Modified: MacRuby/trunk/vm.h
===================================================================
--- MacRuby/trunk/vm.h	2009-11-26 00:52:54 UTC (rev 3055)
+++ MacRuby/trunk/vm.h	2009-11-28 00:57:38 UTC (rev 3056)
@@ -371,6 +371,9 @@
 bool rb_vm_block_saved(void);
 VALUE rb_vm_block_eval(rb_vm_block_t *block, int argc, const VALUE *argv);
 
+rb_vm_block_t *rb_vm_uncache_or_dup_block(rb_vm_block_t *b);
+rb_vm_block_t *rb_vm_dup_block(rb_vm_block_t *b);
+
 static inline void
 rb_vm_block_make_detachable_proc(rb_vm_block_t *b)
 {
@@ -942,6 +945,7 @@
 
 	rb_vm_block_t *uncache_or_create_block(void *key, bool *cached,
 		int dvars_size);
+	rb_vm_block_t *uncache_or_dup_block(rb_vm_block_t *b);
 
 	rb_vm_binding_t *current_binding(void) {
 	    return bindings.empty()
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20091127/31681783/attachment-0001.html>


More information about the macruby-changes mailing list