[#36672] [Bug #616] instance_eval and Module#to_s — Shyouhei Urabe <redmine@...>

Bug #616: instance_eval and Module#to_s

12 messages 2008/10/06

[#36750] [Bug #650] Marshal.load raises RegexpError — Shyouhei Urabe <redmine@...>

Bug #650: Marshal.load raises RegexpError

30 messages 2008/10/15
[#36769] Re: [Bug #650] Marshal.load raises RegexpError — Yukihiro Matsumoto <matz@...> 2008/10/17

まつもと ゆきひろです

[#36771] Re: [Bug #650] Marshal.load raises RegexpError — Urabe Shyouhei <shyouhei@...> 2008/10/17

卜部です。

[#36772] Re: [Bug #650] Marshal.load raises RegexpError — Yukihiro Matsumoto <matz@...> 2008/10/17

まつもと ゆきひろです

[#36773] Re: [Bug #650] Marshal.load raises RegexpError — Urabe Shyouhei <shyouhei@...> 2008/10/17

卜部です。

[#36784] Re: [Bug #650] Marshal.load raises RegexpError — Yukihiro Matsumoto <matz@...> 2008/10/18

まつもと ゆきひろです

[#36785] Re: [Bug #650] Marshal.load raises RegexpError — Urabe Shyouhei <shyouhei@...> 2008/10/18

卜部です。

[#36793] Re: [Bug #650] Marshal.load raises RegexpError — Yukihiro Matsumoto <matz@...> 2008/10/19

まつもと ゆきひろです

[#36794] Re: [Bug #650] Marshal.load raises RegexpError — Urabe Shyouhei <shyouhei@...> 2008/10/19

Yukihiro Matsumoto さんは書きました:

[#36823] Re: [Bug #650] Marshal.load raises RegexpError — Yukihiro Matsumoto <matz@...> 2008/10/21

まつもと ゆきひろです

[#36830] Re: [Bug #650] Marshal.load raises RegexpError — Urabe Shyouhei <shyouhei@...> 2008/10/21

もとの正規表現にバグがあるのは認めますが、それに巻き込まれてでかいPStore

[#36833] Re: [Bug #650] Marshal.load raises RegexpError — Yukihiro Matsumoto <matz@...> 2008/10/21

まつもと ゆきひろです

[#36764] Re: [ruby-cvs:27036] Ruby:r19818 (trunk): * transcode.c (str_transcode0): String#encode without argument now — Martin Duerst <duerst@...>

まつもとさん、こんばんは。

11 messages 2008/10/17
[#36767] Re: [ruby-cvs:27036] Ruby:r19818 (trunk): * transcode.c (str_transcode0): String#encode without argument now — Yukihiro Matsumoto <matz@...> 2008/10/17

まつもと ゆきひろです

[#36799] Re: [ruby-cvs:27036] Ruby:r19818 (trunk): * transcode.c (str_transcode0): String#encode without argument now — Martin Duerst <duerst@...> 2008/10/20

まつもとさん、こんにちは。

[#36774] ConverterNotFoundError while making Ruby in Windows(trunk) — Masaki Suketa <masaki.suketa@...>

助田です。

13 messages 2008/10/17
[#36797] Re: ConverterNotFoundError while making Ruby in Windows(trunk) — "U.Nakamura" <usa@...> 2008/10/20

こんにちは、なかむら(う)です。

[#36800] Re: ConverterNotFoundError while making Ruby in Windows(trunk) — "U.Nakamura" <usa@...> 2008/10/20

こんにちは、なかむら(う)です。

[#36789] [Bug #660] 数字を3桁ずつコンマで区切るsprintf書式指定 — "rubikitch ." <redmine@...>

Bug #660: 数字を3桁ずつコンマで区切るsprintf書式指定

13 messages 2008/10/19

[#37007] [Bug:1.9] 1+1+1+...+1 dumps core — "Yusuke ENDOH" <mame@...>

遠藤です。

13 messages 2008/10/31

[ruby-dev:36734] 共有化された配列の参照カウンタによる開放

From: wanabe <s.wanabe@...>
Date: 2008-10-15 02:25:27 UTC
List: ruby-dev #36734
ワナベと申します。

ary_make_shared() で返される配列(長いので仮に共有配列と呼びます)を
どの配列からも参照されなくなったら rb_gc_force_recycle() するパッチを書きました。
共有配列のARY_CAPAはRARRAY_LENを返すようにし、
空いたaux.capa部分に参照カウンタを格納するようにしています。

たとえば以下のようなスクリプトで効果が期待されます。(恣意的な例ですが)

GC::Profiler.enable
a,b=[1,2,3,4], [5,6,7,8]
Thread.new{$stop=sleep 10}
until $stop
  a.replace b
  b[0] = 1
end
print GC::Profiler.result[/.*\n/]

私の環境ではGC起動回数が約200回→約10回ほどになりました。
今回はlinux(andLinux)でも動作を確認しています。
# [ruby-dev:34355], [ruby-dev:35850] では失礼しました。両方とも直せずじまいです。

Index: array.c
===================================================================
--- array.c	(revision 19779)
+++ array.c	(working copy)
@@ -107,7 +107,8 @@
     } \
 } while (0)

-#define ARY_CAPA(ary) (ARY_EMBED_P(ary) ? RARRAY_EMBED_LEN_MAX :
RARRAY(ary)->as.heap.aux.capa)
+#define ARY_CAPA(ary) (ARY_EMBED_P(ary) ? RARRAY_EMBED_LEN_MAX : \
+		       ARY_SHARED_ROOT_P(ary) ? RARRAY_LEN(ary) :
RARRAY(ary)->as.heap.aux.capa)
 #define ARY_SET_CAPA(ary, n) do { \
     assert(!ARY_EMBED_P(ary)); \
     assert(!ARY_SHARED_P(ary)); \
@@ -119,8 +120,21 @@
 #define ARY_SET_SHARED(ary, value) do { \
     assert(!ARY_EMBED_P(ary)); \
     assert(ARY_SHARED_P(ary)); \
+    assert(ARY_SHARED_ROOT_P(value)); \
     RARRAY(ary)->as.heap.aux.shared = (value); \
 } while (0)
+#define RARRAY_SHARED_ROOT_FLAG FL_USER5
+#define ARY_SHARED_ROOT_P(ary) (FL_TEST(ary, RARRAY_SHARED_ROOT_FLAG))
+#define ARY_SHARED_NUM(ary) \
+    (assert(ARY_SHARED_ROOT_P(ary)), RARRAY(ary)->as.heap.aux.capa)
+#define ARY_SET_SHARED_NUM(ary, value) do { \
+    assert(ARY_SHARED_ROOT_P(ary)); \
+    RARRAY(ary)->as.heap.aux.capa = (value); \
+} while (0)
+#define FL_SET_SHARED_ROOT(ary) do { \
+    assert(!ARY_EMBED_P(ary)); \
+    FL_SET(ary, RARRAY_SHARED_ROOT_FLAG); \
+} while (0)

 static void
 RESIZE_CAPA(VALUE ary, long capacity)
@@ -153,7 +167,48 @@
     }
 }

+static void
+rb_ary_decrement_share(VALUE shared)
+{
+    if (shared) {
+	int num = ARY_SHARED_NUM(shared) - 1;
+	if (num == 0) {
+	    rb_ary_free(shared);
+	    rb_gc_force_recycle(shared);
+	}
+	else if (num > 0) {
+	    ARY_SET_SHARED_NUM(shared, num);
+	}
+    }
+}
+
+static void
+rb_ary_unshare(VALUE ary)
+{
+    VALUE shared = RARRAY(ary)->as.heap.aux.shared;
+    rb_ary_decrement_share(shared);
+    FL_UNSET_SHARED(ary);
+}
+
 static inline void
+rb_ary_unshare_safe(VALUE ary) {
+    if (ARY_SHARED_P(ary) && !ARY_EMBED_P(ary)) {
+	rb_ary_unshare(ary);
+    }
+}
+
+static void
+rb_ary_set_shared(VALUE ary, VALUE shared)
+{
+    int num = ARY_SHARED_NUM(shared);
+    if (num >= 0) {
+	ARY_SET_SHARED_NUM(shared, num + 1);
+    }
+    FL_SET_SHARED(ary);
+    ARY_SET_SHARED(ary, shared);
+}
+
+static inline void
 rb_ary_modify_check(VALUE ary)
 {
     if (OBJ_FROZEN(ary)) rb_error_frozen("array");
@@ -169,16 +224,18 @@
         long len = RARRAY_LEN(ary);
         if (len <= RARRAY_EMBED_LEN_MAX) {
             VALUE *ptr = ARY_HEAP_PTR(ary);
+            VALUE shared = ARY_SHARED(ary);
             FL_UNSET_SHARED(ary);
             FL_SET_EMBED(ary);
             MEMCPY(ARY_EMBED_PTR(ary), ptr, VALUE, len);
+            rb_ary_decrement_share(shared);
             ARY_SET_EMBED_LEN(ary, len);
         }
         else {
             VALUE *ptr = ALLOC_N(VALUE, len);
-            FL_UNSET_SHARED(ary);
+            MEMCPY(ptr, RARRAY_PTR(ary), VALUE, len);
+            rb_ary_unshare(ary);
             ARY_SET_CAPA(ary, len);
-            MEMCPY(ptr, RARRAY_PTR(ary), VALUE, len);
             ARY_SET_PTR(ary, ptr);
         }
     }
@@ -314,7 +371,8 @@

         ARY_SET_LEN((VALUE)shared, RARRAY_LEN(ary));
         ARY_SET_PTR((VALUE)shared, RARRAY_PTR(ary));
-        ARY_SET_CAPA((VALUE)shared, ARY_CAPA(ary));
+	FL_SET_SHARED_ROOT(shared);
+	ARY_SET_SHARED_NUM((VALUE)shared, 1);
 	FL_SET_SHARED(ary);
 	ARY_SET_SHARED(ary, (VALUE)shared);
 	OBJ_FREEZE(shared);
@@ -430,7 +488,7 @@
 	if (ARY_OWNS_HEAP_P(ary) && RARRAY_PTR(ary)) {
 	    xfree(RARRAY_PTR(ary));
 	}
-        FL_UNSET_SHARED(ary);
+        rb_ary_unshare_safe(ary);
         FL_SET_EMBED(ary);
 	ARY_SET_EMBED_LEN(ary, 0);
 	if (rb_block_given_p()) {
@@ -550,8 +608,7 @@
         shared = ary_make_shared(ary);
         ARY_SET_PTR(result, RARRAY_PTR(ary));
         ARY_SET_LEN(result, RARRAY_LEN(ary));
-        FL_SET_SHARED(result);
-        ARY_SET_SHARED(result, shared);
+        rb_ary_set_shared(result, shared);

         ARY_INCREASE_PTR(result, offset);
         ARY_SET_LEN(result, len);
@@ -1700,7 +1757,7 @@
             if (RARRAY_PTR(ary) != RARRAY_PTR(tmp)) {
                 assert(!ARY_SHARED_P(tmp));
                 if (ARY_SHARED_P(ary)) {
-                    FL_UNSET_SHARED(ary);
+                    rb_ary_unshare(ary);
                 }
                 else {
                     xfree(ARY_HEAP_PTR(ary));
@@ -2246,23 +2303,34 @@

     if (RARRAY_LEN(orig) <= RARRAY_EMBED_LEN_MAX) {
         VALUE *ptr;
-        if (ARY_OWNS_HEAP_P(copy)) xfree(RARRAY_PTR(copy));
-        FL_UNSET_SHARED(copy);
+        VALUE shared = 0;
+
+        if (ARY_OWNS_HEAP_P(copy)) {
+            xfree(RARRAY_PTR(copy));
+        }
+        else if (ARY_SHARED_P(copy)) {
+            shared = ARY_SHARED(copy);
+            FL_UNSET_SHARED(copy);
+        }
         FL_SET_EMBED(copy);
         ptr = RARRAY_PTR(orig);
         MEMCPY(RARRAY_PTR(copy), ptr, VALUE, RARRAY_LEN(orig));
+        if (shared) {
+            rb_ary_decrement_share(shared);
+        }
         ARY_SET_LEN(copy, RARRAY_LEN(orig));
     }
     else {
         VALUE shared = ary_make_shared(orig);
         if (ARY_OWNS_HEAP_P(copy)) {
             xfree(RARRAY_PTR(copy));
+        } else {
+            rb_ary_unshare_safe(copy);
         }
         FL_UNSET_EMBED(copy);
-        FL_SET_SHARED(copy);
         ARY_SET_PTR(copy, RARRAY_PTR(orig));
         ARY_SET_LEN(copy, RARRAY_LEN(orig));
-        ARY_SET_SHARED(copy, shared);
+        rb_ary_set_shared(copy, shared);
     }
     return copy;
 }


-- 
ワナベ

In This Thread

Prev Next